import os import requests import json import gradio as gr from typing import Dict, Any, Optional # Set your OpenRouter API key as environment variable # For Hugging Face Spaces, you'll add this as a secret OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY") or os.getenv("my_key") class OpenRouterLLM: def __init__(self, api_key: str, model: str = "deepseek/deepseek-v3.1-terminus"): self.api_key = api_key self.model = model self.base_url = "https://openrouter.ai/api/v1/chat/completions" def __call__(self, prompt: str, max_tokens: int = 1000, temperature: float = 0.3) -> str: """Make API call to OpenRouter with DeepSeek V3.1 Terminus""" if not self.api_key or not self.api_key.startswith('sk-or-v1-'): return "❌ Error: Invalid OpenRouter API key. Please configure your API key." headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", "HTTP-Referer": "https://huggingface.co/spaces/Mehedi2/Gaia-Test-Agent", "X-Title": "AI Navigation Agent" } payload = { "model": self.model, "messages": [ { "role": "system", "content": "You are a helpful navigation assistant. Provide clear, concise, and user-friendly route summaries." }, { "role": "user", "content": prompt } ], "temperature": temperature, "max_tokens": max_tokens, "top_p": 0.9 } try: response = requests.post( self.base_url, headers=headers, json=payload, timeout=30 ) if response.status_code == 401: return "❌ Error: Invalid API key or unauthorized." elif response.status_code == 402: return "❌ Error: Insufficient credits in OpenRouter account." elif response.status_code == 429: return "❌ Error: Rate limit exceeded. Please wait and try again." elif response.status_code != 200: return f"❌ Error: HTTP {response.status_code} - {response.text[:200]}" result = response.json() if "choices" in result and len(result["choices"]) > 0: return result["choices"][0]["message"]["content"].strip() else: return "❌ Error: No response content received." except requests.exceptions.Timeout: return "❌ Error: Request timeout. Please try again." except requests.exceptions.RequestException as e: return f"❌ Error calling OpenRouter API: {str(e)}" except Exception as e: return f"❌ Error: {str(e)}" def fetch_route_from_osrm(origin: str, destination: str) -> str: """Fetch route from OSRM API""" try: # Validate coordinates origin_parts = origin.split(',') dest_parts = destination.split(',') if len(origin_parts) != 2 or len(dest_parts) != 2: return "❌ Error: Coordinates must be in 'longitude,latitude' format" # Parse coordinates float(origin_parts[0]), float(origin_parts[1]) float(dest_parts[0]), float(dest_parts[1]) except (ValueError, IndexError): return "❌ Error: Invalid coordinate format" url = f"http://router.project-osrm.org/route/v1/driving/{origin};{destination}" params = { "overview": "false", "steps": "true", "geometries": "geojson" } try: response = requests.get(url, params=params, timeout=15) response.raise_for_status() data = response.json() if not data.get("routes") or len(data["routes"]) == 0: return "❌ No route found between the specified locations." route = data["routes"][0] total_distance_km = route.get("distance", 0) / 1000 total_duration_min = route.get("duration", 0) / 60 # Process turn-by-turn instructions instructions = [] step_number = 1 for leg in route["legs"]: for step in leg["steps"]: maneuver = step.get("maneuver", {}) step_type = maneuver.get("type", "continue") modifier = maneuver.get("modifier", "") road_name = step.get("name", "") distance_m = step.get("distance", 0) if distance_m < 10: continue instruction = f"{step_number}. " if step_type == "depart": direction = "Start your journey" if modifier: direction += f" heading {modifier}" if road_name: direction += f" on {road_name}" elif step_type == "arrive": instruction += "🎯 You have arrived at your destination!" instructions.append(instruction) break elif step_type == "turn": direction = f"Turn {modifier}" if modifier else "Turn" if road_name: direction += f" onto {road_name}" elif step_type == "merge": direction = f"Merge {modifier}" if modifier else "Merge" if road_name: direction += f" onto {road_name}" elif step_type == "continue": direction = "Continue straight" if road_name: direction += f" on {road_name}" else: direction = f"{step_type.replace('_', ' ').title()}" if modifier: direction += f" {modifier}" if road_name: direction += f" on {road_name}" if distance_m >= 100: if distance_m >= 1000: direction += f" for {distance_m/1000:.1f} km" else: direction += f" for {distance_m:.0f} meters" instruction += direction instructions.append(instruction) step_number += 1 route_summary = f"""📍 ROUTE SUMMARY 📊 Distance: {total_distance_km:.1f} km ⏱️ Estimated Time: {total_duration_min:.0f} minutes 🛣️ From: {origin} → To: {destination} 🧭 TURN-BY-TURN DIRECTIONS: {chr(10).join(instructions)} 💡 Total Steps: {len(instructions)} """ return route_summary.strip() except Exception as e: return f"❌ Error fetching route: {str(e)}" def navigate_with_ai(origin_lat, origin_lon, dest_lat, dest_lon, progress=gr.Progress()): """Main navigation function for Gradio interface""" progress(0, desc="Starting navigation...") # Validate inputs try: origin_lat = float(origin_lat) origin_lon = float(origin_lon) dest_lat = float(dest_lat) dest_lon = float(dest_lon) except (ValueError, TypeError): return "❌ Error: Please enter valid numeric coordinates." # Check coordinate ranges if not (-90 <= origin_lat <= 90) or not (-180 <= origin_lon <= 180): return "❌ Error: Origin coordinates out of valid range." if not (-90 <= dest_lat <= 90) or not (-180 <= dest_lon <= 180): return "❌ Error: Destination coordinates out of valid range." # Format coordinates origin = f"{origin_lon},{origin_lat}" destination = f"{dest_lon},{dest_lat}" progress(0.3, desc="Fetching route data...") # Get route from OSRM raw_route = fetch_route_from_osrm(origin, destination) if raw_route.startswith("❌"): return raw_route progress(0.7, desc="Generating AI summary...") # Check if API key is available if not OPENROUTER_API_KEY: return f"""⚠️ Warning: No API key configured. Showing raw route data: {raw_route} To get AI-enhanced summaries, please configure your OpenRouter API key in the Space settings.""" # Generate AI summary llm = OpenRouterLLM(api_key=OPENROUTER_API_KEY, model="deepseek/deepseek-v3.1-terminus") prompt = f""" Analyze this route information and create a helpful navigation summary: {raw_route} Please provide: 1. A brief overview of the journey 2. Simplified directions with key landmarks 3. Any important notes about the route 4. Travel tips if relevant Format your response to be clear and easy to follow. """ progress(0.9, desc="Finalizing response...") ai_summary = llm(prompt, max_tokens=1200, temperature=0.2) progress(1.0, desc="Complete!") return ai_summary # Predefined location examples LOCATION_EXAMPLES = { "Dhaka, Bangladesh": (23.8103, 90.4125), "Chittagong, Bangladesh": (22.3569, 91.7832), "London, UK": (51.5074, -0.1278), "New York, USA": (40.7128, -74.0060), "Paris, France": (48.8566, 2.3522), "Tokyo, Japan": (35.6762, 139.6503), "Sydney, Australia": (-33.8688, 151.2093) } def set_example_location(location_name, is_destination=False): """Set example location coordinates""" if location_name in LOCATION_EXAMPLES: lat, lon = LOCATION_EXAMPLES[location_name] return lat, lon return None, None # Create Gradio interface def create_gradio_app(): with gr.Blocks( title="🗺️ AI Navigation Agent", theme=gr.themes.Soft(), css=""" .main-header { text-align: center; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 10px; margin-bottom: 20px; } """ ) as app: gr.HTML("""

