aakashdg commited on
Commit
a73e409
·
verified ·
1 Parent(s): 9343516
Files changed (1) hide show
  1. app.py +0 -755
app.py CHANGED
@@ -1,760 +1,5 @@
1
- # # """
2
- # # Farmer.Chat Backend - FastAPI Application
3
- # # Deploy to Hugging Face Space: https://huggingface.co/spaces/aakashdg/farmer-chat-backend
4
- # # """
5
-
6
- # # from fastapi import FastAPI, HTTPException
7
- # # from fastapi.middleware.cors import CORSMiddleware
8
- # # from fastapi.responses import FileResponse, JSONResponse
9
- # # from pydantic import BaseModel, Field
10
- # # from typing import Optional, Dict, Any
11
- # # import os
12
- # # import asyncio
13
- # # import time
14
- # # from datetime import datetime
15
-
16
- # # # Import pipeline components
17
- # # from src.pipeline import FarmerChatPipeline
18
- # # from src.pdf_generator import generate_pdf_report
19
-
20
- # # from openai import OpenAI
21
- # # import httpx
22
-
23
- # # # Initialize FastAPI
24
- # # app = FastAPI(
25
- # # title="Farmer.Chat Backend",
26
- # # description="Multi-stage MCP pipeline for agricultural intelligence",
27
- # # version="2.0.0"
28
- # # )
29
-
30
- # # # CORS - Allow all origins for demo (restrict in production)
31
- # # app.add_middleware(
32
- # # CORSMiddleware,
33
- # # allow_origins=["*"],
34
- # # allow_credentials=True,
35
- # # allow_methods=["*"],
36
- # # allow_headers=["*"],
37
- # # )
38
-
39
- # # # Initialize OpenAI client with FIXED httpx configuration
40
- # # OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
41
- # # if not OPENAI_API_KEY:
42
- # # raise ValueError("OPENAI_API_KEY environment variable not set!")
43
-
44
- # # # FIX: Create httpx client without proxy support
45
- # # http_client = httpx.Client(
46
- # # timeout=httpx.Timeout(60.0),
47
- # # limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
48
- # # )
49
-
50
- # # # Initialize OpenAI with custom http client (bypasses proxy issues)
51
- # # openai_client = OpenAI(
52
- # # api_key=OPENAI_API_KEY,
53
- # # http_client=http_client
54
- # # )
55
-
56
- # # print("✅ OpenAI client initialized with custom httpx client")
57
- # # print(f" Model: gpt-4o")
58
-
59
- # # # Default location (Bangalore Agricultural Region)
60
- # # DEFAULT_LOCATION = {
61
- # # "name": "Bangalore Agricultural Region",
62
- # # "lat": 12.8716,
63
- # # "lon": 77.4946
64
- # # }
65
-
66
- # # # Initialize pipeline
67
- # # pipeline = FarmerChatPipeline(openai_client, DEFAULT_LOCATION)
68
-
69
- # # # Request/Response Models
70
- # # class QueryRequest(BaseModel):
71
- # # query: str = Field(..., min_length=3, max_length=500, description="Farmer's question")
72
- # # location: Optional[Dict[str, Any]] = Field(None, description="Custom location (lat, lon, name)")
73
-
74
- # # class Config:
75
- # # json_schema_extra = {
76
- # # "example": {
77
- # # "query": "Should I plant rice today?",
78
- # # "location": {
79
- # # "name": "Bangalore",
80
- # # "lat": 12.8716,
81
- # # "lon": 77.4946
82
- # # }
83
- # # }
84
- # # }
85
-
86
-
87
- # # class QueryResponse(BaseModel):
88
- # # success: bool
89
- # # query: str
90
- # # advice: str
91
- # # routing: Dict[str, Any]
92
- # # data: Dict[str, Any]
93
- # # execution_time_seconds: float
94
- # # timestamp: str
95
-
96
-
97
- # # # Health check
98
- # # @app.get("/")
99
- # # async def root():
100
- # # return {
101
- # # "service": "Farmer.Chat Backend",
102
- # # "status": "operational",
103
- # # "version": "2.0.0",
104
- # # "endpoints": {
105
- # # "query": "/api/query",
106
- # # "health": "/api/health",
107
- # # "servers": "/api/servers"
108
- # # }
109
- # # }
110
-
111
-
112
- # # @app.get("/api/health")
113
- # # async def health_check():
114
- # # """Health check endpoint"""
115
- # # return {
116
- # # "status": "healthy",
117
- # # "timestamp": datetime.now().isoformat(),
118
- # # "openai_configured": bool(OPENAI_API_KEY),
119
- # # "location": DEFAULT_LOCATION
120
- # # }
121
-
122
-
123
- # # @app.get("/api/servers")
124
- # # async def list_servers():
125
- # # """List available MCP servers"""
126
- # # from src.executor import MCP_SERVER_REGISTRY
127
-
128
- # # return {
129
- # # "total_servers": len(MCP_SERVER_REGISTRY),
130
- # # "servers": MCP_SERVER_REGISTRY
131
- # # }
132
-
133
-
134
- # # @app.post("/api/query", response_model=QueryResponse)
135
- # # async def process_query(request: QueryRequest):
136
- # # """
137
- # # Main query endpoint - processes farmer questions through MCP pipeline
138
- # # """
139
- # # try:
140
- # # start_time = time.time()
141
-
142
- # # # Use custom location if provided, otherwise default
143
- # # location = request.location if request.location else DEFAULT_LOCATION
144
-
145
- # # # Update pipeline location if changed
146
- # # if request.location:
147
- # # pipeline.location = location
148
-
149
- # # # Process query through pipeline
150
- # # result = await pipeline.process_query(request.query, verbose=False)
151
-
152
- # # execution_time = time.time() - start_time
153
-
154
- # # return QueryResponse(
155
- # # success=True,
156
- # # query=request.query,
157
- # # advice=result["advice"],
158
- # # routing=result["routing"],
159
- # # data=result["compiled_data"],
160
- # # execution_time_seconds=round(execution_time, 2),
161
- # # timestamp=datetime.now().isoformat()
162
- # # )
163
-
164
- # # except Exception as e:
165
- # # raise HTTPException(status_code=500, detail=str(e))
166
-
167
-
168
- # # @app.post("/api/export-pdf")
169
- # # async def export_pdf(request: QueryRequest):
170
- # # """
171
- # # Export query result as PDF
172
- # # """
173
- # # try:
174
- # # # Process query
175
- # # result = await pipeline.process_query(request.query, verbose=False)
176
-
177
- # # # Generate PDF
178
- # # pdf_path = generate_pdf_report(
179
- # # query=request.query,
180
- # # advice=result["advice"],
181
- # # data=result["compiled_data"],
182
- # # location=pipeline.location
183
- # # )
184
-
185
- # # # Return PDF file
186
- # # return FileResponse(
187
- # # pdf_path,
188
- # # media_type="application/pdf",
189
- # # filename=f"farmer-chat-report-{int(time.time())}.pdf"
190
- # # )
191
-
192
- # # except Exception as e:
193
- # # raise HTTPException(status_code=500, detail=str(e))
194
-
195
-
196
- # # # Error handlers
197
- # # @app.exception_handler(404)
198
- # # async def not_found_handler(request, exc):
199
- # # return JSONResponse(
200
- # # status_code=404,
201
- # # content={"error": "Endpoint not found", "path": str(request.url)}
202
- # # )
203
-
204
-
205
- # # @app.exception_handler(500)
206
- # # async def server_error_handler(request, exc):
207
- # # return JSONResponse(
208
- # # status_code=500,
209
- # # content={"error": "Internal server error", "detail": str(exc)}
210
- # # )
211
-
212
-
213
- # # if __name__ == "__main__":
214
- # # import uvicorn
215
- # # uvicorn.run(app, host="0.0.0.0", port=7860)
216
-
217
- # """
218
- # Alert Summary Generator Backend - Standalone Version
219
- # FastAPI app with embedded pipeline and location data
220
- # """
221
-
222
- # from fastapi import FastAPI, HTTPException
223
- # from fastapi.middleware.cors import CORSMiddleware
224
- # from pydantic import BaseModel
225
- # from typing import Optional, Dict, Any, List
226
- # import os
227
- # from datetime import datetime
228
- # from openai import OpenAI
229
- # import httpx
230
-
231
- # # ============================================================================
232
- # # OPENAI CLIENT SETUP
233
- # # ============================================================================
234
-
235
- # def get_openai_client():
236
- # """Initialize OpenAI client with API key from environment"""
237
- # api_key = os.getenv("OPENAI_API_KEY")
238
- # if not api_key:
239
- # raise ValueError("OPENAI_API_KEY environment variable not set")
240
- # http_client = httpx.Client(
241
- # timeout=httpx.Timeout(60.0, connect=10.0),
242
- # limits=httpx.Limits(max_keepalive_connections=10, max_connections=20)
243
- # )
244
- # return OpenAI(api_key=api_key, http_client=http_client)
245
-
246
-
247
- # # ============================================================================
248
- # # PIPELINE COMPONENTS
249
- # # ============================================================================
250
-
251
- # class QueryRouter:
252
- # """Routes queries to appropriate MCP servers"""
253
-
254
- # def __init__(self, client):
255
- # self.client = client
256
-
257
- # def route_query(self, query: str, location: Dict[str, float]) -> Dict[str, Any]:
258
- # """Determine which servers to call based on query"""
259
- # prompt = f"""Given the farmer query: "{query}"
260
- # Location: {location['latitude']}, {location['longitude']}
261
-
262
- # Determine which data sources are needed. Return JSON:
263
- # {{
264
- # "weather": true/false,
265
- # "soil": true/false,
266
- # "water": true/false,
267
- # "elevation": true/false,
268
- # "pests": true/false
269
- # }}"""
270
-
271
- # response = self.client.chat.completions.create(
272
- # model="gpt-4",
273
- # messages=[{"role": "user", "content": prompt}],
274
- # temperature=0
275
- # )
276
-
277
- # # Parse routing decision
278
- # import json
279
- # try:
280
- # routing = json.loads(response.choices[0].message.content)
281
- # except:
282
- # # Default: query all servers for alerts
283
- # routing = {
284
- # "weather": True,
285
- # "soil": True,
286
- # "water": True,
287
- # "elevation": True,
288
- # "pests": True
289
- # }
290
-
291
- # return routing
292
-
293
-
294
- # class MCPExecutor:
295
- # """Executes parallel calls to MCP servers"""
296
-
297
- # def __init__(self, client):
298
- # self.client = client
299
-
300
- # def execute_parallel(self, routing: Dict[str, bool], location: Dict[str, float]) -> Dict[str, str]:
301
- # """Execute MCP server calls in parallel"""
302
- # results = {}
303
-
304
- # # Simulate MCP server calls (replace with actual server calls)
305
- # if routing.get("weather"):
306
- # results["weather"] = f"Weather data for {location['latitude']}, {location['longitude']}"
307
-
308
- # if routing.get("soil"):
309
- # results["soil"] = f"Soil data for {location['latitude']}, {location['longitude']}"
310
-
311
- # if routing.get("water"):
312
- # results["water"] = f"Water availability for {location['latitude']}, {location['longitude']}"
313
-
314
- # if routing.get("elevation"):
315
- # results["elevation"] = f"Elevation data for {location['latitude']}, {location['longitude']}"
316
-
317
- # if routing.get("pests"):
318
- # results["pests"] = f"Pest risk data for {location['latitude']}, {location['longitude']}"
319
-
320
- # return results
321
-
322
-
323
- # class ResponseCompiler:
324
- # """Compiles MCP results into coherent response"""
325
-
326
- # def __init__(self, client):
327
- # self.client = client
328
-
329
- # def compile_response(self, query: str, mcp_results: Dict[str, str], location: Dict[str, float]) -> str:
330
- # """Compile MCP results into final response"""
331
-
332
- # # Format MCP results for context
333
- # context = "\n\n".join([f"{k.upper()}: {v}" for k, v in mcp_results.items()])
334
-
335
- # prompt = f"""You are an agricultural assistant. Compile this data into a comprehensive alert summary.
336
-
337
- # FARMER QUERY: {query}
338
- # LOCATION: {location['latitude']}, {location['longitude']}
339
-
340
- # DATA FROM SOURCES:
341
- # {context}
342
-
343
- # Provide a comprehensive agricultural alert covering:
344
- # 1. Current weather conditions and forecast
345
- # 2. Soil health and recommendations
346
- # 3. Water availability status
347
- # 4. Elevation/topography considerations
348
- # 5. Pest risks and preventive measures
349
-
350
- # Be specific, actionable, and farmer-friendly."""
351
-
352
- # response = self.client.chat.completions.create(
353
- # model="gpt-4",
354
- # messages=[{"role": "user", "content": prompt}],
355
- # temperature=0.7
356
- # )
357
-
358
- # return response.choices[0].message.content
359
-
360
-
361
- # class HindiTranslator:
362
- # """Translates responses to Hindi"""
363
-
364
- # def __init__(self, client):
365
- # self.client = client
366
-
367
- # def translate(self, text: str, target_lang: str = "en") -> str:
368
- # """Translate text if needed"""
369
- # if target_lang == "en":
370
- # return text
371
-
372
- # # Add Hindi translation logic here
373
- # return text
374
-
375
-
376
- # class FarmerChatPipeline:
377
- # """Main pipeline orchestrating all stages"""
378
-
379
- # def __init__(self, client, location: Dict[str, float]):
380
- # self.client = client
381
- # self.location = location
382
- # self.router = QueryRouter(client)
383
- # self.executor = MCPExecutor(client)
384
- # self.compiler = ResponseCompiler(client)
385
- # self.translator = HindiTranslator(client)
386
-
387
- # def process_query(self, query: str, language: str = "en") -> str:
388
- # """Process query through full pipeline"""
389
-
390
- # # Stage 1: Route query
391
- # routing = self.router.route_query(query, self.location)
392
-
393
- # # Stage 2: Execute MCP calls
394
- # mcp_results = self.executor.execute_parallel(routing, self.location)
395
-
396
- # # Stage 3: Compile response
397
- # response = self.compiler.compile_response(query, mcp_results, self.location)
398
-
399
- # # Stage 4: Translate if needed
400
- # final_response = self.translator.translate(response, language)
401
-
402
- # return final_response
403
-
404
-
405
- # # ============================================================================
406
- # # BIHAR LOCATION DATA
407
- # # ============================================================================
408
-
409
- # BIHAR_DATA = {
410
- # "Araria": ["Araria", "Forbesganj", "Jokihat", "Raniganj"],
411
- # "Arwal": ["Arwal", "Kaler", "Karpi", "Kurtha"],
412
- # "Aurangabad": ["Aurangabad", "Daudnagar", "Obra", "Nabinagar"],
413
- # "Banka": ["Banka", "Amarpur", "Barahat", "Belhar"],
414
- # "Begusarai": ["Begusarai", "Bakhri", "Barauni", "Teghra"],
415
- # "Bhagalpur": ["Bhagalpur", "Sabour", "Nathnagar", "Kahalgaon"],
416
- # "Bhojpur": ["Arrah", "Jagdishpur", "Piro", "Shahpur"],
417
- # "Buxar": ["Buxar", "Dumraon", "Chausa", "Simri"],
418
- # "Darbhanga": ["Darbhanga", "Baheri", "Jale", "Benipur"],
419
- # "East Champaran": ["Motihari", "Raxaul", "Chakia", "Dhaka"],
420
- # "Gaya": ["Gaya", "Bodh Gaya", "Tekari", "Sherghati"],
421
- # "Gopalganj": ["Gopalganj", "Barauli", "Baikunthpur", "Kateya"],
422
- # "Jamui": ["Jamui", "Jhajha", "Sikandra", "Sono"],
423
- # "Jehanabad": ["Jehanabad", "Ghoshi", "Makhdumpur", "Modanganj"],
424
- # "Kaimur": ["Bhabua", "Mohania", "Ramgarh", "Chainpur"],
425
- # "Katihar": ["Katihar", "Barsoi", "Manihari", "Pranpur"],
426
- # "Khagaria": ["Khagaria", "Parbatta", "Alauli", "Beldaur"],
427
- # "Kishanganj": ["Kishanganj", "Bahadurganj", "Thakurganj", "Dighalbank"],
428
- # "Lakhisarai": ["Lakhisarai", "Halsi", "Suryagarha", "Pipariya"],
429
- # "Madhepura": ["Madhepura", "Udakishanganj", "Murliganj", "Alamnagar"],
430
- # "Madhubani": ["Madhubani", "Jhanjharpur", "Benipatti", "Jainagar"],
431
- # "Munger": ["Munger", "Jamalpur", "Asarganj", "Tarapur"],
432
- # "Muzaffarpur": ["Muzaffarpur", "Sitamarhi", "Minapur", "Bochaha"],
433
- # "Nalanda": ["Bihar Sharif", "Rajgir", "Hilsa", "Biharsharif"],
434
- # "Nawada": ["Nawada", "Rajauli", "Akbarpur", "Hisua"],
435
- # "Patna": ["Patna", "Danapur", "Fatuha", "Khagaul"],
436
- # "Purnia": ["Purnia", "Dhamdaha", "Kasba", "Banmankhi"],
437
- # "Rohtas": ["Sasaram", "Dehri", "Bikramganj", "Nasriganj"],
438
- # "Saharsa": ["Saharsa", "Sonbarsa", "Simri Bakhtiarpur", "Mahishi"],
439
- # "Samastipur": ["Samastipur", "Rosera", "Dalsinghsarai", "Pusa"],
440
- # "Saran": ["Chapra", "Marhaura", "Amnour", "Sonepur"],
441
- # "Sheikhpura": ["Sheikhpura", "Barbigha", "Ariari", "Shekhopur"],
442
- # "Sheohar": ["Sheohar", "Dumri Katsari", "Piprahi", "Tariyani"],
443
- # "Sitamarhi": ["Sitamarhi", "Pupri", "Belsand", "Bathnaha"],
444
- # "Siwan": ["Siwan", "Maharajganj", "Mairwa", "Darauli"],
445
- # "Supaul": ["Supaul", "Nirmali", "Triveniganj", "Chhatapur"],
446
- # "Vaishali": ["Hajipur", "Mahua", "Lalganj", "Desri"],
447
- # "West Champaran": ["Bettiah", "Bagaha", "Narkatiaganj", "Lauriya"]
448
- # }
449
-
450
- # LOCATIONS = {
451
- # "Araria": {"latitude": 26.1523, "longitude": 87.5167},
452
- # "Forbesganj": {"latitude": 26.3023, "longitude": 87.2664},
453
- # "Jokihat": {"latitude": 25.8998, "longitude": 87.2686},
454
- # "Raniganj": {"latitude": 26.0537, "longitude": 87.5333},
455
- # "Arwal": {"latitude": 25.2560, "longitude": 84.6819},
456
- # "Kaler": {"latitude": 25.1960, "longitude": 84.6219},
457
- # "Karpi": {"latitude": 25.2360, "longitude": 84.7019},
458
- # "Kurtha": {"latitude": 25.3160, "longitude": 84.6619},
459
- # "Aurangabad": {"latitude": 24.7521, "longitude": 84.3742},
460
- # "Daudnagar": {"latitude": 25.0337, "longitude": 84.4007},
461
- # "Obra": {"latitude": 24.9923, "longitude": 84.4342},
462
- # "Nabinagar": {"latitude": 24.6087, "longitude": 84.1269},
463
- # "Banka": {"latitude": 24.8893, "longitude": 86.9220},
464
- # "Amarpur": {"latitude": 25.0393, "longitude": 86.9020},
465
- # "Barahat": {"latitude": 24.8393, "longitude": 87.0020},
466
- # "Belhar": {"latitude": 24.9393, "longitude": 86.9620},
467
- # "Begusarai": {"latitude": 25.4182, "longitude": 86.1347},
468
- # "Bakhri": {"latitude": 25.4582, "longitude": 86.0547},
469
- # "Barauni": {"latitude": 25.4751, "longitude": 86.0458},
470
- # "Teghra": {"latitude": 25.5082, "longitude": 85.9347},
471
- # "Bhagalpur": {"latitude": 25.2425, "longitude": 86.9842},
472
- # "Sabour": {"latitude": 25.2375, "longitude": 87.0542},
473
- # "Nathnagar": {"latitude": 25.1225, "longitude": 87.0042},
474
- # "Kahalgaon": {"latitude": 25.1925, "longitude": 87.2142},
475
- # "Arrah": {"latitude": 25.5560, "longitude": 84.6631},
476
- # "Jagdishpur": {"latitude": 25.4660, "longitude": 84.4231},
477
- # "Piro": {"latitude": 25.3260, "longitude": 84.4031},
478
- # "Shahpur": {"latitude": 25.6060, "longitude": 84.4031},
479
- # "Buxar": {"latitude": 25.5641, "longitude": 83.9778},
480
- # "Dumraon": {"latitude": 25.5541, "longitude": 84.1478},
481
- # "Chausa": {"latitude": 25.5241, "longitude": 83.9178},
482
- # "Simri": {"latitude": 25.6141, "longitude": 84.0478},
483
- # "Darbhanga": {"latitude": 26.1542, "longitude": 85.8978},
484
- # "Baheri": {"latitude": 26.0442, "longitude": 85.8378},
485
- # "Jale": {"latitude": 26.2042, "longitude": 85.8578},
486
- # "Benipur": {"latitude": 26.1142, "longitude": 85.9478},
487
- # "Motihari": {"latitude": 26.6484, "longitude": 84.9194},
488
- # "Raxaul": {"latitude": 26.9784, "longitude": 84.8494},
489
- # "Chakia": {"latitude": 26.4184, "longitude": 85.0494},
490
- # "Dhaka": {"latitude": 26.6784, "longitude": 85.1694},
491
- # "Gaya": {"latitude": 24.7955, "longitude": 85.0002},
492
- # "Bodh Gaya": {"latitude": 24.6955, "longitude": 84.9902},
493
- # "Tekari": {"latitude": 24.9455, "longitude": 85.0402},
494
- # "Sherghati": {"latitude": 24.5655, "longitude": 84.7902},
495
- # "Gopalganj": {"latitude": 26.4685, "longitude": 84.4388},
496
- # "Barauli": {"latitude": 26.3785, "longitude": 84.5788},
497
- # "Baikunthpur": {"latitude": 26.5285, "longitude": 84.3588},
498
- # "Kateya": {"latitude": 26.4285, "longitude": 84.6388},
499
- # "Jamui": {"latitude": 24.9272, "longitude": 86.2231},
500
- # "Jhajha": {"latitude": 24.7772, "longitude": 86.3731},
501
- # "Sikandra": {"latitude": 24.9672, "longitude": 86.0631},
502
- # "Sono": {"latitude": 24.8372, "longitude": 86.1431},
503
- # "Jehanabad": {"latitude": 25.2078, "longitude": 84.9869},
504
- # "Ghoshi": {"latitude": 25.1478, "longitude": 84.9269},
505
- # "Makhdumpur": {"latitude": 25.2478, "longitude": 85.0469},
506
- # "Modanganj": {"latitude": 25.2678, "longitude": 84.9069},
507
- # "Bhabua": {"latitude": 25.0405, "longitude": 83.6074},
508
- # "Mohania": {"latitude": 25.1305, "longitude": 83.4774},
509
- # "Ramgarh": {"latitude": 24.9505, "longitude": 83.6874},
510
- # "Chainpur": {"latitude": 25.2005, "longitude": 83.7474},
511
- # "Katihar": {"latitude": 25.5394, "longitude": 87.5839},
512
- # "Barsoi": {"latitude": 25.3794, "longitude": 87.8839},
513
- # "Manihari": {"latitude": 25.3394, "longitude": 87.6239},
514
- # "Pranpur": {"latitude": 25.6894, "longitude": 87.7239},
515
- # "Khagaria": {"latitude": 25.5022, "longitude": 86.4665},
516
- # "Parbatta": {"latitude": 25.5422, "longitude": 86.5865},
517
- # "Alauli": {"latitude": 25.4622, "longitude": 86.3465},
518
- # "Beldaur": {"latitude": 25.5622, "longitude": 86.4265},
519
- # "Kishanganj": {"latitude": 26.1046, "longitude": 87.9475},
520
- # "Bahadurganj": {"latitude": 26.2646, "longitude": 88.1175},
521
- # "Thakurganj": {"latitude": 26.0446, "longitude": 87.8275},
522
- # "Dighalbank": {"latitude": 25.9046, "longitude": 87.9875},
523
- # "Lakhisarai": {"latitude": 25.1678, "longitude": 86.0927},
524
- # "Halsi": {"latitude": 25.2278, "longitude": 86.0327},
525
- # "Suryagarha": {"latitude": 25.1078, "longitude": 86.1527},
526
- # "Pipariya": {"latitude": 25.2078, "longitude": 86.1327},
527
- # "Madhepura": {"latitude": 25.9207, "longitude": 86.7940},
528
- # "Udakishanganj": {"latitude": 25.9807, "longitude": 86.6740},
529
- # "Murliganj": {"latitude": 25.8907, "longitude": 86.9940},
530
- # "Alamnagar": {"latitude": 25.9607, "longitude": 86.7340},
531
- # "Madhubani": {"latitude": 26.3561, "longitude": 86.0644},
532
- # "Jhanjharpur": {"latitude": 26.2661, "longitude": 86.2844},
533
- # "Benipatti": {"latitude": 26.5961, "longitude": 86.1444},
534
- # "Jainagar": {"latitude": 26.2061, "longitude": 86.1644},
535
- # "Munger": {"latitude": 25.3753, "longitude": 86.4734},
536
- # "Jamalpur": {"latitude": 25.3153, "longitude": 86.4934},
537
- # "Asarganj": {"latitude": 25.1453, "longitude": 86.6834},
538
- # "Tarapur": {"latitude": 25.0253, "longitude": 86.6334},
539
- # "Muzaffarpur": {"latitude": 26.1225, "longitude": 85.3906},
540
- # "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806},
541
- # "Minapur": {"latitude": 26.0625, "longitude": 85.2906},
542
- # "Bochaha": {"latitude": 26.0025, "longitude": 85.5306},
543
- # "Bihar Sharif": {"latitude": 25.1979, "longitude": 85.5238},
544
- # "Rajgir": {"latitude": 25.0279, "longitude": 85.4238},
545
- # "Hilsa": {"latitude": 25.3179, "longitude": 85.2838},
546
- # "Biharsharif": {"latitude": 25.1979, "longitude": 85.5238},
547
- # "Nawada": {"latitude": 24.8834, "longitude": 85.5387},
548
- # "Rajauli": {"latitude": 25.0634, "longitude": 85.6387},
549
- # "Akbarpur": {"latitude": 24.8234, "longitude": 85.4587},
550
- # "Hisua": {"latitude": 24.8334, "longitude": 85.4187},
551
- # "Patna": {"latitude": 25.5941, "longitude": 85.1376},
552
- # "Danapur": {"latitude": 25.6341, "longitude": 85.0476},
553
- # "Fatuha": {"latitude": 25.5041, "longitude": 85.3076},
554
- # "Khagaul": {"latitude": 25.5741, "longitude": 85.0476},
555
- # "Purnia": {"latitude": 25.7771, "longitude": 87.4753},
556
- # "Dhamdaha": {"latitude": 25.8871, "longitude": 87.5853},
557
- # "Kasba": {"latitude": 25.8471, "longitude": 87.5353},
558
- # "Banmankhi": {"latitude": 25.8871, "longitude": 87.1953},
559
- # "Sasaram": {"latitude": 24.9520, "longitude": 84.0328},
560
- # "Dehri": {"latitude": 24.9020, "longitude": 84.1828},
561
- # "Bikramganj": {"latitude": 25.2120, "longitude": 84.2628},
562
- # "Nasriganj": {"latitude": 25.0520, "longitude": 84.1228},
563
- # "Saharsa": {"latitude": 25.8769, "longitude": 86.5956},
564
- # "Sonbarsa": {"latitude": 25.9269, "longitude": 86.7356},
565
- # "Simri Bakhtiarpur": {"latitude": 25.9569, "longitude": 86.3556},
566
- # "Mahishi": {"latitude": 25.9969, "longitude": 86.4756},
567
- # "Samastipur": {"latitude": 25.8647, "longitude": 85.7817},
568
- # "Rosera": {"latitude": 25.7947, "longitude": 85.9317},
569
- # "Dalsinghsarai": {"latitude": 25.6647, "longitude": 85.8317},
570
- # "Pusa": {"latitude": 25.9847, "longitude": 85.6717},
571
- # "Chapra": {"latitude": 25.7805, "longitude": 84.7477},
572
- # "Marhaura": {"latitude": 25.9705, "longitude": 84.8677},
573
- # "Amnour": {"latitude": 25.8905, "longitude": 84.9077},
574
- # "Sonepur": {"latitude": 25.6905, "longitude": 85.1777},
575
- # "Sheikhpura": {"latitude": 25.1391, "longitude": 85.8354},
576
- # "Barbigha": {"latitude": 25.2191, "longitude": 85.7354},
577
- # "Ariari": {"latitude": 25.0591, "longitude": 85.9554},
578
- # "Shekhopur": {"latitude": 25.1391, "longitude": 85.8354},
579
- # "Sheohar": {"latitude": 26.5184, "longitude": 85.2959},
580
- # "Dumri Katsari": {"latitude": 26.5784, "longitude": 85.1959},
581
- # "Piprahi": {"latitude": 26.4684, "longitude": 85.4159},
582
- # "Tariyani": {"latitude": 26.5584, "longitude": 85.2359},
583
- # "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806},
584
- # "Pupri": {"latitude": 26.4725, "longitude": 85.7006},
585
- # "Belsand": {"latitude": 26.4425, "longitude": 85.4006},
586
- # "Bathnaha": {"latitude": 26.5925, "longitude": 85.5306},
587
- # "Siwan": {"latitude": 26.2195, "longitude": 84.3564},
588
- # "Maharajganj": {"latitude": 26.1095, "longitude": 84.5064},
589
- # "Mairwa": {"latitude": 26.2295, "longitude": 84.1664},
590
- # "Darauli": {"latitude": 26.1595, "longitude": 84.1464},
591
- # "Supaul": {"latitude": 26.1260, "longitude": 86.6050},
592
- # "Nirmali": {"latitude": 26.3160, "longitude": 86.5850},
593
- # "Triveniganj": {"latitude": 26.2160, "longitude": 87.0250},
594
- # "Chhatapur": {"latitude": 26.2160, "longitude": 86.9050},
595
- # "Hajipur": {"latitude": 25.6851, "longitude": 85.2095},
596
- # "Mahua": {"latitude": 25.9651, "longitude": 85.2895},
597
- # "Lalganj": {"latitude": 25.8751, "longitude": 85.1695},
598
- # "Desri": {"latitude": 25.6051, "longitude": 85.4895},
599
- # "Bettiah": {"latitude": 26.8022, "longitude": 84.5025},
600
- # "Bagaha": {"latitude": 27.0922, "longitude": 84.0925},
601
- # "Narkatiaganj": {"latitude": 26.4322, "longitude": 84.7925},
602
- # "Lauriya": {"latitude": 26.9822, "longitude": 84.3125}
603
- # }
604
-
605
-
606
- # # ============================================================================
607
- # # FASTAPI APP
608
- # # ============================================================================
609
-
610
- # app = FastAPI(title="Farmer.chat Alert Summary API")
611
-
612
- # # CORS middleware
613
- # app.add_middleware(
614
- # CORSMiddleware,
615
- # allow_origins=["*"],
616
- # allow_credentials=True,
617
- # allow_methods=["*"],
618
- # allow_headers=["*"],
619
- # )
620
-
621
- # # Initialize pipeline
622
- # openai_client = None
623
- # pipeline = None
624
-
625
- # @app.on_event("startup")
626
- # async def startup_event():
627
- # """Initialize OpenAI client and pipeline on startup"""
628
- # global openai_client, pipeline
629
- # try:
630
- # openai_client = get_openai_client()
631
- # DEFAULT_LOCATION = {"latitude": 25.5941, "longitude": 85.1376}
632
- # pipeline = FarmerChatPipeline(openai_client, DEFAULT_LOCATION)
633
- # print("✓ Pipeline initialized successfully")
634
- # except Exception as e:
635
- # print(f"✗ Pipeline initialization failed: {e}")
636
- # raise
637
-
638
-
639
- # # ============================================================================
640
- # # API MODELS
641
- # # ============================================================================
642
-
643
- # class LocationRequest(BaseModel):
644
- # location_name: str
645
- # district: Optional[str] = None
646
-
647
-
648
- # class AlertResponse(BaseModel):
649
- # location: str
650
- # coordinates: Dict[str, float]
651
- # district: Optional[str] = None
652
- # alert_summary: str
653
- # timestamp: str
654
-
655
-
656
- # # ============================================================================
657
- # # API ENDPOINTS
658
- # # ============================================================================
659
-
660
- # @app.get("/")
661
- # async def root():
662
- # """Root endpoint"""
663
- # return {
664
- # "message": "Farmer.chat Alert Summary API",
665
- # "version": "1.0.0",
666
- # "endpoints": {
667
- # "/locations": "GET - List all districts and villages",
668
- # "/generate-alert": "POST - Generate alert for location",
669
- # "/health": "GET - Health check"
670
- # }
671
- # }
672
-
673
-
674
- # @app.get("/health")
675
- # async def health_check():
676
- # """Health check endpoint"""
677
- # return {
678
- # "status": "healthy",
679
- # "pipeline": "initialized" if pipeline else "not_initialized",
680
- # "timestamp": datetime.now().isoformat()
681
- # }
682
-
683
-
684
- # @app.get("/locations")
685
- # async def get_locations():
686
- # """Get all districts and villages"""
687
- # return {"districts": BIHAR_DATA}
688
-
689
-
690
- # @app.post("/generate-alert", response_model=AlertResponse)
691
- # async def generate_alert(request: LocationRequest):
692
- # """Generate alert summary for selected location"""
693
-
694
- # if not pipeline:
695
- # raise HTTPException(status_code=500, detail="Pipeline not initialized")
696
-
697
- # # Find location coordinates
698
- # location_name = request.location_name.strip()
699
- # coordinates = None
700
-
701
- # # Case-insensitive search
702
- # for loc_key, loc_coords in LOCATIONS.items():
703
- # if loc_key.lower() == location_name.lower():
704
- # coordinates = loc_coords
705
- # break
706
-
707
- # if not coordinates:
708
- # raise HTTPException(
709
- # status_code=404,
710
- # detail=f"Location '{location_name}' not found in database"
711
- # )
712
-
713
- # # Update pipeline location
714
- # pipeline.location = coordinates
715
-
716
- # # Create comprehensive query for all MCP servers
717
- # query = f"""Generate a comprehensive agricultural alert summary for {location_name} covering:
718
- # 1. Current weather conditions and 7-day forecast
719
- # 2. Soil health analysis and fertilizer recommendations
720
- # 3. Groundwater availability and irrigation status
721
- # 4. Elevation and topography considerations for farming
722
- # 5. Current pest risks and preventive measures
723
-
724
- # Provide actionable insights for farmers."""
725
-
726
- # try:
727
- # # Generate alert
728
- # alert_summary = pipeline.process_query(query)
729
-
730
- # return AlertResponse(
731
- # location=location_name,
732
- # coordinates=coordinates,
733
- # district=request.district,
734
- # alert_summary=alert_summary,
735
- # timestamp=datetime.now().isoformat()
736
- # )
737
-
738
- # except Exception as e:
739
- # raise HTTPException(
740
- # status_code=500,
741
- # detail=f"Error generating alert: {str(e)}"
742
- # )
743
-
744
-
745
- # # ============================================================================
746
- # # RUN SERVER
747
- # # ============================================================================
748
-
749
- # if __name__ == "__main__":
750
- # import uvicorn
751
- # port = int(os.getenv("PORT", 7860))
752
- # uvicorn.run(app, host="0.0.0.0", port=port)
753
-
754
-
755
  """
756
  Farmer.chat Alert Summary Generator - FastAPI Application
757
- FIXED: Proper async handling - endpoints await async pipeline methods
758
  """
759
 
760
  from fastapi import FastAPI, HTTPException
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
  Farmer.chat Alert Summary Generator - FastAPI Application
 
3
  """
4
 
5
  from fastapi import FastAPI, HTTPException