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" | |
| } |