OptiRoute is a production-style MVP for AI-assisted travel optimization. It is not a generic chatbot; it is a deterministic decision engine that evaluates user-provided itineraries against hard constraints and soft preferences, then transparently ranks options with score breakdowns.
Travel decisions are tradeoffs. OptiRoute helps users optimize across:
- cost
- total travel time
- number of stops
- layover quality
- airport transfer inconvenience
- airline preferences
- schedule fit and comfort/value tradeoffs
- risk indicators (self-transfer, low buffer, separate tickets)
optiroute/
backend/
app/
api/
routes/
core/
models/
services/
agents/
scoring/
tests/
data/
requirements.txt
frontend/
docs/
README.md
- Deterministic source-of-truth for validity, scoring, and ranking.
- LLM layer is replaceable and cannot invent flight data.
- Hard constraints are strict: violated itineraries are rejected.
- Soft preferences are tradable: influence ranking but do not invalidate options.
- Explanations are grounded in computed score breakdowns.
cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000API docs: http://localhost:8000/docs
GET /healthPOST /parse-preferencesPOST /score-itinerariesPOST /recommend
{
"preferences": {"origin": "JFK", "destination": "SFO", "hard_constraints": {"max_budget": 550}},
"itineraries": [
{
"itinerary_id": "OPT-101",
"provider": "MockFlights",
"total_price": 420,
"total_duration_minutes": 510,
"stops": 1,
"segments": [...],
"origin": "JFK",
"destination": "SFO",
"airlines": ["DL"]
}
]
}- parsed preferences
- rejected itineraries with explicit reasons
- ranked valid itineraries with score breakdowns
- recommendation buckets: best overall / cheapest / best value / best comfort
- final recommendation and grounded explanation text
- uncertainty notes
The scoring engine computes weighted components:
price_scoreduration_scorestop_penaltybad_layover_penaltyairport_inconvenience_penaltyairline_preference_bonusschedule_fit_bonusstopover_bonusrisk_penalty
Final score is a weighted combination of normalized terms. Weights are configurable via preference payload (scoring_weights).
backend/app/agents/claude_client.py provides hooks for:
extract_preferences(user_text)generate_explanation(context)
In production, this adapter should call Claude API. Deterministic modules still own scoring/ranking/validation.
- mock itineraries:
backend/app/data/mock_itineraries.json - sample preferences:
backend/app/data/sample_preference_payload.json - unit tests:
backend/app/tests/
Run tests:
cd backend
PYTHONPATH=. pytest app/tests -qThis implementation prioritizes:
- schemas
- scoring engine
- recommend endpoint
- explanation integration
- frontend shell (API-first)