aakashdg commited on
Commit
8c08cae
·
verified ·
1 Parent(s): 5e0795d

fix (test app for location selector fixes)

Browse files
Files changed (1) hide show
  1. app.py +455 -254
app.py CHANGED
@@ -216,38 +216,192 @@
216
  # uvicorn.run(app, host="0.0.0.0", port=7860)
217
 
218
  """
219
- Alert Summary Generator Backend
220
- Modified FastAPI app with location-based alert generation
221
  """
222
 
223
  from fastapi import FastAPI, HTTPException
224
  from fastapi.middleware.cors import CORSMiddleware
225
  from pydantic import BaseModel
226
- from typing import Optional, Dict, Any
227
  import os
228
  from datetime import datetime
 
229
 
230
- # Import existing pipeline components
231
- from src.pipeline import FarmerChatPipeline
232
- from src.client import get_openai_client
233
 
234
- app = FastAPI(title="Farmer.chat Alert Summary API")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
- # CORS middleware
237
- app.add_middleware(
238
- CORSMiddleware,
239
- allow_origins=["*"],
240
- allow_credentials=True,
241
- allow_methods=["*"],
242
- allow_headers=["*"],
243
- )
244
 
245
- # Initialize OpenAI client and pipeline
246
- openai_client = get_openai_client()
247
- DEFAULT_LOCATION = {"latitude": 25.5941, "longitude": 85.1376} # Patna default
248
- pipeline = FarmerChatPipeline(openai_client, DEFAULT_LOCATION)
249
 
