Spaces:
Sleeping
Sleeping
| 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(""" | |
| <div class="main-header"> | |
| <h1>πΊοΈ AI Navigation Agent</h1> | |
| <p>Get AI-powered route planning with DeepSeek V3.1 Terminus</p> | |
| </div> | |
| """) | |
| 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) | |