elanuk commited on
Commit
524df2c
Β·
verified Β·
1 Parent(s): 4738572

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +285 -0
app.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+ from datetime import datetime
5
+ import os
6
+
7
+ # Configuration
8
+ MCP_SERVER_URL = os.getenv("MCP_SERVER_URL", "https://elanuk-mcp-hf.hf.space/")
9
+
10
+ # Bihar districts list
11
+ BIHAR_DISTRICTS = [
12
+ "Patna", "Gaya", "Bhagalpur", "Muzaffarpur", "Darbhanga", "Siwan",
13
+ "Begusarai", "Katihar", "Nalanda", "Rohtas", "Saran", "Samastipur",
14
+ "Madhubani", "Purnia", "Araria", "Kishanganj", "Supaul", "Madhepura",
15
+ "Saharsa", "Khagaria", "Munger", "Lakhisarai", "Sheikhpura", "Nawada",
16
+ "Jamui", "Jehanabad", "Aurangabad", "Arwal", "Kaimur", "Buxar",
17
+ "Bhojpur", "Saran", "Siwan", "Gopalganj", "East Champaran", "West Champaran",
18
+ "Sitamarhi", "Sheohar", "Vaishali"
19
+ ]
20
+
21
+ def format_workflow_output(raw_output):
22
+ """Format the workflow output for better display"""
23
+ if not raw_output:
24
+ return "❌ No output received"
25
+
26
+ # Split into lines and format
27
+ lines = raw_output.split('\n')
28
+ formatted_lines = []
29
+
30
+ for line in lines:
31
+ line = line.strip()
32
+ if not line:
33
+ formatted_lines.append("")
34
+ continue
35
+
36
+ # Format headers
37
+ if line.startswith('🌾') and 'Workflow' in line:
38
+ formatted_lines.append(f"## {line}")
39
+ elif line.startswith('=') or line.startswith('-'):
40
+ continue # Skip separator lines
41
+ elif line.startswith('🌀️') or line.startswith('βœ… Workflow'):
42
+ formatted_lines.append(f"### {line}")
43
+ elif line.startswith('πŸ“±') or line.startswith('πŸ“ž') or line.startswith('πŸŽ™οΈ') or line.startswith('πŸ€–'):
44
+ formatted_lines.append(f"#### {line}")
45
+ elif line.startswith('βœ…') or line.startswith('❌'):
46
+ formatted_lines.append(f"- {line}")
47
+ elif line.startswith(' '):
48
+ formatted_lines.append(f" {line.strip()}")
49
+ else:
50
+ formatted_lines.append(line)
51
+
52
+ return '\n'.join(formatted_lines)
53
+
54
+ def format_alert_summary(raw_data):
55
+ """Create a formatted summary of the alert data"""
56
+ if not raw_data or 'alert_data' not in raw_data:
57
+ return "No alert data available"
58
+
59
+ alert_data = raw_data['alert_data']
60
+
61
+ summary = f"""
62
+ ## 🚨 Alert Summary
63
+
64
+ **πŸ“ Location:** {alert_data['location']['village']}, {alert_data['location']['district']}, {alert_data['location']['state']}
65
+
66
+ **🌾 Crop Information:**
67
+ - **Crop:** {alert_data['crop']['name'].title()}
68
+ - **Growth Stage:** {alert_data['crop']['stage']}
69
+ - **Season:** {alert_data['crop']['season'].title()}
70
+
71
+ **🌀️ Weather Conditions:**
72
+ - **Temperature:** {alert_data['weather']['temperature']}
73
+ - **Expected Rainfall:** {alert_data['weather']['expected_rainfall']}
74
+ - **Wind Speed:** {alert_data['weather']['wind_speed']}
75
+ - **Rain Probability:** {alert_data['weather']['rain_probability']}%
76
+
77
+ **⚠️ Alert Details:**
78
+ - **Type:** {alert_data['alert']['type'].replace('_', ' ').title()}
79
+ - **Urgency:** {alert_data['alert']['urgency'].upper()}
80
+ - **AI Enhanced:** {'βœ… Yes' if alert_data['alert']['ai_generated'] else '❌ No'}
81
+
82
+ **πŸ“¨ Alert Message:**
83
+ {alert_data['alert']['message']}
84
+
85
+ **🎯 Action Items:**
86
+ {chr(10).join([f"- {item.replace('_', ' ').title()}" for item in alert_data['alert']['action_items']])}
87
+ """
88
+ return summary
89
+
90
+ def test_mcp_workflow(district):
91
+ """Test the MCP workflow for a given district"""
92
+ if not district:
93
+ return "❌ Please select a district", "", ""
94
+
95
+ try:
96
+ # Make request to MCP server
97
+ payload = {
98
+ "state": "bihar",
99
+ "district": district.lower()
100
+ }
101
+
102
+ response = requests.post(
103
+ f"{MCP_SERVER_URL}/api/run-workflow",
104
+ json=payload,
105
+ timeout=30
106
+ )
107
+
108
+ if response.status_code == 200:
109
+ result = response.json()
110
+
111
+ # Format outputs
112
+ workflow_output = format_workflow_output(result.get('message', ''))
113
+ alert_summary = format_alert_summary(result.get('raw_data', {}))
114
+
115
+ # Create CSV download content
116
+ csv_content = result.get('csv', '')
117
+
118
+ return workflow_output, alert_summary, csv_content
119
+
120
+ else:
121
+ error_msg = f"❌ Server Error ({response.status_code}): {response.text}"
122
+ return error_msg, "", ""
123
+
124
+ except requests.exceptions.Timeout:
125
+ return "⏰ Request timed out. The server might be processing...", "", ""
126
+ except requests.exceptions.ConnectionError:
127
+ return f"πŸ”Œ Connection Error: Cannot reach MCP server at {MCP_SERVER_URL}", "", ""
128
+ except Exception as e:
129
+ return f"❌ Error: {str(e)}", "", ""
130
+
131
+ def check_server_health():
132
+ """Check if the MCP server is running"""
133
+ try:
134
+ response = requests.get(f"{MCP_SERVER_URL}/api/health", timeout=10)
135
+ if response.status_code == 200:
136
+ data = response.json()
137
+ return f"βœ… Server Online | OpenAI: {'βœ…' if data.get('openai_available') else '❌'} | Time: {data.get('timestamp', 'N/A')}"
138
+ else:
139
+ return f"⚠️ Server responded with status {response.status_code}"
140
+ except:
141
+ return f"❌ Server Offline or Unreachable ({MCP_SERVER_URL})"
142
+
143
+ # Create Gradio interface
144
+ with gr.Blocks(
145
+ title="BIHAR AgMCP - Agricultural Weather Alerts",
146
+ theme=gr.themes.Soft(),
147
+ css="""
148
+ .gradio-container {
149
+ max-width: 1200px;
150
+ margin: auto;
151
+ }
152
+ .status-box {
153
+ padding: 10px;
154
+ border-radius: 5px;
155
+ margin: 10px 0;
156
+ }
157
+ """
158
+ ) as demo:
159
+
160
+ gr.Markdown("""
161
+ # 🌾 BIHAR AgMCP - Agricultural Weather Alert System
162
+
163
+ **AI-Powered Weather Alerts for Bihar Farmers**
164
+
165
+ This interface tests the MCP (Model Context Protocol) server that generates personalized weather alerts for agricultural activities in Bihar districts.
166
+
167
+ ## πŸ“‹ How to Use:
168
+ 1. **Select District**: Choose a Bihar district from the dropdown
169
+ 2. **Run Workflow**: Click the button to generate weather alerts
170
+ 3. **View Results**: See formatted workflow output and alert summary
171
+ 4. **Download Data**: Get CSV export of the alert data
172
+
173
+ The system will:
174
+ - Select a random village in the district
175
+ - Choose appropriate crops based on season and region
176
+ - Generate weather-based agricultural alerts
177
+ - Create messages for multiple communication channels (SMS, WhatsApp, etc.)
178
+ """)
179
+
180
+ # Server status
181
+ with gr.Row():
182
+ server_status = gr.Textbox(
183
+ label="πŸ”§ Server Status",
184
+ value=check_server_health(),
185
+ interactive=False,
186
+ container=True
187
+ )
188
+
189
+ refresh_btn = gr.Button("πŸ”„ Refresh Status", size="sm")
190
+ refresh_btn.click(check_server_health, outputs=server_status)
191
+
192
+ # Main interface
193
+ with gr.Row():
194
+ with gr.Column(scale=1):
195
+ district_input = gr.Dropdown(
196
+ choices=BIHAR_DISTRICTS,
197
+ label="πŸ“ Select Bihar District",
198
+ placeholder="Choose a district...",
199
+ value="Patna"
200
+ )
201
+
202
+ run_btn = gr.Button(
203
+ "πŸš€ Generate Weather Alert",
204
+ variant="primary",
205
+ size="lg"
206
+ )
207
+
208
+ gr.Markdown("""
209
+ ### πŸ’‘ What happens next?
210
+ - Weather data collection
211
+ - Crop stage estimation
212
+ - AI-powered alert generation
213
+ - Multi-channel message creation
214
+ - CSV data export
215
+ """)
216
+
217
+ # Results section
218
+ with gr.Row():
219
+ with gr.Column(scale=2):
220
+ workflow_output = gr.Markdown(
221
+ label="πŸ“‹ Workflow Output",
222
+ value="Click 'Generate Weather Alert' to see results..."
223
+ )
224
+
225
+ with gr.Column(scale=1):
226
+ alert_summary = gr.Markdown(
227
+ label="πŸ“Š Alert Summary",
228
+ value="Alert details will appear here..."
229
+ )
230
+
231
+ # CSV export
232
+ with gr.Row():
233
+ csv_output = gr.File(
234
+ label="πŸ“ Download CSV Data",
235
+ visible=False
236
+ )
237
+
238
+ # Event handling
239
+ def run_workflow_with_csv(district):
240
+ workflow, summary, csv_content = test_mcp_workflow(district)
241
+
242
+ # Create temporary CSV file if content exists
243
+ if csv_content:
244
+ filename = f"bihar_alert_{district.lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
245
+ with open(filename, 'w') as f:
246
+ f.write(csv_content)
247
+ return workflow, summary, gr.File(value=filename, visible=True)
248
+ else:
249
+ return workflow, summary, gr.File(visible=False)
250
+
251
+ run_btn.click(
252
+ run_workflow_with_csv,
253
+ inputs=[district_input],
254
+ outputs=[workflow_output, alert_summary, csv_output]
255
+ )
256
+
257
+ # Footer
258
+ gr.Markdown("""
259
+ ---
260
+
261
+ ### πŸ”— System Information:
262
+ - **State Coverage**: Bihar (38 districts)
263
+ - **Crops Supported**: Rice, Wheat, Maize, Sugarcane, Mustard, and more
264
+ - **Weather Sources**: Open-Meteo API with AI enhancement
265
+ - **Communication Channels**: SMS, WhatsApp, USSD, IVR, Telegram
266
+
267
+ ### πŸ“ž Agent Outputs:
268
+ The system generates formatted messages for:
269
+ - **πŸ“± SMS**: Short text alerts for basic phones
270
+ - **πŸ“± WhatsApp**: Rich media messages with emojis
271
+ - **πŸ“ž USSD**: Interactive menu systems
272
+ - **πŸŽ™οΈ IVR**: Voice script for phone calls
273
+ - **πŸ€– Telegram**: Bot-friendly formatted messages
274
+
275
+ *Built with MCP (Model Context Protocol) for agricultural intelligence*
276
+ """)
277
+
278
+ # Launch configuration for HuggingFace Spaces
279
+ if __name__ == "__main__":
280
+ demo.launch(
281
+ share=True,
282
+ server_name="0.0.0.0",
283
+ server_port=7860,
284
+ show_error=True
285
+ )