YouRAG is a production-grade Retrieval-Augmented Generation (RAG) system that turns any YouTube video into a queryable knowledge base. It combines Knowledge Graph, Hybrid Search, Cross-Encoder Reranking, and Citation Grounding — state-of-the-art techniques that eliminate hallucination at the architecture level, backed by a RAGAS benchmark suite used to A/B test every architectural decision (see Benchmark Results).
Not just a video chatbot. YouRAG builds a "digital brain" for each video: extracts entities, builds a knowledge graph, validates every citation, and forces the AI to cross-check facts before answering.
flowchart TD
URL([YouTube URL]) --> YL[YouTubeLoader\npytubefix + transcript-api]
YL -->|no captions| WH[WhisperTranscriber\nfaster-whisper STT]
YL -->|has captions| SC
WH --> SC[SemanticChunker\npause-aware + vector valleys]
SC -->|optional| CE[ContextualEnricher\nLLM prefix injection]
SC -->|optional| LC[LateChunkingEmbedder\nJina jina-embeddings-v3]
CE --> GE
LC --> GE
SC --> GE[GraphExtractor\nrule-based keyword/entity metadata]
GE --> QD[(Qdrant VectorDB\nBAAI/bge-m3 · 1024-dim\ncosine HNSW)]
QD -->|background thread| KGB[KnowledgeGraphBuilder\nLLM triple extraction]
KGB --> KG[(Knowledge Graph\nNetworkX DiGraph)]
Q([User Query]) --> HR[HybridRetriever\nDense + SPLADE + QueryExpansion + HyDE · RRF Fusion]
Q --> GR[GraphRetriever\nmulti-hop traversal]
QD --> HR
KG --> GR
HR --> CR[CrossEncoderReranker\nbge-reranker-v2-m3]
CR --> CC[ContextualCompressor]
CC --> AG[AnswerGenerator]
GR --> AG
AG -->|opt-in flag, off by default| SC2[Self-Correction\nLLM audits draft vs graph facts]
AG -->|default path| CG[Citation Grounding\nremove fabricated timestamps]
SC2 --> CG
CG --> ANS([Final Answer\n+ mm:ss Citations])
[mm:ss] in the answer is validated against retrieved chunks; fabricated citations are removedENABLE_SELF_CORRECTION. Implemented and tested, but a controlled A/B benchmark (33 questions, RAGAS) showed it made factual_correctness worse (0.570 ON vs 0.582 OFF) while adding a full extra LLM call per query — so it's disabled by default. Kept as a flag for future re-evaluation rather than deleted, since the finding was reached by measurement, not assumption. See Benchmark Results.(subject, predicate, object) triples → NetworkX directed graph → multi-hop reasoningX-API-Key header protects all write endpoints/health endpoint — Checks Qdrant, Redis, Generator, Reranker; returns 200 or 503GROQ_API_KEYS)| Component | Technology |
|---|---|
| Backend API | FastAPI 0.110 + Uvicorn |
| Frontend | Next.js 14, TypeScript, Tailwind CSS |
| Vector DB | Qdrant (HNSW, cosine similarity) |
| Embeddings | BAAI/bge-m3 (1024-dim, multilingual) |
| Reranker | BAAI/bge-reranker-v2-m3 (multilingual, CPU+GPU) |
| LLM primary | Groq llama-3.3-70b-versatile |
| LLM fallback | Groq backup key rotation (GROQ_API_KEYS) |
| Chat history | PostgreSQL 15 + Redis 7 (dual-layer) |
| Sparse Retrieval | SPLADE (naver/efficient-splade-VI-BT-large, bilingual) |
| Knowledge Graph | NetworkX (JSON serialization, no pickle) |
| Evaluation | RAGAS framework |
| Build | uv (Docker), Poetry (local/CI) |
| CI/CD | GitHub Actions — Ruff + Bandit + Pytest |
git clone https://github.com/td041/YouRAG.git
cd YouRAG
cp .env.example .env
# Edit .env and set GROQ_API_KEY
docker compose up -d --build
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:8000 |
| API Docs | http://localhost:8000/docs |
| Health Check | http://localhost:8000/health |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | / | — | Status check |
GET | /health | — | Deep health check (Qdrant, Redis, models) |
GET | /collections | — | List ingested videos |
POST | /ingest | ✅ | Ingest YouTube video (async, returns job_id) |
GET | /ingest/status/{job_id} | — | Poll ingest job status |
POST | /chat | ✅ | RAG chat (sync) |
POST | /chat/stream | ✅ | RAG chat (streaming) |
GET | /suggestions/{collection} | ✅ | Get 4 dynamic suggested questions |
GET | /summarize/{collection} | ✅ | Video summary |
GET | /history/{session_id} | — | Chat history |
GET | /quiz/{collection} | ✅ | Generate quiz (MCQ) or flashcards |
POST | /graph/build/{collection} | ✅ | Build/rebuild knowledge graph |
DELETE | /collections/{name} | ✅ | Delete video |
Protected endpoints require X-API-Key header when API_KEY is set in .env.
# Unit tests (266 tests, all mocked)
poetry run pytest tests/unit/ -v --cov=src --cov-report=term-missing
# Lint
poetry run ruff check src/ tests/
# Security
poetry run bandit -r src/ -ll
# RAGAS benchmark
make benchmark
# or with specific collection:
make benchmark COLLECTION=your-collection-name
Evaluated on 33 questions (mixed difficulty: factual, reasoning, comparative, synthesis) using:
llama-3.3-70b-versatile via Groq (multi-key round-robin)mistral-small-latest via Mistral AIBAAI/bge-reranker-v2-m3paraphrase-multilingual-MiniLM-L12-v2 (multilingual)Run: 2026-07-16, current codebase (ENABLE_SELF_CORRECTION=false, prompt-leak guard, GPU-lock + model-warmup fixes for concurrent local inference).
| Metric | Score |
|---|---|
| Faithfulness | 0.813 |
| Answer Relevancy | 0.789 |
| Context Precision | 0.794 |
| Context Recall | 0.909 |
| Factual Correctness | 0.582 |
| Latency (avg / median) | 17.1s / 14.6s |
factual_correctness reads lower than the other four metrics by design of the metric, not the model: RAGAS decomposes answers into atomic claims and scores strict claim-level F1 against a terse reference, which penalizes correct-but-elaborated answers (our answers average ~4x longer than the reference text). A manual audit of the mid-scoring questions confirmed most of that gap is measurement strictness, not factual errors — see commit history / tests/benchmark/eval_dataset.json for the audited dataset.
ENABLE_SELF_CORRECTION gates a second LLM call that audits the draft answer against Knowledge Graph facts. It sounds like it should only help — in practice, a controlled A/B run (same 33 questions, same code, only the flag flipped) showed the opposite:
| Metric | Self-Correction ON | Self-Correction OFF |
|---|---|---|
| Faithfulness | 0.760 | 0.813 |
| Answer Relevancy | 0.791 | 0.789 |
| Context Precision | 0.812 | 0.794 |
| Context Recall | 0.879 | 0.909 |
| Factual Correctness | 0.570 | 0.582 |
| Latency (s) | 24.6 | 17.1 |
ON loses on 4 of 5 quality metrics and is ~44% slower (one extra LLM round-trip per query). Disabled by default as a result — see the Anti-Hallucination Stack section for how the flag is kept for future re-evaluation instead of deleted.
Isolates the retrieval architecture's contribution: same 33 questions, same generation step, only the retrieval tier changes.
| Metric | Naive (Dense) | Hybrid (SPLADE+RRF) | Advanced (Rerank) |
|---|---|---|---|
| Faithfulness | 0.797 | 0.753 | 0.872 |
| Answer Relevancy | 0.682 | 0.720 | 0.743 |
| Context Precision | 0.593 | 0.709 | 0.880 |
| Context Recall | 0.818 | 0.909 | 0.939 |
| Factual Correctness | 0.534 | 0.518 | 0.540 |
| Latency (s) | 18.48 | 25.24 | 35.05 |
Advanced tier wins on all 5 RAGAS metrics — the cross-encoder reranker's context precision gain (+48% over naive) is the largest single driver. Run: 2026-07-07, predates the self-correction A/B fix and current baseline above — kept for the relative naive→hybrid→advanced trend, not as an absolute comparison to the current baseline table.
See .env.example for full reference.
| Variable | Required | Description |
|---|---|---|
GROQ_API_KEY | ✅ | Primary LLM (llama-3.3-70b) |
GROQ_API_KEYS | Optional | Backup Groq keys (comma-separated) for benchmark rotation |
API_KEY | Recommended | Protects write endpoints |
MISTRAL_EVAL_API_KEY | Recommended | RAGAS benchmark evaluator (no daily quota) |
JINA_API_KEY | Optional | Late Chunking embeddings |
QDRANT_SERVER_URL | Production | Qdrant Cloud URL |
Built by td041
121 commits
Python
78.2%
TypeScript
19.8%
YouRAG is a production-grade Retrieval-Augmented Generation (RAG) system that turns any YouTube video into a queryable knowledge base. It combines Knowledge Graph, Hybrid Search, Cross-Encoder Reranking, and Citation Grounding — state-of-the-art techniques that eliminate hallucination at the architecture level, backed by a RAGAS benchmark suite used to A/B test every architectural decision (see Benchmark Results).
Not just a video chatbot. YouRAG builds a "digital brain" for each video: extracts entities, builds a knowledge graph, validates every citation, and forces the AI to cross-check facts before answering.
flowchart TD
URL([YouTube URL]) --> YL[YouTubeLoader\npytubefix + transcript-api]
YL -->|no captions| WH[WhisperTranscriber\nfaster-whisper STT]
YL -->|has captions| SC
WH --> SC[SemanticChunker\npause-aware + vector valleys]
SC -->|optional| CE[ContextualEnricher\nLLM prefix injection]
SC -->|optional| LC[LateChunkingEmbedder\nJina jina-embeddings-v3]
CE --> GE
LC --> GE
SC --> GE[GraphExtractor\nrule-based keyword/entity metadata]
GE --> QD[(Qdrant VectorDB\nBAAI/bge-m3 · 1024-dim\ncosine HNSW)]
QD -->|background thread| KGB[KnowledgeGraphBuilder\nLLM triple extraction]
KGB --> KG[(Knowledge Graph\nNetworkX DiGraph)]
Q([User Query]) --> HR[HybridRetriever\nDense + SPLADE + QueryExpansion + HyDE · RRF Fusion]
Q --> GR[GraphRetriever\nmulti-hop traversal]
QD --> HR
KG --> GR
HR --> CR[CrossEncoderReranker\nbge-reranker-v2-m3]
CR --> CC[ContextualCompressor]
CC --> AG[AnswerGenerator]
GR --> AG
AG -->|opt-in flag, off by default| SC2[Self-Correction\nLLM audits draft vs graph facts]
AG -->|default path| CG[Citation Grounding\nremove fabricated timestamps]
SC2 --> CG
CG --> ANS([Final Answer\n+ mm:ss Citations])
[mm:ss] in the answer is validated against retrieved chunks; fabricated citations are removedENABLE_SELF_CORRECTION. Implemented and tested, but a controlled A/B benchmark (33 questions, RAGAS) showed it made factual_correctness worse (0.570 ON vs 0.582 OFF) while adding a full extra LLM call per query — so it's disabled by default. Kept as a flag for future re-evaluation rather than deleted, since the finding was reached by measurement, not assumption. See Benchmark Results.(subject, predicate, object) triples → NetworkX directed graph → multi-hop reasoningX-API-Key header protects all write endpoints/health endpoint — Checks Qdrant, Redis, Generator, Reranker; returns 200 or 503GROQ_API_KEYS)| Component | Technology |
|---|---|
| Backend API | FastAPI 0.110 + Uvicorn |
| Frontend | Next.js 14, TypeScript, Tailwind CSS |
| Vector DB | Qdrant (HNSW, cosine similarity) |
| Embeddings | BAAI/bge-m3 (1024-dim, multilingual) |
| Reranker | BAAI/bge-reranker-v2-m3 (multilingual, CPU+GPU) |
| LLM primary | Groq llama-3.3-70b-versatile |
| LLM fallback | Groq backup key rotation (GROQ_API_KEYS) |
| Chat history | PostgreSQL 15 + Redis 7 (dual-layer) |
| Sparse Retrieval | SPLADE (naver/efficient-splade-VI-BT-large, bilingual) |
| Knowledge Graph | NetworkX (JSON serialization, no pickle) |
| Evaluation | RAGAS framework |
| Build | uv (Docker), Poetry (local/CI) |
| CI/CD | GitHub Actions — Ruff + Bandit + Pytest |
git clone https://github.com/td041/YouRAG.git
cd YouRAG
cp .env.example .env
# Edit .env and set GROQ_API_KEY
docker compose up -d --build
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:8000 |
| API Docs | http://localhost:8000/docs |
| Health Check | http://localhost:8000/health |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | / | — | Status check |
GET | /health | — | Deep health check (Qdrant, Redis, models) |
GET | /collections | — | List ingested videos |
POST | /ingest | ✅ | Ingest YouTube video (async, returns job_id) |
GET | /ingest/status/{job_id} | — | Poll ingest job status |
POST | /chat | ✅ | RAG chat (sync) |
POST | /chat/stream | ✅ | RAG chat (streaming) |
GET | /suggestions/{collection} | ✅ | Get 4 dynamic suggested questions |
GET | /summarize/{collection} | ✅ | Video summary |
GET | /history/{session_id} | — | Chat history |
GET | /quiz/{collection} | ✅ | Generate quiz (MCQ) or flashcards |
POST | /graph/build/{collection} | ✅ | Build/rebuild knowledge graph |
DELETE | /collections/{name} | ✅ | Delete video |
Protected endpoints require X-API-Key header when API_KEY is set in .env.
# Unit tests (266 tests, all mocked)
poetry run pytest tests/unit/ -v --cov=src --cov-report=term-missing
# Lint
poetry run ruff check src/ tests/
# Security
poetry run bandit -r src/ -ll
# RAGAS benchmark
make benchmark
# or with specific collection:
make benchmark COLLECTION=your-collection-name
Evaluated on 33 questions (mixed difficulty: factual, reasoning, comparative, synthesis) using:
llama-3.3-70b-versatile via Groq (multi-key round-robin)mistral-small-latest via Mistral AIBAAI/bge-reranker-v2-m3paraphrase-multilingual-MiniLM-L12-v2 (multilingual)Run: 2026-07-16, current codebase (ENABLE_SELF_CORRECTION=false, prompt-leak guard, GPU-lock + model-warmup fixes for concurrent local inference).
| Metric | Score |
|---|---|
| Faithfulness | 0.813 |
| Answer Relevancy | 0.789 |
| Context Precision | 0.794 |
| Context Recall | 0.909 |
| Factual Correctness | 0.582 |
| Latency (avg / median) | 17.1s / 14.6s |
factual_correctness reads lower than the other four metrics by design of the metric, not the model: RAGAS decomposes answers into atomic claims and scores strict claim-level F1 against a terse reference, which penalizes correct-but-elaborated answers (our answers average ~4x longer than the reference text). A manual audit of the mid-scoring questions confirmed most of that gap is measurement strictness, not factual errors — see commit history / tests/benchmark/eval_dataset.json for the audited dataset.
ENABLE_SELF_CORRECTION gates a second LLM call that audits the draft answer against Knowledge Graph facts. It sounds like it should only help — in practice, a controlled A/B run (same 33 questions, same code, only the flag flipped) showed the opposite:
| Metric | Self-Correction ON | Self-Correction OFF |
|---|---|---|
| Faithfulness | 0.760 | 0.813 |
| Answer Relevancy | 0.791 | 0.789 |
| Context Precision | 0.812 | 0.794 |
| Context Recall | 0.879 | 0.909 |
| Factual Correctness | 0.570 | 0.582 |
| Latency (s) | 24.6 | 17.1 |
ON loses on 4 of 5 quality metrics and is ~44% slower (one extra LLM round-trip per query). Disabled by default as a result — see the Anti-Hallucination Stack section for how the flag is kept for future re-evaluation instead of deleted.
Isolates the retrieval architecture's contribution: same 33 questions, same generation step, only the retrieval tier changes.
| Metric | Naive (Dense) | Hybrid (SPLADE+RRF) | Advanced (Rerank) |
|---|---|---|---|
| Faithfulness | 0.797 | 0.753 | 0.872 |
| Answer Relevancy | 0.682 | 0.720 | 0.743 |
| Context Precision | 0.593 | 0.709 | 0.880 |
| Context Recall | 0.818 | 0.909 | 0.939 |
| Factual Correctness | 0.534 | 0.518 | 0.540 |
| Latency (s) | 18.48 | 25.24 | 35.05 |
Advanced tier wins on all 5 RAGAS metrics — the cross-encoder reranker's context precision gain (+48% over naive) is the largest single driver. Run: 2026-07-07, predates the self-correction A/B fix and current baseline above — kept for the relative naive→hybrid→advanced trend, not as an absolute comparison to the current baseline table.
See .env.example for full reference.
| Variable | Required | Description |
|---|---|---|
GROQ_API_KEY | ✅ | Primary LLM (llama-3.3-70b) |
GROQ_API_KEYS | Optional | Backup Groq keys (comma-separated) for benchmark rotation |
API_KEY | Recommended | Protects write endpoints |
MISTRAL_EVAL_API_KEY | Recommended | RAGAS benchmark evaluator (no daily quota) |
JINA_API_KEY | Optional | Late Chunking embeddings |
QDRANT_SERVER_URL | Production | Qdrant Cloud URL |
Built by td041
121 commits
Python
78.2%
TypeScript
19.8%