pythonprincess commited on
Commit
c1821b1
·
verified ·
1 Parent(s): 397d743

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +277 -0
  2. requirements.txt +97 -0
app.py ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 🤖 PENNY Gradio Interface
3
+ Hugging Face Space Entry Point
4
+
5
+ This file connects PENNY's FastAPI 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
+ from typing import List, Tuple
13
+ from datetime import datetime
14
+
15
+ # Setup logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
19
+ handlers=[logging.StreamHandler(sys.stdout)]
20
+ )
21
+ logger = logging.getLogger(__name__)
22
+
23
+ # Import Penny's orchestrator
24
+ try:
25
+ from app.orchestrator import run_orchestrator, get_service_availability
26
+ from app.location_utils import SupportedCities
27
+ logger.info("✅ Successfully imported PENNY modules")
28
+ except ImportError as e:
29
+ logger.error(f"❌ Failed to import PENNY modules: {e}")
30
+ raise
31
+
32
+ # ============================================================
33
+ # GRADIO CHAT INTERFACE
34
+ # ============================================================
35
+
36
+ async def chat_with_penny(
37
+ message: str,
38
+ city: str,
39
+ history: List[Tuple[str, str]]
40
+ ) -> Tuple[List[Tuple[str, str]], str]:
41
+ """
42
+ Process user message through PENNY's orchestrator and return response.
43
+
44
+ Args:
45
+ message: User's input text
46
+ city: Selected city/tenant_id
47
+ history: Chat history (list of (user_msg, bot_msg) tuples)
48
+
49
+ Returns:
50
+ Tuple of (updated_history, empty_string_to_clear_input)
51
+ """
52
+ if not message.strip():
53
+ return history, ""
54
+
55
+ try:
56
+ # Build context from selected city
57
+ context = {}
58
+ if city and city != "Not sure / Other":
59
+ context["tenant_id"] = city
60
+
61
+ logger.info(f"Processing message: '{message[:50]}...' for city: {city}")
62
+
63
+ # Call PENNY's orchestrator
64
+ result = await run_orchestrator(message, context)
65
+
66
+ # Extract response
67
+ reply = result.get("reply", "I'm having trouble right now. Please try again! 💛")
68
+
69
+ # Add to history
70
+ history.append((message, reply))
71
+
72
+ logger.info(f"Response generated successfully (intent: {result.get('intent')})")
73
+
74
+ return history, ""
75
+
76
+ except Exception as e:
77
+ logger.error(f"Error processing message: {e}", exc_info=True)
78
+ error_reply = (
79
+ "I'm having trouble processing your request right now. "
80
+ "Please try again in a moment! 💛"
81
+ )
82
+ history.append((message, error_reply))
83
+ return history, ""
84
+
85
+
86
+ def get_city_choices() -> List[str]:
87
+ """Get list of supported cities for dropdown."""
88
+ try:
89
+ cities = SupportedCities.get_all_cities()
90
+ city_names = [city.full_name for city in cities]
91
+ return ["Not sure / Other"] + sorted(city_names)
92
+ except Exception as e:
93
+ logger.error(f"Error loading cities: {e}")
94
+ return ["Not sure / Other", "Atlanta, GA", "Seattle, WA"]
95
+
96
+
97
+ def get_service_status() -> str:
98
+ """Display current service availability status."""
99
+ try:
100
+ services = get_service_availability()
101
+ status_lines = ["**PENNY Service Status:**\n"]
102
+
103
+ for service, available in services.items():
104
+ icon = "✅" if available else "⚠️"
105
+ status = "Available" if available else "Limited"
106
+ status_lines.append(f"{icon} {service.replace('_', ' ').title()}: {status}")
107
+
108
+ return "\n".join(status_lines)
109
+ except Exception as e:
110
+ logger.error(f"Error getting service status: {e}")
111
+ return "**Status:** Unable to check service availability"
112
+
113
+
114
+ # ============================================================
115
+ # GRADIO UI DEFINITION
116
+ # ============================================================
117
+
118
+ # Custom CSS for a polished look
119
+ custom_css = """
120
+ #chatbot {
121
+ height: 500px;
122
+ overflow-y: auto;
123
+ }
124
+ .gradio-container {
125
+ font-family: 'Inter', sans-serif;
126
+ }
127
+ footer {
128
+ display: none !important;
129
+ }
130
+ """
131
+
132
+ # Build the Gradio interface
133
+ with gr.Blocks(
134
+ theme=gr.themes.Soft(primary_hue="amber", secondary_hue="blue"),
135
+ css=custom_css,
136
+ title="PENNY - Civic Assistant"
137
+ ) as demo:
138
+
139
+ # Header
140
+ gr.Markdown(
141
+ """
142
+ # 🤖 PENNY - People's Engagement Network Navigator for You
143
+
144
+ **Your multilingual civic assistant connecting residents to local services.**
145
+
146
+ Ask me about:
147
+ - 🌤️ Weather conditions
148
+ - 📅 Community events
149
+ - 🏛️ Local resources (shelters, libraries, food banks)
150
+ - 🌍 Translation (27 languages)
151
+ - 📄 Document help
152
+ """
153
+ )
154
+
155
+ with gr.Row():
156
+ with gr.Column(scale=2):
157
+ # City selector
158
+ city_dropdown = gr.Dropdown(
159
+ choices=get_city_choices(),
160
+ value="Not sure / Other",
161
+ label="📍 Select Your City",
162
+ info="Choose your city for location-specific information"
163
+ )
164
+
165
+ # Chat interface
166
+ chatbot = gr.Chatbot(
167
+ label="Chat with PENNY",
168
+ elem_id="chatbot",
169
+ avatar_images=(None, "🤖"),
170
+ show_label=False
171
+ )
172
+
173
+ # Input row
174
+ with gr.Row():
175
+ msg_input = gr.Textbox(
176
+ placeholder="Type your message here... (e.g., 'What's the weather today?')",
177
+ show_label=False,
178
+ scale=4,
179
+ container=False
180
+ )
181
+ submit_btn = gr.Button("Send", variant="primary", scale=1)
182
+
183
+ # Example queries
184
+ gr.Examples(
185
+ examples=[
186
+ ["What's the weather today?"],
187
+ ["Any events this weekend?"],
188
+ ["I need help finding a library"],
189
+ ["Show me local resources"],
190
+ ["Translate 'hello' to Spanish"]
191
+ ],
192
+ inputs=msg_input,
193
+ label="💡 Try asking:"
194
+ )
195
+
196
+ with gr.Column(scale=1):
197
+ # Service status panel
198
+ status_display = gr.Markdown(
199
+ value=get_service_status(),
200
+ label="System Status"
201
+ )
202
+
203
+ gr.Markdown(
204
+ """
205
+ ### 🌟 Features
206
+
207
+ - **27 Languages** supported
208
+ - **Real-time weather** via Azure Maps
209
+ - **Community events** database
210
+ - **Local resource** finder
211
+ - **Document processing** help
212
+
213
+ ---
214
+
215
+ ### 📍 Supported Cities
216
+
217
+ - Atlanta, GA
218
+ - Birmingham, AL
219
+ - Chesterfield, VA
220
+ - El Paso, TX
221
+ - Providence, RI
222
+ - Seattle, WA
223
+
224
+ ---
225
+
226
+ 💛 *PENNY is here to help connect you with civic resources!*
227
+ """
228
+ )
229
+
230
+ # Event handlers
231
+ submit_btn.click(
232
+ fn=chat_with_penny,
233
+ inputs=[msg_input, city_dropdown, chatbot],
234
+ outputs=[chatbot, msg_input]
235
+ )
236
+
237
+ msg_input.submit(
238
+ fn=chat_with_penny,
239
+ inputs=[msg_input, city_dropdown, chatbot],
240
+ outputs=[chatbot, msg_input]
241
+ )
242
+
243
+ # Footer
244
+ gr.Markdown(
245
+ """
246
+ ---
247
+ **Built with:** FastAPI • Gradio • Azure ML • Transformers
248
+ """
249
+ )
250
+
251
+
252
+ # ============================================================
253
+ # LAUNCH
254
+ # ============================================================
255
+
256
+ if __name__ == "__main__":
257
+ logger.info("=" * 60)
258
+ logger.info("🚀 Launching PENNY Gradio Interface")
259
+ logger.info("=" * 60)
260
+
261
+ # Display service availability at startup
262
+ logger.info("\n📊 Service Availability Check:")
263
+ services = get_service_availability()
264
+ for service, available in services.items():
265
+ status = "✅" if available else "❌"
266
+ logger.info(f" {status} {service}: {'Available' if available else 'Not loaded'}")
267
+
268
+ logger.info("\n" + "=" * 60)
269
+ logger.info("🤖 PENNY is ready to help residents!")
270
+ logger.info("=" * 60 + "\n")
271
+
272
+ # Launch the Gradio app
273
+ demo.launch(
274
+ server_name="0.0.0.0",
275
+ server_port=7860,
276
+ share=False
277
+ )
requirements.txt ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ============================================
2
+ # PENNY Project - Azure ML Production Dependencies
3
+ # Civic Engagement AI - Python 3.10+
4
+ # ============================================
5
+
6
+ # ============================================
7
+ # FastAPI Core & Web Framework
8
+ # ============================================
9
+ fastapi==0.111.0
10
+ uvicorn[standard]==0.29.0
11
+ httpx==0.27.0
12
+ python-multipart==0.0.9
13
+ pydantic==2.6.4
14
+ pydantic-settings==2.2.1
15
+
16
+ # ============================================
17
+ # Gradio UI Framework (Hugging Face Spaces)
18
+ # ============================================
19
+ gradio==4.44.0
20
+
21
+ # ============================================
22
+ # Configuration & Environment
23
+ # ============================================
24
+ python-dotenv==1.0.1
25
+
26
+ # ============================================
27
+ # Azure SDK & Cloud Integration
28
+ # ============================================
29
+ azure-identity==1.15.0
30
+ azure-keyvault-secrets==4.7.0
31
+ azure-storage-blob==12.19.0
32
+ azure-ai-ml==1.14.0
33
+
34
+ # ============================================
35
+ # HTTP & API Clients
36
+ # ============================================
37
+ requests==2.31.0
38
+ aiohttp==3.9.3
39
+
40
+ # ============================================
41
+ # Machine Learning & NLP (Optimized for Production)
42
+ # ============================================
43
+ # Core ML framework (CPU-optimized for Azure Container Instances)
44
+ torch==2.2.1
45
+ transformers==4.38.2
46
+ sentencepiece==0.2.0
47
+ tokenizers==0.15.2
48
+
49
+ # Model acceleration (only if GPU available)
50
+ accelerate==0.27.2
51
+
52
+ # Scientific computing
53
+ numpy==1.26.4
54
+ scipy==1.12.0
55
+
56
+ # ============================================
57
+ # Data Processing & Validation
58
+ # ============================================
59
+ pandas==2.2.1
60
+ jsonschema==4.21.1
61
+
62
+ # ============================================
63
+ # Logging & Monitoring
64
+ # ============================================
65
+ python-json-logger==2.0.7
66
+ structlog==24.1.0
67
+
68
+ # Azure Application Insights integration
69
+ opencensus-ext-azure==1.1.13
70
+ opencensus-ext-logging==0.1.1
71
+
72
+ # ============================================
73
+ # Date/Time Handling
74
+ # ============================================
75
+ python-dateutil==2.9.0
76
+ pytz==2024.1
77
+
78
+ # ============================================
79
+ # Security & Cryptography
80
+ # ============================================
81
+ cryptography==42.0.5
82
+
83
+ # ============================================
84
+ # Testing & Development (optional - install separately for dev)
85
+ # ============================================
86
+ # pytest==8.1.1
87
+ # pytest-asyncio==0.23.5
88
+ # pytest-cov==4.1.0
89
+ # httpx==0.27.0 # Already included above
90
+ # black==24.3.0
91
+ # flake8==7.0.0
92
+ # mypy==1.9.0
93
+
94
+ # ============================================
95
+ # Production Server Optimization
96
+ # ============================================
97
+ gunicorn==21.2.0 # Alternative to uvicorn for production