Skip to content

Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (RAG)

Authors: Patrick Lewis, Ethan Perez, Aleksandra Piktus, et al. (Facebook AI Research, UCL, NYU) Published: May 2020 (NeurIPS 2020) Paper: arxiv.org/abs/2005.11401


Why This Matters

RAG solved a fundamental problem with language models: they can't access updated information or cite sources. By combining neural retrieval with generation, RAG:

  • Grounds responses in facts: Retrieves relevant documents before generating
  • Updates knowledge without retraining: Just update the document database
  • Enables citations: Can point to source documents
  • Reduces hallucinations: Generates from retrieved evidence

Real-world impact: - Powers ChatGPT plugins, Bing Chat, Perplexity AI - Enables enterprise AI with private knowledge bases - Standard pattern for production LLM applications - Foundation for question answering, summarization, fact-checking

RAG made LLMs practical for knowledge-intensive real-world applications.


The Problem

Limitations of pure language models (2020):

  1. Static knowledge
  2. Knowledge frozen at training time
  3. Can't access new information
  4. Requires retraining to update

  5. Hallucination

  6. Generate plausible but false information
  7. No grounding in verifiable sources
  8. Confident-sounding mistakes

  9. No attribution

  10. Can't cite sources
  11. Difficult to verify claims
  12. Low trust in critical applications

  13. Limited memory

  14. All knowledge must fit in parameters
  15. Struggles with rare facts
  16. Poor at long-tail knowledge

The question: Can we give language models access to external knowledge dynamically?


Core Innovation

Retrieval + Generation = RAG

The key insight: Treat generation as a two-stage process:

  1. Retrieve: Find relevant documents from a large corpus
  2. Generate: Condition language model on retrieved documents

Architecture:

Input Question
     ↓
Retrieve (top-k documents from knowledge base)
     ↓
Concatenate: [question + retrieved docs]
     ↓
Generate (using seq2seq model)
     ↓
Output Answer

Two RAG Variants

RAG-Sequence: - Retrieve once for entire sequence - Use same documents for all tokens - Simpler, faster

RAG-Token: - Can retrieve different docs for each token - Marginalize over retrieved docs per token - More flexible, slower


Architecture Details

Components

1. Retriever: Dense Passage Retrieval (DPR) - Bi-encoder architecture - Query encoder: BERT_Q - Document encoder: BERT_D

Retrieval process:

# Encode query
q = BERT_Q(question)

# Encode all documents (pre-computed)
d_i = BERT_D(doc_i) for all docs

# Find top-k by dot product similarity
scores = q · d_i
top_k = argsort(scores)[-k:]

2. Generator: BART - Pre-trained seq2seq model (BART-large) - 400M parameters - Fine-tuned on task with retrieved context

3. Knowledge Source - Wikipedia (21M passages of 100 words) - Pre-indexed with document embeddings - Can swap for domain-specific corpus

Training Approach

End-to-end training: - Jointly train retriever and generator - Retriever learns what to retrieve for generation - Generator learns to use retrieved content

Loss function:

L = -log P(y | x, z)

Where:
  x = input question
  y = target answer
  z = retrieved documents

Key trick: Marginalize over top-k retrieved documents

P(y | x) = Σ_z P(z | x) P(y | x, z)

P(z | x) = softmax(query · doc)
P(y | x, z) = BART(y | x, z)

Gradient flow: - Generator loss backprops through retriever - Retriever learns to fetch documents that help generation - Uses differentiable top-k approximation


How It Works (Step-by-Step)

Example: Question Answering

Input: "When was the first iPhone released?"

Step 1: Encode query

q_embed = BERT_Q("When was the first iPhone released?")

Step 2: Retrieve top-k passages

# Pre-computed document embeddings
doc_scores = q_embed · all_doc_embeddings

# Get top-5
top_docs = [
  "The iPhone was announced by Steve Jobs on January 9, 2007...",
  "Apple Inc. released the first generation iPhone on June 29, 2007...",
  "The original iPhone was marketed as combining three products...",
  ...
]

Step 3: Generate answer

# RAG-Sequence: Use all docs together
input = "Question: When was the first iPhone released?\n\n" +
        "Context: " + join(top_docs) + "\n\n" +
        "Answer:"

output = BART.generate(input)
# "June 29, 2007"

