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"""
🗺️ Alle {len(locations)} Orte in Google Maps öffnen
Gefundene Orte:
{", ".join(location_names)}
""" else: map_html = """

⚠️ Keine spezifischen Orte gefunden.

""" else: map_html = """

ℹ️ Keine Kartendaten verfügbar.

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

Systemfehler: {str(e)}

""" 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()