SemanticRouting / app.py
mgokg's picture
Update app.py
2d04d45 verified
import os
import gradio as gr
from google import genai
from google.genai import types
from urllib.parse import quote
def search_with_maps(user_query):
try:
# Setup client with provided API key
# Note: This is the Gemini API Key (AI Studio)
client = genai.Client(api_key=os.environ.get("GEMINI_API_KEY"))
# Configure the Google Maps tool
config = types.GenerateContentConfig(
tools=[types.Tool(google_maps=types.GoogleMaps())]
)
# Generate content
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=f"antworte immer auf deutsch: {user_query}",
config=config
)
# Get the text response
response_text = response.text
# Extract grounding metadata (Maps sources)
map_html = ""
locations = []
# Check if we have valid grounding metadata
if (response.candidates[0].grounding_metadata and
response.candidates[0].grounding_metadata.grounding_chunks):
metadata = response.candidates[0].grounding_metadata
# Collect all locations
for chunk in metadata.grounding_chunks:
if chunk.maps:
locations.append({
'title': chunk.maps.title,
'uri': chunk.maps.uri
})
if locations:
# 1. Create the link for the Button (Opens in new tab)
# "maps/search" is perfect for the external link
location_names = [loc['title'] for loc in locations]
search_terms = " ".join(location_names) # Removing '|' often helps generic search
# External link URL
maps_external_url = f"https://www.google.com/maps/search/{quote(search_terms)}"
# 2. Create the URL for the Iframe (Embedding)
# Standard maps/search URLs get blocked by X-Frame-Options.
# OPTION A: Use Google Maps Embed API (Best for production)
# Requires a Google Cloud API Key with 'Maps Embed API' enabled.
maps_api_key = os.environ.get("GOOGLE_MAPS_API_KEY")
if maps_api_key:
# Search mode with API Key
embed_src = f"https://www.google.com/maps/embed/v1/search?key={maps_api_key}&q={quote(search_terms)}"
else:
# OPTION B: Legacy embedding (Free/No Key)
# We use maps.google.com with output=embed.
# Note: We prioritize the first location found for the embed preview
# because the legacy embed doesn't handle list searches well.
primary_location = locations[1]['title']
embed_src = f"https://maps.google.com/maps?q={quote(primary_location)}&t=&z=13&ie=UTF8&iwloc=&output=embed"
# Create HTML with embedded map and location list src="{embed_src}"
map_html = f"""
<div style="width: 100%; display: flex; flex-direction: column; gap: 10px;">
<iframe
src="{embed_src}"
width="100%"
height="450"
style="border:0; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade">
</iframe>
<a href="{maps_external_url}" target="_blank"
style="display: block; text-align: center; padding: 12px; background: #4a90e2; color: white;
text-decoration: none; border-radius: 6px; font-weight: bold;
transition: background 0.3s;">
🗺️ Alle {len(locations)} Orte in Google Maps öffnen
</a>
<div style="font-size: 0.9em; color: #666; background: #f5f5f5; padding: 10px; border-radius: 6px;">
<strong>Gefundene Orte:</strong><br>
{", ".join(location_names)}
</div>
</div>
"""
else:
map_html = """
<div style="padding: 20px; background: #fff3cd; border: 1px solid #ffc107; border-radius: 5px;">
<p style="margin: 0; color: #856404;">⚠️ Keine spezifischen Orte gefunden.</p>
</div>
"""
else:
map_html = """
<div style="padding: 20px; background: #f8f9fa; border: 1px solid #ddd; border-radius: 5px;">
<p style="margin: 0; color: #666;">ℹ️ Keine Kartendaten verfügbar.</p>
</div>
"""
return response_text, map_html
except Exception as e:
import traceback
traceback.print_exc() # Print full error to console for debugging
error_msg = f"❌ Error: {str(e)}"
error_html = f"""
<div style="padding: 20px; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 5px;">
<p style="margin: 0; color: #721c24;"><strong>Systemfehler:</strong> {str(e)}</p>
</div>
"""
return error_msg, error_html
# Create Gradio interface
with gr.Blocks(title="Gemini Maps Search", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🗺️ Gemini Maps Search")
with gr.Row():
sources_output = gr.HTML(label="📍 Karte")
with gr.Row():
response_output = gr.Markdown(label="🤖 Antwort")
with gr.Row():
query_input = gr.Textbox(
label="Suchanfrage",
placeholder="z.B. Zeige mir die besten Restaurants in Berlin Mitte",
lines=2
)
with gr.Row():
search_btn = gr.Button("🔍 Suchen", variant="primary")
# Set up the event handler
search_btn.click(
fn=search_with_maps,
inputs=query_input,
outputs=[response_output, sources_output]
)
query_input.submit(
fn=search_with_maps,
inputs=query_input,
outputs=[response_output, sources_output]
)
if __name__ == "__main__":
demo.launch()