250
- # Bihar location data
251
  BIHAR_DATA = {
252
  "Araria": ["Araria", "Forbesganj", "Jokihat", "Raniganj"],
253
  "Arwal": ["Arwal", "Kaler", "Karpi", "Kurtha"],
@@ -265,188 +419,223 @@ BIHAR_DATA = {
265
  "Jehanabad": ["Jehanabad", "Ghoshi", "Makhdumpur", "Modanganj"],
266
  "Kaimur": ["Bhabua", "Mohania", "Ramgarh", "Chainpur"],
267
  "Katihar": ["Katihar", "Barsoi", "Manihari", "Pranpur"],
268
- "Khagaria": ["Khagaria", "Gogri", "Mansi", "Alauli"],
269
- "Kishanganj": ["Kishanganj", "Bahadurganj", "Thakurganj", "Kochadhaman"],
270
- "Lakhisarai": ["Lakhisarai", "Barahiya", "Halsi", "Surajgarha"],
271
- "Madhepura": ["Madhepura", "Bihariganj", "Murliganj", "Udakishunganj"],
272
- "Madhubani": ["Madhubani", "Jhanjharpur", "Benipatti", "Phulparas"],
273
- "Munger": ["Munger", "Jamalpur", "Kharagpur", "Tarapur"],
274
- "Muzaffarpur": ["Muzaffarpur", "Motipur", "Kanti", "Saraiya"],
275
- "Nalanda": ["Bihar Sharif", "Rajgir", "Hilsa", "Islampur"],
276
- "Nawada": ["Nawada", "Rajauli", "Hisua", "Warsaliganj"],
277
- "Patna": ["Patna", "Danapur", "Masaurhi", "Phulwari", "Barh"],
278
- "Purnia": ["Purnia", "Banmankhi", "Dhamdaha", "Baisi"],
279
- "Rohtas": ["Sasaram", "Dehri", "Bikramganj", "Nokha"],
280
- "Saharsa": ["Saharsa", "Simri Bakhtiyarpur", "Salkhua", "Sonbarsa"],
281
- "Samastipur": ["Samastipur", "Rosera", "Dalsinghsarai", "Patori"],
282
- "Saran": ["Chhapra", "Marhaura", "Dariapur", "Amnour"],
283
- "Sheikhpura": ["Sheikhpura", "Barbigha", "Chewara", "Ghatkusumbha"],
284
- "Sheohar": ["Sheohar", "Piprahi", "Tariyani", "Dumri Katsari"],
285
- "Sitamarhi": ["Sitamarhi", "Bairgania", "Belsand", "Parihar"],
286
- "Siwan": ["Siwan", "Maharajganj", "Goriakothi", "Barharia"],
287
- "Supaul": ["Supaul", "Birpur", "Triveniganj", "Nirmali"],
288
- "Vaishali": ["Hajipur", "Mahnar", "Lalganj", "Raghopur"],
289
- "West Champaran": ["Bettiah", "Bagaha", "Narkatiaganj", "Ramnagar"],
290
  }
291
 
292
- # Location coordinates
293
  LOCATIONS = {
294
- "alauli": {'latitude': 25.6392, 'longitude': 86.3854},
295
- "amarpur": {'latitude': 25.0217, 'longitude': 86.8932},
296
- "amnour": {'latitude': 25.9264, 'longitude': 84.9129},
297
- "araria": {'latitude': 26.1346, 'longitude': 87.4654},
298
- "arrah": {'latitude': 25.5603, 'longitude': 84.6632},
299
- "arwal": {'latitude': 25.2369, 'longitude': 84.6738},
300
- "aurangabad": {'latitude': 24.7863, 'longitude': 84.4145},
301
- "bagaha": {'latitude': 27.059, 'longitude': 84.2065},
302
- "bahadurganj": {'latitude': 26.2702, 'longitude': 87.8373},
303
- "baheri": {'latitude': 26.0043, 'longitude': 86.0405},
304
- "baikunthpur": {'latitude': 26.2817, 'longitude': 84.7428},
305
- "bairgania": {'latitude': 26.7401, 'longitude': 85.2755},
306
- "baisi": {'latitude': 25.8396, 'longitude': 87.7509},
307
- "bakhri": {'latitude': 25.5743, 'longitude': 86.244},
308
- "banka": {'latitude': 24.8669, 'longitude': 86.9126},
309
- "banmankhi": {'latitude': 25.8976, 'longitude': 87.1659},
310
- "barahat": {'latitude': 24.8869, 'longitude': 87.0296},
311
- "barahiya": {'latitude': 25.2636, 'longitude': 86.0055},
312
- "barauli": {'latitude': 26.3966, 'longitude': 84.6005},
313
- "barauni": {'latitude': 25.4315, 'longitude': 86.0284},
314
- "barbigha": {'latitude': 25.207, 'longitude': 85.7715},
315
- "barh": {'latitude': 25.451, 'longitude': 85.7002},
316
- "barharia": {'latitude': 26.3156, 'longitude': 84.456},
317
- "barsoi": {'latitude': 25.6206, 'longitude': 87.9744},
318
- "begusarai": {'latitude': 25.4139, 'longitude': 86.1349},
319
- "belhar": {'latitude': 24.906, 'longitude': 86.6074},
320
- "belsand": {'latitude': 26.4323, 'longitude': 85.3946},
321
- "benipatti": {'latitude': 26.4435, 'longitude': 85.9105},
322
- "benipur": {'latitude': 26.0754, 'longitude': 86.1245},
323
- "bettiah": {'latitude': 26.8023, 'longitude': 84.5074},
324
- "bhabua": {'latitude': 25.0763, 'longitude': 83.6336},
325
- "bhagalpur": {'latitude': 25.2495, 'longitude': 86.9828},
326
- "bihar sharif": {'latitude': 25.1939, 'longitude': 85.5209},
327
- "bihariganj": {'latitude': 25.741, 'longitude': 86.9758},
328
- "bikramganj": {'latitude': 25.2184, 'longitude': 84.2324},
329
- "birpur": {'latitude': 26.5152, 'longitude': 87.0085},
330
- "bodh gaya": {'latitude': 24.6776, 'longitude': 84.9727},
331
- "buxar": {'latitude': 25.5612, 'longitude': 83.9813},
332
- "chainpur": {'latitude': 24.9811, 'longitude': 83.4203},
333
- "chakia": {'latitude': 26.4704, 'longitude': 84.9933},
334
- "chausa": {'latitude': 25.4514, 'longitude': 83.8621},
335
- "chewara": {'latitude': 25.054, 'longitude': 85.9335},
336
- "chhapra": {'latitude': 25.7784, 'longitude': 84.7515},
337
- "dalsinghsarai": {'latitude': 25.6727, 'longitude': 85.8124},
338
- "danapur": {'latitude': 25.6359, 'longitude': 85.0474},
339
- "darbhanga": {'latitude': 26.157, 'longitude': 85.8995},
340
- "dariapur": {'latitude': 25.8275, 'longitude': 85.0565},
341
- "daudnagar": {'latitude': 25.044, 'longitude': 84.4323},
342
- "dehri": {'latitude': 24.9259, 'longitude': 84.1729},
343
- "dhaka": {'latitude': 26.6924, 'longitude': 85.1986},
344
- "dhamdaha": {'latitude': 25.7378, 'longitude': 87.2338},
345
- "dumraon": {'latitude': 25.5238, 'longitude': 84.16},
346
- "dumri katsari": {'latitude': 26.4691, 'longitude': 85.2195},
347
- "forbesganj": {'latitude': 26.2784, 'longitude': 87.2988},
348
- "gaya": {'latitude': 24.7964, 'longitude': 85.008},
349
- "ghatkusumbha": {'latitude': 25.2127, 'longitude': 85.9308},
350
- "ghoshi": {'latitude': 25.1296, 'longitude': 85.0976},
351
- "gogri": {'latitude': 25.4294, 'longitude': 86.7107},
352
- "gopalganj": {'latitude': 26.5382, 'longitude': 84.4589},
353
- "goriakothi": {'latitude': 26.2448, 'longitude': 84.575},
354
- "hajipur": {'latitude': 25.6906, 'longitude': 85.209},
355
- "halsi": {'latitude': 25.0332, 'longitude': 86.0554},
356
- "hilsa": {'latitude': 25.3007, 'longitude': 85.2494},
357
- "hisua": {'latitude': 24.8457, 'longitude': 85.3954},
358
- "islampur": {'latitude': 25.0969, 'longitude': 85.2604},
359
- "jagdishpur": {'latitude': 25.4819, 'longitude': 84.4569},
360
- "jale": {'latitude': 26.3563, 'longitude': 85.769},
361
- "jamalpur": {'latitude': 25.3139, 'longitude': 86.4897},
362
- "jamui": {'latitude': 24.9669, 'longitude': 86.174},
363
- "jehanabad": {'latitude': 25.2265, 'longitude': 84.9911},
364
- "jhajha": {'latitude': 24.7729, 'longitude': 86.3863},
365
- "jhanjharpur": {'latitude': 26.2872, 'longitude': 86.3404},
366
- "jokihat": {'latitude': 26.0816, 'longitude': 87.5935},
367
- "kahalgaon": {'latitude': 25.2652, 'longitude': 87.2835},
368
- "kaler": {'latitude': 25.1549, 'longitude': 84.5414},
369
- "kanti": {'latitude': 26.1819, 'longitude': 85.2711},
370
- "karpi": {'latitude': 25.1714, 'longitude': 84.7256},
371
- "kateya": {'latitude': 26.5723, 'longitude': 84.0811},
372
- "katihar": {'latitude': 25.5434, 'longitude': 87.569},
373
- "khagaria": {'latitude': 25.5064, 'longitude': 86.4663},
374
- "kharagpur": {'latitude': 25.133, 'longitude': 86.5248},
375
- "kishanganj": {'latitude': 26.1014, 'longitude': 87.9508},
376
- "kochadhaman": {'latitude': 26.1014, 'longitude': 87.9508},
377
- "kurtha": {'latitude': 25.1333, 'longitude': 84.8113},
378
- "lakhisarai": {'latitude': 25.1678, 'longitude': 86.0594},
379
- "lalganj": {'latitude': 25.8521, 'longitude': 85.1896},
380
- "madhepura": {'latitude': 25.926, 'longitude': 86.8204},
381
- "madhubani": {'latitude': 26.3489, 'longitude': 86.0772},
382
- "maharajganj": {'latitude': 26.141, 'longitude': 84.5318},
383
- "mahnar": {'latitude': 25.622, 'longitude': 85.5091},
384
- "makhdumpur": {'latitude': 25.0739, 'longitude': 84.9879},
385
- "manihari": {'latitude': 25.3414, 'longitude': 87.6195},
386
- "mansi": {'latitude': 25.546, 'longitude': 86.5504},
387
- "marhaura": {'latitude': 25.9302, 'longitude': 84.795},
388
- "masaurhi": {'latitude': 25.3516, 'longitude': 84.9873},
389
- "modanganj": {'latitude': 25.2591, 'longitude': 85.1584},
390
- "mohania": {'latitude': 25.1677, 'longitude': 83.6216},
391
- "motihari": {'latitude': 26.6507, 'longitude': 84.9115},
392
- "motipur": {'latitude': 26.2571, 'longitude': 85.1689},
393
- "munger": {'latitude': 25.3774, 'longitude': 86.4731},
394
- "murliganj": {'latitude': 25.8764, 'longitude': 86.9369},
395
- "muzaffarpur": {'latitude': 26.1183, 'longitude': 85.3858},
396
- "nabinagar": {'latitude': 24.6428, 'longitude': 84.0968},
397
- "narkatiaganj": {'latitude': 27.0969, 'longitude': 84.4585},
398
- "nathnagar": {'latitude': 25.2184, 'longitude': 86.9177},
399
- "nawada": {'latitude': 24.9348, 'longitude': 85.5488},
400
- "nirmali": {'latitude': 26.3789, 'longitude': 86.7324},
401
- "nokha": {'latitude': 25.0832, 'longitude': 84.0932},
402
- "obra": {'latitude': 24.9377, 'longitude': 84.4326},
403
- "parihar": {'latitude': 26.7512, 'longitude': 85.6799},
404
- "patna": {'latitude': 25.6093, 'longitude': 85.1235},
405
- "patori": {'latitude': 25.622, 'longitude': 85.5869},
406
- "phulparas": {'latitude': 26.386, 'longitude': 86.4547},
407
- "phulwari": {'latitude': 25.543, 'longitude': 85.0523},
408
- "piprahi": {'latitude': 26.3489, 'longitude': 86.0772},
409
- "piro": {'latitude': 25.3383, 'longitude': 84.3541},
410
- "pranpur": {'latitude': 25.4876, 'longitude': 87.7082},
411
- "purnia": {'latitude': 25.7774, 'longitude': 87.4731},
412
- "raghopur": {'latitude': 25.5714, 'longitude': 85.3241},
413
- "rajauli": {'latitude': 24.6343, 'longitude': 85.5609},
414
- "rajgir": {'latitude': 25.03, 'longitude': 85.4207},
415
- "ramgarh": {'latitude': 25.304, 'longitude': 83.6808},
416
- "ramnagar": {'latitude': 27.2909, 'longitude': 84.2936},
417
- "raniganj": {'latitude': 26.0553, 'longitude': 87.3077},
418
- "raxaul": {'latitude': 26.9869, 'longitude': 84.8447},
419
- "rosera": {'latitude': 25.7798, 'longitude': 86.0425},
420
- "sabour": {'latitude': 25.2282, 'longitude': 87.0636},
421
- "saharsa": {'latitude': 25.8759, 'longitude': 86.5927},
422
- "salkhua": {'latitude': 25.6653, 'longitude': 86.5498},
423
- "samastipur": {'latitude': 25.8597, 'longitude': 85.7839},
424
- "saraiya": {'latitude': 26.0701, 'longitude': 85.1843},
425
- "sasaram": {'latitude': 24.951, 'longitude': 84.0149},
426
- "shahpur": {'latitude': 25.6593, 'longitude': 84.4295},
427
- "sheikhpura": {'latitude': 25.1493, 'longitude': 85.8766},
428
- "sheohar": {'latitude': 26.5158, 'longitude': 85.2849},
429
- "sherghati": {'latitude': 24.5939, 'longitude': 84.8479},
430
- "sikandra": {'latitude': 24.9251, 'longitude': 86.0462},
431
- "simri": {'latitude': 25.6499, 'longitude': 84.1384},
432
- "simri bakhtiyarpur": {'latitude': 25.7209, 'longitude': 86.5975},
433
- "sitamarhi": {'latitude': 26.5943, 'longitude': 85.5004},
434
- "siwan": {'latitude': 26.2185, 'longitude': 84.3585},
435
- "sonbarsa": {'latitude': 25.7013, 'longitude': 86.7794},
436
- "sono": {'latitude': 24.6998, 'longitude': 86.2794},
437
- "supaul": {'latitude': 26.0846, 'longitude': 86.5785},
438
- "surajgarha": {'latitude': 25.188, 'longitude': 86.2868},
439
- "tarapur": {'latitude': 25.1039, 'longitude': 86.647},
440
- "tariyani": {'latitude': 26.5158, 'longitude': 85.2849},
441
- "teghra": {'latitude': 25.4727, 'longitude': 85.9368},
442
- "tekari": {'latitude': 24.9411, 'longitude': 84.843},
443
- "thakurganj": {'latitude': 26.4275, 'longitude': 88.129},
444
- "triveniganj": {'latitude': 26.127, 'longitude': 86.8873},
445
- "udakishunganj": {'latitude': 25.926, 'longitude': 86.8204},
446
- "warsaliganj": {'latitude': 24.9348, 'longitude': 85.5488},
447
  }
448
 
449
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  class LocationRequest(BaseModel):
451
  location_name: str
452
  district: Optional[str] = None
@@ -455,91 +644,103 @@ class LocationRequest(BaseModel):
455
  class AlertResponse(BaseModel):
456
  location: str
457
  coordinates: Dict[str, float]
 
458
  alert_summary: str
459
  timestamp: str
460
- district: Optional[str] = None
461
 
462
 
 
 
 
 
463
  @app.get("/")
464
  async def root():
 
465
  return {
466
  "message": "Farmer.chat Alert Summary API",
467
  "version": "1.0.0",
468
  "endpoints": {
469
- "/locations": "Get all available districts and villages",
470
- "/generate-alert": "Generate alert summary for a location"
 
471
  }
472
  }
473
 
474
 
475
- @app.get("/locations")
476
- async def get_locations():
477
- """Get all available districts and villages in Bihar"""
478
  return {
479
- "state": "Bihar",
480
- "districts": BIHAR_DATA,
481
- "total_districts": len(BIHAR_DATA),
482
- "total_villages": sum(len(villages) for villages in BIHAR_DATA.values())
483
  }
484
 
485
 
 
 
 
 
 
 
486
  @app.post("/generate-alert", response_model=AlertResponse)
487
  async def generate_alert(request: LocationRequest):
488
- """
489
- Generate comprehensive alert summary for a specific location.
490
- Automatically queries all MCP servers (Weather, Soil, Water, Elevation, Pests).
491
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
  try:
493
- # Get coordinates for the location
494
- location_key = request.location_name.lower()
495
- coords = LOCATIONS.get(location_key)
496
-
497
- if not coords:
498
- raise HTTPException(
499
- status_code=404,
500
- detail=f"Location '{request.location_name}' not found in database"
501
- )
502
-
503
- # Update pipeline location
504
- pipeline.location = coords
505
-
506
- # Create comprehensive query for alert generation
507
- alert_query = f"""Generate a comprehensive agricultural alert summary for {request.location_name}, Bihar.
508
-
509
- Please provide:
510
- 1. Weather conditions and forecast
511
- 2. Soil analysis and recommendations
512
- 3. Water availability status
513
- 4. Elevation and topography considerations
514
- 5. Pest risk assessment and preventive measures
515
-
516
- Format the response as a clear, actionable alert summary for farmers."""
517
-
518
- # Process through the pipeline
519
- result = await pipeline.process(alert_query, coords)
520
 
521
  return AlertResponse(
522
- location=request.location_name.title(),
523
- coordinates=coords,
524
- alert_summary=result,
525
- timestamp=datetime.utcnow().isoformat(),
526
- district=request.district
527
  )
528
-
529
- except HTTPException:
530
- raise
531
  except Exception as e:
532
- raise HTTPException(status_code=500, detail=str(e))
533
-
 
 
534
 
535
- @app.get("/health")
536
- async def health_check():
537
- return {
538
- "status": "healthy",
539
- "timestamp": datetime.utcnow().isoformat(),
540
- "pipeline_initialized": pipeline is not None
541
- }
542
 
 
 
 
543
 
544
  if __name__ == "__main__":
545
  import uvicorn
 
216
  # uvicorn.run(app, host="0.0.0.0", port=7860)
217
 
218
  """
219
+ Alert Summary Generator Backend - Standalone Version
220
+ FastAPI app with embedded pipeline and location data
221
  """
222
 
223
  from fastapi import FastAPI, HTTPException
224
  from fastapi.middleware.cors import CORSMiddleware
225
  from pydantic import BaseModel
226
+ from typing import Optional, Dict, Any, List
227
  import os
228
  from datetime import datetime
229
+ from openai import OpenAI
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
+ return OpenAI(api_key=api_key)
241
+
242
+
243
+ # ============================================================================
244
+ # PIPELINE COMPONENTS
245
+ # ============================================================================
246
+
247
+ class QueryRouter:
248
+ """Routes queries to appropriate MCP servers"""
249
+
250
+ def __init__(self, client):
251
+ self.client = client
252
+
253
+ def route_query(self, query: str, location: Dict[str, float]) -> Dict[str, Any]:
254
+ """Determine which servers to call based on query"""
255
+ prompt = f"""Given the farmer query: "{query}"
256
+ Location: {location['latitude']}, {location['longitude']}
257
+
258
+ Determine which data sources are needed. Return JSON:
259
+ {{
260
+ "weather": true/false,
261
+ "soil": true/false,
262
+ "water": true/false,
263
+ "elevation": true/false,
264
+ "pests": true/false
265
+ }}"""
266
+
267
+ response = self.client.chat.completions.create(
268
+ model="gpt-4",
269
+ messages=[{"role": "user", "content": prompt}],
270
+ temperature=0
271
+ )
272
+
273
+ # Parse routing decision
274
+ import json
275
+ try:
276
+ routing = json.loads(response.choices[0].message.content)
277
+ except:
278
+ # Default: query all servers for alerts
279
+ routing = {
280
+ "weather": True,
281
+ "soil": True,
282
+ "water": True,
283
+ "elevation": True,
284
+ "pests": True
285
+ }
286
+
287
+ return routing
288
+
289
+
290
+ class MCPExecutor:
291
+ """Executes parallel calls to MCP servers"""
292
+
293
+ def __init__(self, client):
294
+ self.client = client
295
+
296
+ def execute_parallel(self, routing: Dict[str, bool], location: Dict[str, float]) -> Dict[str, str]:
297
+ """Execute MCP server calls in parallel"""
298
+ results = {}
299
+
300
+ # Simulate MCP server calls (replace with actual server calls)
301
+ if routing.get("weather"):
302
+ results["weather"] = f"Weather data for {location['latitude']}, {location['longitude']}"
303
+
304
+ if routing.get("soil"):
305
+ results["soil"] = f"Soil data for {location['latitude']}, {location['longitude']}"
306
+
307
+ if routing.get("water"):
308
+ results["water"] = f"Water availability for {location['latitude']}, {location['longitude']}"
309
+
310
+ if routing.get("elevation"):
311
+ results["elevation"] = f"Elevation data for {location['latitude']}, {location['longitude']}"
312
+
313
+ if routing.get("pests"):
314
+ results["pests"] = f"Pest risk data for {location['latitude']}, {location['longitude']}"
315
+
316
+ return results
317
+
318
+
319
+ class ResponseCompiler:
320
+ """Compiles MCP results into coherent response"""
321
+
322
+ def __init__(self, client):
323
+ self.client = client
324
+
325
+ def compile_response(self, query: str, mcp_results: Dict[str, str], location: Dict[str, float]) -> str:
326
+ """Compile MCP results into final response"""
327
+
328
+ # Format MCP results for context
329
+ context = "\n\n".join([f"{k.upper()}: {v}" for k, v in mcp_results.items()])
330
+
331
+ prompt = f"""You are an agricultural assistant. Compile this data into a comprehensive alert summary.
332
+
333
+ FARMER QUERY: {query}
334
+ LOCATION: {location['latitude']}, {location['longitude']}
335
+
336
+ DATA FROM SOURCES:
337
+ {context}
338
+
339
+ Provide a comprehensive agricultural alert covering:
340
+ 1. Current weather conditions and forecast
341
+ 2. Soil health and recommendations
342
+ 3. Water availability status
343
+ 4. Elevation/topography considerations
344
+ 5. Pest risks and preventive measures
345
+
346
+ Be specific, actionable, and farmer-friendly."""
347
+
348
+ response = self.client.chat.completions.create(
349
+ model="gpt-4",
350
+ messages=[{"role": "user", "content": prompt}],
351
+ temperature=0.7
352
+ )
353
+
354
+ return response.choices[0].message.content
355
+
356
+
357
+ class HindiTranslator:
358
+ """Translates responses to Hindi"""
359
+
360
+ def __init__(self, client):
361
+ self.client = client
362
+
363
+ def translate(self, text: str, target_lang: str = "en") -> str:
364
+ """Translate text if needed"""
365
+ if target_lang == "en":
366
+ return text
367
+
368
+ # Add Hindi translation logic here
369
+ return text
370
+
371
+
372
+ class FarmerChatPipeline:
373
+ """Main pipeline orchestrating all stages"""
374
+
375
+ def __init__(self, client, location: Dict[str, float]):
376
+ self.client = client
377
+ self.location = location
378
+ self.router = QueryRouter(client)
379
+ self.executor = MCPExecutor(client)
380
+ self.compiler = ResponseCompiler(client)
381
+ self.translator = HindiTranslator(client)
382
+
383
+ def process_query(self, query: str, language: str = "en") -> str:
384
+ """Process query through full pipeline"""
385
+
386
+ # Stage 1: Route query
387
+ routing = self.router.route_query(query, self.location)
388
+
389
+ # Stage 2: Execute MCP calls
390
+ mcp_results = self.executor.execute_parallel(routing, self.location)
391
+
392
+ # Stage 3: Compile response
393
+ response = self.compiler.compile_response(query, mcp_results, self.location)
394
+
395
+ # Stage 4: Translate if needed
396
+ final_response = self.translator.translate(response, language)
397
+
398
+ return final_response
399
 
 
 
 
 
 
 
 
 
400
 
401
+ # ============================================================================
402
+ # BIHAR LOCATION DATA
403
+ # ============================================================================
 
404
 
 
405
  BIHAR_DATA = {
406
  "Araria": ["Araria", "Forbesganj", "Jokihat", "Raniganj"],
407
  "Arwal": ["Arwal", "Kaler", "Karpi", "Kurtha"],
 
419
  "Jehanabad": ["Jehanabad", "Ghoshi", "Makhdumpur", "Modanganj"],
420
  "Kaimur": ["Bhabua", "Mohania", "Ramgarh", "Chainpur"],
421
  "Katihar": ["Katihar", "Barsoi", "Manihari", "Pranpur"],
422
+ "Khagaria": ["Khagaria", "Parbatta", "Alauli", "Beldaur"],
423
+ "Kishanganj": ["Kishanganj", "Bahadurganj", "Thakurganj", "Dighalbank"],
424
+ "Lakhisarai": ["Lakhisarai", "Halsi", "Suryagarha", "Pipariya"],
425
+ "Madhepura": ["Madhepura", "Udakishanganj", "Murliganj", "Alamnagar"],
426
+ "Madhubani": ["Madhubani", "Jhanjharpur", "Benipatti", "Jainagar"],
427
+ "Munger": ["Munger", "Jamalpur", "Asarganj", "Tarapur"],
428
+ "Muzaffarpur": ["Muzaffarpur", "Sitamarhi", "Minapur", "Bochaha"],
429
+ "Nalanda": ["Bihar Sharif", "Rajgir", "Hilsa", "Biharsharif"],
430
+ "Nawada": ["Nawada", "Rajauli", "Akbarpur", "Hisua"],
431
+ "Patna": ["Patna", "Danapur", "Fatuha", "Khagaul"],
432
+ "Purnia": ["Purnia", "Dhamdaha", "Kasba", "Banmankhi"],
433
+ "Rohtas": ["Sasaram", "Dehri", "Bikramganj", "Nasriganj"],
434
+ "Saharsa": ["Saharsa", "Sonbarsa", "Simri Bakhtiarpur", "Mahishi"],
435
+ "Samastipur": ["Samastipur", "Rosera", "Dalsinghsarai", "Pusa"],
436
+ "Saran": ["Chapra", "Marhaura", "Amnour", "Sonepur"],
437
+ "Sheikhpura": ["Sheikhpura", "Barbigha", "Ariari", "Shekhopur"],
438
+ "Sheohar": ["Sheohar", "Dumri Katsari", "Piprahi", "Tariyani"],
439
+ "Sitamarhi": ["Sitamarhi", "Pupri", "Belsand", "Bathnaha"],
440
+ "Siwan": ["Siwan", "Maharajganj", "Mairwa", "Darauli"],
441
+ "Supaul": ["Supaul", "Nirmali", "Triveniganj", "Chhatapur"],
442
+ "Vaishali": ["Hajipur", "Mahua", "Lalganj", "Desri"],
443
+ "West Champaran": ["Bettiah", "Bagaha", "Narkatiaganj", "Lauriya"]
444
  }
445
 
 
446
  LOCATIONS = {
447
+ "Araria": {"latitude": 26.1523, "longitude": 87.5167},
448
+ "Forbesganj": {"latitude": 26.3023, "longitude": 87.2664},
449
+ "Jokihat": {"latitude": 25.8998, "longitude": 87.2686},
450
+ "Raniganj": {"latitude": 26.0537, "longitude": 87.5333},
451
+ "Arwal": {"latitude": 25.2560, "longitude": 84.6819},
452
+ "Kaler": {"latitude": 25.1960, "longitude": 84.6219},
453
+ "Karpi": {"latitude": 25.2360, "longitude": 84.7019},
454
+ "Kurtha": {"latitude": 25.3160, "longitude": 84.6619},
455
+ "Aurangabad": {"latitude": 24.7521, "longitude": 84.3742},
456
+ "Daudnagar": {"latitude": 25.0337, "longitude": 84.4007},
457
+ "Obra": {"latitude": 24.9923, "longitude": 84.4342},
458
+ "Nabinagar": {"latitude": 24.6087, "longitude": 84.1269},
459
+ "Banka": {"latitude": 24.8893, "longitude": 86.9220},
460
+ "Amarpur": {"latitude": 25.0393, "longitude": 86.9020},
461
+ "Barahat": {"latitude": 24.8393, "longitude": 87.0020},
462
+ "Belhar": {"latitude": 24.9393, "longitude": 86.9620},
463
+ "Begusarai": {"latitude": 25.4182, "longitude": 86.1347},
464
+ "Bakhri": {"latitude": 25.4582, "longitude": 86.0547},
465
+ "Barauni": {"latitude": 25.4751, "longitude": 86.0458},
466
+ "Teghra": {"latitude": 25.5082, "longitude": 85.9347},
467
+ "Bhagalpur": {"latitude": 25.2425, "longitude": 86.9842},
468
+ "Sabour": {"latitude": 25.2375, "longitude": 87.0542},
469
+ "Nathnagar": {"latitude": 25.1225, "longitude": 87.0042},
470
+ "Kahalgaon": {"latitude": 25.1925, "longitude": 87.2142},
471
+ "Arrah": {"latitude": 25.5560, "longitude": 84.6631},
472
+ "Jagdishpur": {"latitude": 25.4660, "longitude": 84.4231},
473
+ "Piro": {"latitude": 25.3260, "longitude": 84.4031},
474
+ "Shahpur": {"latitude": 25.6060, "longitude": 84.4031},
475
+ "Buxar": {"latitude": 25.5641, "longitude": 83.9778},
476
+ "Dumraon": {"latitude": 25.5541, "longitude": 84.1478},
477
+ "Chausa": {"latitude": 25.5241, "longitude": 83.9178},
478
+ "Simri": {"latitude": 25.6141, "longitude": 84.0478},
479
+ "Darbhanga": {"latitude": 26.1542, "longitude": 85.8978},
480
+ "Baheri": {"latitude": 26.0442, "longitude": 85.8378},
481
+ "Jale": {"latitude": 26.2042, "longitude": 85.8578},
482
+ "Benipur": {"latitude": 26.1142, "longitude": 85.9478},
483
+ "Motihari": {"latitude": 26.6484, "longitude": 84.9194},
484
+ "Raxaul": {"latitude": 26.9784, "longitude": 84.8494},
485
+ "Chakia": {"latitude": 26.4184, "longitude": 85.0494},
486
+ "Dhaka": {"latitude": 26.6784, "longitude": 85.1694},
487
+ "Gaya": {"latitude": 24.7955, "longitude": 85.0002},
488
+ "Bodh Gaya": {"latitude": 24.6955, "longitude": 84.9902},
489
+ "Tekari": {"latitude": 24.9455, "longitude": 85.0402},
490
+ "Sherghati": {"latitude": 24.5655, "longitude": 84.7902},
491
+ "Gopalganj": {"latitude": 26.4685, "longitude": 84.4388},
492
+ "Barauli": {"latitude": 26.3785, "longitude": 84.5788},
493
+ "Baikunthpur": {"latitude": 26.5285, "longitude": 84.3588},
494
+ "Kateya": {"latitude": 26.4285, "longitude": 84.6388},
495
+ "Jamui": {"latitude": 24.9272, "longitude": 86.2231},
496
+ "Jhajha": {"latitude": 24.7772, "longitude": 86.3731},
497
+ "Sikandra": {"latitude": 24.9672, "longitude": 86.0631},
498
+ "Sono": {"latitude": 24.8372, "longitude": 86.1431},
499
+ "Jehanabad": {"latitude": 25.2078, "longitude": 84.9869},
500
+ "Ghoshi": {"latitude": 25.1478, "longitude": 84.9269},
501
+ "Makhdumpur": {"latitude": 25.2478, "longitude": 85.0469},
502
+ "Modanganj": {"latitude": 25.2678, "longitude": 84.9069},
503
+ "Bhabua": {"latitude": 25.0405, "longitude": 83.6074},
504
+ "Mohania": {"latitude": 25.1305, "longitude": 83.4774},
505
+ "Ramgarh": {"latitude": 24.9505, "longitude": 83.6874},
506
+ "Chainpur": {"latitude": 25.2005, "longitude": 83.7474},
507
+ "Katihar": {"latitude": 25.5394, "longitude": 87.5839},
508
+ "Barsoi": {"latitude": 25.3794, "longitude": 87.8839},
509
+ "Manihari": {"latitude": 25.3394, "longitude": 87.6239},
510
+ "Pranpur": {"latitude": 25.6894, "longitude": 87.7239},
511
+ "Khagaria": {"latitude": 25.5022, "longitude": 86.4665},
512
+ "Parbatta": {"latitude": 25.5422, "longitude": 86.5865},
513
+ "Alauli": {"latitude": 25.4622, "longitude": 86.3465},
514
+ "Beldaur": {"latitude": 25.5622, "longitude": 86.4265},
515
+ "Kishanganj": {"latitude": 26.1046, "longitude": 87.9475},
516
+ "Bahadurganj": {"latitude": 26.2646, "longitude": 88.1175},
517
+ "Thakurganj": {"latitude": 26.0446, "longitude": 87.8275},
518
+ "Dighalbank": {"latitude": 25.9046, "longitude": 87.9875},
519
+ "Lakhisarai": {"latitude": 25.1678, "longitude": 86.0927},
520
+ "Halsi": {"latitude": 25.2278, "longitude": 86.0327},
521
+ "Suryagarha": {"latitude": 25.1078, "longitude": 86.1527},
522
+ "Pipariya": {"latitude": 25.2078, "longitude": 86.1327},
523
+ "Madhepura": {"latitude": 25.9207, "longitude": 86.7940},
524
+ "Udakishanganj": {"latitude": 25.9807, "longitude": 86.6740},
525
+ "Murliganj": {"latitude": 25.8907, "longitude": 86.9940},
526
+ "Alamnagar": {"latitude": 25.9607, "longitude": 86.7340},
527
+ "Madhubani": {"latitude": 26.3561, "longitude": 86.0644},
528
+ "Jhanjharpur": {"latitude": 26.2661, "longitude": 86.2844},
529
+ "Benipatti": {"latitude": 26.5961, "longitude": 86.1444},
530
+ "Jainagar": {"latitude": 26.2061, "longitude": 86.1644},
531
+ "Munger": {"latitude": 25.3753, "longitude": 86.4734},
532
+ "Jamalpur": {"latitude": 25.3153, "longitude": 86.4934},
533
+ "Asarganj": {"latitude": 25.1453, "longitude": 86.6834},
534
+ "Tarapur": {"latitude": 25.0253, "longitude": 86.6334},
535
+ "Muzaffarpur": {"latitude": 26.1225, "longitude": 85.3906},
536
+ "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806},
537
+ "Minapur": {"latitude": 26.0625, "longitude": 85.2906},
538
+ "Bochaha": {"latitude": 26.0025, "longitude": 85.5306},
539
+ "Bihar Sharif": {"latitude": 25.1979, "longitude": 85.5238},
540
+ "Rajgir": {"latitude": 25.0279, "longitude": 85.4238},
541
+ "Hilsa": {"latitude": 25.3179, "longitude": 85.2838},
542
+ "Biharsharif": {"latitude": 25.1979, "longitude": 85.5238},
543
+ "Nawada": {"latitude": 24.8834, "longitude": 85.5387},
544
+ "Rajauli": {"latitude": 25.0634, "longitude": 85.6387},
545
+ "Akbarpur": {"latitude": 24.8234, "longitude": 85.4587},
546
+ "Hisua": {"latitude": 24.8334, "longitude": 85.4187},
547
+ "Patna": {"latitude": 25.5941, "longitude": 85.1376},
548
+ "Danapur": {"latitude": 25.6341, "longitude": 85.0476},
549
+ "Fatuha": {"latitude": 25.5041, "longitude": 85.3076},
550
+ "Khagaul": {"latitude": 25.5741, "longitude": 85.0476},
551
+ "Purnia": {"latitude": 25.7771, "longitude": 87.4753},
552
+ "Dhamdaha": {"latitude": 25.8871, "longitude": 87.5853},
553
+ "Kasba": {"latitude": 25.8471, "longitude": 87.5353},
554
+ "Banmankhi": {"latitude": 25.8871, "longitude": 87.1953},
555
+ "Sasaram": {"latitude": 24.9520, "longitude": 84.0328},
556
+ "Dehri": {"latitude": 24.9020, "longitude": 84.1828},
557
+ "Bikramganj": {"latitude": 25.2120, "longitude": 84.2628},
558
+ "Nasriganj": {"latitude": 25.0520, "longitude": 84.1228},
559
+ "Saharsa": {"latitude": 25.8769, "longitude": 86.5956},
560
+ "Sonbarsa": {"latitude": 25.9269, "longitude": 86.7356},
561
+ "Simri Bakhtiarpur": {"latitude": 25.9569, "longitude": 86.3556},
562
+ "Mahishi": {"latitude": 25.9969, "longitude": 86.4756},
563
+ "Samastipur": {"latitude": 25.8647, "longitude": 85.7817},
564
+ "Rosera": {"latitude": 25.7947, "longitude": 85.9317},
565
+ "Dalsinghsarai": {"latitude": 25.6647, "longitude": 85.8317},
566
+ "Pusa": {"latitude": 25.9847, "longitude": 85.6717},
567
+ "Chapra": {"latitude": 25.7805, "longitude": 84.7477},
568
+ "Marhaura": {"latitude": 25.9705, "longitude": 84.8677},
569
+ "Amnour": {"latitude": 25.8905, "longitude": 84.9077},
570
+ "Sonepur": {"latitude": 25.6905, "longitude": 85.1777},
571
+ "Sheikhpura": {"latitude": 25.1391, "longitude": 85.8354},
572
+ "Barbigha": {"latitude": 25.2191, "longitude": 85.7354},
573
+ "Ariari": {"latitude": 25.0591, "longitude": 85.9554},
574
+ "Shekhopur": {"latitude": 25.1391, "longitude": 85.8354},
575
+ "Sheohar": {"latitude": 26.5184, "longitude": 85.2959},
576
+ "Dumri Katsari": {"latitude": 26.5784, "longitude": 85.1959},
577
+ "Piprahi": {"latitude": 26.4684, "longitude": 85.4159},
578
+ "Tariyani": {"latitude": 26.5584, "longitude": 85.2359},
579
+ "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806},
580
+ "Pupri": {"latitude": 26.4725, "longitude": 85.7006},
581
+ "Belsand": {"latitude": 26.4425, "longitude": 85.4006},
582
+ "Bathnaha": {"latitude": 26.5925, "longitude": 85.5306},
583
+ "Siwan": {"latitude": 26.2195, "longitude": 84.3564},
584
+ "Maharajganj": {"latitude": 26.1095, "longitude": 84.5064},
585
+ "Mairwa": {"latitude": 26.2295, "longitude": 84.1664},
586
+ "Darauli": {"latitude": 26.1595, "longitude": 84.1464},
587
+ "Supaul": {"latitude": 26.1260, "longitude": 86.6050},
588
+ "Nirmali": {"latitude": 26.3160, "longitude": 86.5850},
589
+ "Triveniganj": {"latitude": 26.2160, "longitude": 87.0250},
590
+ "Chhatapur": {"latitude": 26.2160, "longitude": 86.9050},
591
+ "Hajipur": {"latitude": 25.6851, "longitude": 85.2095},
592
+ "Mahua": {"latitude": 25.9651, "longitude": 85.2895},
593
+ "Lalganj": {"latitude": 25.8751, "longitude": 85.1695},
594
+ "Desri": {"latitude": 25.6051, "longitude": 85.4895},
595
+ "Bettiah": {"latitude": 26.8022, "longitude": 84.5025},
596
+ "Bagaha": {"latitude": 27.0922, "longitude": 84.0925},
597
+ "Narkatiaganj": {"latitude": 26.4322, "longitude": 84.7925},
598
+ "Lauriya": {"latitude": 26.9822, "longitude": 84.3125}
 
599
  }
600
 
601
 
602
+ # ============================================================================
603
+ # FASTAPI APP
604
+ # ============================================================================
605
+
606
+ app = FastAPI(title="Farmer.chat Alert Summary API")
607
+
608
+ # CORS middleware
609
+ app.add_middleware(
610
+ CORSMiddleware,
611
+ allow_origins=["*"],
612
+ allow_credentials=True,
613
+ allow_methods=["*"],
614
+ allow_headers=["*"],
615
+ )
616
+
617
+ # Initialize pipeline
618
+ openai_client = None
619
+ pipeline = None
620
+
621
+ @app.on_event("startup")
622
+ async def startup_event():
623
+ """Initialize OpenAI client and pipeline on startup"""
624
+ global openai_client, pipeline
625
+ try:
626
+ openai_client = get_openai_client()
627
+ DEFAULT_LOCATION = {"latitude": 25.5941, "longitude": 85.1376}
628
+ pipeline = FarmerChatPipeline(openai_client, DEFAULT_LOCATION)
629
+ print("✓ Pipeline initialized successfully")
630
+ except Exception as e:
631
+ print(f"✗ Pipeline initialization failed: {e}")
632
+ raise
633
+
634
+
635
+ # ============================================================================
636
+ # API MODELS
637
+ # ============================================================================
638
+
639
  class LocationRequest(BaseModel):
640
  location_name: str
641
  district: Optional[str] = None
 
644
  class AlertResponse(BaseModel):
645
  location: str
646
  coordinates: Dict[str, float]
647
+ district: Optional[str] = None
648
  alert_summary: str
649
  timestamp: str
 
650
 
651
 
652
+ # ============================================================================
653
+ # API ENDPOINTS
654
+ # ============================================================================
655
+
656
  @app.get("/")
657
  async def root():
658
+ """Root endpoint"""
659
  return {
660
  "message": "Farmer.chat Alert Summary API",
661
  "version": "1.0.0",
662
  "endpoints": {
663
+ "/locations": "GET - List all districts and villages",
664
+ "/generate-alert": "POST - Generate alert for location",
665
+ "/health": "GET - Health check"
666
  }
667
  }
668
 
669
 
670
+ @app.get("/health")
671
+ async def health_check():
672
+ """Health check endpoint"""
673
  return {
674
+ "status": "healthy",
675
+ "pipeline": "initialized" if pipeline else "not_initialized",
676
+ "timestamp": datetime.now().isoformat()
 
677
  }
678
 
679
 
680
+ @app.get("/locations")
681
+ async def get_locations():
682
+ """Get all districts and villages"""
683
+ return {"districts": BIHAR_DATA}
684
+
685
+
686
  @app.post("/generate-alert", response_model=AlertResponse)
687
  async def generate_alert(request: LocationRequest):
688
+ """Generate alert summary for selected location"""
689
+
690
+ if not pipeline:
691
+ raise HTTPException(status_code=500, detail="Pipeline not initialized")
692
+
693
+ # Find location coordinates
694
+ location_name = request.location_name.strip()
695
+ coordinates = None
696
+
697
+ # Case-insensitive search
698
+ for loc_key, loc_coords in LOCATIONS.items():
699
+ if loc_key.lower() == location_name.lower():
700
+ coordinates = loc_coords
701
+ break
702
+
703
+ if not coordinates:
704
+ raise HTTPException(
705
+ status_code=404,
706
+ detail=f"Location '{location_name}' not found in database"
707
+ )
708
+
709
+ # Update pipeline location
710
+ pipeline.location = coordinates
711
+
712
+ # Create comprehensive query for all MCP servers
713
+ query = f"""Generate a comprehensive agricultural alert summary for {location_name} covering:
714
+ 1. Current weather conditions and 7-day forecast
715
+ 2. Soil health analysis and fertilizer recommendations
716
+ 3. Groundwater availability and irrigation status
717
+ 4. Elevation and topography considerations for farming
718
+ 5. Current pest risks and preventive measures
719
+
720
+ Provide actionable insights for farmers."""
721
+
722
  try:
723
+ # Generate alert
724
+ alert_summary = pipeline.process_query(query)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725
 
726
  return AlertResponse(
727
+ location=location_name,
728
+ coordinates=coordinates,
729
+ district=request.district,
730
+ alert_summary=alert_summary,
731
+ timestamp=datetime.now().isoformat()
732
  )
733
+
 
 
734
  except Exception as e:
735
+ raise HTTPException(
736
+ status_code=500,
737
+ detail=f"Error generating alert: {str(e)}"
738
+ )
739
 
 
 
 
 
 
 
 
740
 
741
+ # ============================================================================
742
+ # RUN SERVER
743
+ # ============================================================================
744
 
745
  if __name__ == "__main__":
746
  import uvicorn