kardwalker commited on
Commit
882be04
Β·
verified Β·
1 Parent(s): 91fef04

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +409 -56
app.py CHANGED
@@ -1,64 +1,417 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
- from Search_Agent import search_agent
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
-
9
-
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
-
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
25
 
26
- messages.append({"role": "user", "content": message})
27
-
28
- response = ""
29
-
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
 
 
 
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- demo = gr.ChatInterface(
47
- respond,
48
- additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
- ),
59
- ],
60
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
 
63
  if __name__ == "__main__":
64
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import asyncio
3
+ import json
4
+ import time
5
+ from datetime import datetime
6
+ import pandas as pd
7
+ import plotly.graph_objects as go
8
+ import plotly.express as px
9
+ from typing import Dict, List, Optional, Tuple
10
+ import nest_asyncio
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ # Apply nest_asyncio for compatibility with Gradio
13
+ nest_asyncio.apply()
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ # Import your existing search agent classes and functions
16
+ # (Assuming all the previous code is imported or defined above)
17
 
18
+ class GradioSearchInterface:
19
+ def __init__(self):
20
+ self.search_workflow = create_search_workflow()
21
+ self.search_history = []
22
+ self.performance_metrics = {
23
+ 'queries': 0,
24
+ 'avg_processing_time': 0,
25
+ 'avg_confidence': 0,
26
+ 'total_results': 0
27
+ }
28
+
29
+ async def process_search_async(self, query: str, intent_override: str = None) -> Tuple[str, str, str, str, str]:
30
+ """Process search query asynchronously"""
31
+ if not query.strip():
32
+ return "Please enter a search query.", "", "", "", ""
33
+
34
+ # Initialize state
35
+ initial_state = AgentState(
36
+ query=query.strip(),
37
+ intent=QueryIntent[intent_override] if intent_override and intent_override != "Auto-detect" else None,
38
+ expanded_queries=[],
39
+ search_results=[],
40
+ semantic_index=None,
41
+ ranked_results=[],
42
+ verified_facts=[],
43
+ answer="",
44
+ confidence_score=0.0,
45
+ error_log=[],
46
+ cache_hits=0,
47
+ processing_time=0.0,
48
+ user_context={},
49
+ iteration=0
50
+ )
51
+
52
+ start_time = time.time()
53
+
54
+ try:
55
+ # Run the workflow
56
+ final_state = await self.search_workflow.ainvoke(initial_state)
57
+ processing_time = time.time() - start_time
58
+
59
+ # Update performance metrics
60
+ self.performance_metrics['queries'] += 1
61
+ self.performance_metrics['avg_processing_time'] = (
62
+ (self.performance_metrics['avg_processing_time'] * (self.performance_metrics['queries'] - 1) + processing_time)
63
+ / self.performance_metrics['queries']
64
+ )
65
+ self.performance_metrics['avg_confidence'] = (
66
+ (self.performance_metrics['avg_confidence'] * (self.performance_metrics['queries'] - 1) + final_state['confidence_score'])
67
+ / self.performance_metrics['queries']
68
+ )
69
+ self.performance_metrics['total_results'] += len(final_state['search_results'])
70
+
71
+ # Store in history
72
+ search_record = {
73
+ 'timestamp': datetime.now().isoformat(),
74
+ 'query': query,
75
+ 'intent': final_state['intent'].value if final_state['intent'] else 'unknown',
76
+ 'processing_time': processing_time,
77
+ 'confidence': final_state['confidence_score'],
78
+ 'results_count': len(final_state['search_results']),
79
+ 'answer': final_state['answer']
80
+ }
81
+ self.search_history.append(search_record)
82
+
83
+ # Format results
84
+ answer = final_state['answer']
85
+
86
+ # Create summary
87
+ summary = f"""
88
+ ## Search Summary
89
+ - **Query Intent**: {final_state['intent'].value if final_state['intent'] else 'Unknown'}
90
+ - **Expanded Queries**: {len(final_state['expanded_queries'])} queries generated
91
+ - **Total Results Found**: {len(final_state['search_results'])} results
92
+ - **Top Results Analyzed**: {len(final_state['ranked_results'])} results
93
+ - **Verified Facts**: {len(final_state['verified_facts'])} facts
94
+ - **Processing Time**: {processing_time:.2f} seconds
95
+ - **Confidence Score**: {final_state['confidence_score']:.2%}
96
  """
