01 The Problem
Movie databases like TMDB are exhaustive but rigid. They expose genre filters, release years, and ratings โ but they cannot interpret themes, compare filmographies, or synthesise critical perspective. A single LLM call lacks live data. A single API lacks semantic understanding. The only viable solution is decomposition: multiple specialised agents working in parallel, coordinated by an orchestrator.
02 System Architecture
User (browser) โ HTTPS โ Cloudflare CDN + SSL termination โ Nginx (reverse proxy, OVH VPS) โโโ / โ React frontend (static, port 5174) โโโ /api/* โ FastAPI backend (uvicorn, port 8001) โ โ Server-Sent Events stream โ LangGraph StateGraph โ โโโโโโโโโโโโโดโโโโโโโโโโโโโ โ supervisor_route โ โ decides which agents to invoke โโโโฌโโโโโโโโโโโฌโโโโโโโฌโโโโ โ โ โ (parallel fan-out) tmdb_agent rag_agent search_agent TMDB API Milvus Tavily Web (httpx) :19530 API โ โ โ โโโโดโโโโโโโโโโโดโโโโโโโดโโโโ โ synthesise โ merges results, streams answer โ SSE โ browser (token by token)
Each layer has a single, clear responsibility. The supervisor decides routing. Agents specialise. The synthesiser integrates. The SSE stream makes the entire process visible to the user in real time.
03 Core Technologies
LangGraph โ Multi-Agent Orchestration
LangGraph models the AI pipeline as a directed graph. Each node is an async Python function (an agent); each edge is conditional routing logic. A shared StateGraph object carries conversation state between nodes, and MemorySaver checkpoints that state to disk so multi-turn conversation context persists across queries on the same thread.
Milvus โ Hybrid Vector Search
Milvus stores the movie knowledge corpus (critical essays, directorial analyses, genre guides). The RAG agent retrieves relevant passages using hybrid search: a fusion of two complementary retrieval methods ranked by Reciprocal Rank Fusion (RRF).
Groq โ Fast LLM Inference
Groq runs llama-3.3-70b-versatile on custom LPU (Language Processing Unit) hardware, delivering roughly 10ร the token throughput of comparable GPU cloud providers at a fraction of the cost. In a streaming UI where users watch tokens appear in real time, inference latency is the user experience โ this choice is why the first tokens arrive within ~1 second.
FastAPI + Server-Sent Events
The backend exposes a single streaming endpoint. It runs the LangGraph pipeline with astream_events() and translates internal events โ agent lifecycle, LLM tokens, retrieved chunks, TMDB results โ into a typed SSE stream consumed by the browser.
EventSource in the browser auto-reconnects on drop. WebSockets add bidirectional protocol overhead that is unnecessary here.React + TypeScript Frontend
The frontend is a Vite SPA that maintains a live EventSource connection per query. It renders the pipeline in real time across four tabs: an animated pipeline graph (node status), a Gantt timeline (agent latency), a typed event log, and a context panel (retrieved chunks and TMDB cards). The AI process is visible, not a black box.
04 A Query, Step by Step
Tracing "Show me good bank heist movies" through the full stack:
Supervisor receives the question, calls Groq to classify intent โ routes to all three agents in parallel: tmdb + rag + search
TMDB agent calls Groq to extract intent (discover, genre: Crime/Thriller) โ queries TMDB API โ calls Groq to write a grounded answer citing specific films with ratings
RAG agent embeds the query with OpenAI โ runs hybrid BM25+dense search in Milvus โ retrieves heist film corpus chunks โ calls Groq to synthesise a knowledge-based answer
Search agent sends the query to Tavily โ retrieves current web results โ calls Groq to ground the answer in recent criticism and best-of lists
Synthesiser receives all three outputs, calls Groq to merge them into a single coherent answer โ deduplicating overlapping film mentions and attributing sources
SSE stream delivers typed events to the browser as they occur: pipeline_start โ routing_decision โ agent_start โ token (รN) โ tmdb_results โ chunks_retrieved โ agent_end โ done
05 Technical Highlights
asyncio.gather. Each agent also parallelises its own internal fetches โ movie details and actor filmography are fetched simultaneously.
MemorySaver + thread_id gives the supervisor history across turns. "What about his other films?" works correctly without re-stating context.
movie_and_person intent type fetches movie detail and actor filmography in parallel, sorts by rating, and hands the ranked list to the synthesis LLM โ turning "is this their best film?" from a non-answer into a precise ranked response.
06 Full Stack Summary
| Layer | Technology | Role |
|---|---|---|
| Orchestration | LangGraph 1.1 | Multi-agent state machine with conditional routing and conversation memory |
| LLM inference | Groq (llama-3.3-70b) | All reasoning: routing decisions, intent extraction, answer generation |
| Vector DB | Milvus 2.5 | Hybrid BM25 + dense search over the movie knowledge corpus |
| Embeddings | OpenAI text-embedding-3-small | 1536-dim dense vectors for semantic retrieval |
| Movie data | TMDB API | Real-time film/TV metadata, cast, ratings, trending, person filmography |
| Web search | Tavily API | Current web results as a third retrieval source |
| Backend | FastAPI + uvicorn | Async SSE streaming, typed event protocol |
| Frontend | React + TypeScript + Vite | Real-time pipeline visualisation, conversation UI, dark/light theme |
| Infrastructure | Docker Compose + Nginx + Cloudflare | Containerised deployment, reverse proxy, SSL termination, CDN |