Spaces:
Sleeping
title: Roam
colorFrom: blue
colorTo: purple
sdk: docker
pinned: false
roam
An AI-powered travel itinerary generator. Give it a destination, trip duration, transport mode, and your interests β it returns a day-by-day itinerary with stops ordered to minimize travel time.
Most "AI" travel apps are LLM wrappers: prompt GPT, display output. Roam builds the actual ML stack underneath.
How it works
User Input (destination, days, transport, goals)
β
βΌ
βββββββββββββββββββ
β RAG Retrieval β β FAISS vector search over scraped Wikivoyage + Reddit content
β β sentence-transformers (all-MiniLM-L6-v2) embeddings
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β POI Fetcher β β Overpass API (OpenStreetMap) β local places only, chains filtered
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β Preference β β LightGBM LambdaRank model trained on (goal, POI, relevance) triplets
β Ranker β 8 features: semantic similarity + category match signals
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β VRP Optimizer β β OR-Tools TSP with time windows β minimizes daily travel time
β β Assigns POIs across days, respects 10hr daily budget
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β LLM Synthesis β β Groq (Llama 3.3 70B) generates natural language itinerary
β β from optimized route + retrieved travel context
ββββββββββ¬βββββββββ
β
βΌ
Mobile App (React Native + MapLibre)
ML Components
1. RAG Pipeline (backend/ml/rag/)
Retrieval-Augmented Generation over real travel content β not just prompting an LLM blind.
- Scrapes Wikivoyage travel guides + Reddit trip reports per destination
- Chunks text into overlapping 512-word windows
- Embeds with
sentence-transformers/all-MiniLM-L6-v2(384-dim, runs locally) - Stores in FAISS flat index (cosine similarity via inner product on normalized vectors)
- At query time, retrieves top-5 semantically relevant chunks to ground the LLM
2. Learning-to-Rank (backend/ml/ranker/)
A trained model that scores POIs against user goals β not keyword matching.
- Features: cosine similarity between goal embedding and POI description, category match signals (food/nature/history/nightlife), name specificity, tag richness
- Model: LightGBM with
lambdarankobjective β the same ranking approach used in production search engines (NDCG-optimized) - Training data: synthetic (goal, POI list, relevance scores) scenarios covering 5 travel styles
- Feedback hook: stubbed for online learning β thumbs up/down signals can trigger incremental retraining
3. VRP Route Optimizer (backend/ml/optimizer/)
Formulates itinerary generation as a constrained Vehicle Routing Problem β not just sorting by distance.
- Builds NxN travel time matrix (OpenRouteService API, Haversine fallback)
- Solves TSP per day using OR-Tools with time windows (opening hours) and visit duration constraints
- Greedy day assignment: spreads ranked POIs across trip days respecting 10-hour daily budget
- Returns estimated arrival times per stop
Stack
| Layer | Tech |
|---|---|
| Mobile | React Native (Expo) + MapLibre |
| Backend | Python + FastAPI |
| Embeddings | sentence-transformers (all-MiniLM-L6-v2) |
| Vector Store | FAISS |
| Ranking | LightGBM LambdaRank |
| Route Optimization | Google OR-Tools (TSP/VRP) |
| LLM | Groq API (Llama 3.3 70B) |
| POI Data | OpenStreetMap / Overpass API |
| Routing | OpenRouteService |
| Geocoding | Nominatim |
Everything except Groq is free and open source. Groq has a free tier.
Project Structure
roam/
βββ backend/
β βββ api/
β β βββ routes.py # FastAPI endpoints β wires full pipeline
β βββ ml/
β β βββ rag/
β β β βββ scraper.py # Wikivoyage + Reddit scraper
β β β βββ chunker.py # Overlapping text chunker
β β β βββ embedder.py # sentence-transformers encoding
β β β βββ vector_store.py # FAISS index build/save/load
β β β βββ retriever.py # Query-time retrieval
β β β βββ build_pipeline.py # One-shot index builder
β β βββ ranker/
β β β βββ features.py # Feature extraction (embeddings + metadata)
β β β βββ model.py # LightGBM LambdaRank model
β β β βββ trainer.py # Training on synthetic data
β β β βββ scorer.py # Runtime scoring + feedback hook
β β βββ optimizer/
β β βββ distance.py # Travel time matrix (ORS + Haversine fallback)
β β βββ vrp.py # OR-Tools TSP solver with time windows
β β βββ scheduler.py # Day assignment + route optimization
β βββ services/
β β βββ overpass.py # OSM POI fetcher (chains filtered)
β β βββ nominatim.py # Geocoding
β β βββ groq_client.py # LLM synthesis
β βββ main.py
βββ mobile/
β βββ app/
β β βββ index.tsx # Home screen (trip input)
β β βββ itinerary.tsx # Results screen (list + map view)
β βββ services/
β βββ api.ts # Typed API client
βββ data/ # FAISS index + trained model (gitignored)
Setup
Backend
cd roam
python3 -m venv .venv && source .venv/bin/activate
pip install -r backend/requirements.txt
# Add your Groq API key (free at console.groq.com)
cp backend/.env.example backend/.env
# Edit backend/.env and set GROQ_API_KEY
# Build RAG index (scrapes + embeds ~8 cities, takes ~5 min)
python -m backend.ml.rag.build_pipeline
# Train the ranker
python -m backend.ml.ranker.trainer
# Start the API
uvicorn backend.main:app --reload
Mobile
cd mobile
npm install
cp .env.example .env
npx expo start
Scan the QR code with Expo Go (iOS / Android). Phone and Mac must be on the same WiFi.
API
POST /api/itinerary
{
"destination": "Tokyo",
"days": 3,
"transport": "walking",
"goals": ["food", "history", "hidden gems"]
}
Returns a structured day-by-day itinerary with stops, arrival times, descriptions, and coordinates.
POST /api/feedback
{
"poi_id": 12345,
"relevant": true
}
Logs positive/negative signals for future ranker retraining.