Spaces:
Sleeping
Sleeping
| # # """ | |
| # # Farmer.Chat Backend - FastAPI Application | |
| # # Deploy to Hugging Face Space: https://huggingface.co/spaces/aakashdg/farmer-chat-backend | |
| # # """ | |
| # # from fastapi import FastAPI, HTTPException | |
| # # from fastapi.middleware.cors import CORSMiddleware | |
| # # from fastapi.responses import FileResponse, JSONResponse | |
| # # from pydantic import BaseModel, Field | |
| # # from typing import Optional, Dict, Any | |
| # # import os | |
| # # import asyncio | |
| # # import time | |
| # # from datetime import datetime | |
| # # # Import pipeline components | |
| # # from src.pipeline import FarmerChatPipeline | |
| # # from src.pdf_generator import generate_pdf_report | |
| # # from openai import OpenAI | |
| # # import httpx | |
| # # # Initialize FastAPI | |
| # # app = FastAPI( | |
| # # title="Farmer.Chat Backend", | |
| # # description="Multi-stage MCP pipeline for agricultural intelligence", | |
| # # version="2.0.0" | |
| # # ) | |
| # # # CORS - Allow all origins for demo (restrict in production) | |
| # # app.add_middleware( | |
| # # CORSMiddleware, | |
| # # allow_origins=["*"], | |
| # # allow_credentials=True, | |
| # # allow_methods=["*"], | |
| # # allow_headers=["*"], | |
| # # ) | |
| # # # Initialize OpenAI client with FIXED httpx configuration | |
| # # OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") | |
| # # if not OPENAI_API_KEY: | |
| # # raise ValueError("OPENAI_API_KEY environment variable not set!") | |
| # # # FIX: Create httpx client without proxy support | |
| # # http_client = httpx.Client( | |
| # # timeout=httpx.Timeout(60.0), | |
| # # limits=httpx.Limits(max_keepalive_connections=5, max_connections=10) | |
| # # ) | |
| # # # Initialize OpenAI with custom http client (bypasses proxy issues) | |
| # # openai_client = OpenAI( | |
| # # api_key=OPENAI_API_KEY, | |
| # # http_client=http_client | |
| # # ) | |
| # # print("✅ OpenAI client initialized with custom httpx client") | |
| # # print(f" Model: gpt-4o") | |
| # # # Default location (Bangalore Agricultural Region) | |
| # # DEFAULT_LOCATION = { | |
| # # "name": "Bangalore Agricultural Region", | |
| # # "lat": 12.8716, | |
| # # "lon": 77.4946 | |
| # # } | |
| # # # Initialize pipeline | |
| # # pipeline = FarmerChatPipeline(openai_client, DEFAULT_LOCATION) | |
| # # # Request/Response Models | |
| # # class QueryRequest(BaseModel): | |
| # # query: str = Field(..., min_length=3, max_length=500, description="Farmer's question") | |
| # # location: Optional[Dict[str, Any]] = Field(None, description="Custom location (lat, lon, name)") | |
| # # class Config: | |
| # # json_schema_extra = { | |
| # # "example": { | |
| # # "query": "Should I plant rice today?", | |
| # # "location": { | |
| # # "name": "Bangalore", | |
| # # "lat": 12.8716, | |
| # # "lon": 77.4946 | |
| # # } | |
| # # } | |
| # # } | |
| # # class QueryResponse(BaseModel): | |
| # # success: bool | |
| # # query: str | |
| # # advice: str | |
| # # routing: Dict[str, Any] | |
| # # data: Dict[str, Any] | |
| # # execution_time_seconds: float | |
| # # timestamp: str | |
| # # # Health check | |
| # # @app.get("/") | |
| # # async def root(): | |
| # # return { | |
| # # "service": "Farmer.Chat Backend", | |
| # # "status": "operational", | |
| # # "version": "2.0.0", | |
| # # "endpoints": { | |
| # # "query": "/api/query", | |
| # # "health": "/api/health", | |
| # # "servers": "/api/servers" | |
| # # } | |
| # # } | |
| # # @app.get("/api/health") | |
| # # async def health_check(): | |
| # # """Health check endpoint""" | |
| # # return { | |
| # # "status": "healthy", | |
| # # "timestamp": datetime.now().isoformat(), | |
| # # "openai_configured": bool(OPENAI_API_KEY), | |
| # # "location": DEFAULT_LOCATION | |
| # # } | |
| # # @app.get("/api/servers") | |
| # # async def list_servers(): | |
| # # """List available MCP servers""" | |
| # # from src.executor import MCP_SERVER_REGISTRY | |
| # # return { | |
| # # "total_servers": len(MCP_SERVER_REGISTRY), | |
| # # "servers": MCP_SERVER_REGISTRY | |
| # # } | |
| # # @app.post("/api/query", response_model=QueryResponse) | |
| # # async def process_query(request: QueryRequest): | |
| # # """ | |
| # # Main query endpoint - processes farmer questions through MCP pipeline | |
| # # """ | |
| # # try: | |
| # # start_time = time.time() | |
| # # # Use custom location if provided, otherwise default | |
| # # location = request.location if request.location else DEFAULT_LOCATION | |
| # # # Update pipeline location if changed | |
| # # if request.location: | |
| # # pipeline.location = location | |
| # # # Process query through pipeline | |
| # # result = await pipeline.process_query(request.query, verbose=False) | |
| # # execution_time = time.time() - start_time | |
| # # return QueryResponse( | |
| # # success=True, | |
| # # query=request.query, | |
| # # advice=result["advice"], | |
| # # routing=result["routing"], | |
| # # data=result["compiled_data"], | |
| # # execution_time_seconds=round(execution_time, 2), | |
| # # timestamp=datetime.now().isoformat() | |
| # # ) | |
| # # except Exception as e: | |
| # # raise HTTPException(status_code=500, detail=str(e)) | |
| # # @app.post("/api/export-pdf") | |
| # # async def export_pdf(request: QueryRequest): | |
| # # """ | |
| # # Export query result as PDF | |
| # # """ | |
| # # try: | |
| # # # Process query | |
| # # result = await pipeline.process_query(request.query, verbose=False) | |
| # # # Generate PDF | |
| # # pdf_path = generate_pdf_report( | |
| # # query=request.query, | |
| # # advice=result["advice"], | |
| # # data=result["compiled_data"], | |
| # # location=pipeline.location | |
| # # ) | |
| # # # Return PDF file | |
| # # return FileResponse( | |
| # # pdf_path, | |
| # # media_type="application/pdf", | |
| # # filename=f"farmer-chat-report-{int(time.time())}.pdf" | |
| # # ) | |
| # # except Exception as e: | |
| # # raise HTTPException(status_code=500, detail=str(e)) | |
| # # # Error handlers | |
| # # @app.exception_handler(404) | |
| # # async def not_found_handler(request, exc): | |
| # # return JSONResponse( | |
| # # status_code=404, | |
| # # content={"error": "Endpoint not found", "path": str(request.url)} | |
| # # ) | |
| # # @app.exception_handler(500) | |
| # # async def server_error_handler(request, exc): | |
| # # return JSONResponse( | |
| # # status_code=500, | |
| # # content={"error": "Internal server error", "detail": str(exc)} | |
| # # ) | |
| # # if __name__ == "__main__": | |
| # # import uvicorn | |
| # # uvicorn.run(app, host="0.0.0.0", port=7860) | |
| # """ | |
| # Alert Summary Generator Backend - Standalone Version | |
| # FastAPI app with embedded pipeline and location data | |
| # """ | |
| # from fastapi import FastAPI, HTTPException | |
| # from fastapi.middleware.cors import CORSMiddleware | |
| # from pydantic import BaseModel | |
| # from typing import Optional, Dict, Any, List | |
| # import os | |
| # from datetime import datetime | |
| # from openai import OpenAI | |
| # import httpx | |
| # # ============================================================================ | |
| # # OPENAI CLIENT SETUP | |
| # # ============================================================================ | |
| # def get_openai_client(): | |
| # """Initialize OpenAI client with API key from environment""" | |
| # api_key = os.getenv("OPENAI_API_KEY") | |
| # if not api_key: | |
| # raise ValueError("OPENAI_API_KEY environment variable not set") | |
| # http_client = httpx.Client( | |
| # timeout=httpx.Timeout(60.0, connect=10.0), | |
| # limits=httpx.Limits(max_keepalive_connections=10, max_connections=20) | |
| # ) | |
| # return OpenAI(api_key=api_key, http_client=http_client) | |
| # # ============================================================================ | |
| # # PIPELINE COMPONENTS | |
| # # ============================================================================ | |
| # class QueryRouter: | |
| # """Routes queries to appropriate MCP servers""" | |
| # def __init__(self, client): | |
| # self.client = client | |
| # def route_query(self, query: str, location: Dict[str, float]) -> Dict[str, Any]: | |
| # """Determine which servers to call based on query""" | |
| # prompt = f"""Given the farmer query: "{query}" | |
| # Location: {location['latitude']}, {location['longitude']} | |
| # Determine which data sources are needed. Return JSON: | |
| # {{ | |
| # "weather": true/false, | |
| # "soil": true/false, | |
| # "water": true/false, | |
| # "elevation": true/false, | |
| # "pests": true/false | |
| # }}""" | |
| # response = self.client.chat.completions.create( | |
| # model="gpt-4", | |
| # messages=[{"role": "user", "content": prompt}], | |
| # temperature=0 | |
| # ) | |
| # # Parse routing decision | |
| # import json | |
| # try: | |
| # routing = json.loads(response.choices[0].message.content) | |
| # except: | |
| # # Default: query all servers for alerts | |
| # routing = { | |
| # "weather": True, | |
| # "soil": True, | |
| # "water": True, | |
| # "elevation": True, | |
| # "pests": True | |
| # } | |
| # return routing | |
| # class MCPExecutor: | |
| # """Executes parallel calls to MCP servers""" | |
| # def __init__(self, client): | |
| # self.client = client | |
| # def execute_parallel(self, routing: Dict[str, bool], location: Dict[str, float]) -> Dict[str, str]: | |
| # """Execute MCP server calls in parallel""" | |
| # results = {} | |
| # # Simulate MCP server calls (replace with actual server calls) | |
| # if routing.get("weather"): | |
| # results["weather"] = f"Weather data for {location['latitude']}, {location['longitude']}" | |
| # if routing.get("soil"): | |
| # results["soil"] = f"Soil data for {location['latitude']}, {location['longitude']}" | |
| # if routing.get("water"): | |
| # results["water"] = f"Water availability for {location['latitude']}, {location['longitude']}" | |
| # if routing.get("elevation"): | |
| # results["elevation"] = f"Elevation data for {location['latitude']}, {location['longitude']}" | |
| # if routing.get("pests"): | |
| # results["pests"] = f"Pest risk data for {location['latitude']}, {location['longitude']}" | |
| # return results | |
| # class ResponseCompiler: | |
| # """Compiles MCP results into coherent response""" | |
| # def __init__(self, client): | |
| # self.client = client | |
| # def compile_response(self, query: str, mcp_results: Dict[str, str], location: Dict[str, float]) -> str: | |
| # """Compile MCP results into final response""" | |
| # # Format MCP results for context | |
| # context = "\n\n".join([f"{k.upper()}: {v}" for k, v in mcp_results.items()]) | |
| # prompt = f"""You are an agricultural assistant. Compile this data into a comprehensive alert summary. | |
| # FARMER QUERY: {query} | |
| # LOCATION: {location['latitude']}, {location['longitude']} | |
| # DATA FROM SOURCES: | |
| # {context} | |
| # Provide a comprehensive agricultural alert covering: | |
| # 1. Current weather conditions and forecast | |
| # 2. Soil health and recommendations | |
| # 3. Water availability status | |
| # 4. Elevation/topography considerations | |
| # 5. Pest risks and preventive measures | |
| # Be specific, actionable, and farmer-friendly.""" | |
| # response = self.client.chat.completions.create( | |
| # model="gpt-4", | |
| # messages=[{"role": "user", "content": prompt}], | |
| # temperature=0.7 | |
| # ) | |
| # return response.choices[0].message.content | |
| # class HindiTranslator: | |
| # """Translates responses to Hindi""" | |
| # def __init__(self, client): | |
| # self.client = client | |
| # def translate(self, text: str, target_lang: str = "en") -> str: | |
| # """Translate text if needed""" | |
| # if target_lang == "en": | |
| # return text | |
| # # Add Hindi translation logic here | |
| # return text | |
| # class FarmerChatPipeline: | |
| # """Main pipeline orchestrating all stages""" | |
| # def __init__(self, client, location: Dict[str, float]): | |
| # self.client = client | |
| # self.location = location | |
| # self.router = QueryRouter(client) | |
| # self.executor = MCPExecutor(client) | |
| # self.compiler = ResponseCompiler(client) | |
| # self.translator = HindiTranslator(client) | |
| # def process_query(self, query: str, language: str = "en") -> str: | |
| # """Process query through full pipeline""" | |
| # # Stage 1: Route query | |
| # routing = self.router.route_query(query, self.location) | |
| # # Stage 2: Execute MCP calls | |
| # mcp_results = self.executor.execute_parallel(routing, self.location) | |
| # # Stage 3: Compile response | |
| # response = self.compiler.compile_response(query, mcp_results, self.location) | |
| # # Stage 4: Translate if needed | |
| # final_response = self.translator.translate(response, language) | |
| # return final_response | |
| # # ============================================================================ | |
| # # BIHAR LOCATION DATA | |
| # # ============================================================================ | |
| # BIHAR_DATA = { | |
| # "Araria": ["Araria", "Forbesganj", "Jokihat", "Raniganj"], | |
| # "Arwal": ["Arwal", "Kaler", "Karpi", "Kurtha"], | |
| # "Aurangabad": ["Aurangabad", "Daudnagar", "Obra", "Nabinagar"], | |
| # "Banka": ["Banka", "Amarpur", "Barahat", "Belhar"], | |
| # "Begusarai": ["Begusarai", "Bakhri", "Barauni", "Teghra"], | |
| # "Bhagalpur": ["Bhagalpur", "Sabour", "Nathnagar", "Kahalgaon"], | |
| # "Bhojpur": ["Arrah", "Jagdishpur", "Piro", "Shahpur"], | |
| # "Buxar": ["Buxar", "Dumraon", "Chausa", "Simri"], | |
| # "Darbhanga": ["Darbhanga", "Baheri", "Jale", "Benipur"], | |
| # "East Champaran": ["Motihari", "Raxaul", "Chakia", "Dhaka"], | |
| # "Gaya": ["Gaya", "Bodh Gaya", "Tekari", "Sherghati"], | |
| # "Gopalganj": ["Gopalganj", "Barauli", "Baikunthpur", "Kateya"], | |
| # "Jamui": ["Jamui", "Jhajha", "Sikandra", "Sono"], | |
| # "Jehanabad": ["Jehanabad", "Ghoshi", "Makhdumpur", "Modanganj"], | |
| # "Kaimur": ["Bhabua", "Mohania", "Ramgarh", "Chainpur"], | |
| # "Katihar": ["Katihar", "Barsoi", "Manihari", "Pranpur"], | |
| # "Khagaria": ["Khagaria", "Parbatta", "Alauli", "Beldaur"], | |
| # "Kishanganj": ["Kishanganj", "Bahadurganj", "Thakurganj", "Dighalbank"], | |
| # "Lakhisarai": ["Lakhisarai", "Halsi", "Suryagarha", "Pipariya"], | |
| # "Madhepura": ["Madhepura", "Udakishanganj", "Murliganj", "Alamnagar"], | |
| # "Madhubani": ["Madhubani", "Jhanjharpur", "Benipatti", "Jainagar"], | |
| # "Munger": ["Munger", "Jamalpur", "Asarganj", "Tarapur"], | |
| # "Muzaffarpur": ["Muzaffarpur", "Sitamarhi", "Minapur", "Bochaha"], | |
| # "Nalanda": ["Bihar Sharif", "Rajgir", "Hilsa", "Biharsharif"], | |
| # "Nawada": ["Nawada", "Rajauli", "Akbarpur", "Hisua"], | |
| # "Patna": ["Patna", "Danapur", "Fatuha", "Khagaul"], | |
| # "Purnia": ["Purnia", "Dhamdaha", "Kasba", "Banmankhi"], | |
| # "Rohtas": ["Sasaram", "Dehri", "Bikramganj", "Nasriganj"], | |
| # "Saharsa": ["Saharsa", "Sonbarsa", "Simri Bakhtiarpur", "Mahishi"], | |
| # "Samastipur": ["Samastipur", "Rosera", "Dalsinghsarai", "Pusa"], | |
| # "Saran": ["Chapra", "Marhaura", "Amnour", "Sonepur"], | |
| # "Sheikhpura": ["Sheikhpura", "Barbigha", "Ariari", "Shekhopur"], | |
| # "Sheohar": ["Sheohar", "Dumri Katsari", "Piprahi", "Tariyani"], | |
| # "Sitamarhi": ["Sitamarhi", "Pupri", "Belsand", "Bathnaha"], | |
| # "Siwan": ["Siwan", "Maharajganj", "Mairwa", "Darauli"], | |
| # "Supaul": ["Supaul", "Nirmali", "Triveniganj", "Chhatapur"], | |
| # "Vaishali": ["Hajipur", "Mahua", "Lalganj", "Desri"], | |
| # "West Champaran": ["Bettiah", "Bagaha", "Narkatiaganj", "Lauriya"] | |
| # } | |
| # LOCATIONS = { | |
| # "Araria": {"latitude": 26.1523, "longitude": 87.5167}, | |
| # "Forbesganj": {"latitude": 26.3023, "longitude": 87.2664}, | |
| # "Jokihat": {"latitude": 25.8998, "longitude": 87.2686}, | |
| # "Raniganj": {"latitude": 26.0537, "longitude": 87.5333}, | |
| # "Arwal": {"latitude": 25.2560, "longitude": 84.6819}, | |
| # "Kaler": {"latitude": 25.1960, "longitude": 84.6219}, | |
| # "Karpi": {"latitude": 25.2360, "longitude": 84.7019}, | |
| # "Kurtha": {"latitude": 25.3160, "longitude": 84.6619}, | |
| # "Aurangabad": {"latitude": 24.7521, "longitude": 84.3742}, | |
| # "Daudnagar": {"latitude": 25.0337, "longitude": 84.4007}, | |
| # "Obra": {"latitude": 24.9923, "longitude": 84.4342}, | |
| # "Nabinagar": {"latitude": 24.6087, "longitude": 84.1269}, | |
| # "Banka": {"latitude": 24.8893, "longitude": 86.9220}, | |
| # "Amarpur": {"latitude": 25.0393, "longitude": 86.9020}, | |
| # "Barahat": {"latitude": 24.8393, "longitude": 87.0020}, | |
| # "Belhar": {"latitude": 24.9393, "longitude": 86.9620}, | |
| # "Begusarai": {"latitude": 25.4182, "longitude": 86.1347}, | |
| # "Bakhri": {"latitude": 25.4582, "longitude": 86.0547}, | |
| # "Barauni": {"latitude": 25.4751, "longitude": 86.0458}, | |
| # "Teghra": {"latitude": 25.5082, "longitude": 85.9347}, | |
| # "Bhagalpur": {"latitude": 25.2425, "longitude": 86.9842}, | |
| # "Sabour": {"latitude": 25.2375, "longitude": 87.0542}, | |
| # "Nathnagar": {"latitude": 25.1225, "longitude": 87.0042}, | |
| # "Kahalgaon": {"latitude": 25.1925, "longitude": 87.2142}, | |
| # "Arrah": {"latitude": 25.5560, "longitude": 84.6631}, | |
| # "Jagdishpur": {"latitude": 25.4660, "longitude": 84.4231}, | |
| # "Piro": {"latitude": 25.3260, "longitude": 84.4031}, | |
| # "Shahpur": {"latitude": 25.6060, "longitude": 84.4031}, | |
| # "Buxar": {"latitude": 25.5641, "longitude": 83.9778}, | |
| # "Dumraon": {"latitude": 25.5541, "longitude": 84.1478}, | |
| # "Chausa": {"latitude": 25.5241, "longitude": 83.9178}, | |
| # "Simri": {"latitude": 25.6141, "longitude": 84.0478}, | |
| # "Darbhanga": {"latitude": 26.1542, "longitude": 85.8978}, | |
| # "Baheri": {"latitude": 26.0442, "longitude": 85.8378}, | |
| # "Jale": {"latitude": 26.2042, "longitude": 85.8578}, | |
| # "Benipur": {"latitude": 26.1142, "longitude": 85.9478}, | |
| # "Motihari": {"latitude": 26.6484, "longitude": 84.9194}, | |
| # "Raxaul": {"latitude": 26.9784, "longitude": 84.8494}, | |
| # "Chakia": {"latitude": 26.4184, "longitude": 85.0494}, | |
| # "Dhaka": {"latitude": 26.6784, "longitude": 85.1694}, | |
| # "Gaya": {"latitude": 24.7955, "longitude": 85.0002}, | |
| # "Bodh Gaya": {"latitude": 24.6955, "longitude": 84.9902}, | |
| # "Tekari": {"latitude": 24.9455, "longitude": 85.0402}, | |
| # "Sherghati": {"latitude": 24.5655, "longitude": 84.7902}, | |
| # "Gopalganj": {"latitude": 26.4685, "longitude": 84.4388}, | |
| # "Barauli": {"latitude": 26.3785, "longitude": 84.5788}, | |
| # "Baikunthpur": {"latitude": 26.5285, "longitude": 84.3588}, | |
| # "Kateya": {"latitude": 26.4285, "longitude": 84.6388}, | |
| # "Jamui": {"latitude": 24.9272, "longitude": 86.2231}, | |
| # "Jhajha": {"latitude": 24.7772, "longitude": 86.3731}, | |
| # "Sikandra": {"latitude": 24.9672, "longitude": 86.0631}, | |
| # "Sono": {"latitude": 24.8372, "longitude": 86.1431}, | |
| # "Jehanabad": {"latitude": 25.2078, "longitude": 84.9869}, | |
| # "Ghoshi": {"latitude": 25.1478, "longitude": 84.9269}, | |
| # "Makhdumpur": {"latitude": 25.2478, "longitude": 85.0469}, | |
| # "Modanganj": {"latitude": 25.2678, "longitude": 84.9069}, | |
| # "Bhabua": {"latitude": 25.0405, "longitude": 83.6074}, | |
| # "Mohania": {"latitude": 25.1305, "longitude": 83.4774}, | |
| # "Ramgarh": {"latitude": 24.9505, "longitude": 83.6874}, | |
| # "Chainpur": {"latitude": 25.2005, "longitude": 83.7474}, | |
| # "Katihar": {"latitude": 25.5394, "longitude": 87.5839}, | |
| # "Barsoi": {"latitude": 25.3794, "longitude": 87.8839}, | |
| # "Manihari": {"latitude": 25.3394, "longitude": 87.6239}, | |
| # "Pranpur": {"latitude": 25.6894, "longitude": 87.7239}, | |
| # "Khagaria": {"latitude": 25.5022, "longitude": 86.4665}, | |
| # "Parbatta": {"latitude": 25.5422, "longitude": 86.5865}, | |
| # "Alauli": {"latitude": 25.4622, "longitude": 86.3465}, | |
| # "Beldaur": {"latitude": 25.5622, "longitude": 86.4265}, | |
| # "Kishanganj": {"latitude": 26.1046, "longitude": 87.9475}, | |
| # "Bahadurganj": {"latitude": 26.2646, "longitude": 88.1175}, | |
| # "Thakurganj": {"latitude": 26.0446, "longitude": 87.8275}, | |
| # "Dighalbank": {"latitude": 25.9046, "longitude": 87.9875}, | |
| # "Lakhisarai": {"latitude": 25.1678, "longitude": 86.0927}, | |
| # "Halsi": {"latitude": 25.2278, "longitude": 86.0327}, | |
| # "Suryagarha": {"latitude": 25.1078, "longitude": 86.1527}, | |
| # "Pipariya": {"latitude": 25.2078, "longitude": 86.1327}, | |
| # "Madhepura": {"latitude": 25.9207, "longitude": 86.7940}, | |
| # "Udakishanganj": {"latitude": 25.9807, "longitude": 86.6740}, | |
| # "Murliganj": {"latitude": 25.8907, "longitude": 86.9940}, | |
| # "Alamnagar": {"latitude": 25.9607, "longitude": 86.7340}, | |
| # "Madhubani": {"latitude": 26.3561, "longitude": 86.0644}, | |
| # "Jhanjharpur": {"latitude": 26.2661, "longitude": 86.2844}, | |
| # "Benipatti": {"latitude": 26.5961, "longitude": 86.1444}, | |
| # "Jainagar": {"latitude": 26.2061, "longitude": 86.1644}, | |
| # "Munger": {"latitude": 25.3753, "longitude": 86.4734}, | |
| # "Jamalpur": {"latitude": 25.3153, "longitude": 86.4934}, | |
| # "Asarganj": {"latitude": 25.1453, "longitude": 86.6834}, | |
| # "Tarapur": {"latitude": 25.0253, "longitude": 86.6334}, | |
| # "Muzaffarpur": {"latitude": 26.1225, "longitude": 85.3906}, | |
| # "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806}, | |
| # "Minapur": {"latitude": 26.0625, "longitude": 85.2906}, | |
| # "Bochaha": {"latitude": 26.0025, "longitude": 85.5306}, | |
| # "Bihar Sharif": {"latitude": 25.1979, "longitude": 85.5238}, | |
| # "Rajgir": {"latitude": 25.0279, "longitude": 85.4238}, | |
| # "Hilsa": {"latitude": 25.3179, "longitude": 85.2838}, | |
| # "Biharsharif": {"latitude": 25.1979, "longitude": 85.5238}, | |
| # "Nawada": {"latitude": 24.8834, "longitude": 85.5387}, | |
| # "Rajauli": {"latitude": 25.0634, "longitude": 85.6387}, | |
| # "Akbarpur": {"latitude": 24.8234, "longitude": 85.4587}, | |
| # "Hisua": {"latitude": 24.8334, "longitude": 85.4187}, | |
| # "Patna": {"latitude": 25.5941, "longitude": 85.1376}, | |
| # "Danapur": {"latitude": 25.6341, "longitude": 85.0476}, | |
| # "Fatuha": {"latitude": 25.5041, "longitude": 85.3076}, | |
| # "Khagaul": {"latitude": 25.5741, "longitude": 85.0476}, | |
| # "Purnia": {"latitude": 25.7771, "longitude": 87.4753}, | |
| # "Dhamdaha": {"latitude": 25.8871, "longitude": 87.5853}, | |
| # "Kasba": {"latitude": 25.8471, "longitude": 87.5353}, | |
| # "Banmankhi": {"latitude": 25.8871, "longitude": 87.1953}, | |
| # "Sasaram": {"latitude": 24.9520, "longitude": 84.0328}, | |
| # "Dehri": {"latitude": 24.9020, "longitude": 84.1828}, | |
| # "Bikramganj": {"latitude": 25.2120, "longitude": 84.2628}, | |
| # "Nasriganj": {"latitude": 25.0520, "longitude": 84.1228}, | |
| # "Saharsa": {"latitude": 25.8769, "longitude": 86.5956}, | |
| # "Sonbarsa": {"latitude": 25.9269, "longitude": 86.7356}, | |
| # "Simri Bakhtiarpur": {"latitude": 25.9569, "longitude": 86.3556}, | |
| # "Mahishi": {"latitude": 25.9969, "longitude": 86.4756}, | |
| # "Samastipur": {"latitude": 25.8647, "longitude": 85.7817}, | |
| # "Rosera": {"latitude": 25.7947, "longitude": 85.9317}, | |
| # "Dalsinghsarai": {"latitude": 25.6647, "longitude": 85.8317}, | |
| # "Pusa": {"latitude": 25.9847, "longitude": 85.6717}, | |
| # "Chapra": {"latitude": 25.7805, "longitude": 84.7477}, | |
| # "Marhaura": {"latitude": 25.9705, "longitude": 84.8677}, | |
| # "Amnour": {"latitude": 25.8905, "longitude": 84.9077}, | |
| # "Sonepur": {"latitude": 25.6905, "longitude": 85.1777}, | |
| # "Sheikhpura": {"latitude": 25.1391, "longitude": 85.8354}, | |
| # "Barbigha": {"latitude": 25.2191, "longitude": 85.7354}, | |
| # "Ariari": {"latitude": 25.0591, "longitude": 85.9554}, | |
| # "Shekhopur": {"latitude": 25.1391, "longitude": 85.8354}, | |
| # "Sheohar": {"latitude": 26.5184, "longitude": 85.2959}, | |
| # "Dumri Katsari": {"latitude": 26.5784, "longitude": 85.1959}, | |
| # "Piprahi": {"latitude": 26.4684, "longitude": 85.4159}, | |
| # "Tariyani": {"latitude": 26.5584, "longitude": 85.2359}, | |
| # "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806}, | |
| # "Pupri": {"latitude": 26.4725, "longitude": 85.7006}, | |
| # "Belsand": {"latitude": 26.4425, "longitude": 85.4006}, | |
| # "Bathnaha": {"latitude": 26.5925, "longitude": 85.5306}, | |
| # "Siwan": {"latitude": 26.2195, "longitude": 84.3564}, | |
| # "Maharajganj": {"latitude": 26.1095, "longitude": 84.5064}, | |
| # "Mairwa": {"latitude": 26.2295, "longitude": 84.1664}, | |
| # "Darauli": {"latitude": 26.1595, "longitude": 84.1464}, | |
| # "Supaul": {"latitude": 26.1260, "longitude": 86.6050}, | |
| # "Nirmali": {"latitude": 26.3160, "longitude": 86.5850}, | |
| # "Triveniganj": {"latitude": 26.2160, "longitude": 87.0250}, | |
| # "Chhatapur": {"latitude": 26.2160, "longitude": 86.9050}, | |
| # "Hajipur": {"latitude": 25.6851, "longitude": 85.2095}, | |
| # "Mahua": {"latitude": 25.9651, "longitude": 85.2895}, | |
| # "Lalganj": {"latitude": 25.8751, "longitude": 85.1695}, | |
| # "Desri": {"latitude": 25.6051, "longitude": 85.4895}, | |
| # "Bettiah": {"latitude": 26.8022, "longitude": 84.5025}, | |
| # "Bagaha": {"latitude": 27.0922, "longitude": 84.0925}, | |
| # "Narkatiaganj": {"latitude": 26.4322, "longitude": 84.7925}, | |
| # "Lauriya": {"latitude": 26.9822, "longitude": 84.3125} | |
| # } | |
| # # ============================================================================ | |
| # # FASTAPI APP | |
| # # ============================================================================ | |
| # app = FastAPI(title="Farmer.chat Alert Summary API") | |
| # # CORS middleware | |
| # app.add_middleware( | |
| # CORSMiddleware, | |
| # allow_origins=["*"], | |
| # allow_credentials=True, | |
| # allow_methods=["*"], | |
| # allow_headers=["*"], | |
| # ) | |
| # # Initialize pipeline | |
| # openai_client = None | |
| # pipeline = None | |
| # @app.on_event("startup") | |
| # async def startup_event(): | |
| # """Initialize OpenAI client and pipeline on startup""" | |
| # global openai_client, pipeline | |
| # try: | |
| # openai_client = get_openai_client() | |
| # DEFAULT_LOCATION = {"latitude": 25.5941, "longitude": 85.1376} | |
| # pipeline = FarmerChatPipeline(openai_client, DEFAULT_LOCATION) | |
| # print("✓ Pipeline initialized successfully") | |
| # except Exception as e: | |
| # print(f"✗ Pipeline initialization failed: {e}") | |
| # raise | |
| # # ============================================================================ | |
| # # API MODELS | |
| # # ============================================================================ | |
| # class LocationRequest(BaseModel): | |
| # location_name: str | |
| # district: Optional[str] = None | |
| # class AlertResponse(BaseModel): | |
| # location: str | |
| # coordinates: Dict[str, float] | |
| # district: Optional[str] = None | |
| # alert_summary: str | |
| # timestamp: str | |
| # # ============================================================================ | |
| # # API ENDPOINTS | |
| # # ============================================================================ | |
| # @app.get("/") | |
| # async def root(): | |
| # """Root endpoint""" | |
| # return { | |
| # "message": "Farmer.chat Alert Summary API", | |
| # "version": "1.0.0", | |
| # "endpoints": { | |
| # "/locations": "GET - List all districts and villages", | |
| # "/generate-alert": "POST - Generate alert for location", | |
| # "/health": "GET - Health check" | |
| # } | |
| # } | |
| # @app.get("/health") | |
| # async def health_check(): | |
| # """Health check endpoint""" | |
| # return { | |
| # "status": "healthy", | |
| # "pipeline": "initialized" if pipeline else "not_initialized", | |
| # "timestamp": datetime.now().isoformat() | |
| # } | |
| # @app.get("/locations") | |
| # async def get_locations(): | |
| # """Get all districts and villages""" | |
| # return {"districts": BIHAR_DATA} | |
| # @app.post("/generate-alert", response_model=AlertResponse) | |
| # async def generate_alert(request: LocationRequest): | |
| # """Generate alert summary for selected location""" | |
| # if not pipeline: | |
| # raise HTTPException(status_code=500, detail="Pipeline not initialized") | |
| # # Find location coordinates | |
| # location_name = request.location_name.strip() | |
| # coordinates = None | |
| # # Case-insensitive search | |
| # for loc_key, loc_coords in LOCATIONS.items(): | |
| # if loc_key.lower() == location_name.lower(): | |
| # coordinates = loc_coords | |
| # break | |
| # if not coordinates: | |
| # raise HTTPException( | |
| # status_code=404, | |
| # detail=f"Location '{location_name}' not found in database" | |
| # ) | |
| # # Update pipeline location | |
| # pipeline.location = coordinates | |
| # # Create comprehensive query for all MCP servers | |
| # query = f"""Generate a comprehensive agricultural alert summary for {location_name} covering: | |
| # 1. Current weather conditions and 7-day forecast | |
| # 2. Soil health analysis and fertilizer recommendations | |
| # 3. Groundwater availability and irrigation status | |
| # 4. Elevation and topography considerations for farming | |
| # 5. Current pest risks and preventive measures | |
| # Provide actionable insights for farmers.""" | |
| # try: | |
| # # Generate alert | |
| # alert_summary = pipeline.process_query(query) | |
| # return AlertResponse( | |
| # location=location_name, | |
| # coordinates=coordinates, | |
| # district=request.district, | |
| # alert_summary=alert_summary, | |
| # timestamp=datetime.now().isoformat() | |
| # ) | |
| # except Exception as e: | |
| # raise HTTPException( | |
| # status_code=500, | |
| # detail=f"Error generating alert: {str(e)}" | |
| # ) | |
| # # ============================================================================ | |
| # # RUN SERVER | |
| # # ============================================================================ | |
| # if __name__ == "__main__": | |
| # import uvicorn | |
| # port = int(os.getenv("PORT", 7860)) | |
| # uvicorn.run(app, host="0.0.0.0", port=port) | |
| """ | |
| Farmer.chat Alert Summary Generator - FastAPI Application | |
| Modular architecture with alert-focused intelligence | |
| """ | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| from typing import Optional, Dict | |
| from datetime import datetime | |
| import os | |
| # Import pipeline components | |
| from src.pipeline import FarmerChatPipeline | |
| # Import MCP servers (assuming they exist in src/servers/) | |
| from src.servers.weather import WeatherServer | |
| from src.servers.soil import SoilPropertiesServer | |
| from src.servers.water import WaterServer | |
| from src.servers.elevation import ElevationServer | |
| from src.servers.pests import PestsServer | |
| # ============================================================================ | |
| # PYDANTIC MODELS | |
| # ============================================================================ | |
| class LocationRequest(BaseModel): | |
| """Request model for alert generation""" | |
| location_name: str | |
| district: Optional[str] = None | |
| class AlertResponse(BaseModel): | |
| """Response model for generated alerts""" | |
| location: str | |
| coordinates: Dict[str, float] | |
| district: Optional[str] | |
| alert_summary: str | |
| timestamp: str | |
| class QueryRequest(BaseModel): | |
| """Request model for specific queries""" | |
| query: str | |
| location_name: Optional[str] = None | |
| district: Optional[str] = None | |
| # ============================================================================ | |
| # LOCATION DATA | |
| # ============================================================================ | |
| BIHAR_DATA = { | |
| "Araria": ["Araria", "Forbesganj", "Jokihat", "Raniganj"], | |
| "Arwal": ["Arwal", "Kaler", "Karpi", "Kurtha"], | |
| "Aurangabad": ["Aurangabad", "Daudnagar", "Obra", "Nabinagar"], | |
| "Banka": ["Banka", "Amarpur", "Barahat", "Belhar"], | |
| "Begusarai": ["Begusarai", "Bakhri", "Barauni", "Teghra"], | |
| "Bhagalpur": ["Bhagalpur", "Sabour", "Nathnagar", "Kahalgaon"], | |
| "Bhojpur": ["Arrah", "Jagdishpur", "Piro", "Shahpur"], | |
| "Buxar": ["Buxar", "Dumraon", "Chausa", "Simri"], | |
| "Darbhanga": ["Darbhanga", "Baheri", "Jale", "Benipur"], | |
| "East Champaran": ["Motihari", "Raxaul", "Chakia", "Dhaka"], | |
| "Gaya": ["Gaya", "Bodh Gaya", "Tekari", "Sherghati"], | |
| "Gopalganj": ["Gopalganj", "Barauli", "Baikunthpur", "Kateya"], | |
| "Jamui": ["Jamui", "Jhajha", "Sikandra", "Sono"], | |
| "Jehanabad": ["Jehanabad", "Ghoshi", "Makhdumpur", "Modanganj"], | |
| "Kaimur": ["Bhabua", "Mohania", "Ramgarh", "Chainpur"], | |
| "Katihar": ["Katihar", "Barsoi", "Manihari", "Pranpur"], | |
| "Khagaria": ["Khagaria", "Parbatta", "Alauli", "Beldaur"], | |
| "Kishanganj": ["Kishanganj", "Bahadurganj", "Thakurganj", "Dighalbank"], | |
| "Lakhisarai": ["Lakhisarai", "Halsi", "Suryagarha", "Pipariya"], | |
| "Madhepura": ["Madhepura", "Udakishanganj", "Murliganj", "Alamnagar"], | |
| "Madhubani": ["Madhubani", "Jhanjharpur", "Benipatti", "Jainagar"], | |
| "Munger": ["Munger", "Jamalpur", "Asarganj", "Tarapur"], | |
| "Muzaffarpur": ["Muzaffarpur", "Sitamarhi", "Minapur", "Bochaha"], | |
| "Nalanda": ["Bihar Sharif", "Rajgir", "Hilsa", "Biharsharif"], | |
| "Nawada": ["Nawada", "Rajauli", "Akbarpur", "Hisua"], | |
| "Patna": ["Patna", "Danapur", "Fatuha", "Khagaul"], | |
| "Purnia": ["Purnia", "Dhamdaha", "Kasba", "Banmankhi"], | |
| "Rohtas": ["Sasaram", "Dehri", "Bikramganj", "Nasriganj"], | |
| "Saharsa": ["Saharsa", "Sonbarsa", "Simri Bakhtiarpur", "Mahishi"], | |
| "Samastipur": ["Samastipur", "Rosera", "Dalsinghsarai", "Pusa"], | |
| "Saran": ["Chapra", "Marhaura", "Amnour", "Sonepur"], | |
| "Sheikhpura": ["Sheikhpura", "Barbigha", "Ariari", "Shekhopur"], | |
| "Sheohar": ["Sheohar", "Dumri Katsari", "Piprahi", "Tariyani"], | |
| "Sitamarhi": ["Sitamarhi", "Pupri", "Belsand", "Bathnaha"], | |
| "Siwan": ["Siwan", "Maharajganj", "Mairwa", "Darauli"], | |
| "Supaul": ["Supaul", "Nirmali", "Triveniganj", "Chhatapur"], | |
| "Vaishali": ["Hajipur", "Mahua", "Lalganj", "Desri"], | |
| "West Champaran": ["Bettiah", "Bagaha", "Narkatiaganj", "Lauriya"] | |
| } | |
| LOCATIONS = { | |
| "Araria": {"latitude": 26.1523, "longitude": 87.5167}, | |
| "Forbesganj": {"latitude": 26.3023, "longitude": 87.2664}, | |
| "Jokihat": {"latitude": 25.8998, "longitude": 87.2686}, | |
| "Raniganj": {"latitude": 26.0537, "longitude": 87.5333}, | |
| "Arwal": {"latitude": 25.2560, "longitude": 84.6819}, | |
| "Kaler": {"latitude": 25.1960, "longitude": 84.6219}, | |
| "Karpi": {"latitude": 25.2360, "longitude": 84.7019}, | |
| "Kurtha": {"latitude": 25.3160, "longitude": 84.6619}, | |
| "Aurangabad": {"latitude": 24.7521, "longitude": 84.3742}, | |
| "Daudnagar": {"latitude": 25.0337, "longitude": 84.4007}, | |
| "Obra": {"latitude": 24.9923, "longitude": 84.4342}, | |
| "Nabinagar": {"latitude": 24.6087, "longitude": 84.1269}, | |
| "Banka": {"latitude": 24.8893, "longitude": 86.9220}, | |
| "Amarpur": {"latitude": 25.0393, "longitude": 86.9020}, | |
| "Barahat": {"latitude": 24.8393, "longitude": 87.0020}, | |
| "Belhar": {"latitude": 24.9393, "longitude": 86.9620}, | |
| "Begusarai": {"latitude": 25.4182, "longitude": 86.1347}, | |
| "Bakhri": {"latitude": 25.4582, "longitude": 86.0547}, | |
| "Barauni": {"latitude": 25.4751, "longitude": 86.0458}, | |
| "Teghra": {"latitude": 25.5082, "longitude": 85.9347}, | |
| "Bhagalpur": {"latitude": 25.2425, "longitude": 86.9842}, | |
| "Sabour": {"latitude": 25.2375, "longitude": 87.0542}, | |
| "Nathnagar": {"latitude": 25.1225, "longitude": 87.0042}, | |
| "Kahalgaon": {"latitude": 25.1925, "longitude": 87.2142}, | |
| "Arrah": {"latitude": 25.5560, "longitude": 84.6631}, | |
| "Jagdishpur": {"latitude": 25.4660, "longitude": 84.4231}, | |
| "Piro": {"latitude": 25.3260, "longitude": 84.4031}, | |
| "Shahpur": {"latitude": 25.6060, "longitude": 84.4031}, | |
| "Buxar": {"latitude": 25.5641, "longitude": 83.9778}, | |
| "Dumraon": {"latitude": 25.5541, "longitude": 84.1478}, | |
| "Chausa": {"latitude": 25.5241, "longitude": 83.9178}, | |
| "Simri": {"latitude": 25.6141, "longitude": 84.0478}, | |
| "Darbhanga": {"latitude": 26.1542, "longitude": 85.8978}, | |
| "Baheri": {"latitude": 26.0442, "longitude": 85.8378}, | |
| "Jale": {"latitude": 26.2042, "longitude": 85.8578}, | |
| "Benipur": {"latitude": 26.1142, "longitude": 85.9478}, | |
| "Motihari": {"latitude": 26.6484, "longitude": 84.9194}, | |
| "Raxaul": {"latitude": 26.9784, "longitude": 84.8494}, | |
| "Chakia": {"latitude": 26.4184, "longitude": 85.0494}, | |
| "Dhaka": {"latitude": 26.6784, "longitude": 85.1694}, | |
| "Gaya": {"latitude": 24.7955, "longitude": 85.0002}, | |
| "Bodh Gaya": {"latitude": 24.6955, "longitude": 84.9902}, | |
| "Tekari": {"latitude": 24.9455, "longitude": 85.0402}, | |
| "Sherghati": {"latitude": 24.5655, "longitude": 84.7902}, | |
| "Gopalganj": {"latitude": 26.4685, "longitude": 84.4388}, | |
| "Barauli": {"latitude": 26.3785, "longitude": 84.5788}, | |
| "Baikunthpur": {"latitude": 26.5285, "longitude": 84.3588}, | |
| "Kateya": {"latitude": 26.4285, "longitude": 84.6388}, | |
| "Jamui": {"latitude": 24.9272, "longitude": 86.2231}, | |
| "Jhajha": {"latitude": 24.7772, "longitude": 86.3731}, | |
| "Sikandra": {"latitude": 24.9672, "longitude": 86.0631}, | |
| "Sono": {"latitude": 24.8372, "longitude": 86.1431}, | |
| "Jehanabad": {"latitude": 25.2078, "longitude": 84.9869}, | |
| "Ghoshi": {"latitude": 25.1478, "longitude": 84.9269}, | |
| "Makhdumpur": {"latitude": 25.2478, "longitude": 85.0469}, | |
| "Modanganj": {"latitude": 25.2678, "longitude": 84.9069}, | |
| "Bhabua": {"latitude": 25.0405, "longitude": 83.6074}, | |
| "Mohania": {"latitude": 25.1305, "longitude": 83.4774}, | |
| "Ramgarh": {"latitude": 24.9505, "longitude": 83.6874}, | |
| "Chainpur": {"latitude": 25.2005, "longitude": 83.7474}, | |
| "Katihar": {"latitude": 25.5394, "longitude": 87.5839}, | |
| "Barsoi": {"latitude": 25.3794, "longitude": 87.8839}, | |
| "Manihari": {"latitude": 25.3394, "longitude": 87.6239}, | |
| "Pranpur": {"latitude": 25.6894, "longitude": 87.7239}, | |
| "Khagaria": {"latitude": 25.5022, "longitude": 86.4665}, | |
| "Parbatta": {"latitude": 25.5422, "longitude": 86.5865}, | |
| "Alauli": {"latitude": 25.4622, "longitude": 86.3465}, | |
| "Beldaur": {"latitude": 25.5622, "longitude": 86.4265}, | |
| "Kishanganj": {"latitude": 26.1046, "longitude": 87.9475}, | |
| "Bahadurganj": {"latitude": 26.2646, "longitude": 88.1175}, | |
| "Thakurganj": {"latitude": 26.0446, "longitude": 87.8275}, | |
| "Dighalbank": {"latitude": 25.9046, "longitude": 87.9875}, | |
| "Lakhisarai": {"latitude": 25.1678, "longitude": 86.0927}, | |
| "Halsi": {"latitude": 25.2278, "longitude": 86.0327}, | |
| "Suryagarha": {"latitude": 25.1078, "longitude": 86.1527}, | |
| "Pipariya": {"latitude": 25.2078, "longitude": 86.1327}, | |
| "Madhepura": {"latitude": 25.9207, "longitude": 86.7940}, | |
| "Udakishanganj": {"latitude": 25.9807, "longitude": 86.6740}, | |
| "Murliganj": {"latitude": 25.8907, "longitude": 86.9940}, | |
| "Alamnagar": {"latitude": 25.9607, "longitude": 86.7340}, | |
| "Madhubani": {"latitude": 26.3561, "longitude": 86.0644}, | |
| "Jhanjharpur": {"latitude": 26.2661, "longitude": 86.2844}, | |
| "Benipatti": {"latitude": 26.5961, "longitude": 86.1444}, | |
| "Jainagar": {"latitude": 26.2061, "longitude": 86.1644}, | |
| "Munger": {"latitude": 25.3753, "longitude": 86.4734}, | |
| "Jamalpur": {"latitude": 25.3153, "longitude": 86.4934}, | |
| "Asarganj": {"latitude": 25.1453, "longitude": 86.6834}, | |
| "Tarapur": {"latitude": 25.0253, "longitude": 86.6334}, | |
| "Muzaffarpur": {"latitude": 26.1225, "longitude": 85.3906}, | |
| "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806}, | |
| "Minapur": {"latitude": 26.0625, "longitude": 85.2906}, | |
| "Bochaha": {"latitude": 26.0025, "longitude": 85.5306}, | |
| "Bihar Sharif": {"latitude": 25.1979, "longitude": 85.5238}, | |
| "Rajgir": {"latitude": 25.0279, "longitude": 85.4238}, | |
| "Hilsa": {"latitude": 25.3179, "longitude": 85.2838}, | |
| "Biharsharif": {"latitude": 25.1979, "longitude": 85.5238}, | |
| "Nawada": {"latitude": 24.8834, "longitude": 85.5387}, | |
| "Rajauli": {"latitude": 25.0634, "longitude": 85.6387}, | |
| "Akbarpur": {"latitude": 24.8234, "longitude": 85.4587}, | |
| "Hisua": {"latitude": 24.8334, "longitude": 85.4187}, | |
| "Patna": {"latitude": 25.5941, "longitude": 85.1376}, | |
| "Danapur": {"latitude": 25.6341, "longitude": 85.0476}, | |
| "Fatuha": {"latitude": 25.5041, "longitude": 85.3076}, | |
| "Khagaul": {"latitude": 25.5741, "longitude": 85.0476}, | |
| "Purnia": {"latitude": 25.7771, "longitude": 87.4753}, | |
| "Dhamdaha": {"latitude": 25.8871, "longitude": 87.5853}, | |
| "Kasba": {"latitude": 25.8471, "longitude": 87.5353}, | |
| "Banmankhi": {"latitude": 25.8871, "longitude": 87.1953}, | |
| "Sasaram": {"latitude": 24.9520, "longitude": 84.0328}, | |
| "Dehri": {"latitude": 24.9020, "longitude": 84.1828}, | |
| "Bikramganj": {"latitude": 25.2120, "longitude": 84.2628}, | |
| "Nasriganj": {"latitude": 25.0520, "longitude": 84.1228}, | |
| "Saharsa": {"latitude": 25.8769, "longitude": 86.5956}, | |
| "Sonbarsa": {"latitude": 25.9269, "longitude": 86.7356}, | |
| "Simri Bakhtiarpur": {"latitude": 25.9569, "longitude": 86.3556}, | |
| "Mahishi": {"latitude": 25.9969, "longitude": 86.4756}, | |
| "Samastipur": {"latitude": 25.8647, "longitude": 85.7817}, | |
| "Rosera": {"latitude": 25.7947, "longitude": 85.9317}, | |
| "Dalsinghsarai": {"latitude": 25.6647, "longitude": 85.8317}, | |
| "Pusa": {"latitude": 25.9847, "longitude": 85.6717}, | |
| "Chapra": {"latitude": 25.7805, "longitude": 84.7477}, | |
| "Marhaura": {"latitude": 25.9705, "longitude": 84.8677}, | |
| "Amnour": {"latitude": 25.8905, "longitude": 84.9077}, | |
| "Sonepur": {"latitude": 25.6905, "longitude": 85.1777}, | |
| "Sheikhpura": {"latitude": 25.1391, "longitude": 85.8354}, | |
| "Barbigha": {"latitude": 25.2191, "longitude": 85.7354}, | |
| "Ariari": {"latitude": 25.0591, "longitude": 85.9554}, | |
| "Shekhopur": {"latitude": 25.1391, "longitude": 85.8354}, | |
| "Sheohar": {"latitude": 26.5184, "longitude": 85.2959}, | |
| "Dumri Katsari": {"latitude": 26.5784, "longitude": 85.1959}, | |
| "Piprahi": {"latitude": 26.4684, "longitude": 85.4159}, | |
| "Tariyani": {"latitude": 26.5584, "longitude": 85.2359}, | |
| "Sitamarhi": {"latitude": 26.5925, "longitude": 85.4806}, | |
| "Pupri": {"latitude": 26.4725, "longitude": 85.7006}, | |
| "Belsand": {"latitude": 26.4425, "longitude": 85.4006}, | |
| "Bathnaha": {"latitude": 26.5925, "longitude": 85.5306}, | |
| "Siwan": {"latitude": 26.2195, "longitude": 84.3564}, | |
| "Maharajganj": {"latitude": 26.1095, "longitude": 84.5064}, | |
| "Mairwa": {"latitude": 26.2295, "longitude": 84.1664}, | |
| "Darauli": {"latitude": 26.1595, "longitude": 84.1464}, | |
| "Supaul": {"latitude": 26.1260, "longitude": 86.6050}, | |
| "Nirmali": {"latitude": 26.3160, "longitude": 86.5850}, | |
| "Triveniganj": {"latitude": 26.2160, "longitude": 87.0250}, | |
| "Chhatapur": {"latitude": 26.2160, "longitude": 86.9050}, | |
| "Hajipur": {"latitude": 25.6851, "longitude": 85.2095}, | |
| "Mahua": {"latitude": 25.9651, "longitude": 85.2895}, | |
| "Lalganj": {"latitude": 25.8751, "longitude": 85.1695}, | |
| "Desri": {"latitude": 25.6051, "longitude": 85.4895}, | |
| "Bettiah": {"latitude": 26.8022, "longitude": 84.5025}, | |
| "Bagaha": {"latitude": 27.0922, "longitude": 84.0925}, | |
| "Narkatiaganj": {"latitude": 26.4322, "longitude": 84.7925}, | |
| "Lauriya": {"latitude": 26.9822, "longitude": 84.3125} | |
| } | |
| # ============================================================================ | |
| # FASTAPI APPLICATION | |
| # ============================================================================ | |
| app = FastAPI( | |
| title="Farmer.chat Alert Summary API", | |
| description="Agricultural intelligence system with alert-focused MCP pipeline", | |
| version="2.0.0" | |
| ) | |
| # CORS configuration | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # ============================================================================ | |
| # GLOBAL STATE | |
| # ============================================================================ | |
| pipeline: Optional[FarmerChatPipeline] = None | |
| servers: Dict = {} | |
| # ============================================================================ | |
| # STARTUP & SHUTDOWN | |
| # ============================================================================ | |
| async def startup_event(): | |
| """Initialize MCP servers and pipeline on startup""" | |
| global pipeline, servers | |
| try: | |
| print("\n" + "="*60) | |
| print("Initializing Farmer.chat Alert System") | |
| print("="*60 + "\n") | |
| # Initialize MCP servers | |
| print("Initializing MCP servers...") | |
| # Note: Your servers don't need arguments in their constructors | |
| # WaterServer hardcodes cache_dir internally | |
| servers = { | |
| "weather": WeatherServer(), | |
| "soil": SoilPropertiesServer(), | |
| "water": WaterServer(), | |
| "elevation": ElevationServer(), | |
| "pests": PestsServer() | |
| } | |
| print("✓ All MCP servers initialized successfully\n") | |
| # Initialize pipeline with default location (Patna) | |
| default_location = LOCATIONS.get("patna", {"latitude": 25.6093, "longitude": 85.1235}) | |
| pipeline = FarmerChatPipeline( | |
| servers=servers, | |
| location=default_location | |
| ) | |
| print("\n" + "="*60) | |
| print("✓ Farmer.chat Alert System Ready") | |
| print("="*60 + "\n") | |
| except Exception as e: | |
| print(f"✗ Pipeline initialization failed: {str(e)}") | |
| raise | |
| async def shutdown_event(): | |
| """Cleanup on shutdown""" | |
| print("\nShutting down Farmer.chat Alert System...") | |
| # ============================================================================ | |
| # API ENDPOINTS | |
| # ============================================================================ | |
| async def root(): | |
| """Root endpoint with API information""" | |
| return { | |
| "service": "Farmer.chat Alert Summary Generator", | |
| "version": "2.0.0", | |
| "status": "operational", | |
| "architecture": "Modular MCP Pipeline", | |
| "endpoints": { | |
| "locations": "/locations - Get all available locations", | |
| "generate_alert": "/generate-alert - Generate alert summary for location", | |
| "query": "/query - Process specific farmer query", | |
| "health": "/health - Health check", | |
| "server_status": "/server-status - Check MCP server status" | |
| } | |
| } | |
| async def health_check(): | |
| """Health check endpoint""" | |
| if pipeline is None: | |
| raise HTTPException(status_code=503, detail="Pipeline not initialized") | |
| return { | |
| "status": "healthy", | |
| "pipeline": "operational", | |
| "servers": len(servers), | |
| "timestamp": datetime.utcnow().isoformat() | |
| } | |
| async def server_status(): | |
| """Get status of all MCP servers""" | |
| if pipeline is None: | |
| raise HTTPException(status_code=503, detail="Pipeline not initialized") | |
| status = pipeline.get_server_status() | |
| return { | |
| "servers": status, | |
| "timestamp": datetime.utcnow().isoformat() | |
| } | |
| async def get_locations(): | |
| """Get all available districts and villages""" | |
| return { | |
| "districts": BIHAR_DATA, | |
| "total_locations": len(LOCATIONS), | |
| "coverage": "Bihar, India" | |
| } | |
| async def generate_alert(request: LocationRequest): | |
| """ | |
| Generate comprehensive alert summary for a location. | |
| Queries all MCP servers and compiles an actionable alert summary | |
| focusing on critical information and recommendations. | |
| """ | |
| if pipeline is None: | |
| raise HTTPException(status_code=503, detail="Pipeline not initialized") | |
| # Lookup location coordinates | |
| location_key = request.location_name.lower().strip() | |
| if location_key not in LOCATIONS: | |
| # Try case-insensitive partial match | |
| matches = [k for k in LOCATIONS.keys() if location_key in k.lower()] | |
| if matches: | |
| location_key = matches[0] | |
| else: | |
| raise HTTPException( | |
| status_code=404, | |
| detail=f"Location '{request.location_name}' not found in database" | |
| ) | |
| coordinates = LOCATIONS[location_key] | |
| try: | |
| # Generate alert using pipeline | |
| result = pipeline.generate_alert( | |
| location=coordinates, | |
| location_name=request.location_name | |
| ) | |
| return AlertResponse( | |
| location=request.location_name, | |
| coordinates=coordinates, | |
| district=request.district, | |
| alert_summary=result["alert_summary"], | |
| timestamp=datetime.utcnow().isoformat() | |
| ) | |
| except Exception as e: | |
| raise HTTPException( | |
| status_code=500, | |
| detail=f"Failed to generate alert: {str(e)}" | |
| ) | |
| async def process_query(request: QueryRequest): | |
| """ | |
| Process a specific farmer query. | |
| Queries all MCP servers and returns a response focusing on | |
| information relevant to the question. | |
| """ | |
| if pipeline is None: | |
| raise HTTPException(status_code=503, detail="Pipeline not initialized") | |
| # Determine location | |
| location = None | |
| if request.location_name: | |
| location_key = request.location_name.lower().strip() | |
| if location_key in LOCATIONS: | |
| location = LOCATIONS[location_key] | |
| else: | |
| matches = [k for k in LOCATIONS.keys() if location_key in k.lower()] | |
| if matches: | |
| location = LOCATIONS[matches[0]] | |
| try: | |
| # Process query through pipeline | |
| result = pipeline.process_query( | |
| query=request.query, | |
| location=location | |
| ) | |
| return { | |
| "query": request.query, | |
| "response": result["response"], | |
| "location": result["location"], | |
| "servers_queried": list(result["mcp_results"].keys()), | |
| "timestamp": datetime.utcnow().isoformat() | |
| } | |
| except Exception as e: | |
| raise HTTPException( | |
| status_code=500, | |
| detail=f"Failed to process query: {str(e)}" | |
| ) | |
| # ============================================================================ | |
| # MAIN (for local testing) | |
| # ============================================================================ | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=7680) | |