Chat-based interface for finding places and getting directions using Google Maps. Ask natural language questions like "Find sushi restaurants in Tokyo" or "How do I get from Times Square to Central Park?" and see results on an embedded map.
# Terminal 1: Start Ollama server
ollama serve
# Terminal 2: Pull and verify model
ollama pull phi3:mini# Navigate to project directory
cd llm-maps-assistant
# Activate virtual environment
source .venv/bin/activate
# Start backend server
uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 --reload# Open in browser
xdg-open frontend/public/chat.html
# Or manually open: frontend/public/chat.htmlTry these prompts:
- "Find sushi restaurants in Tokyo"
- "Show me coffee shops near Central Park"
- "How do I get from Times Square to Empire State Building?"
- "Directions from Brooklyn Bridge to Statue of Liberty by walking"
- Python 3.10+
- Ollama - For running local LLM (phi3:mini)
- Google Cloud project with: Places API, Directions API, Maps Embed API enabled
- Modern web browser (Chrome, Firefox, Safari)
-
Create
.envfile from.env.exampleand setGOOGLE_MAPS_API_KEY:cp .env.example .env # Edit .env and add your Google Maps API key -
Create virtual environment (if missing venv support:
sudo apt install -y python3-venv):python3 -m venv .venv && source .venv/bin/activate
-
Install dependencies:
pip install -r requirements.txt
-
Run backend:
uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 --reload
-
Open chat interface:
- Open
frontend/public/chat.htmlin your browser - Or run:
xdg-open frontend/public/chat.html
- Open
Just type what you're looking for:
- "Find pizza places in Manhattan"
- "Show me museums in Paris"
- "Coffee shops near Brooklyn Bridge"
Use natural language:
- "How do I get from A to B?"
- "Directions from Times Square to Central Park"
- "Show me the way from Brooklyn to Manhattan by walking"
Travel modes: walking, driving, bicycling, transit
- Chat (left): See place details, ratings, addresses
- Map (right): Interactive embedded Google Maps
- Open in Google Maps: Click link to open in full Google Maps app
The chat.html interface now uses Ollama (phi3:mini) for intelligent conversations:
- β Real LLM responses - Powered by phi3:mini local model
- β Natural language understanding - True conversational AI
- β Context awareness - Remembers conversation history
- β Automatic Maps integration - LLM calls Google Maps APIs
- β Split-screen view - Chat on the left, embedded Google Maps on the right
- β Quick prompts - Pre-built examples to get started
- β Typing indicator - Shows when LLM is thinking
- β Responsive design - Works on desktop and mobile
- You type your question in natural language
- Frontend sends message to backend
/api/llm/chatendpoint - Backend forwards to Ollama (phi3:mini) with system prompt
- LLM generates intelligent response
- Backend detects if Maps API call is needed (places/directions)
- Backend calls Google Maps APIs and enriches LLM response
- Frontend displays LLM response in chat + embedded map on right
- You can click "Open in Google Maps" for full navigation
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check |
| POST | /api/llm/chat |
Chat with LLM (main endpoint) |
| POST | /api/search |
Search for places |
| POST | /api/place |
Get place details |
| POST | /api/directions |
Get directions |
| GET | /api/embed/place/{place_id} |
Get embed URLs for place |
| GET | /api/embed/directions |
Get embed URLs for directions |
| GET | /docs |
Interactive API documentation (Swagger UI) |
Chat with LLM (Main Endpoint):
curl -X POST http://localhost:8000/api/llm/chat \
-H "Content-Type: application/json" \
-d '{"message": "Find sushi restaurants in Tokyo", "history": []}'Search Places (Direct):
curl -X POST http://localhost:8000/api/search \
-H "Content-Type: application/json" \
-d '{"query": "sushi near nyc", "location":"40.7,-74.0", "radius": 2000}'Get Place Embed:
curl http://localhost:8000/api/embed/place/ChIJN1t_tDeuEmsRUsoyG83frY4Get Directions:
curl "http://localhost:8000/api/embed/directions?origin=Times%20Square&destination=Central%20Park&mode=walking"- β
API key stored in
.envfile (server-side only) - β Never exposed to client/frontend
- β
.envin.gitignore - β
.env.exampleprovided as template
- β CORS protection with configurable allowed origins
- β Rate limiting enabled (60 requests/minute default)
- β Input validation via Pydantic schemas
- β Server-side API calls only
Required APIs:
- Places API (New)
- Directions API
- Maps Embed API
Recommended API Key Restrictions:
Application Restrictions:
- IP addresses: Your server IP
- HTTP referrers: http://localhost:*
API Restrictions:
- Restrict to: Places API, Directions API, Maps Embed API
Quotas:
- Set daily quota limits to prevent unexpected charges
- Monitor usage in Google Cloud Console
1. Health Check:
curl http://localhost:8000/health
# Expected: {"status":"ok"}2. Search Places:
curl -X POST http://localhost:8000/api/search \
-H "Content-Type: application/json" \
-d '{"query": "coffee shops in New York", "radius": 5000}'3. Test Embed URLs:
curl http://localhost:8000/api/embed/place/PLACE_ID_HERE1. Open Chat Interface:
xdg-open frontend/public/chat.html2. Test Place Search:
- Type: "Find sushi restaurants in Tokyo"
- Verify: Results appear with map on right side
3. Test Directions:
- Type: "How do I get from Times Square to Central Park by walking?"
- Verify: Route appears on map with travel mode
4. Test Quick Prompts:
- Click any quick prompt button
- Verify it auto-fills and sends the query
python3 verify_setup.py- Make sure backend is running on port 8000
- Check:
curl http://localhost:8000/health - Should return:
{"status":"ok"}
- Verify Google Maps API key is set in
.env - Check that Maps Embed API is enabled in Google Cloud Console
- Look for errors in browser console (F12)
- Verify "null" origin is in
allowed_origins(for file:// protocol)
- Activate virtual environment:
source .venv/bin/activate - Install dependencies:
pip install -r requirements.txt - Check
.envfile exists with valid API key - Check Python version:
python --version(should be 3.10+)
- Check browser console for JavaScript errors
- Verify backend API is accessible
- Test API directly with curl commands
- Adjust limits in
backend/app/config.py - Modify
ratelimit_requestsandratelimit_window_seconds
llm-maps-assistant/
βββ backend/
β βββ app/
β βββ main.py # FastAPI app, CORS, middleware
β βββ routes.py # API endpoints
β βββ google_maps.py # Google Maps client
β βββ config.py # Settings, environment vars
β βββ schemas.py # Pydantic models
β βββ rate_limit.py # Rate limiting config
β
βββ frontend/
β βββ public/
β βββ chat.html # Chat interface (MAIN UI)
β
βββ .env # API key (gitignored)
βββ .env.example # Template for API key
βββ requirements.txt # Python dependencies
βββ verify_setup.py # Setup verification script
βββ README.md # This file
Backend:
- Python 3.12
- FastAPI - Web framework
- Uvicorn - ASGI server
- httpx - Async HTTP client
- Pydantic - Data validation
- SlowAPI - Rate limiting
Frontend:
- HTML5 - Structure
- CSS3 - Styling with gradients and animations
- JavaScript (ES6+) - Logic and API calls
- No frameworks - Vanilla JS for simplicity
APIs:
- Google Places API (New) - Place search
- Google Directions API - Route calculation
- Google Maps Embed API - Map display
- ChatGPT-like interface for natural language interaction
- No actual LLM required - Simple intent detection
- Client-side JavaScript parses queries
- Can be opened directly in browser with
file://protocol - Split-screen view with embedded maps
- Direction keywords: "direction", "how to get", "from...to"
- Travel mode keywords: "walk", "drive", "bike", "transit", "bus", "train"
- Default behavior: If no direction keywords, treat as place search
- Parsing: Uses regex to extract origin/destination from natural language
- User types: "Find sushi restaurants in Tokyo"
- Interface detects search intent (no direction keywords)
- Calls backend
/api/searchwith query - Backend calls Google Places API
- Interface receives results, displays top result
- Calls
/api/embed/placewith place_id - Displays embedded map on right side
- Shows place details in chat with "Open in Google Maps" link
- User types: "How do I get from Times Square to Central Park?"
- Interface detects direction intent ("from...to" pattern)
- Parses origin and destination
- Detects travel mode from keywords (walking/driving/etc.)
- Calls
/api/embed/directionswith parameters - Displays route on embedded map
- Shows directions info in chat with external link
You: I'm hungry, find me a good burger place in NYC
Assistant: I found several great burger places! Here's the top result:
Shake Shack
π Madison Square Park, New York, NY
β Rating: 4.3/5
You can view it on the map here: [Open in Google Maps]
You: How do I get from Central Park to Times Square by walking?
Assistant: πΆ Here are directions from Central Park to Times Square by walking!
I've shown the route on the map. You can also [open it in Google Maps] for turn-by-turn navigation.
- Be specific: "Coffee shops in Brooklyn" works better than just "coffee"
- Use landmarks: "Near Times Square" or "Near Central Park"
- Specify travel mode: Add "by walking" or "by driving" for directions
- Try quick prompts: Click the suggestion buttons to see examples
Edit backend/app/config.py to adjust:
allowed_origins = [
"http://localhost:5173",
"http://localhost:3000",
"http://127.0.0.1:3000",
"null", # For file:// protocol
]
ratelimit_requests = 60
ratelimit_window_seconds = 60GOOGLE_MAPS_API_KEY=your_api_key_here
ENVIRONMENT=development- Caching - Redis for API response caching
- Authentication - User accounts and API keys
- Database - Store search history and favorites
- Real LLM - Integrate with Ollama/Open WebUI for smarter conversations
- Multi-language - Support for multiple languages
- Voice input - Speech-to-text for queries
- Favorites - Save favorite places
- Sharing - Share maps with others
- Docker - Containerize backend and frontend
- CI/CD - GitHub Actions for automated testing
- Monitoring - Prometheus + Grafana
- Logging - Structured logging with ELK stack
- CDN - CloudFlare for frontend assets
- Load balancing - Nginx for multiple backend instances
| Requirement | Status | Implementation |
|---|---|---|
| Local LLM interface | β | Chat interface with intent detection |
| Find places | β | Google Places API integration |
| Get directions | β | Google Directions API integration |
| Embedded maps | β | Google Maps Embed API |
| External links | β | "Open in Google Maps" buttons |
| Python backend | β | FastAPI with async/await |
| Security best practices | β | Server-side API key, CORS, rate limiting |
| Usage limits | β | Rate limiting, configurable quotas |
Status: β ALL REQUIREMENTS MET
Visit http://localhost:8000/docs for interactive API documentation (Swagger UI)
Run python3 verify_setup.py to check your setup
Built with β€οΈ in Indonesia
Last Updated: 2025-10-06