Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
-
import subprocess
|
3 |
-
import threading
|
4 |
-
import time
|
5 |
import requests
|
6 |
-
import json
|
7 |
from datetime import datetime
|
8 |
-
import os
|
9 |
-
|
10 |
-
# Configuration
|
11 |
-
MCP_SERVER_PORT = 8001
|
12 |
-
MCP_SERVER_URL = "https://elanuk-mcp-hf.hf.space/"
|
13 |
|
14 |
# Bihar districts list
|
15 |
BIHAR_DISTRICTS = [
|
@@ -22,44 +13,8 @@ BIHAR_DISTRICTS = [
|
|
22 |
"Sitamarhi", "Sheohar", "Vaishali"
|
23 |
]
|
24 |
|
25 |
-
def start_mcp_server():
|
26 |
-
"""Start the MCP server in background"""
|
27 |
-
try:
|
28 |
-
print("π Starting MCP Server...")
|
29 |
-
# Set environment variable for the server port
|
30 |
-
env = os.environ.copy()
|
31 |
-
env["PORT"] = str(MCP_SERVER_PORT)
|
32 |
-
|
33 |
-
process = subprocess.Popen(
|
34 |
-
["python", "mcp_server.py"],
|
35 |
-
stdout=subprocess.PIPE,
|
36 |
-
stderr=subprocess.PIPE,
|
37 |
-
env=env,
|
38 |
-
text=True
|
39 |
-
)
|
40 |
-
|
41 |
-
# Wait for server to start
|
42 |
-
print("β³ Waiting for server to start...")
|
43 |
-
time.sleep(15)
|
44 |
-
|
45 |
-
# Check if server is running
|
46 |
-
try:
|
47 |
-
response = requests.get(f"{MCP_SERVER_URL}/api/health", timeout=5)
|
48 |
-
if response.status_code == 200:
|
49 |
-
print("β
MCP Server started successfully!")
|
50 |
-
return process
|
51 |
-
except:
|
52 |
-
pass
|
53 |
-
|
54 |
-
print("β οΈ Server may still be starting...")
|
55 |
-
return process
|
56 |
-
|
57 |
-
except Exception as e:
|
58 |
-
print(f"β Failed to start MCP server: {e}")
|
59 |
-
return None
|
60 |
-
|
61 |
def format_workflow_output(raw_output):
|
62 |
-
"""Format the workflow output for
|
63 |
if not raw_output:
|
64 |
return "β No output received"
|
65 |
|
@@ -82,8 +37,6 @@ def format_workflow_output(raw_output):
|
|
82 |
formatted_lines.append(f"#### {line}")
|
83 |
elif line.startswith('β
') or line.startswith('β'):
|
84 |
formatted_lines.append(f"- {line}")
|
85 |
-
elif line.startswith(' '):
|
86 |
-
formatted_lines.append(f" {line.strip()}")
|
87 |
else:
|
88 |
formatted_lines.append(line)
|
89 |
|
@@ -125,8 +78,8 @@ def format_alert_summary(raw_data):
|
|
125 |
"""
|
126 |
return summary
|
127 |
|
128 |
-
def
|
129 |
-
"""
|
130 |
if not district:
|
131 |
return "β Please select a district", "", ""
|
132 |
|
@@ -136,17 +89,9 @@ def test_mcp_workflow(district):
|
|
136 |
"district": district.lower()
|
137 |
}
|
138 |
|
139 |
-
#
|
140 |
-
try:
|
141 |
-
health_check = requests.get(f"{MCP_SERVER_URL}/", timeout=5)
|
142 |
-
if health_check.status_code != 200:
|
143 |
-
return f"β MCP Server not responding properly (status: {health_check.status_code})", "", ""
|
144 |
-
except:
|
145 |
-
return "β MCP Server is not running. Please check server status above.", "", ""
|
146 |
-
|
147 |
-
# Try the workflow endpoint
|
148 |
response = requests.post(
|
149 |
-
|
150 |
json=payload,
|
151 |
timeout=60
|
152 |
)
|
@@ -158,69 +103,27 @@ def test_mcp_workflow(district):
|
|
158 |
alert_summary = format_alert_summary(result.get('raw_data', {}))
|
159 |
csv_content = result.get('csv', '')
|
160 |
|
161 |
-
|
162 |
-
|
163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
else:
|
165 |
-
error_msg = f"β Server Error ({response.status_code})
|
166 |
-
return error_msg, "",
|
167 |
|
168 |
-
except requests.exceptions.Timeout:
|
169 |
-
return "β° Request timed out. The workflow is taking longer than expected...", "", ""
|
170 |
-
except requests.exceptions.ConnectionError:
|
171 |
-
return f"π Connection Error: Cannot reach MCP server at {MCP_SERVER_URL}", "", ""
|
172 |
except Exception as e:
|
173 |
-
|
174 |
-
|
175 |
-
def check_server_health():
|
176 |
-
"""Check if the MCP server is running"""
|
177 |
-
try:
|
178 |
-
# Try the health endpoint first
|
179 |
-
response = requests.get(f"{MCP_SERVER_URL}/api/health", timeout=10)
|
180 |
-
if response.status_code == 200:
|
181 |
-
data = response.json()
|
182 |
-
return f"β
Server Online | OpenAI: {'β
' if data.get('openai_available') else 'β'} | Time: {data.get('timestamp', 'N/A')}"
|
183 |
-
elif response.status_code == 404:
|
184 |
-
# Try the root endpoint as fallback
|
185 |
-
try:
|
186 |
-
root_response = requests.get(f"{MCP_SERVER_URL}/", timeout=5)
|
187 |
-
if root_response.status_code == 200:
|
188 |
-
root_data = root_response.json()
|
189 |
-
if "MCP Weather Server" in str(root_data):
|
190 |
-
return f"β οΈ Server Running (health endpoint missing) | Status: {root_data.get('status', 'unknown')}"
|
191 |
-
return f"β οΈ Server responded with status {response.status_code} (health endpoint not found)"
|
192 |
-
except:
|
193 |
-
return f"β οΈ Server responded with status {response.status_code} (health endpoint not found)"
|
194 |
-
else:
|
195 |
-
return f"β οΈ Server responded with status {response.status_code}"
|
196 |
-
except requests.exceptions.ConnectionError:
|
197 |
-
return f"β Cannot connect to server at {MCP_SERVER_URL}"
|
198 |
-
except requests.exceptions.Timeout:
|
199 |
-
return f"β° Server connection timeout"
|
200 |
-
except Exception as e:
|
201 |
-
return f"β Server check failed: {str(e)}"
|
202 |
-
|
203 |
-
# Start server in background thread
|
204 |
-
print("π§ Initializing BIHAR AgMCP...")
|
205 |
-
server_process = None
|
206 |
-
|
207 |
-
def start_server_thread():
|
208 |
-
global server_process
|
209 |
-
server_process = start_mcp_server()
|
210 |
-
|
211 |
-
server_thread = threading.Thread(target=start_server_thread, daemon=True)
|
212 |
-
server_thread.start()
|
213 |
|
214 |
# Create Gradio interface
|
215 |
with gr.Blocks(
|
216 |
title="BIHAR AgMCP - Agricultural Weather Alerts",
|
217 |
-
theme=gr.themes.Soft()
|
218 |
-
css="""
|
219 |
-
.gradio-container {
|
220 |
-
max-width: 1200px;
|
221 |
-
margin: auto;
|
222 |
-
}
|
223 |
-
"""
|
224 |
) as demo:
|
225 |
|
226 |
gr.Markdown("""
|
@@ -228,43 +131,20 @@ with gr.Blocks(
|
|
228 |
|
229 |
**AI-Powered Weather Alerts for Bihar Farmers**
|
230 |
|
231 |
-
|
232 |
-
|
233 |
-
## π How to Use:
|
234 |
-
1. **Wait for Server**: Ensure server status shows "Online" below
|
235 |
-
2. **Select District**: Choose a Bihar district from the dropdown
|
236 |
-
3. **Run Workflow**: Click the button to generate weather alerts
|
237 |
-
4. **View Results**: See formatted workflow output and alert summary
|
238 |
-
5. **Download Data**: Get CSV export of the alert data
|
239 |
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
- Create messages for multiple communication channels
|
245 |
""")
|
246 |
|
247 |
-
# Server status
|
248 |
-
with gr.Row():
|
249 |
-
with gr.Column(scale=3):
|
250 |
-
server_status = gr.Textbox(
|
251 |
-
label="π§ Server Status",
|
252 |
-
value="π Starting server...",
|
253 |
-
interactive=False,
|
254 |
-
container=True
|
255 |
-
)
|
256 |
-
with gr.Column(scale=1):
|
257 |
-
refresh_btn = gr.Button("π Check Status", size="sm")
|
258 |
-
debug_btn = gr.Button("π Debug Info", size="sm", variant="secondary")
|
259 |
-
|
260 |
-
# Main interface
|
261 |
with gr.Row():
|
262 |
with gr.Column(scale=1):
|
263 |
district_input = gr.Dropdown(
|
264 |
choices=BIHAR_DISTRICTS,
|
265 |
label="π Select Bihar District",
|
266 |
-
value="Patna"
|
267 |
-
info="Choose a district to generate weather alerts"
|
268 |
)
|
269 |
|
270 |
run_btn = gr.Button(
|
@@ -272,112 +152,34 @@ with gr.Blocks(
|
|
272 |
variant="primary",
|
273 |
size="lg"
|
274 |
)
|
275 |
-
|
276 |
-
gr.Markdown("""
|
277 |
-
### π‘ What happens next?
|
278 |
-
- Weather data collection from multiple sources
|
279 |
-
- Intelligent crop stage estimation
|
280 |
-
- AI-powered alert generation
|
281 |
-
- Multi-channel message creation (SMS, WhatsApp, etc.)
|
282 |
-
- Comprehensive CSV data export
|
283 |
-
""")
|
284 |
|
285 |
-
# Results section
|
286 |
with gr.Row():
|
287 |
with gr.Column(scale=2):
|
288 |
workflow_output = gr.Markdown(
|
289 |
label="π Workflow Output",
|
290 |
-
value="
|
291 |
)
|
292 |
|
293 |
with gr.Column(scale=1):
|
294 |
alert_summary = gr.Markdown(
|
295 |
-
label="π Alert Summary",
|
296 |
-
value="Alert details will appear here
|
297 |
)
|
298 |
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
visible=False
|
304 |
-
)
|
305 |
-
|
306 |
-
# Event handling
|
307 |
-
def run_workflow_with_csv(district):
|
308 |
-
workflow, summary, csv_content = test_mcp_workflow(district)
|
309 |
-
|
310 |
-
if csv_content and not csv_content.startswith("Error"):
|
311 |
-
filename = f"bihar_alert_{district.lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
|
312 |
-
with open(filename, 'w', encoding='utf-8') as f:
|
313 |
-
f.write(csv_content)
|
314 |
-
return workflow, summary, gr.File(value=filename, visible=True)
|
315 |
-
else:
|
316 |
-
return workflow, summary, gr.File(visible=False)
|
317 |
-
|
318 |
-
# Connect events
|
319 |
-
refresh_btn.click(check_server_health, outputs=server_status)
|
320 |
-
|
321 |
-
def debug_server():
|
322 |
-
"""Debug server endpoints"""
|
323 |
-
try:
|
324 |
-
debug_info = []
|
325 |
-
|
326 |
-
# Test root endpoint
|
327 |
-
try:
|
328 |
-
root_resp = requests.get(f"{MCP_SERVER_URL}/", timeout=5)
|
329 |
-
debug_info.append(f"β
Root endpoint: {root_resp.status_code} - {root_resp.text[:100]}")
|
330 |
-
except Exception as e:
|
331 |
-
debug_info.append(f"β Root endpoint failed: {str(e)}")
|
332 |
-
|
333 |
-
# Test health endpoint
|
334 |
-
try:
|
335 |
-
health_resp = requests.get(f"{MCP_SERVER_URL}/api/health", timeout=5)
|
336 |
-
debug_info.append(f"β
Health endpoint: {health_resp.status_code} - {health_resp.text[:100]}")
|
337 |
-
except Exception as e:
|
338 |
-
debug_info.append(f"β Health endpoint failed: {str(e)}")
|
339 |
-
|
340 |
-
# List what we're trying to connect to
|
341 |
-
debug_info.append(f"π Trying to connect to: {MCP_SERVER_URL}")
|
342 |
-
debug_info.append(f"π³ Container environment: {os.getenv('SPACE_ID', 'Not in HF Spaces')}")
|
343 |
-
|
344 |
-
return "π **Debug Information:**\n\n" + "\n".join(debug_info)
|
345 |
-
|
346 |
-
except Exception as e:
|
347 |
-
return f"β Debug failed: {str(e)}"
|
348 |
|
349 |
-
|
350 |
run_btn.click(
|
351 |
-
|
352 |
-
inputs=[district_input],
|
353 |
outputs=[workflow_output, alert_summary, csv_output]
|
354 |
)
|
355 |
-
|
356 |
-
# Auto-refresh server status after a delay
|
357 |
-
def auto_check_status():
|
358 |
-
time.sleep(20) # Wait 20 seconds
|
359 |
-
return check_server_health()
|
360 |
-
|
361 |
-
demo.load(auto_check_status, outputs=server_status)
|
362 |
-
|
363 |
-
# Footer
|
364 |
-
gr.Markdown("""
|
365 |
-
---
|
366 |
-
|
367 |
-
### π System Information:
|
368 |
-
- **State Coverage**: Bihar (38+ districts)
|
369 |
-
- **Crops Supported**: Rice, Wheat, Maize, Sugarcane, Mustard, and more
|
370 |
-
- **Weather Sources**: Open-Meteo API with AI enhancement
|
371 |
-
- **Communication Channels**: SMS, WhatsApp, USSD, IVR, Telegram
|
372 |
-
|
373 |
-
*Built with MCP (Model Context Protocol) for agricultural intelligence*
|
374 |
-
""")
|
375 |
|
376 |
-
# Launch the interface
|
377 |
if __name__ == "__main__":
|
378 |
-
print("πΎ Launching BIHAR AgMCP Interface...")
|
379 |
demo.launch(
|
380 |
server_name="0.0.0.0",
|
381 |
-
server_port=7860
|
382 |
-
show_error=True
|
383 |
)
|
|
|
1 |
import gradio as gr
|
|
|
|
|
|
|
2 |
import requests
|
|
|
3 |
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
# Bihar districts list
|
6 |
BIHAR_DISTRICTS = [
|
|
|
13 |
"Sitamarhi", "Sheohar", "Vaishali"
|
14 |
]
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
def format_workflow_output(raw_output):
|
17 |
+
"""Format the workflow output for display"""
|
18 |
if not raw_output:
|
19 |
return "β No output received"
|
20 |
|
|
|
37 |
formatted_lines.append(f"#### {line}")
|
38 |
elif line.startswith('β
') or line.startswith('β'):
|
39 |
formatted_lines.append(f"- {line}")
|
|
|
|
|
40 |
else:
|
41 |
formatted_lines.append(line)
|
42 |
|
|
|
78 |
"""
|
79 |
return summary
|
80 |
|
81 |
+
def run_workflow(district):
|
82 |
+
"""Run the workflow and return results"""
|
83 |
if not district:
|
84 |
return "β Please select a district", "", ""
|
85 |
|
|
|
89 |
"district": district.lower()
|
90 |
}
|
91 |
|
92 |
+
# Call your existing endpoint directly
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
response = requests.post(
|
94 |
+
"http://localhost:8000/api/run-workflow",
|
95 |
json=payload,
|
96 |
timeout=60
|
97 |
)
|
|
|
103 |
alert_summary = format_alert_summary(result.get('raw_data', {}))
|
104 |
csv_content = result.get('csv', '')
|
105 |
|
106 |
+
# Create CSV file if content exists
|
107 |
+
if csv_content:
|
108 |
+
filename = f"bihar_alert_{district.lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
|
109 |
+
with open(filename, 'w', encoding='utf-8') as f:
|
110 |
+
f.write(csv_content)
|
111 |
+
return workflow_output, alert_summary, gr.File(value=filename, visible=True)
|
112 |
+
else:
|
113 |
+
return workflow_output, alert_summary, gr.File(visible=False)
|
114 |
+
|
115 |
else:
|
116 |
+
error_msg = f"β Server Error ({response.status_code})"
|
117 |
+
return error_msg, "", gr.File(visible=False)
|
118 |
|
|
|
|
|
|
|
|
|
119 |
except Exception as e:
|
120 |
+
error_msg = f"β Error: {str(e)}"
|
121 |
+
return error_msg, "", gr.File(visible=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
|
123 |
# Create Gradio interface
|
124 |
with gr.Blocks(
|
125 |
title="BIHAR AgMCP - Agricultural Weather Alerts",
|
126 |
+
theme=gr.themes.Soft()
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
) as demo:
|
128 |
|
129 |
gr.Markdown("""
|
|
|
131 |
|
132 |
**AI-Powered Weather Alerts for Bihar Farmers**
|
133 |
|
134 |
+
Generate personalized weather alerts for agricultural activities in Bihar districts.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
|
136 |
+
## How to Use:
|
137 |
+
1. Select a Bihar district from the dropdown
|
138 |
+
2. Click "Generate Weather Alert"
|
139 |
+
3. View the formatted results and download CSV data
|
|
|
140 |
""")
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
with gr.Row():
|
143 |
with gr.Column(scale=1):
|
144 |
district_input = gr.Dropdown(
|
145 |
choices=BIHAR_DISTRICTS,
|
146 |
label="π Select Bihar District",
|
147 |
+
value="Patna"
|
|
|
148 |
)
|
149 |
|
150 |
run_btn = gr.Button(
|
|
|
152 |
variant="primary",
|
153 |
size="lg"
|
154 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
|
|
156 |
with gr.Row():
|
157 |
with gr.Column(scale=2):
|
158 |
workflow_output = gr.Markdown(
|
159 |
label="π Workflow Output",
|
160 |
+
value="Select a district and click the button to generate alerts..."
|
161 |
)
|
162 |
|
163 |
with gr.Column(scale=1):
|
164 |
alert_summary = gr.Markdown(
|
165 |
+
label="π Alert Summary",
|
166 |
+
value="Alert details will appear here..."
|
167 |
)
|
168 |
|
169 |
+
csv_output = gr.File(
|
170 |
+
label="π Download CSV Data",
|
171 |
+
visible=False
|
172 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
|
174 |
+
# Connect the button
|
175 |
run_btn.click(
|
176 |
+
run_workflow,
|
177 |
+
inputs=[district_input],
|
178 |
outputs=[workflow_output, alert_summary, csv_output]
|
179 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
|
|
|
181 |
if __name__ == "__main__":
|
|
|
182 |
demo.launch(
|
183 |
server_name="0.0.0.0",
|
184 |
+
server_port=7860
|
|
|
185 |
)
|