gaia_test_agent / app.py
Mehedi2's picture
Update app.py
f73d5ba verified
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)