97
+
98
+ # Format search results
99
+ results_df = []
100
+ for i, result in enumerate(final_state['ranked_results'][:10]): # Top 10 results
101
+ results_df.append({
102
+ 'Rank': i + 1,
103
+ 'Title': result['title'][:100] + '...' if len(result['title']) > 100 else result['title'],
104
+ 'Source': result['source'].title(),
105
+ 'Authority Score': f"{result.get('authority_score', 0):.2f}",
106
+ 'Relevance Score': f"{result.get('relevance_score', 0):.2f}",
107
+ 'Composite Score': f"{result.get('composite_score', 0):.2f}",
108
+ 'URL': result['url']
109
+ })
110
+
111
+ results_table = pd.DataFrame(results_df) if results_df else pd.DataFrame()
112
+
113
+ # Format verified facts
114
+ facts_text = ""
115
+ if final_state['verified_facts']:
116
+ facts_text = "## Verified Facts\n\n"
117
+ for i, fact in enumerate(final_state['verified_facts'][:5], 1):
118
+ confidence = fact.get('confidence', 0)
119
+ facts_text += f"{i}. **{fact['fact']}** (Confidence: {confidence:.1%})\n\n"
120
+
121
+ # Error log
122
+ errors = "\n".join(final_state['error_log']) if final_state['error_log'] else "No errors occurred."
123
+
124
+ return answer, summary, results_table, facts_text, errors
125
+
126
+ except Exception as e:
127
+ error_msg = f"Error processing search: {str(e)}"
128
+ return error_msg, "", pd.DataFrame(), "", error_msg
129
+
130
+ def process_search(self, query: str, intent_override: str = "Auto-detect") -> Tuple[str, str, str, str, str]:
131
+ """Synchronous wrapper for async search processing"""
132
+ loop = asyncio.new_event_loop()
133
+ asyncio.set_event_loop(loop)
134
+ try:
135
+ return loop.run_until_complete(self.process_search_async(query, intent_override))
136
+ finally:
137
+ loop.close()
138
+
139
+ def get_search_history(self) -> pd.DataFrame:
140
+ """Get search history as DataFrame"""
141
+ if not self.search_history:
142
+ return pd.DataFrame()
143
+
144
+ df = pd.DataFrame(self.search_history)
145
+ df['timestamp'] = pd.to_datetime(df['timestamp'])
146
+ return df[['timestamp', 'query', 'intent', 'processing_time', 'confidence', 'results_count']]
147
+
148
+ def get_performance_chart(self):
149
+ """Create performance visualization"""
150
+ if not self.search_history:
151
+ return None
152
+
153
+ df = pd.DataFrame(self.search_history)
154
+ df['timestamp'] = pd.to_datetime(df['timestamp'])
155
+
156
+ # Processing time over time
157
+ fig = go.Figure()
158
+ fig.add_trace(go.Scatter(
159
+ x=df['timestamp'],
160
+ y=df['processing_time'],
161
+ mode='lines+markers',
162
+ name='Processing Time (s)',
163
+ line=dict(color='blue')
164
+ ))
165
+
166
+ fig.update_layout(
167
+ title='Search Performance Over Time',
168
+ xaxis_title='Time',
169
+ yaxis_title='Processing Time (seconds)',
170
+ hovermode='x unified'
171
+ )
172
+
173
+ return fig
174
+
175
+ def get_confidence_distribution(self):
176
+ """Create confidence score distribution"""
177
+ if not self.search_history:
178
+ return None
179
+
180
+ df = pd.DataFrame(self.search_history)
181
+
182
+ fig = px.histogram(
183
+ df,
184
+ x='confidence',
185
+ nbins=20,
186
+ title='Confidence Score Distribution',
187
+ labels={'confidence': 'Confidence Score', 'count': 'Frequency'}
188
+ )
189
+
190
+ return fig
191
+
192
+ def clear_history(self):
193
+ """Clear search history"""
194
+ self.search_history = []
195
+ self.performance_metrics = {
196
+ 'queries': 0,
197
+ 'avg_processing_time': 0,
198
+ 'avg_confidence': 0,
199
+ 'total_results': 0
200
+ }
201
+ return "Search history cleared!", pd.DataFrame(), None, None
202
+
203
+ # Initialize the interface
204
+ search_interface = GradioSearchInterface()
205
 