🗺️ AI Navigation Agent

Get AI-powered route planning with DeepSeek V3.1 Terminus

""") with gr.Row(): with gr.Column(): gr.Markdown("### 📍 Origin (Starting Point)") with gr.Row(): origin_lat = gr.Number( label="Latitude", placeholder="e.g., 23.8103", value=23.8103, precision=6 ) origin_lon = gr.Number( label="Longitude", placeholder="e.g., 90.4125", value=90.4125, precision=6 ) origin_examples = gr.Dropdown( choices=list(LOCATION_EXAMPLES.keys()), label="Or choose a preset location", value=None ) with gr.Column(): gr.Markdown("### 🎯 Destination (End Point)") with gr.Row(): dest_lat = gr.Number( label="Latitude", placeholder="e.g., 22.3569", value=22.3569, precision=6 ) dest_lon = gr.Number( label="Longitude", placeholder="e.g., 91.7832", value=91.7832, precision=6 ) dest_examples = gr.Dropdown( choices=list(LOCATION_EXAMPLES.keys()), label="Or choose a preset location", value=None ) with gr.Row(): clear_btn = gr.Button("🗑️ Clear", variant="secondary") navigate_btn = gr.Button("🧭 Get Navigation", variant="primary", size="lg") with gr.Row(): output = gr.Textbox( label="🗺️ Navigation Result", lines=20, placeholder="Your navigation instructions will appear here...", show_copy_button=True ) gr.Markdown(""" ### 💡 How to Use: 1. Enter latitude and longitude coordinates for origin and destination 2. Or use the dropdown to select preset locations 3. Click "Get Navigation" to generate AI-powered route instructions 4. The system uses OSRM for routing and DeepSeek V3.1 Terminus for summaries ### 📝 Coordinate Format: - Latitude: -90 to 90 (North/South) - Longitude: -180 to 180 (East/West) - Example: Dhaka is at 23.8103, 90.4125 ### 🔧 Features: - Real-time route calculation - AI-enhanced navigation summaries - Distance and time estimates - Turn-by-turn directions """) # Event handlers def set_origin_example(location): if location: lat, lon = set_example_location(location) return lat, lon return gr.update(), gr.update() def set_dest_example(location): if location: lat, lon = set_example_location(location) return lat, lon return gr.update(), gr.update() def clear_all(): return "", "", "", "", None, None, "" # Wire up events origin_examples.change( fn=set_origin_example, inputs=[origin_examples], outputs=[origin_lat, origin_lon] ) dest_examples.change( fn=set_dest_example, inputs=[dest_examples], outputs=[dest_lat, dest_lon] ) navigate_btn.click( fn=navigate_with_ai, inputs=[origin_lat, origin_lon, dest_lat, dest_lon], outputs=[output], show_progress=True ) clear_btn.click( fn=clear_all, outputs=[origin_lat, origin_lon, dest_lat, dest_lon, origin_examples, dest_examples, output] ) return app # Launch the app if __name__ == "__main__": app = create_gradio_app() # Check if running on Hugging Face Spaces if os.getenv("SPACE_ID"): # Running on HF Spaces app.launch( server_name="0.0.0.0", server_port=7860, show_api=False ) else: # Running locally app.launch( share=True, show_api=False ) import gradio as gr from gaia_api import app as gaia_app from app import run_agent # or correct import demo = gr.Interface(fn=run_agent, inputs="text", outputs="text") demo.launch(server_name="0.0.0.0", server_port=7860) demo.app.mount("/gaia", gaia_app)