Project Overview

GeoChat transcends standard chatbots by acting as an Agentic System. Instead of merely generating text, it converses with the user, detects spatial intents, and acts on them by calling an external geocoding tool (Nominatim). It seamlessly retrieves reliable $latitude$ and $longitude$ coordinates, stores them in the session state, and renders them as interactive markers on a Folium map embedded within the Streamlit UI.

Project Overview
Project Overview

Key Features & Capabilities

  • Tool-Calling (Function Calling): The LLM autonomously decides when to trigger the geocode function based on conversational context.
  • Context Memory Management: Implements an auto-trim and summarization mechanism. When the chat history exceeds 10 turns, the LLM compresses the history into a summary to prevent exceeding the context window limit.
  • Dynamic Folium Mapping: Renders a responsive Leaflet map in the Streamlit sidebar, dynamically injecting markers as the conversation evolves.
  • Geodesic Distance Filtering: Uses geopy to calculate the spatial distance between points, filtering out near-duplicates to avoid visual clutter on the map.

Theory: Function Calling & Deterministic Grounding

LLMs are inherently probabilistic and prone to hallucinating factual data like exact GPS coordinates. The Tool-Calling pattern solves this by transforming the LLM into an orchestrator. When the user asks "Where is Málaga?", the LLM outputs a structured JSON request matching the injected tool schema rather than attempting to guess the coordinates.

The system intercepts this request, queries the deterministic Nominatim API, and injects the JSON response back into the prompt as a tool message. This forces the LLM to ground its final natural language response in verified, real-world data.

Theory: Spatial Deduplication

To prevent the map from becoming unreadable when a user repeatedly asks about closely clustered locations, the system employs spatial deduplication. Before a new coordinate is appended to the map state, the system calculates the geodesic distance $d(p_1, p_2)$ between the new point $p_1$ and all existing points $p_2$ using the WGS-84 ellipsoid model.

If the distance is below a predefined threshold $epsilon$ (e.g., 2 kilometers), the new marker is discarded. This ensures high visual fidelity in the UI.

Execution Pipeline (ReAct Loop)

  1. User submits a natural language prompt via Streamlit.
  2. ask_llm is invoked with the System Prompt, Chat History, and the JSON Schema of available Tools.
  3. If the LLM detects a geographic entity, it halts generation and outputs a tool_call argument.
  4. execute_tools intercepts the call, parses the arguments, and fires an HTTP GET request to the Nominatim API.
  5. The Geocoder returns exact coordinates, which are appended to the message history as a tool response.
  6. The LLM resumes, generating a final, context-aware answer for the user.
  7. The Folium map re-renders, adding the new coordinate if it passes the geodesic distance filter.

Production Readiness & Suggested Improvements

  • API Caching (Redis/SQLite): Nominatim has strict rate limits (1 request/second). Implementing an LRU cache or local SQLite database for frequent queries (e.g., "Madrid", "New York") would drastically reduce external API latency.
  • Multi-Tool Expansion: Add additional tools like a Weather API or a Places API (Google/Yelp) so the agent can answer "Find me a cafe near my current location" and plot the results.
  • Vector Memory (RAG): Transition from naive "summarization pruning" to a proper Vector Database (like Qdrant or ChromaDB) for the chat history, allowing the agent to recall locations mentioned days or weeks ago seamlessly.