A persona-aware movie recommendation agent powered by single-agent orchestration, RAG with semantic search, persistent user memory, and confidence-weighted deterministic ranking.
Built with FastAPI + React 19 + Qdrant + Sentence Transformers.
Status: 73/73 E2E tests passing | Frontend builds clean | All 5 priority APIs verified
USER → React UI → FastAPI → CinePersonaAgent → Qdrant (RAG) → SQLite (Memory) → TMDB
The entire recommendation pipeline is driven by one intelligent agent (CinePersonaAgent) with six capabilities:
- Understand — LLM extracts mood, intent, and preferences from natural language
- Retrieve — Semantic search via Qdrant (bge-small-en-v1.5 embeddings)
- Rank — Deterministic scoring (semantic 35%, persona 20%, mood 15%, context 10%, quality 10%, novelty 5%, diversity 5%)
- Confidence check — Auto-expands search if confidence < 0.70
- Explain — LLM generates personalized reasons per movie
- Learn — Feedback updates persona memory for better future recommendations
cd backend
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
# Edit .env with your TMDB_API_KEY and OPENROUTER_API_KEY
# Seed data
python -m app.scripts.fetch_corpus # Fetch 5000+ movies from TMDB
python -m app.scripts.build_embeddings # Compute embeddings → Qdrant
# Run tests (73 E2E tests)
python test_cinepersona.py
# Start
uvicorn app.main:app --reloadcd frontend
npm install
npm run dev
# Opens at http://localhost:5173
# API calls proxied through Vite → http://127.0.0.1:8000| Document | Description |
|---|---|
| Backend | Architecture, directory structure, ranking formula |
| Frontend | Component tree, theme, data flow |
| API Reference | All endpoints with request/response examples |
| Workflow | Agent workflow diagram, state machine, learning loop |
| Example Walkthrough | Complete recommendation flow with a real scenario |
| Usage Guide | Setup, writing queries, feedback loop, production notes |
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/v1/agent/recommend |
Main recommendation |
| POST | /api/v1/agent/chat |
Follow-up conversation |
| POST | /api/v1/feedback |
Like/dislike/watched/save |
| GET | /api/v1/movies/{id} |
Movie details |
| GET | /api/v1/movies/search |
Search local corpus |
| GET | /api/v1/movies/{id}/similar |
Similar movies |
| GET | /api/v1/users/{id}/persona |
User persona |
| GET | /api/v1/users/{id}/history |
Session history |
| DELETE | /api/v1/users/{id}/memory |
Clear memory |
| Layer | Technology |
|---|---|
| Backend | FastAPI, SQLite (SQLAlchemy async), Qdrant, Sentence Transformers, OpenRouter |
| Frontend | React 19, TypeScript, Vite, TanStack Query, Zustand, Framer Motion, Lucide |
| Embeddings | BAAI/bge-small-en-v1.5 (384-dim) |
| LLM | OpenRouter (gpt-4o-mini) / NVIDIA |
- Single agent — one
CinePersonaAgentclass, not LangGraph multi-agent - Deterministic ranking — LLM only understands and explains; scoring is pure Python
- Confidence loop — same agent re-searches if confidence < 0.70
- Persistent persona — user preferences stored in SQLite, updated on every feedback
- Dark UI — cinematic dark theme (#080808) with amber accents, not a Netflix clone