adeena43 commited on
Commit
1d4f70f
Β·
verified Β·
1 Parent(s): fece80e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +429 -429
app.py CHANGED
@@ -1,430 +1,430 @@
1
- # app.py
2
-
3
- import streamlit as st
4
- from rag_engine import (
5
- load_user_document,
6
- build_retriever_from_docs,
7
- answer_question
8
- )
9
- import os
10
-
11
- # Set environment variables
12
- os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
13
- os.environ["USER_AGENT"] = "PythonicAI/1.0 (+adinafraz01@gmail.com)"
14
-
15
- st.set_page_config(
16
- page_title="AI Documentation Assistant",
17
- layout="wide",
18
- initial_sidebar_state="expanded"
19
- )
20
-
21
- # -------------------- SESSION STATE --------------------
22
- if "retriever" not in st.session_state:
23
- st.session_state.retriever = None
24
-
25
- if "docs_loaded" not in st.session_state:
26
- st.session_state.docs_loaded = False
27
-
28
- if "current_url" not in st.session_state:
29
- st.session_state.current_url = None
30
-
31
- if "processing" not in st.session_state:
32
- st.session_state.processing = False
33
-
34
- # -------------------- CUSTOM CSS --------------------
35
- st.markdown("""
36
- <style>
37
- body {
38
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
39
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
40
- min-height: 100vh;
41
- }
42
-
43
- .main-container {
44
- max-width: 1000px;
45
- margin: 0 auto;
46
- }
47
-
48
- .header-card {
49
- background: rgba(255,255,255,0.95);
50
- border-radius: 20px;
51
- padding: 30px;
52
- margin-bottom: 30px;
53
- box-shadow: 0 10px 40px rgba(0,0,0,0.1);
54
- backdrop-filter: blur(10px);
55
- border: 1px solid rgba(255,255,255,0.2);
56
- }
57
-
58
- .input-card {
59
- background: rgba(255,255,255,0.95);
60
- border-radius: 15px;
61
- padding: 25px;
62
- margin-bottom: 25px;
63
- box-shadow: 0 8px 32px rgba(0,0,0,0.1);
64
- border: 1px solid rgba(255,255,255,0.2);
65
- }
66
-
67
- .answer-card {
68
- background: white;
69
- border-radius: 15px;
70
- padding: 30px;
71
- margin-top: 25px;
72
- box-shadow: 0 10px 40px rgba(0,0,0,0.08);
73
- animation: fadeIn 0.5s ease;
74
- border-left: 5px solid #667eea;
75
- }
76
-
77
- .url-display {
78
- background: #f0f4ff;
79
- border-radius: 10px;
80
- padding: 15px;
81
- margin: 15px 0;
82
- border-left: 4px solid #4f46e5;
83
- word-break: break-all;
84
- }
85
-
86
- .stButton button {
87
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
88
- color: white;
89
- font-weight: 600;
90
- border: none;
91
- border-radius: 12px;
92
- padding: 14px 28px;
93
- width: 100%;
94
- transition: all 0.3s;
95
- font-size: 16px;
96
- }
97
-
98
- .stButton button:hover {
99
- transform: translateY(-3px);
100
- box-shadow: 0 7px 20px rgba(0,0,0,0.2);
101
- }
102
-
103
- .primary-btn {
104
- background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
105
- }
106
-
107
- .secondary-btn {
108
- background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
109
- }
110
-
111
- .question-box {
112
- background: #f8fafc;
113
- border-radius: 12px;
114
- padding: 20px;
115
- border: 2px solid #e2e8f0;
116
- font-size: 16px;
117
- min-height: 120px;
118
- }
119
-
120
- .info-box {
121
- background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
122
- color: white;
123
- padding: 20px;
124
- border-radius: 15px;
125
- margin: 15px 0;
126
- }
127
-
128
- .example-chip {
129
- display: inline-block;
130
- background: #e0e7ff;
131
- color: #4f46e5;
132
- padding: 8px 16px;
133
- margin: 5px;
134
- border-radius: 20px;
135
- cursor: pointer;
136
- font-size: 14px;
137
- transition: all 0.2s;
138
- border: 1px solid #c7d2fe;
139
- }
140
-
141
- .example-chip:hover {
142
- background: #c7d2fe;
143
- transform: translateY(-2px);
144
- }
145
-
146
- @keyframes fadeIn {
147
- from { opacity:0; transform:translateY(10px); }
148
- to { opacity:1; transform:translateY(0); }
149
- }
150
-
151
- /* Scrollbar styling */
152
- ::-webkit-scrollbar {
153
- width: 8px;
154
- }
155
-
156
- ::-webkit-scrollbar-track {
157
- background: #f1f1f1;
158
- border-radius: 10px;
159
- }
160
-
161
- ::-webkit-scrollbar-thumb {
162
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
163
- border-radius: 10px;
164
- }
165
-
166
- ::-webkit-scrollbar-thumb:hover {
167
- background: linear-gradient(135deg, #5a67d8 0%, #6d28d9 100%);
168
- }
169
- </style>
170
- """, unsafe_allow_html=True)
171
-
172
- # -------------------- SIDEBAR --------------------
173
- with st.sidebar:
174
- st.markdown("""
175
- <div style="text-align:center; padding:18px 0;">
176
- <h2 style="color:black; margin-bottom:2px; font-size:20px;">πŸ“š AI Doc Assistant</h2>
177
- <p style="color:black; font-size:20px;">Python Documentation Q&A</p>
178
- </div>
179
- """, unsafe_allow_html=True)
180
-
181
- st.markdown("---")
182
-
183
- if st.session_state.docs_loaded:
184
- st.markdown("### βœ… Document Status")
185
- st.success("Document Loaded Successfully")
186
-
187
- if st.session_state.current_url:
188
- st.markdown("**Current URL:**")
189
- st.code(st.session_state.current_url[:80] + "..." if len(st.session_state.current_url) > 80 else st.session_state.current_url, language="text")
190
-
191
- if st.button("πŸ—‘οΈ Clear Document", use_container_width=True):
192
- st.session_state.docs_loaded = False
193
- st.session_state.retriever = None
194
- st.session_state.current_url = None
195
- st.rerun()
196
- else:
197
- st.markdown("### ⚠️ Status")
198
- st.info("No document loaded")
199
-
200
- st.markdown("---")
201
- st.markdown("### πŸ“– How to Use")
202
- st.markdown("""
203
- 1. **Enter a URL** pointing to Python documentation
204
- 2. Click **Load Document** to process
205
- 3. Ask **Python-related questions** about the content
206
- 4. Get instant, context-aware answers
207
- """)
208
-
209
- st.markdown("---")
210
- st.markdown("### πŸ’‘ Example URLs")
211
- urls = [
212
- "https://numpy.org/doc/2.3/user/absolute_beginners.html",
213
- "https://pandas.pydata.org/docs/",
214
- "https://matplotlib.org/stable/users/index.html",
215
- "https://scikit-learn.org/stable/user_guide.html"
216
- ]
217
-
218
- for url in urls:
219
- if st.button(f"πŸ“„ {url.split('/')[2]}", key=f"url_{url}"):
220
- st.session_state.url_input = url
221
- st.rerun()
222
-
223
- st.markdown("---")
224
- st.markdown("""
225
- <div style="text-align:center; color:black; font-size:12px; padding:10px;">
226
- Powered by OpenAI β€’ LangChain β€’ FAISS
227
- </div>
228
- """, unsafe_allow_html=True)
229
-
230
- # -------------------- MAIN CONTENT --------------------
231
- st.markdown('<div class="main-container">', unsafe_allow_html=True)
232
-
233
- # Header
234
- st.markdown("""
235
- <div class="header-card">
236
- <h1 style="text-align:center; font-size:42px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom:10px;">
237
- πŸ€– AI Documentation Assistant
238
- </h1>
239
- <p style="text-align:center; font-size:18px; color:#4b5563; margin-bottom:20px;">
240
- Ask questions about any Python documentation from a URL
241
- </p>
242
- </div>
243
- """, unsafe_allow_html=True)
244
-
245
- # URL Input Section
246
- st.markdown('<div class="input-card">', unsafe_allow_html=True)
247
- st.markdown("### 🌐 Enter Documentation URL")
248
-
249
- # Initialize session state for URL if not exists
250
- if "url_input" not in st.session_state:
251
- st.session_state.url_input = "https://numpy.org/doc/2.3/user/absolute_beginners.html"
252
-
253
- url = st.text_input(
254
- "Enter the URL of Python documentation:",
255
- value=st.session_state.url_input,
256
- placeholder="https://example.com/python-docs",
257
- label_visibility="collapsed",
258
- key="url_input_field"
259
- )
260
-
261
- col1, col2 = st.columns([1, 1])
262
-
263
- with col1:
264
- load_clicked = st.button(
265
- "πŸ“₯ Load Document",
266
- use_container_width=True,
267
- type="primary",
268
- disabled=not url.strip()
269
- )
270
-
271
- with col2:
272
- if st.session_state.docs_loaded:
273
- if st.button("πŸ”„ Reload", use_container_width=True):
274
- load_clicked = True
275
-
276
- st.markdown('</div>', unsafe_allow_html=True)
277
-
278
- # Handle document loading
279
- if load_clicked:
280
- if not url.strip():
281
- st.error("❌ Please enter a valid URL")
282
- else:
283
- try:
284
- with st.spinner("πŸ” Loading and processing documentation..."):
285
- # Store current URL
286
- st.session_state.current_url = url
287
-
288
- # Show progress
289
- progress_text = st.empty()
290
- progress_bar = st.progress(0)
291
-
292
- progress_text.text("Downloading document...")
293
- docs = load_user_document(url)
294
- progress_bar.progress(30)
295
-
296
- progress_text.text("Processing content...")
297
- st.session_state.retriever = build_retriever_from_docs(docs)
298
- progress_bar.progress(70)
299
-
300
- progress_text.text("Finalizing...")
301
- st.session_state.docs_loaded = True
302
- progress_bar.progress(100)
303
-
304
- progress_text.text("βœ… Ready!")
305
-
306
- st.success(f"βœ… Successfully loaded documentation from: {url}")
307
-
308
-
309
- # Show document info
310
- st.markdown(f"""
311
- <div class="url-display">
312
- <strong>πŸ“„ Loaded Document:</strong> {url}<br>
313
- <strong>πŸ“Š Pages Processed:</strong> {len(docs)}<br>
314
- <strong>βœ… Status:</strong> Ready for questions
315
- </div>
316
- """, unsafe_allow_html=True)
317
-
318
- except Exception as e:
319
- st.error(f"❌ Error loading document: {str(e)}")
320
-
321
- # Question Input Section (only show if document is loaded)
322
- if st.session_state.docs_loaded:
323
- st.markdown('<div class="input-card">', unsafe_allow_html=True)
324
-
325
- st.markdown("### πŸ’­ Ask a Question")
326
-
327
- # Example questions
328
- st.markdown("**πŸ’‘ Try asking:**")
329
- col1, col2, col3, col4 = st.columns(4)
330
-
331
- example_questions = [
332
- "What is this library about?",
333
- "How to get started?",
334
- "What are the main functions?",
335
- "Give me a code example"
336
- ]
337
-
338
- for i, question in enumerate(example_questions):
339
- col = [col1, col2, col3, col4][i]
340
- with col:
341
- if st.button(question, use_container_width=True):
342
- st.session_state.question_input = question
343
- st.rerun()
344
-
345
- # Question input
346
- question = st.text_area(
347
- "Enter your Python-related question:",
348
- value=st.session_state.get("question_input", ""),
349
- placeholder="Example: What is NumPy? How to create arrays? What are the main functions?",
350
- height=120,
351
- key="question_input_area"
352
- )
353
-
354
- # Answer button
355
- col1, col2, col3 = st.columns([2, 1, 1])
356
-
357
- with col2:
358
- if st.button("πŸš€ Get Answer", type="primary", use_container_width=True):
359
- if not question.strip():
360
- st.warning("Please enter a question")
361
- else:
362
- st.session_state.processing = True
363
- st.session_state.current_question = question
364
-
365
- with col3:
366
- if st.button("πŸ—‘οΈ Clear", use_container_width=True):
367
- st.session_state.question_input = ""
368
- st.rerun()
369
-
370
- st.markdown('</div>', unsafe_allow_html=True)
371
-
372
- # Process and display answer
373
- if st.session_state.get("processing") and st.session_state.get("current_question"):
374
- with st.spinner("πŸ€” Analyzing document and generating answer..."):
375
- try:
376
- answer = answer_question(
377
- st.session_state.current_question,
378
- st.session_state.retriever
379
- )
380
-
381
- st.markdown("### πŸ“ Answer")
382
- st.markdown(f'<div class="answer-card">{answer}</div>', unsafe_allow_html=True)
383
-
384
- # Reset processing state
385
- st.session_state.processing = False
386
-
387
- except Exception as e:
388
- st.error(f"❌ Error generating answer: {str(e)}")
389
- st.session_state.processing = False
390
-
391
- # Quick actions
392
- st.markdown("""
393
- <div style="text-align:center; margin-top:30px;">
394
- <hr style="border:none; height:1px; background:linear-gradient(90deg, transparent, #667eea, transparent); margin:20px 0;">
395
- <p style="color:#6b7280; font-size:14px;">
396
- πŸ’‘ Tip: Ask specific questions for better answers. Try asking about functions, usage examples, or concepts.
397
- </p>
398
- </div>
399
- """, unsafe_allow_html=True)
400
-
401
- else:
402
- # Welcome message when no document is loaded
403
- st.markdown("""
404
- <div class="info-box">
405
- <h3>πŸ‘‹ Welcome to AI Documentation Assistant!</h3>
406
- <p>Get started by entering a URL to Python documentation above.</p>
407
- <p><strong>Try the default URL</strong> or enter your own documentation link.</p>
408
- </div>
409
-
410
- <div style="background:white; border-radius:15px; padding:30px; margin-top:20px;">
411
- <h3 style="color:#4f46e5;">✨ Features:</h3>
412
- <ul style="font-size:16px; line-height:1.8;">
413
- <li><strong>πŸ“š URL-based</strong> - Just paste a documentation URL</li>
414
- <li><strong>πŸ€– AI-powered</strong> - Get intelligent answers from docs</li>
415
- <li><strong>⚑ Fast processing</strong> - Quick document analysis</li>
416
- <li><strong>πŸ’¬ Interactive</strong> - Ask follow-up questions</li>
417
- <li><strong>🎯 Python-focused</strong> - Optimized for Python documentation</li>
418
- </ul>
419
-
420
- <h3 style="color:#4f46e5; margin-top:30px;">πŸš€ Quick Start:</h3>
421
- <ol style="font-size:16px; line-height:1.8;">
422
- <li>Enter a Python documentation URL (or use the default)</li>
423
- <li>Click <strong>"Load Document"</strong></li>
424
- <li>Wait a few seconds for processing</li>
425
- <li>Ask any Python-related question about the documentation</li>
426
- </ol>
427
- </div>
428
- """, unsafe_allow_html=True)
429
-
430
  st.markdown('</div>', unsafe_allow_html=True)
 