Step 4: (Optional) Return sources

# Can cite which documents were used
sources = [doc_urls[i] for i in top_k_indices]


Experimental Results

Tasks Tested

Open-domain Question Answering: - Natural Questions - TriviaQA - WebQuestions - CuratedTREC

Performance (Exact Match accuracy):

Model Natural Questions TriviaQA WebQuestions
BART (no retrieval) 24.0% 35.0% 28.0%
DPR + BART (pipeline) 41.5% 56.8% 42.4%
RAG-Token 44.5% 56.1% 45.2%
RAG-Sequence 44.1% 56.8% 45.5%

Key finding: RAG beats pipeline approach (retrieve then generate separately).

Fact Verification (FEVER)

Model Accuracy
BERT baseline 75.6%
RAG-Sequence 78.1%

Jeopardy Question Generation

Human evaluation: - RAG generates more factual questions - Better at incorporating specific knowledge - Fewer hallucinations


Key Advantages

1. Dynamic Knowledge

  • Update knowledge base without retraining
  • Access to latest information
  • Add domain-specific documents easily

Example use case: - Corporate knowledge base with internal docs - Medical database with latest research - Legal system with current statutes

2. Reduced Hallucination

  • Grounded in retrieved evidence
  • Can't generate facts not in corpus
  • Explicit provenance

Comparison: - Pure LM: "The Eiffel Tower is 450 meters tall" (hallucinated) - RAG: "According to [doc], the Eiffel Tower is 330 meters tall"

3. Interpretability

  • Can inspect retrieved documents
  • Understand why model gave answer
  • Debug by examining retrieval quality

4. Efficiency

  • Don't need to store all knowledge in parameters
  • Smaller models can access vast knowledge
  • Modular: Improve retrieval or generation independently

5. Verifiability

  • Cite sources for fact-checking
  • Transparent reasoning process
  • Build trust in high-stakes domains

Limitations

1. Retrieval Quality Bottleneck

  • If retrieval fails, generation fails
  • Out-of-domain queries struggle
  • Need high-quality, comprehensive corpus

Example failure: - Question about very recent event - Not in knowledge base → can't answer

2. Latency

  • Two-stage process is slower
  • Retrieval adds overhead
  • Not suitable for real-time applications without optimization

3. Context Length Limits

  • Can only include top-k docs (e.g., 5)
  • May miss relevant information in doc #6
  • Generator has limited context window

4. Training Complexity

  • End-to-end training is challenging
  • Requires large corpus and compute
  • Balancing retrieval and generation objectives

5. Contradictory Sources

  • Retrieved docs may conflict
  • Model must resolve contradictions
  • No built-in source reliability weighting

Practical Applications

Production RAG Systems

1. Customer Support Chatbots

# Retrieve from company knowledge base
docs = retrieve(user_question, kb="company_docs")
answer = generate(user_question, context=docs)

2. Research Assistants - Perplexity AI: Search + RAG for citations - Bing Chat: Web search + GPT-4 - Elicit: Academic paper search + summarization

3. Enterprise AI - Internal document search and QA - Compliance checking against regulations - Technical support with manuals

4. Educational Tools - Textbook-grounded tutoring - Homework help with citations - Exam preparation with verified facts

5. Content Creation - Blog writing with source material - Report generation from data - News summarization with links


Implementation Guide

Basic RAG Pipeline

from transformers import RagTokenizer, RagRetriever, RagTokenForGeneration

# Load RAG model
tokenizer = RagTokenizer.from_pretrained("facebook/rag-token-nq")
retriever = RagRetriever.from_pretrained(
    "facebook/rag-token-nq",
    index_name="exact",
    use_dummy_dataset=True  # Use real index for production
)
model = RagTokenForGeneration.from_pretrained(
    "facebook/rag-token-nq",
    retriever=retriever
)

# Question answering
question = "When was the first iPhone released?"
inputs = tokenizer(question, return_tensors="pt")

# Generate (retrieval happens inside)
generated = model.generate(**inputs)
answer = tokenizer.decode(generated[0], skip_special_tokens=True)

print(answer)  # "June 29, 2007"

# Access retrieved documents
retrieved_docs = retriever(inputs["input_ids"], n_docs=5)
for doc in retrieved_docs:
    print(doc["title"], doc["text"][:100])

