Spaces:
Running
Running
fix (missing await in endpoint)
Browse files
app.py
CHANGED
|
@@ -752,10 +752,9 @@
|
|
| 752 |
# uvicorn.run(app, host="0.0.0.0", port=port)
|
| 753 |
|
| 754 |
|
| 755 |
-
|
| 756 |
"""
|
| 757 |
Farmer.chat Alert Summary Generator - FastAPI Application
|
| 758 |
-
|
| 759 |
"""
|
| 760 |
|
| 761 |
from fastapi import FastAPI, HTTPException
|
|
@@ -768,7 +767,7 @@ import os
|
|
| 768 |
# Import pipeline components
|
| 769 |
from src.pipeline import FarmerChatPipeline
|
| 770 |
|
| 771 |
-
# Import MCP servers
|
| 772 |
from src.servers.weather import WeatherServer
|
| 773 |
from src.servers.soil import SoilPropertiesServer
|
| 774 |
from src.servers.water import WaterServer
|
|
@@ -803,7 +802,7 @@ class QueryRequest(BaseModel):
|
|
| 803 |
|
| 804 |
|
| 805 |
# ============================================================================
|
| 806 |
-
# LOCATION DATA
|
| 807 |
# ============================================================================
|
| 808 |
|
| 809 |
BIHAR_DATA = {
|
|
@@ -1003,6 +1002,7 @@ LOCATIONS = {
|
|
| 1003 |
}
|
| 1004 |
|
| 1005 |
|
|
|
|
| 1006 |
# ============================================================================
|
| 1007 |
# FASTAPI APPLICATION
|
| 1008 |
# ============================================================================
|
|
@@ -1013,7 +1013,7 @@ app = FastAPI(
|
|
| 1013 |
version="2.0.0"
|
| 1014 |
)
|
| 1015 |
|
| 1016 |
-
# CORS configuration
|
| 1017 |
app.add_middleware(
|
| 1018 |
CORSMiddleware,
|
| 1019 |
allow_origins=["*"],
|
|
@@ -1032,24 +1032,24 @@ servers: Dict = {}
|
|
| 1032 |
|
| 1033 |
|
| 1034 |
# ============================================================================
|
| 1035 |
-
# STARTUP & SHUTDOWN
|
| 1036 |
# ============================================================================
|
| 1037 |
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
|
|
|
|
|
|
| 1041 |
global pipeline, servers
|
| 1042 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1043 |
try:
|
| 1044 |
-
print("\n" + "="*60)
|
| 1045 |
-
print("Initializing Farmer.chat Alert System")
|
| 1046 |
-
print("="*60 + "\n")
|
| 1047 |
-
|
| 1048 |
# Initialize MCP servers
|
| 1049 |
print("Initializing MCP servers...")
|
| 1050 |
-
|
| 1051 |
-
# Note: Your servers don't need arguments in their constructors
|
| 1052 |
-
# WaterServer hardcodes cache_dir internally
|
| 1053 |
servers = {
|
| 1054 |
"weather": WeatherServer(),
|
| 1055 |
"soil": SoilPropertiesServer(),
|
|
@@ -1057,11 +1057,10 @@ async def startup_event():
|
|
| 1057 |
"elevation": ElevationServer(),
|
| 1058 |
"pests": PestsServer()
|
| 1059 |
}
|
| 1060 |
-
|
| 1061 |
print("✓ All MCP servers initialized successfully\n")
|
| 1062 |
|
| 1063 |
# Initialize pipeline with default location (Patna)
|
| 1064 |
-
default_location =
|
| 1065 |
|
| 1066 |
pipeline = FarmerChatPipeline(
|
| 1067 |
servers=servers,
|
|
@@ -1075,12 +1074,29 @@ async def startup_event():
|
|
| 1075 |
except Exception as e:
|
| 1076 |
print(f"✗ Pipeline initialization failed: {str(e)}")
|
| 1077 |
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1078 |
|
| 1079 |
|
| 1080 |
-
|
| 1081 |
-
|
| 1082 |
-
"
|
| 1083 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1084 |
|
| 1085 |
|
| 1086 |
# ============================================================================
|
|
@@ -1094,13 +1110,11 @@ async def root():
|
|
| 1094 |
"service": "Farmer.chat Alert Summary Generator",
|
| 1095 |
"version": "2.0.0",
|
| 1096 |
"status": "operational",
|
| 1097 |
-
"architecture": "Modular MCP Pipeline",
|
| 1098 |
"endpoints": {
|
| 1099 |
-
"locations": "/locations
|
| 1100 |
-
"generate_alert": "/generate-alert
|
| 1101 |
-
"query": "/query
|
| 1102 |
-
"health": "/health
|
| 1103 |
-
"server_status": "/server-status - Check MCP server status"
|
| 1104 |
}
|
| 1105 |
}
|
| 1106 |
|
|
@@ -1119,22 +1133,9 @@ async def health_check():
|
|
| 1119 |
}
|
| 1120 |
|
| 1121 |
|
| 1122 |
-
@app.get("/server-status")
|
| 1123 |
-
async def server_status():
|
| 1124 |
-
"""Get status of all MCP servers"""
|
| 1125 |
-
if pipeline is None:
|
| 1126 |
-
raise HTTPException(status_code=503, detail="Pipeline not initialized")
|
| 1127 |
-
|
| 1128 |
-
status = pipeline.get_server_status()
|
| 1129 |
-
return {
|
| 1130 |
-
"servers": status,
|
| 1131 |
-
"timestamp": datetime.utcnow().isoformat()
|
| 1132 |
-
}
|
| 1133 |
-
|
| 1134 |
-
|
| 1135 |
@app.get("/locations")
|
| 1136 |
async def get_locations():
|
| 1137 |
-
"""Get all available
|
| 1138 |
return {
|
| 1139 |
"districts": BIHAR_DATA,
|
| 1140 |
"total_locations": len(LOCATIONS),
|
|
@@ -1146,33 +1147,30 @@ async def get_locations():
|
|
| 1146 |
async def generate_alert(request: LocationRequest):
|
| 1147 |
"""
|
| 1148 |
Generate comprehensive alert summary for a location.
|
| 1149 |
-
|
| 1150 |
-
Queries all MCP servers and compiles an actionable alert summary
|
| 1151 |
-
focusing on critical information and recommendations.
|
| 1152 |
"""
|
| 1153 |
-
|
| 1154 |
if pipeline is None:
|
| 1155 |
raise HTTPException(status_code=503, detail="Pipeline not initialized")
|
| 1156 |
|
| 1157 |
-
# Lookup location
|
| 1158 |
location_key = request.location_name.lower().strip()
|
| 1159 |
|
| 1160 |
if location_key not in LOCATIONS:
|
| 1161 |
-
# Try
|
| 1162 |
matches = [k for k in LOCATIONS.keys() if location_key in k.lower()]
|
| 1163 |
if matches:
|
| 1164 |
location_key = matches[0]
|
| 1165 |
else:
|
| 1166 |
raise HTTPException(
|
| 1167 |
status_code=404,
|
| 1168 |
-
detail=f"Location '{request.location_name}' not found
|
| 1169 |
)
|
| 1170 |
|
| 1171 |
coordinates = LOCATIONS[location_key]
|
| 1172 |
|
| 1173 |
try:
|
| 1174 |
-
#
|
| 1175 |
-
result = pipeline.generate_alert(
|
| 1176 |
location=coordinates,
|
| 1177 |
location_name=request.location_name
|
| 1178 |
)
|
|
@@ -1196,11 +1194,8 @@ async def generate_alert(request: LocationRequest):
|
|
| 1196 |
async def process_query(request: QueryRequest):
|
| 1197 |
"""
|
| 1198 |
Process a specific farmer query.
|
| 1199 |
-
|
| 1200 |
-
Queries all MCP servers and returns a response focusing on
|
| 1201 |
-
information relevant to the question.
|
| 1202 |
"""
|
| 1203 |
-
|
| 1204 |
if pipeline is None:
|
| 1205 |
raise HTTPException(status_code=503, detail="Pipeline not initialized")
|
| 1206 |
|
|
@@ -1216,8 +1211,8 @@ async def process_query(request: QueryRequest):
|
|
| 1216 |
location = LOCATIONS[matches[0]]
|
| 1217 |
|
| 1218 |
try:
|
| 1219 |
-
#
|
| 1220 |
-
result = pipeline.process_query(
|
| 1221 |
query=request.query,
|
| 1222 |
location=location
|
| 1223 |
)
|
|
@@ -1238,10 +1233,11 @@ async def process_query(request: QueryRequest):
|
|
| 1238 |
|
| 1239 |
|
| 1240 |
# ============================================================================
|
| 1241 |
-
# MAIN
|
| 1242 |
# ============================================================================
|
| 1243 |
|
| 1244 |
if __name__ == "__main__":
|
| 1245 |
import uvicorn
|
| 1246 |
-
|
|
|
|
| 1247 |
|
|
|
|
| 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
|
|
|
|
| 767 |
# Import pipeline components
|
| 768 |
from src.pipeline import FarmerChatPipeline
|
| 769 |
|
| 770 |
+
# Import MCP servers
|
| 771 |
from src.servers.weather import WeatherServer
|
| 772 |
from src.servers.soil import SoilPropertiesServer
|
| 773 |
from src.servers.water import WaterServer
|
|
|
|
| 802 |
|
| 803 |
|
| 804 |
# ============================================================================
|
| 805 |
+
# BIHAR LOCATION DATA
|
| 806 |
# ============================================================================
|
| 807 |
|
| 808 |
BIHAR_DATA = {
|
|
|
|
| 1002 |
}
|
| 1003 |
|
| 1004 |
|
| 1005 |
+
|
| 1006 |
# ============================================================================
|
| 1007 |
# FASTAPI APPLICATION
|
| 1008 |
# ============================================================================
|
|
|
|
| 1013 |
version="2.0.0"
|
| 1014 |
)
|
| 1015 |
|
| 1016 |
+
# CORS configuration - allow all for development
|
| 1017 |
app.add_middleware(
|
| 1018 |
CORSMiddleware,
|
| 1019 |
allow_origins=["*"],
|
|
|
|
| 1032 |
|
| 1033 |
|
| 1034 |
# ============================================================================
|
| 1035 |
+
# STARTUP & SHUTDOWN (using lifespan - modern FastAPI pattern)
|
| 1036 |
# ============================================================================
|
| 1037 |
|
| 1038 |
+
from contextlib import asynccontextmanager
|
| 1039 |
+
|
| 1040 |
+
@asynccontextmanager
|
| 1041 |
+
async def lifespan(app: FastAPI):
|
| 1042 |
+
"""Initialize on startup, cleanup on shutdown"""
|
| 1043 |
global pipeline, servers
|
| 1044 |
|
| 1045 |
+
# STARTUP
|
| 1046 |
+
print("\n" + "="*60)
|
| 1047 |
+
print("Initializing Farmer.chat Alert System")
|
| 1048 |
+
print("="*60 + "\n")
|
| 1049 |
+
|
| 1050 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1051 |
# Initialize MCP servers
|
| 1052 |
print("Initializing MCP servers...")
|
|
|
|
|
|
|
|
|
|
| 1053 |
servers = {
|
| 1054 |
"weather": WeatherServer(),
|
| 1055 |
"soil": SoilPropertiesServer(),
|
|
|
|
| 1057 |
"elevation": ElevationServer(),
|
| 1058 |
"pests": PestsServer()
|
| 1059 |
}
|
|
|
|
| 1060 |
print("✓ All MCP servers initialized successfully\n")
|
| 1061 |
|
| 1062 |
# Initialize pipeline with default location (Patna)
|
| 1063 |
+
default_location = {"latitude": 25.6093, "longitude": 85.1235}
|
| 1064 |
|
| 1065 |
pipeline = FarmerChatPipeline(
|
| 1066 |
servers=servers,
|
|
|
|
| 1074 |
except Exception as e:
|
| 1075 |
print(f"✗ Pipeline initialization failed: {str(e)}")
|
| 1076 |
raise
|
| 1077 |
+
|
| 1078 |
+
yield # Application runs here
|
| 1079 |
+
|
| 1080 |
+
# SHUTDOWN
|
| 1081 |
+
print("\nShutting down Farmer.chat Alert System...")
|
| 1082 |
|
| 1083 |
|
| 1084 |
+
# Apply lifespan to app
|
| 1085 |
+
app = FastAPI(
|
| 1086 |
+
title="Farmer.chat Alert Summary API",
|
| 1087 |
+
description="Agricultural intelligence system with alert-focused MCP pipeline",
|
| 1088 |
+
version="2.0.0",
|
| 1089 |
+
lifespan=lifespan
|
| 1090 |
+
)
|
| 1091 |
+
|
| 1092 |
+
# Re-add CORS after recreating app
|
| 1093 |
+
app.add_middleware(
|
| 1094 |
+
CORSMiddleware,
|
| 1095 |
+
allow_origins=["*"],
|
| 1096 |
+
allow_credentials=True,
|
| 1097 |
+
allow_methods=["*"],
|
| 1098 |
+
allow_headers=["*"],
|
| 1099 |
+
)
|
| 1100 |
|
| 1101 |
|
| 1102 |
# ============================================================================
|
|
|
|
| 1110 |
"service": "Farmer.chat Alert Summary Generator",
|
| 1111 |
"version": "2.0.0",
|
| 1112 |
"status": "operational",
|
|
|
|
| 1113 |
"endpoints": {
|
| 1114 |
+
"locations": "/locations",
|
| 1115 |
+
"generate_alert": "/generate-alert",
|
| 1116 |
+
"query": "/query",
|
| 1117 |
+
"health": "/health"
|
|
|
|
| 1118 |
}
|
| 1119 |
}
|
| 1120 |
|
|
|
|
| 1133 |
}
|
| 1134 |
|
| 1135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1136 |
@app.get("/locations")
|
| 1137 |
async def get_locations():
|
| 1138 |
+
"""Get all available locations"""
|
| 1139 |
return {
|
| 1140 |
"districts": BIHAR_DATA,
|
| 1141 |
"total_locations": len(LOCATIONS),
|
|
|
|
| 1147 |
async def generate_alert(request: LocationRequest):
|
| 1148 |
"""
|
| 1149 |
Generate comprehensive alert summary for a location.
|
| 1150 |
+
FIX: Now properly awaits the async pipeline method.
|
|
|
|
|
|
|
| 1151 |
"""
|
|
|
|
| 1152 |
if pipeline is None:
|
| 1153 |
raise HTTPException(status_code=503, detail="Pipeline not initialized")
|
| 1154 |
|
| 1155 |
+
# Lookup location (case-insensitive)
|
| 1156 |
location_key = request.location_name.lower().strip()
|
| 1157 |
|
| 1158 |
if location_key not in LOCATIONS:
|
| 1159 |
+
# Try partial match
|
| 1160 |
matches = [k for k in LOCATIONS.keys() if location_key in k.lower()]
|
| 1161 |
if matches:
|
| 1162 |
location_key = matches[0]
|
| 1163 |
else:
|
| 1164 |
raise HTTPException(
|
| 1165 |
status_code=404,
|
| 1166 |
+
detail=f"Location '{request.location_name}' not found"
|
| 1167 |
)
|
| 1168 |
|
| 1169 |
coordinates = LOCATIONS[location_key]
|
| 1170 |
|
| 1171 |
try:
|
| 1172 |
+
# FIX: AWAIT the async method!
|
| 1173 |
+
result = await pipeline.generate_alert(
|
| 1174 |
location=coordinates,
|
| 1175 |
location_name=request.location_name
|
| 1176 |
)
|
|
|
|
| 1194 |
async def process_query(request: QueryRequest):
|
| 1195 |
"""
|
| 1196 |
Process a specific farmer query.
|
| 1197 |
+
FIX: Now properly awaits the async pipeline method.
|
|
|
|
|
|
|
| 1198 |
"""
|
|
|
|
| 1199 |
if pipeline is None:
|
| 1200 |
raise HTTPException(status_code=503, detail="Pipeline not initialized")
|
| 1201 |
|
|
|
|
| 1211 |
location = LOCATIONS[matches[0]]
|
| 1212 |
|
| 1213 |
try:
|
| 1214 |
+
# FIX: AWAIT the async method!
|
| 1215 |
+
result = await pipeline.process_query(
|
| 1216 |
query=request.query,
|
| 1217 |
location=location
|
| 1218 |
)
|
|
|
|
| 1233 |
|
| 1234 |
|
| 1235 |
# ============================================================================
|
| 1236 |
+
# MAIN
|
| 1237 |
# ============================================================================
|
| 1238 |
|
| 1239 |
if __name__ == "__main__":
|
| 1240 |
import uvicorn
|
| 1241 |
+
port = int(os.getenv("PORT", 7860))
|
| 1242 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
| 1243 |
|