Code Architecture — RAG (Retrieval-Augmented Generation)
Overview
This notebook implements a compact end-to-end RAG pipeline that mirrors the core architecture from Lewis et al. (2020): a dense retriever that fetches relevant passages from a document index, and a seq2seq generator that produces grounded answers conditioned on both the query and retrieved passages. The implementation uses small pre-trained models to stay within Kaggle’s GPU/time constraints while faithfully demonstrating the RAG-Sequence and RAG-Token formulations.
Section-by-Section Breakdown
1. Environment Setup & Imports
- Installs
sentence-transformers,faiss-cpu, andtransformersvia pip. - Imports PyTorch, transformers, sentence-transformers, and FAISS.
- Sets device (CUDA if available, else CPU).
2. Toy Document Collection (Non-Parametric Memory)
- Creates a toy knowledge base of ~40 short Wikipedia-style passages spanning science, history, geography, and technology.
- Each passage is a self-contained “document” (analogous to the 100-token Wikipedia chunks used in the paper).
- This replaces the 21M-passage Wikipedia index with a manageable toy set that demonstrates the full pipeline.
3. Dense Retriever (DPR Analog)
- Uses
sentence-transformers/all-MiniLM-L6-v2as the passage/question encoder (a compact BERT-based encoder, analogous to DPR’s dual-BERT encoders). - Encodes all documents into dense vectors (384-dim) and builds a FAISS index for fast Maximum Inner Product Search (MIPS).
retrieve(query, k=5)returns the top-k passages with their similarity scores.- Deliberate simplification: The original paper uses two separate encoders (one for questions, one for passages) trained with contrastive learning. We use a single pre-trained bi-encoder for simplicity — the retriever is not fine-tuned end-to-end with the generator (the toy scale makes joint fine-tuning impractical).
4. RAG Generator (BART Analog)
- Uses
google/flan-t5-base(247.6M params) as the seq2seq generator — a smaller stand-in for BART-large (400M). - The generator takes a formatted prompt:
"question: <query> context: <retrieved_passage>"and generates an answer. - This mirrors the paper’s approach of concatenating the retrieved passage with the query as input to the seq2seq model.
5. RAG-Sequence Implementation
- Retrieves top-k passages for a query.
- For each retrieved passage, runs the generator independently to produce a candidate answer.
- Scores each candidate as retrieval probability p(z|x) (softmax of retrieval scores) plus the generator log-probability log p(y|x,z).
- Returns the highest-scoring single candidate. This is a simplification: the paper’s RAG-Sequence sums over documents, argmax_y Σ_i p(z_i|x) · p(y|x, z_i), and the notebook’s score mixes a probability with a log-probability.
- Key function:
rag_sequence_answer(query, k=5)— returns the best answer, all candidates, and their scores.
6. RAG-Token Implementation
- Retrieves top-k passages for a query.
- At each generation step, the next-token distribution is the weighted sum of the per-document next-token distributions (greedy decoding).
- This allows different documents to influence different tokens in the output.
- Key function:
rag_token_answer(query, k=5)— returns the RAG-Token answer with per-step document contributions. - Deliberate simplification: Full RAG-Token beam search requires custom beam search code that interleaves retriever weights at each step. We implement a greedy version that computes per-token weighted distributions, which captures the core idea.
7. Parametric-Only Baseline (No Retrieval)
- Runs the same generator with NO retrieved context (just the question).
- This is the “parametric-only” baseline from the paper — the model relies entirely on its weights.
- Key function:
parametric_answer(query)— baseline for comparison.
8. Comparison & Evaluation
- Tests the pipeline on 5 knowledge-intensive questions.
- Prints answers from: (a) parametric-only, (b) RAG-Sequence, (c) RAG-Token.
- Shows which passages were retrieved for each query.
- In the saved run, both RAG versions answer all 5 questions correctly and the parametric-only baseline gets all 5 wrong.
9. Retrieval Quality Analysis
- Visualizes retrieval scores for sample queries.
- Shows the top-5 retrieved passages with similarity scores.
- Demonstrates the retriever’s ability to find relevant passages.
10. Knowledge Update Demonstration
- Adds a new passage to the index and asks the same question again, to show that knowledge can be updated without retraining.
- Note: in the saved run the answer did not change (“New York Harbor” before and after), because an unrelated passage still ranked first. The printed message says otherwise; this needs a code fix and a re-run.
Key Functions/Classes
| Function | Purpose |
|---|---|
| (cell 6, no function) | Encodes passages into dense vectors, builds the FAISS index |
retrieve(query, k=5) | Top-k retrieval from the FAISS index |
format_prompt(query, passage) | Formats query + passage as generator input |
rag_sequence_answer(query, k=5) | RAG-Sequence: best of k per-document answers |
rag_token_answer(query, k=5) | RAG-Token: per-token weighted marginalization |
parametric_answer(query) | Baseline: generation without retrieval |
generate_answer(prompt, max_new_tokens=64) | Greedy generation with Flan-T5 |
compute_logprob(prompt, answer) | Computes log p(y|x,z) for scoring |
Data Flow / Shapes
Query (str)
→ Retriever encoder → query_vec (1, 384)
→ FAISS search → top-k indices (k,) + scores (k,)
→ k retrieved passages (k, str)
→ For each passage:
format_prompt(query, passage) → input_ids (1, seq_len)
generator.generate() → answer (str), logprob (float)
→ RAG-Sequence: weight by softmax(retrieval_scores) → best answer
→ RAG-Token: per-token weighted logits → greedy decode
Deliberate Simplifications vs Full Paper
- Retriever: Single pre-trained sentence encoder (
all-MiniLM-L6-v2) instead of DPR’s two BERT encoders. No end-to-end retriever fine-tuning. - Generator:
flan-t5-base(247.6M) instead ofbart-large(400M). Not fine-tuned on downstream tasks (the paper fine-tunes on NQ/TriviaQA/WebQ). - Index: ~40 toy passages instead of 21M Wikipedia passages. FAISS-cpu instead of FAISS-GPU.
- RAG-Token: Greedy decoding instead of full beam search with per-step document marginalization (the concept is the same; beam search adds significant complexity for marginal quality gain at this scale).
- No end-to-end fine-tuning: The paper jointly fine-tunes retriever + generator. We use off-the-shelf models and demonstrate the inference-time RAG pipeline, which is how RAG is most commonly deployed in practice today.
- Evaluation: Qualitative comparison on 5 questions instead of quantitative benchmarks (NQ, TriviaQA, WebQuestions) which require full datasets and fine-tuning.