Custom RAG with LangChain

from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA

# Build knowledge base
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(documents, embeddings)

# Create RAG chain
qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(),
    retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
    return_source_documents=True
)

# Query
result = qa_chain({"query": "When was the first iPhone released?"})
print(result["result"])
print(result["source_documents"])

Key Hyperparameters

Retrieval: - k: Number of documents to retrieve (typically 5-10) - similarity_metric: dot product, cosine, L2 - index_type: exact, HNSW, IVF (for large scale)

Generation: - max_length: Maximum generation length - num_beams: Beam search width - temperature: Sampling randomness

Training: - batch_size: 32-128 (depends on GPU memory) - learning_rate: 1e-5 for fine-tuning - n_docs: Number of docs to marginalize over


Evolution and Improvements

Subsequent Work

1. Fusion-in-Decoder (FiD) (2020) - Process each retrieved doc independently - Fuse in decoder layer - Better parallelization

2. RETRO (2021, DeepMind) - Retrieval-enhanced Transformer - Chunk-based retrieval during training - Scales to 7B parameters

3. Atlas (2022) - Few-shot RAG - Joint pre-training of retriever and LM - State-of-the-art on many tasks

4. Self-RAG (2023) - Model learns when to retrieve - Retrieval as needed, not always - Self-reflection on retrieved content

5. RALM (2023) - Reinforcement learning for retrieval - Optimizes for end task performance - Better retrieval strategies


Modern RAG (2024-2025)

Current Best Practices

1. Hybrid Search - Combine dense (embedding) and sparse (BM25) retrieval - Better coverage of different query types

2. Reranking - Two-stage retrieval: fast retrieval → slow reranking - Use cross-encoder for reranking top-k

3. Chunking Strategies - Semantic chunking vs fixed-size - Overlapping chunks for context - Metadata filtering

4. Query Rewriting - Expand or clarify user query before retrieval - Hypothetical document embeddings (HyDE)

5. Multi-hop Reasoning - Iterative retrieval for complex questions - Chain retrieved docs for reasoning


RAG vs Fine-tuning vs Prompt Engineering

Approach Best For Pros Cons
RAG Dynamic knowledge, citations Updatable, grounded Latency, retrieval dependency
Fine-tuning Task specialization, style Fast inference, internalized knowledge Static, expensive to update
Prompting Quick prototypes, few-shot No training, flexible Token limits, no new knowledge

Combined approach: - Fine-tune base model for domain/task - Add RAG for dynamic facts - Use prompting for instructions


Key Takeaways

  1. RAG combines retrieval and generation for knowledge-grounded text
  2. End-to-end training teaches retriever what's useful for generation
  3. Reduces hallucinations by grounding in retrieved evidence
  4. Dynamic knowledge without retraining the model
  5. Production standard for enterprise AI applications
  6. Modular design allows independent improvement of components

Further Reading

Original Paper

  • RAG (Facebook AI): https://arxiv.org/abs/2005.11401

Follow-up Papers

  • Fusion-in-Decoder: https://arxiv.org/abs/2007.01282
  • RETRO (DeepMind): https://arxiv.org/abs/2112.04426
  • Atlas: https://arxiv.org/abs/2208.03299
  • Self-RAG: https://arxiv.org/abs/2310.11511

Practical Guides

  • LangChain RAG Tutorial: https://python.langchain.com/docs/use_cases/question_answering/
  • LlamaIndex Documentation: https://docs.llamaindex.ai/
  • Hugging Face RAG: https://huggingface.co/docs/transformers/model_doc/rag

Code Implementations

  • Original RAG (Hugging Face): https://github.com/huggingface/transformers/tree/main/examples/research_projects/rag
  • LangChain: https://github.com/langchain-ai/langchain
  • LlamaIndex: https://github.com/run-llama/llama_index
  • Haystack: https://github.com/deepset-ai/haystack

Advanced Topics

  • Dense Passage Retrieval: https://arxiv.org/abs/2004.04906
  • ColBERT (Late Interaction): https://arxiv.org/abs/2004.12832
  • Vector Database Comparison: Pinecone, Weaviate, Milvus docs

Published: May 2020 Impact Factor: 2,500+ citations Legacy: Made LLMs practical for knowledge-intensive applications, became standard pattern for production AI systems.