pythonprincess commited on
Commit
6498306
·
verified ·
1 Parent(s): 215af39

Delete gradio_app.py

Browse files
Files changed (1) hide show
  1. gradio_app.py +0 -497
gradio_app.py DELETED
@@ -1,497 +0,0 @@
1
- """
2
- 🤖 PENNY V2.2 Gradio Interface
3
- Hugging Face Space Entry Point
4
-
5
- This file connects PENNY's backend to a Gradio chat interface,
6
- allowing users to interact with PENNY through a web UI on Hugging Face Spaces.
7
- """
8
-
9
- import gradio as gr
10
- import logging
11
- import sys
12
- import asyncio
13
- import os
14
- from dotenv import load_dotenv # Add this
15
- from typing import List, Tuple, Dict, Any
16
- from datetime import datetime
17
-
18
- # Load environment variables from .env file
19
- load_dotenv() # Add this line
20
-
21
- # Verify the key loaded (optional debug)
22
- if os.getenv("AZURE_MAPS_KEY"):
23
- print("✅ AZURE_MAPS_KEY loaded successfully")
24
- else:
25
- print("⚠️ AZURE_MAPS_KEY not found!")
26
-
27
- from typing import List, Tuple, Dict, Any
28
- from datetime import datetime
29
-
30
- # Setup logging
31
- logging.basicConfig(
32
- level=logging.INFO,
33
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
34
- handlers=[logging.StreamHandler(sys.stdout)]
35
- )
36
- logger = logging.getLogger(__name__)
37
-
38
- # ============================================================
39
- # IMPORT PENNY MODULES - FIXED FOR ACTUAL FILE STRUCTURE
40
- # ============================================================
41
-
42
- try:
43
- # Core orchestration and routing
44
- from app.orchestrator import run_orchestrator
45
- # REMOVED: from app.router import route_query # Function doesn't exist
46
-
47
- # Utilities
48
- from app.location_utils import geocode_address, get_user_location
49
- from app.logging_utils import setup_logger
50
-
51
- # Event and weather handling
52
- from app.event_weather import get_event_recommendations_with_weather # FIXED: was get_weather_info
53
-
54
- # Tool agent for officials and resources
55
- from app.tool_agent import handle_tool_request # FIXED: removed non-existent functions
56
-
57
- # REMOVED: initialize_models doesn't exist in model_loader
58
- # from app.model_loader import initialize_models
59
-
60
- # Intent classification
61
- from app.intents import classify_intent, IntentType
62
-
63
- logger.info("✅ Successfully imported PENNY modules from app/")
64
-
65
- except ImportError as import_error:
66
- logger.error(f"❌ Failed to import PENNY modules: {import_error}")
67
- logger.error(f" Make sure all files exist in app/ folder")
68
- logger.error(f" Current error: {str(import_error)}")
69
-
70
- # Create fallback functions so the interface can still load
71
- async def run_orchestrator(message: str, context: Dict[str, Any]) -> Dict[str, Any]:
72
- return {
73
- "reply": "⚠️ PENNY is initializing. Please try again in a moment.",
74
- "intent": "error",
75
- "confidence": 0.0
76
- }
77
-
78
- def get_service_availability() -> Dict[str, bool]:
79
- return {
80
- "orchestrator": False,
81
- "weather_service": False,
82
- "event_database": False,
83
- "resource_finder": False
84
- }
85
-
86
- # ============================================================
87
- # SERVICE AVAILABILITY CHECK
88
- # ============================================================
89
-
90
- def get_service_availability() -> Dict[str, bool]:
91
- """
92
- Check which PENNY services are available.
93
- Returns dict of service_name -> availability status.
94
- """
95
- services = {}
96
-
97
- try:
98
- # Check if orchestrator is callable
99
- services["orchestrator"] = callable(run_orchestrator)
100
- except:
101
- services["orchestrator"] = False
102
-
103
- try:
104
- # Check if event/weather module loaded
105
- from app.event_weather import get_event_recommendations_with_weather # FIXED
106
- services["weather_service"] = True
107
- except:
108
- services["weather_service"] = False
109
-
110
- try:
111
- # Check if event database accessible
112
- from app.event_weather import get_event_recommendations_with_weather # FIXED
113
- services["event_database"] = True
114
- except:
115
- services["event_database"] = False
116
-
117
- try:
118
- # Check if tool agent loaded
119
- from app.tool_agent import handle_tool_request # FIXED: was search_resources
120
- services["resource_finder"] = True
121
- except:
122
- services["resource_finder"] = False
123
-
124
- return services
125
-
126
-
127
- # ============================================================
128
- # SUPPORTED CITIES CONFIGURATION
129
- # ============================================================
130
-
131
- SUPPORTED_CITIES = [
132
- "Atlanta, GA",
133
- "Birmingham, AL",
134
- "Chesterfield, VA",
135
- "El Paso, TX",
136
- "Norfolk, VA",
137
- "Providence, RI",
138
- "Seattle, WA"
139
- ]
140
-
141
- def get_city_choices() -> List[str]:
142
- """Get list of supported cities for dropdown."""
143
- try:
144
- return ["Not sure / Other"] + sorted(SUPPORTED_CITIES)
145
- except Exception as e:
146
- logger.error(f"Error loading cities: {e}")
147
- return ["Not sure / Other", "Norfolk, VA"]
148
-
149
-
150
- # ============================================================
151
- # CHAT HANDLER
152
- # ============================================================
153
-
154
- async def chat_with_penny(
155
- message: str,
156
- city: str,
157
- history: List[Tuple[str, str]]
158
- ) -> Tuple[List[Tuple[str, str]], str]:
159
- """
160
- Process user message through PENNY's orchestrator and return response.
161
-
162
- Args:
163
- message: User's input text
164
- city: Selected city/location
165
- history: Chat history (list of (user_msg, bot_msg) tuples)
166
-
167
- Returns:
168
- Tuple of (updated_history, empty_string_to_clear_input)
169
- """
170
- if not message.strip():
171
- return history, ""
172
-
173
- try:
174
- # Build context from selected city
175
- context = {
176
- "timestamp": datetime.now().isoformat(),
177
- "conversation_history": history[-5:] if history else [] # Last 5 exchanges
178
- }
179
-
180
- # Add location if specified
181
- if city and city != "Not sure / Other":
182
- context["location"] = city
183
- context["tenant_id"] = city.split(",")[0].lower().replace(" ", "_")
184
-
185
- logger.info(f"📨 Processing: '{message[:60]}...' | City: {city}")
186
-
187
- # Call PENNY's orchestrator
188
- result = await run_orchestrator(message, context)
189
-
190
- # Extract response
191
- reply = result.get("reply", "I'm having trouble right now. Please try again! 💛")
192
- intent = result.get("intent", "unknown")
193
- confidence = result.get("confidence", 0.0)
194
-
195
- # Add to history
196
- history.append((message, reply))
197
-
198
- logger.info(f"✅ Response generated | Intent: {intent} | Confidence: {confidence:.2f}")
199
-
200
- return history, ""
201
-
202
- except Exception as e:
203
- logger.error(f"❌ Error processing message: {e}", exc_info=True)
204
-
205
- error_reply = (
206
- "I'm having trouble processing your request right now. "
207
- "Please try again in a moment! 💛\n\n"
208
- f"_Error: {str(e)[:100]}_"
209
- )
210
- history.append((message, error_reply))
211
- return history, ""
212
-
213
-
214
- def chat_with_penny_sync(message: str, city: str, history: List[Tuple[str, str]]) -> Tuple[List[Tuple[str, str]], str]:
215
- """
216
- Synchronous wrapper for chat_with_penny to work with Gradio.
217
- Gradio expects sync functions, so we create an event loop here.
218
- """
219
- try:
220
- # Create new event loop for this call
221
- loop = asyncio.new_event_loop()
222
- asyncio.set_event_loop(loop)
223
- result = loop.run_until_complete(chat_with_penny(message, city, history))
224
- loop.close()
225
- return result
226
- except Exception as e:
227
- logger.error(f"Error in sync wrapper: {e}")
228
- error_msg = f"Error: {str(e)}"
229
- history.append((message, error_msg))
230
- return history, ""
231
-
232
-
233
- # ============================================================
234
- # SERVICE STATUS DISPLAY
235
- # ============================================================
236
-
237
- def get_service_status() -> str:
238
- """Display current service availability status."""
239
- try:
240
- services = get_service_availability()
241
- status_lines = ["**🔧 PENNY Service Status:**\n"]
242
-
243
- service_names = {
244
- "orchestrator": "🧠 Core Orchestrator",
245
- "weather_service": "🌤️ Weather Service",
246
- "event_database": "📅 Event Database",
247
- "resource_finder": "🏛️ Resource Finder"
248
- }
249
-
250
- for service_key, available in services.items():
251
- icon = "✅" if available else "⚠️"
252
- status = "Online" if available else "Limited"
253
- name = service_names.get(service_key, service_key.replace('_', ' ').title())
254
- status_lines.append(f"{icon} **{name}**: {status}")
255
-
256
- return "\n".join(status_lines)
257
- except Exception as e:
258
- logger.error(f"Error getting service status: {e}")
259
- return "**⚠️ Status:** Unable to check service availability"
260
-
261
-
262
- # ============================================================
263
- # GRADIO UI DEFINITION
264
- # ============================================================
265
-
266
- # Custom CSS for enhanced styling
267
- custom_css = """
268
- #chatbot {
269
- height: 500px;
270
- overflow-y: auto;
271
- border-radius: 8px;
272
- }
273
- .gradio-container {
274
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
275
- }
276
- #status-panel {
277
- background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
278
- padding: 15px;
279
- border-radius: 8px;
280
- margin: 10px 0;
281
- }
282
- footer {
283
- display: none !important;
284
- }
285
- .message-user {
286
- background-color: #e3f2fd !important;
287
- }
288
- .message-bot {
289
- background-color: #fff3e0 !important;
290
- }
291
- """
292
-
293
- # Build the Gradio interface
294
- with gr.Blocks(
295
- theme=gr.themes.Soft(primary_hue="amber", secondary_hue="blue"),
296
- css=custom_css,
297
- title="PENNY V2.2 - Civic Assistant"
298
- ) as demo:
299
-
300
- # Header
301
- gr.Markdown(
302
- """
303
- # 🤖 PENNY V2.2 - People's Engagement Network Navigator for You
304
-
305
- **Your multilingual civic assistant connecting residents to local government services and community resources.**
306
-
307
- ### 💬 Ask me about:
308
- - 🌤️ **Weather conditions** and forecasts
309
- - 📅 **Community events** and activities
310
- - 🏛️ **Local resources** (shelters, libraries, food banks, healthcare)
311
- - 👥 **Elected officials** and government contacts
312
- - 🌍 **Translation** services (27+ languages)
313
- - 📄 **Document assistance** and form help
314
- """
315
- )
316
-
317
- with gr.Row():
318
- with gr.Column(scale=2):
319
- # City selector
320
- city_dropdown = gr.Dropdown(
321
- choices=get_city_choices(),
322
- value="Norfolk, VA",
323
- label="📍 Select Your City",
324
- info="Choose your city for location-specific information",
325
- interactive=True
326
- )
327
-
328
- # Chat interface
329
- chatbot = gr.Chatbot(
330
- label="💬 Chat with PENNY",
331
- elem_id="chatbot",
332
- avatar_images=(None, "🤖"),
333
- show_label=True,
334
- height=500,
335
- bubble_full_width=False
336
- )
337
-
338
- # Input row
339
- with gr.Row():
340
- msg_input = gr.Textbox(
341
- placeholder="Type your message here... (e.g., 'What's the weather today?')",
342
- show_label=False,
343
- scale=4,
344
- container=False,
345
- lines=1
346
- )
347
- submit_btn = gr.Button("Send 📤", variant="primary", scale=1)
348
-
349
- # Clear button
350
- clear_btn = gr.Button("🗑️ Clear Chat", variant="secondary", size="sm")
351
-
352
- # Example queries
353
- gr.Examples(
354
- examples=[
355
- ["What's the weather in Norfolk today?"],
356
- ["Any community events this weekend?"],
357
- ["I need help finding a food bank"],
358
- ["Who is my city council representative?"],
359
- ["Show me local libraries"],
360
- ["Translate 'hello' to Spanish"],
361
- ["Help me understand this document"]
362
- ],
363
- inputs=msg_input,
364
- label="💡 Try asking:"
365
- )
366
-
367
- with gr.Column(scale=1):
368
- # Service status panel
369
- status_display = gr.Markdown(
370
- value=get_service_status(),
371
- label="System Status",
372
- elem_id="status-panel"
373
- )
374
-
375
- # Refresh status button
376
- refresh_btn = gr.Button("🔄 Refresh Status", size="sm", variant="secondary")
377
-
378
- gr.Markdown(
379
- """
380
- ### 🌟 Key Features
381
-
382
- - ✅ **27+ Languages** supported
383
- - ✅ **Real-time weather** via Azure Maps
384
- - ✅ **Community events** database
385
- - ✅ **Local resource** finder
386
- - ✅ **Government contact** lookup
387
- - ✅ **Document processing** help
388
- - ✅ **Multilingual** support
389
-
390
- ---
391
-
392
- ### 📍 Supported Cities
393
-
394
- - Atlanta, GA
395
- - Birmingham, AL
396
- - Chesterfield, VA
397
- - El Paso, TX
398
- - Norfolk, VA
399
- - Providence, RI
400
- - Seattle, WA
401
-
402
- ---
403
-
404
- ### 🆘 Need Help?
405
-
406
- PENNY can assist with:
407
- - Finding emergency services
408
- - Locating government offices
409
- - Understanding civic processes
410
- - Accessing community programs
411
-
412
- ---
413
-
414
- 💛 *PENNY is here to help connect you with civic resources!*
415
- """
416
- )
417
-
418
- # Event handlers
419
- submit_btn.click(
420
- fn=chat_with_penny_sync,
421
- inputs=[msg_input, city_dropdown, chatbot],
422
- outputs=[chatbot, msg_input]
423
- )
424
-
425
- msg_input.submit(
426
- fn=chat_with_penny_sync,
427
- inputs=[msg_input, city_dropdown, chatbot],
428
- outputs=[chatbot, msg_input]
429
- )
430
-
431
- clear_btn.click(
432
- fn=lambda: ([], ""),
433
- inputs=None,
434
- outputs=[chatbot, msg_input]
435
- )
436
-
437
- refresh_btn.click(
438
- fn=get_service_status,
439
- inputs=None,
440
- outputs=status_display
441
- )
442
-
443
- # Footer
444
- gr.Markdown(
445
- """
446
- ---
447
- **Built with:** Python • FastAPI • Gradio • Azure ML • Hugging Face Transformers
448
-
449
- **Version:** 2.2 | **Last Updated:** November 2025
450
-
451
- _PENNY is an open-source civic engagement platform designed to improve access to government services._
452
- """
453
- )
454
-
455
-
456
- # ============================================================
457
- # INITIALIZATION AND LAUNCH
458
- # ============================================================
459
-
460
- def initialize_penny():
461
- """Initialize PENNY services at startup."""
462
- logger.info("=" * 70)
463
- logger.info("🚀 Initializing PENNY V2.2 Gradio Interface")
464
- logger.info("=" * 70)
465
-
466
- # Display service availability at startup
467
- logger.info("\n📊 Service Availability Check:")
468
- services = get_service_availability()
469
-
470
- all_available = True
471
- for service, available in services.items():
472
- status = "✅ Available" if available else "❌ Not loaded"
473
- logger.info(f" {service.ljust(20)}: {status}")
474
- if not available:
475
- all_available = False
476
-
477
- if all_available:
478
- logger.info("\n✅ All services loaded successfully!")
479
- else:
480
- logger.warning("\n⚠️ Some services are not available. PENNY will run with limited functionality.")
481
-
482
- logger.info("\n" + "=" * 70)
483
- logger.info("🤖 PENNY is ready to help residents!")
484
- logger.info("=" * 70 + "\n")
485
-
486
-
487
- if __name__ == "__main__":
488
- # Initialize services
489
- initialize_penny()
490
-
491
- # Launch the Gradio app
492
- demo.launch(
493
- server_name="0.0.0.0",
494
- server_port=7860,
495
- share=False,
496
- show_error=True
497
- )