206
+ # Create the Gradio interface
207
+ def create_gradio_app():
208
+ with gr.Blocks(
209
+ title="Advanced Multi-Source Search Agent",
210
+ theme=gr.themes.Soft(),
211
+ css="""
212
+ .gradio-container {
213
+ max-width: 1200px !important;
214
+ }
215
+ .main-header {
216
+ text-align: center;
217
+ color: #2563eb;
218
+ margin-bottom: 20px;
219
+ }
220
+ """
221
+ ) as app:
222
+
223
+ gr.Markdown(
224
+ """
225
+ # πŸ” Advanced Multi-Source Search Agent
226
+
227
+ This intelligent search agent combines multiple search engines, semantic analysis, and fact verification
228
+ to provide comprehensive and reliable answers to your queries.
229
+
230
+ **Features:**
231
+ - Multi-source search (Google, DuckDuckGo)
232
+ - Intent classification and query expansion
233
+ - Semantic ranking and fact verification
234
+ - Real-time performance analytics
235
+ """,
236
+ elem_classes=["main-header"]
237
+ )
238
+
239
+ with gr.Tab("πŸ” Search"):
240
+ with gr.Row():
241
+ with gr.Column(scale=3):
242
+ query_input = gr.Textbox(
243
+ label="Search Query",
244
+ placeholder="Enter your search query here...",
245
+ lines=2
246
+ )
247
+
248
+ intent_dropdown = gr.Dropdown(
249
+ choices=["Auto-detect"] + [intent.value.title() for intent in QueryIntent],
250
+ value="Auto-detect",
251
+ label="Query Intent (Optional)",
252
+ info="Override automatic intent detection"
253
+ )
254
+
255
+ search_btn = gr.Button("πŸ” Search", variant="primary", size="lg")
256
+
257
+ with gr.Column(scale=1):
258
+ gr.Markdown("### Quick Stats")
259
+ stats_display = gr.Markdown("No searches yet.")
260
+
261
+ with gr.Tab("πŸ“‹ Results"):
262
+ with gr.Row():
263
+ with gr.Column():
264
+ answer_output = gr.Markdown(label="Answer")
265
+
266
+ with gr.Row():
267
+ with gr.Column():
268
+ summary_output = gr.Markdown(label="Search Summary")
269
+
270
+ with gr.Column():
271
+ facts_output = gr.Markdown(label="Verified Facts")
272
+
273
+ with gr.Row():
274
+ results_table = gr.DataFrame(
275
+ label="Top Search Results",
276
+ interactive=False,
277
+ wrap=True
278
+ )
279
+
280
+ with gr.Tab("πŸ“Š Analytics"):
281
+ with gr.Row():
282
+ with gr.Column():
283
+ performance_chart = gr.Plot(label="Performance Over Time")
284
+
285
+ with gr.Column():
286
+ confidence_chart = gr.Plot(label="Confidence Distribution")
287
+
288
+ with gr.Row():
289
+ history_table = gr.DataFrame(
290
+ label="Search History",
291
+ interactive=False
292
+ )
293
+
294
+ with gr.Tab("βš™οΈ System"):
295
+ with gr.Row():
296
+ with gr.Column():
297
+ gr.Markdown("### System Information")
298
+ system_info = gr.Markdown(
299
+ """
300
+ **Search Sources:** Google, DuckDuckGo
301
+ **Embedding Model:** all-MiniLM-L6-v2
302
+ **LLM:** GPT-4o-mini (Azure)
303
+ **Semantic Search:** FAISS
304
+ **Caching:** Redis (if available)
305
+ """
306
+ )
307
+
308
+ with gr.Column():
309
+ gr.Markdown("### Controls")
310
+ clear_btn = gr.Button("πŸ—‘οΈ Clear History", variant="secondary")
311
+
312
+ error_log = gr.Textbox(
313
+ label="Error Log",
314
+ lines=5,
315
+ interactive=False
316
+ )
317
+
318
+ # Event handlers
319
+ def update_stats():
320
+ metrics = search_interface.performance_metrics
321
+ return f"""
322
+ **Total Queries:** {metrics['queries']}
323
+ **Avg Processing Time:** {metrics['avg_processing_time']:.2f}s
324
+ **Avg Confidence:** {metrics['avg_confidence']:.1%}
325
+ **Total Results:** {metrics['total_results']}
326
+ """
327
+
328
+ def search_and_update(query, intent):
329
+ # Perform search
330
+ answer, summary, results_df, facts, errors = search_interface.process_search(query, intent)
331
+
332
+ # Update stats
333
+ stats = update_stats()
334
+
335
+ # Update history and charts
336
+ history_df = search_interface.get_search_history()
337
+ perf_chart = search_interface.get_performance_chart()
338
+ conf_chart = search_interface.get_confidence_distribution()
339
+
340
+ return (
341
+ answer, # answer_output
342
+ summary, # summary_output
343
+ results_df, # results_table
344
+ facts, # facts_output
345
+ errors, # error_log
346
+ stats, # stats_display
347
+ history_df, # history_table
348
+ perf_chart, # performance_chart
349
+ conf_chart # confidence_chart
350
+ )
351
+
352
+ def clear_and_update():
353
+ message, empty_df, empty_chart1, empty_chart2 = search_interface.clear_history()
354
+ stats = update_stats()
355
+ return message, empty_df, empty_chart1, empty_chart2, stats
356
+
357
+ # Connect events
358
+ search_btn.click(
359
+ fn=search_and_update,
360
+ inputs=[query_input, intent_dropdown],
361
+ outputs=[
362
+ answer_output,
363
+ summary_output,
364
+ results_table,
365
+ facts_output,
366
+ error_log,
367
+ stats_display,
368
+ history_table,
369
+ performance_chart,
370
+ confidence_chart
371
+ ]
372
+ )
373
+
374
+ query_input.submit(
375
+ fn=search_and_update,
376
+ inputs=[query_input, intent_dropdown],
377
+ outputs=[
378
+ answer_output,
379
+ summary_output,
380
+ results_table,
381
+ facts_output,
382
+ error_log,
383
+ stats_display,
384
+ history_table,
385
+ performance_chart,
386
+ confidence_chart
387
+ ]
388
+ )
389
+
390
+ clear_btn.click(
391
+ fn=clear_and_update,
392
+ outputs=[error_log, history_table, performance_chart, confidence_chart, stats_display]
393
+ )
394
+
395
+ # Load initial history on startup
396
+ app.load(
397
+ fn=lambda: (search_interface.get_search_history(), update_stats()),
398
+ outputs=[history_table, stats_display]
399
+ )
400
+
401
+ return app
402
 
403
+ # Launch the application
404
  if __name__ == "__main__":
405
+ # Create and launch the Gradio app
406
+ app = create_gradio_app()
407
+
408
+ # Launch with custom settings
409
+ app.launch(
410
+ server_name="0.0.0.0", # Allow external access
411
+ server_port=7860, # Default Gradio port
412
+ share=False, # Set to True to create public link
413
+ debug=True, # Enable debug mode
414
+ show_error=True, # Show detailed errors
415
+ favicon_path=None, # Add custom favicon if desired
416
+ auth=None, # Add authentication if needed: ("username", "password")
417
+ )