Spaces:
Sleeping
Sleeping
| # """ | |
| # Stage 1: Query Router - Intelligent Server Selection | |
| # """ | |
| # import json | |
| # from typing import Dict, Any | |
| # from openai import OpenAI | |
| # class QueryRouter: | |
| # """Stage 1: Routes queries to appropriate MCP servers""" | |
| # def __init__(self, client: OpenAI, registry: Dict[str, Any]): | |
| # self.client = client | |
| # self.registry = registry | |
| # def route(self, query: str, location: Dict[str, Any]) -> Dict[str, Any]: | |
| # """ | |
| # Analyze query and determine which MCP servers are needed | |
| # Returns: | |
| # { | |
| # "intent": str, | |
| # "required_servers": List[str], | |
| # "reasoning": str | |
| # } | |
| # """ | |
| # # Create registry summary | |
| # registry_text = "Available MCP Servers:\n" | |
| # for server_id, info in self.registry.items(): | |
| # registry_text += f"\n{server_id}:\n" | |
| # registry_text += f" Description: {info['description']}\n" | |
| # registry_text += f" Use for: {', '.join(info['use_for'][:5])}\n" | |
| # system_prompt = f"""You are a query router for Farmer.chat agricultural system. | |
| # Your task: Analyze the farmer's query and select which MCP servers are needed. | |
| # {registry_text} | |
| # Location: {location['name']} ({location['lat']}°N, {location['lon']}°E) | |
| # CRITICAL RULES: | |
| # 1. Select ALL servers that provide data relevant to answering the query completely | |
| # 2. Consider IMPLICIT needs - look for context clues in the query | |
| # 3. Keywords that trigger elevation: "elevation", "slope", "terrain", "my land", "my field", "drainage", "waterlogged", "frost risk", "wind exposure" | |
| # 4. For crop decisions: ALWAYS include soil_properties + water + weather (comprehensive assessment) | |
| # 5. For weather risk questions (wind, frost, flood): Include weather + elevation (terrain affects risk) | |
| # 6. For pest questions with weather context: Include pests + weather | |
| # 7. Be generous - better to have extra data than miss critical information | |
| # 8. When farmer mentions location characteristics (height, slope, elevation), ALWAYS include elevation | |
| # FEW-SHOT EXAMPLES: | |
| # Example 1: | |
| # Query: "Are strong winds expected at my land elevation?" | |
| # Required: ["weather", "elevation"] | |
| # Reasoning: Wind forecast from weather, but elevation affects wind exposure and risk. Farmer explicitly mentions elevation. | |
| # Example 2: | |
| # Query: "Should I plant rice today?" | |
| # Required: ["weather", "soil_properties", "water"] | |
| # Reasoning: Planting decisions need weather conditions, soil suitability, and water availability for comprehensive assessment. | |
| # Example 3: | |
| # Query: "Is there risk of frost tonight?" | |
| # Required: ["weather", "elevation"] | |
| # Reasoning: Frost risk depends on temperature from weather AND elevation (cold air sinks to lower areas). | |
| # Example 4: | |
| # Query: "What's my soil composition?" | |
| # Required: ["soil_properties"] | |
| # Reasoning: Direct soil query, only soil data needed. No implicit needs. | |
| # Example 5: | |
| # Query: "Can I grow tomatoes here?" | |
| # Required: ["soil_properties", "water", "weather"] | |
| # Reasoning: Crop suitability requires soil type, water availability, and climate conditions. | |
| # Example 6: | |
| # Query: "My field gets waterlogged after rain" | |
| # Required: ["elevation", "soil_properties", "weather"] | |
| # Reasoning: Waterlogging relates to drainage (elevation/slope), soil permeability, and rainfall patterns. | |
| # Example 7: | |
| # Query: "Should I spray pesticides now?" | |
| # Required: ["pests", "weather"] | |
| # Reasoning: Need to know pest presence AND weather conditions for optimal application timing. | |
| # Example 8: | |
| # Query: "How's the weather?" | |
| # Required: ["weather"] | |
| # Reasoning: Direct weather query, no implicit needs. | |
| # Example 9: | |
| # Query: "Give me complete farm status" | |
| # Required: ["weather", "soil_properties", "water", "elevation", "pests"] | |
| # Reasoning: Comprehensive assessment requires all available data sources. | |
| # Example 10: | |
| # Query: "Will it be too windy on my elevated farm?" | |
| # Required: ["weather", "elevation"] | |
| # Reasoning: Wind from weather, elevation affects exposure. "Elevated" is explicit context clue. | |
| # Response format (JSON only): | |
| # {{ | |
| # "intent": "brief description of farmer's need", | |
| # "required_servers": ["server_id1", "server_id2"], | |
| # "reasoning": "why these servers" | |
| # }} | |
| # """ | |
| # try: | |
| # response = self.client.chat.completions.create( | |
| # model="gpt-4o", | |
| # messages=[ | |
| # {"role": "system", "content": system_prompt}, | |
| # {"role": "user", "content": query} | |
| # ], | |
| # temperature=0.3 | |
| # ) | |
| # result_text = response.choices[0].message.content.strip() | |
| # result_text = result_text.replace("```json", "").replace("```", "").strip() | |
| # routing_decision = json.loads(result_text) | |
| # return routing_decision | |
| # except Exception as e: | |
| # print(f"❌ Routing error: {e}") | |
| # # Fallback - include common servers | |
| # return { | |
| # "intent": "general_inquiry", | |
| # "required_servers": ["weather", "soil_properties", "water"], | |
| # "reasoning": "Fallback routing due to error" | |
| # } | |
| """ | |
| Query Router - Stage 1 | |
| Simple router that always queries all MCP servers for alert generation. | |
| The intelligence is in the compiler, not the router. | |
| """ | |
| from typing import Dict, Any | |
| class QueryRouter: | |
| """ | |
| Router for alert generation system. | |
| For alert generation, ALWAYS queries all MCP servers since we need | |
| comprehensive data to identify potential issues. The compiler handles | |
| the intelligence of extracting only alerting/concerning information. | |
| """ | |
| def __init__(self): | |
| """Initialize router - no LLM needed for simple all-server routing""" | |
| pass | |
| def route_alert_query(self, location: Dict[str, float]) -> Dict[str, bool]: | |
| """ | |
| Route for alert generation - always query ALL servers. | |
| Args: | |
| location: Dict with 'latitude' and 'longitude' keys | |
| Returns: | |
| Dict with all servers set to True | |
| """ | |
| return { | |
| "weather": True, | |
| "soil": True, | |
| "water": True, | |
| "elevation": True, | |
| "pests": True | |
| } | |
| def route_query(self, query: str, location: Dict[str, float]) -> Dict[str, bool]: | |
| """ | |
| Route a general query - for now, also queries all servers. | |
| In the future, could use LLM to determine which servers are relevant | |
| to the specific query. But for alert generation, we always want all data. | |
| Args: | |
| query: User's query | |
| location: Dict with 'latitude' and 'longitude' keys | |
| Returns: | |
| Dict indicating which servers to query | |
| """ | |
| # For now, query all servers for any query | |
| # The compiler will extract relevant information | |
| return self.route_alert_query(location) |