1
+ # app.py
2
+
3
+ import streamlit as st
4
+ from rag_engine import (
5
+ load_user_document,
6
+ build_retriever_from_docs,
7
+ answer_question
8
+ )
9
+ import os
10
+
11
+ # Set environment variables
12
+ os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
13
+ os.environ["USER_AGENT"] = "PythonicAI/1.0 (+adinafraz01@gmail.com)"
14
+
15
+ st.set_page_config(
16
+ page_title="AI Documentation Assistant",
17
+ layout="wide",
18
+ initial_sidebar_state="expanded"
19
+ )
20
+
21
+ # -------------------- SESSION STATE --------------------
22
+ if "retriever" not in st.session_state:
23
+ st.session_state.retriever = None
24
+
25
+ if "docs_loaded" not in st.session_state:
26
+ st.session_state.docs_loaded = False
27
+
28
+ if "current_url" not in st.session_state:
29
+ st.session_state.current_url = None
30
+
31
+ if "processing" not in st.session_state:
32
+ st.session_state.processing = False
33
+
34
+ # -------------------- CUSTOM CSS --------------------
35
+ st.markdown("""
36
+ <style>
37
+ body {
38
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
39
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
40
+ min-height: 100vh;
41
+ }
42
+
43
+ .main-container {
44
+ max-width: 1000px;
45
+ margin: 0 auto;
46
+ }
47
+
48
+ .header-card {
49
+ background: rgba(255,255,255,0.95);
50
+ border-radius: 20px;
51
+ padding: 30px;
52
+ margin-bottom: 30px;
53
+ box-shadow: 0 10px 40px rgba(0,0,0,0.1);
54
+ backdrop-filter: blur(10px);
55
+ border: 1px solid rgba(255,255,255,0.2);
56
+ }
57
+
58
+ .input-card {
59
+ background: rgba(255,255,255,0.95);
60
+ border-radius: 15px;
61
+ padding: 25px;
62
+ margin-bottom: 25px;
63
+ box-shadow: 0 8px 32px rgba(0,0,0,0.1);
64
+ border: 1px solid rgba(255,255,255,0.2);
65
+ }
66
+
67
+ .answer-card {
68
+ background: white;
69
+ border-radius: 15px;
70
+ padding: 30px;
71
+ margin-top: 25px;
72
+ box-shadow: 0 10px 40px rgba(0,0,0,0.08);
73
+ animation: fadeIn 0.5s ease;
74
+ border-left: 5px solid #667eea;
75
+ }
76
+
77
+ .url-display {
78
+ background: #f0f4ff;
79
+ border-radius: 10px;
80
+ padding: 15px;
81
+ margin: 15px 0;
82
+ border-left: 4px solid #4f46e5;
83
+ word-break: break-all;
84
+ }
85
+
86
+ .stButton button {
87
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
88
+ color: white;
89
+ font-weight: 600;
90
+ border: none;
91
+ border-radius: 12px;
92
+ padding: 14px 28px;
93
+ width: 100%;
94
+ transition: all 0.3s;
95
+ font-size: 16px;
96
+ }
97
+
98
+ .stButton button:hover {
99
+ transform: translateY(-3px);
100
+ box-shadow: 0 7px 20px rgba(0,0,0,0.2);
101
+ }
102
+
103
+ .primary-btn {
104
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
105
+ }
106
+
107
+ .secondary-btn {
108
+ background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
109
+ }
110
+
111
+ .question-box {
112
+ background: #f8fafc;
113
+ border-radius: 12px;
114
+ padding: 20px;
115
+ border: 2px solid #e2e8f0;
116
+ font-size: 16px;
117
+ min-height: 120px;
118
+ }
119
+
120
+ .info-box {
121
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
122
+ color: white;
123
+ padding: 20px;
124
+ border-radius: 15px;
125
+ margin: 15px 0;
126
+ }
127
+
128
+ .example-chip {
129
+ display: inline-block;
130
+ background: #e0e7ff;
131
+ color: #4f46e5;
132
+ padding: 8px 16px;
133
+ margin: 5px;
134
+ border-radius: 20px;
135
+ cursor: pointer;
136
+ font-size: 14px;
137
+ transition: all 0.2s;
138
+ border: 1px solid #c7d2fe;
139
+ }
140
+
141
+ .example-chip:hover {
142
+ background: #c7d2fe;
143
+ transform: translateY(-2px);
144
+ }
145
+
146
+ @keyframes fadeIn {
147
+ from { opacity:0; transform:translateY(10px); }
148
+ to { opacity:1; transform:translateY(0); }
149
+ }
150
+
151
+ /* Scrollbar styling */
152
+ ::-webkit-scrollbar {
153
+ width: 8px;
154
+ }
155
+
156
+ ::-webkit-scrollbar-track {
157
+ background: #f1f1f1;
158
+ border-radius: 10px;
159
+ }
160
+
161
+ ::-webkit-scrollbar-thumb {
162
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
163
+ border-radius: 10px;
164
+ }
165
+
166
+ ::-webkit-scrollbar-thumb:hover {
167
+ background: linear-gradient(135deg, #5a67d8 0%, #6d28d9 100%);
168
+ }
169
+ </style>
170
+ """, unsafe_allow_html=True)
171
+
172
+ # -------------------- SIDEBAR --------------------
173
+ with st.sidebar:
174
+ st.markdown("""
175
+ <div style="text-align:center; padding:18px 0;">
176
+ <h2 style="color:black; margin-bottom:2px; font-size:20px;">πŸ“š AI Doc Assistant</h2>
177
+ <p style="color:black; font-size:20px;">Python Documentation Q&A</p>
178
+ </div>
179
+ """, unsafe_allow_html=True)
180
+
181
+ st.markdown("---")
182
+
183
+ if st.session_state.docs_loaded:
184
+ st.markdown("### βœ… Document Status")
185
+ st.success("Document Loaded Successfully")
186
+
187
+ if st.session_state.current_url:
188
+ st.markdown("**Current URL:**")
189
+ st.code(st.session_state.current_url[:80] + "..." if len(st.session_state.current_url) > 80 else st.session_state.current_url, language="text")
190
+
191
+ if st.button("πŸ—‘οΈ Clear Document", use_container_width=True):
192
+ st.session_state.docs_loaded = False
193
+ st.session_state.retriever = None
194
+ st.session_state.current_url = None
195
+ st.rerun()
196
+ else:
197
+ st.markdown("### ⚠️ Status")
198
+ st.info("No document loaded")
199
+
200
+ st.markdown("---")
201
+ st.markdown("### πŸ“– How to Use")
202
+ st.markdown("""
203
+ 1. **Enter a URL** pointing to Python documentation
204
+ 2. Click **Load Document** to process
205
+ 3. Ask **Python-related questions** about the content
206
+ 4. Get instant, context-aware answers
207
+ """)
208
+
209
+ st.markdown("---")
210
+ st.markdown("### πŸ’‘ Example URLs")
211
+ urls = [
212
+ "https://numpy.org/doc/2.3/user/absolute_beginners.html",
213
+ "https://pandas.pydata.org/docs/",
214
+ "https://matplotlib.org/stable/users/index.html",
215
+ "https://scikit-learn.org/stable/user_guide.html"
216
+ ]
217
+
218
+ for url in urls:
219
+ if st.button(f"πŸ“„ {url.split('/')[2]}", key=f"url_{url}"):
220
+ st.session_state.url_input = url
221
+ st.rerun()
222
+
223
+ st.markdown("---")
224
+ st.markdown("""
225
+ <div style="text-align:center; color:black; font-size:12px; padding:10px;">
226
+ Powered by OpenAI β€’ LangChain β€’ FAISS
227
+ </div>
228
+ """, unsafe_allow_html=True)
229
+
230
+ # -------------------- MAIN CONTENT --------------------
231
+ st.markdown('<div class="main-container">', unsafe_allow_html=True)
232
+
233
+ # Header
234
+ st.markdown("""
235
+ <div class="header-card">
236
+ <h1 style="text-align:center; font-size:42px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom:10px;">
237
+ πŸ€– AI Documentation Assistant
238
+ </h1>
239
+ <p style="text-align:center; font-size:18px; color:#4b5563; margin-bottom:20px;">
240
+ Ask questions about any Python documentation from a URL
241
+ </p>
242
+ </div>
243
+ """, unsafe_allow_html=True)
244
+
245
+ # URL Input Section
246
+ st.markdown('<div class="input-card">', unsafe_allow_html=True)
247
+ st.markdown("### 🌐 Enter Documentation URL")
248
+
249
+ # Initialize session state for URL if not exists
250
+ if "url_input" not in st.session_state:
251
+ st.session_state.url_input = "https://numpy.org/doc/2.3/user/absolute_beginners.html"
252
+
253
+ url = st.text_input(
254
+ "Enter the URL of Python documentation:",
255
+ value=st.session_state.url_input,
256
+ placeholder="https://example.com/python-docs",
257
+ label_visibility="collapsed",
258
+ key="url_input_field"
259
+ )
260
+
261
+ col1, col2 = st.columns([1, 1])
262
+
263
+ with col1:
264
+ load_clicked = st.button(
265
+ "πŸ“₯ Load Document",
266
+ use_container_width=True,
267
+ type="primary",
268
+ disabled=not url.strip()
269
+ )
270
+
271
+ with col2:
272
+ if st.session_state.docs_loaded:
273
+ if st.button("πŸ”„ Reload", use_container_width=True):
274
+ load_clicked = True
275
+
276
+ st.markdown('</div>', unsafe_allow_html=True)
277
+
278
+ # Handle document loading
279
+ if load_clicked:
280
+ if not url.strip():
281
+ st.error("❌ Please enter a valid URL")
282
+ else:
283
+ try:
284
+ with st.spinner("πŸ” Loading and processing documentation..."):
285
+ # Store current URL
286
+ st.session_state.current_url = url
287
+
288
+ # Show progress
289
+ progress_text = st.empty()
290
+ progress_bar = st.progress(0)
291
+
292
+ progress_text.text("Downloading document...")
293
+ docs = load_user_document(url)
294
+ progress_bar.progress(30)
295
+
296
+ progress_text.text("Processing content...")
297
+ st.session_state.retriever = build_retriever_from_docs(docs)
298
+ progress_bar.progress(70)
299
+
300
+ progress_text.text("Finalizing...")
301
+ st.session_state.docs_loaded = True
302
+ progress_bar.progress(100)
303
+
304
+ progress_text.text("βœ… Ready!")
305
+
306
+ st.success(f"βœ… Successfully loaded documentation from: {url}")
307
+
308
+
309
+ # Show document info
310
+ st.markdown(f"""
311
+ <div class="url-display">
312
+ <strong>πŸ“„ Loaded Document:</strong> {url}<br>
313
+ <strong>πŸ“Š Pages Processed:</strong> {len(docs)}<br>
314
+ <strong>βœ… Status:</strong> Ready for questions
315
+ </div>
316
+ """, unsafe_allow_html=True)
317
+
318
+ except Exception as e:
319
+ st.error(f"❌ Error loading document: {str(e)}")
320
+
321
+ # Question Input Section (only show if document is loaded)
322
+ if st.session_state.docs_loaded:
323
+ st.markdown('<div class="input-card">', unsafe_allow_html=True)
324
+
325
+ st.markdown("### πŸ’­ Ask a Question")
326
+
327
+ # Example questions
328
+ st.markdown("**πŸ’‘ Try asking:**")
329
+ col1, col2, col3, col4 = st.columns(4)
330
+
331
+ example_questions = [
332
+ "What is this library about?",
333
+ "How to get started?",
334
+ "What are the main functions?",
335
+ "Give me a code example"
336
+ ]
337
+
338
+ for i, question in enumerate(example_questions):
339
+ col = [col1, col2, col3, col4][i]
340
+ with col:
341
+ if st.button(question, use_container_width=True):
342
+ st.session_state.question_input = question
343
+ st.rerun()
344
+
345
+ # Question input
346
+ question = st.text_area(
347
+ "Enter your Python-related question:",
348
+ value=st.session_state.get("question_input", ""),
349
+ placeholder="Example: What is NumPy? How to create arrays? What are the main functions?",
350
+ height=120,
351
+ key="question_input_area"
352
+ )
353
+
354
+ # Answer button
355
+ col1, col2, col3 = st.columns([2, 1, 1])
356
+
357
+ with col2:
358
+ if st.button("πŸš€ Get Answer", type="primary", use_container_width=True):
359
+ if not question.strip():
360
+ st.warning("Please enter a question")
361
+ else:
362
+ st.session_state.processing = True
363
+ st.session_state.current_question = question
364
+
365
+ with col3:
366
+ if st.button("πŸ—‘οΈ Clear", use_container_width=True):
367
+ st.session_state.question_input = ""
368
+ st.rerun()
369
+
370
+ st.markdown('</div>', unsafe_allow_html=True)
371
+
372
+ # Process and display answer
373
+ if st.session_state.get("processing") and st.session_state.get("current_question"):
374
+ with st.spinner("πŸ€” Analyzing document and generating answer..."):
375
+ try:
376
+ answer = answer_question(
377
+ st.session_state.current_question,
378
+ st.session_state.retriever
379
+ )
380
+
381
+ st.markdown("### πŸ“ Answer")
382
+ st.markdown(f'<div class="answer-card">{answer}</div>', unsafe_allow_html=True)
383
+
384
+ # Reset processing state
385
+ st.session_state.processing = False
386
+
387
+ except Exception as e:
388
+ st.error(f"❌ Error generating answer: {str(e)}")
389
+ st.session_state.processing = False
390
+
391
+ # Quick actions
392
+ st.markdown("""
393
+ <div style="text-align:center; margin-top:30px;">
394
+ <hr style="border:none; height:1px; background:linear-gradient(90deg, transparent, #667eea, transparent); margin:20px 0;">
395
+ <p style="color:#6b7280; font-size:14px;">
396
+ πŸ’‘ Tip: Ask specific questions for better answers. Try asking about functions, usage examples, or concepts.
397
+ </p>
398
+ </div>
399
+ """, unsafe_allow_html=True)
400
+
401
+ else:
402
+ # Welcome message when no document is loaded
403
+ st.markdown("""
404
+ <div class="info-box">
405
+ <h3>πŸ‘‹ Welcome to AI Documentation Assistant!</h3>
406
+ <p>Get started by entering a URL to Python documentation above.</p>
407
+ <p><strong>Try the default URL</strong> or enter your own documentation link.</p>
408
+ </div>
409
+
410
+ <div style="background:white; border-radius:15px; padding:30px; margin-top:20px;">
411
+ <h3 style="color:#4f46e5;">✨ Features:</h3>
412
+ <ul style="font-size:16px; line-height:1.8;">
413
+ <li><strong>πŸ“š URL-based</strong> - Just paste a documentation URL</li>
414
+ <li><strong>πŸ€– AI-powered</strong> - Get intelligent answers from docs</li>
415
+ <li><strong>⚑ Fast processing</strong> - Quick document analysis</li>
416
+ <li><strong>πŸ’¬ Interactive</strong> - Ask follow-up questions</li>
417
+ <li><strong>🎯 Python-focused</strong> - Optimized for Python documentation</li>
418
+ </ul>
419
+
420
+ <h3 style="color:#4f46e5; margin-top:30px;">πŸš€ Quick Start:</h3>
421
+ <ol style="font-size:16px; line-height:1.8;">
422
+ <li>Enter a Python documentation URL (or use the default)</li>
423
+ <li>Click <strong>"Load Document"</strong></li>
424
+ <li>Wait a few seconds for processing</li>
425
+ <li>Ask any Python-related question about the documentation</li>
426
+ </ol>
427
+ </div>
428
+ """, unsafe_allow_html=True)
429
+
430
  st.markdown('</div>', unsafe_allow_html=True)