TAI BUI
Back to curriculum
BuildPython

Question Answering Systems

QA went through three eras: extractive systems that found a span, retrieval-augmented systems that grounded that span in real documents, and generative systems that write the answer from memory. Everything you use today is some blend of the three.

TIME: ~75 minutesPREREQUISITES: Phase 5 · 11 (Machine Translation), Phase 5 · 10 (Attention Mechanism)

Learning Objectives

  • Distinguish extractive, open-domain (retrieve-then-read), and generative closed-book QA, and explain which failure mode each architecture is structurally immune to and which one it can't escape.
  • Build an extractive QA pipeline with a pretrained SQuAD2 model, then wrap it in a two-stage retrieval-augmented pipeline using a dense retriever.
  • Evaluate QA output with EM and F1 for benchmarks, and with production metrics (answer accuracy, citation accuracy, refusal calibration, retrieval recall) plus RAGAS's four reference-free dimensions for live RAG systems.
  • Explain why grounding the generation prompt and calibrating refusal ('I don't know') matter more in practice than benchmark scores, and when extractive QA still beats generative RAG.

The Problem

A user types "When did the first iPhone launch?" and expects "June 29, 2007." Not "Apple's history is long and varied." Not "2007" sitting on its own with no sentence around it. A direct, grounded, correct answer.

Three architectures have dominated QA for the last decade, and each one answers a different question about where the answer comes from.

  • Extractive QA. Given a question and a passage known to contain the answer, find the start and end indices of the answer span inside that passage. SQuAD is the canonical benchmark.
  • Open-domain QA. No passage is given up front. Retrieve the relevant passage first, then extract or generate an answer from it. This is the bedrock of every RAG pipeline running today.
  • Generative / closed-book QA. A large language model answers straight from its parametric memory, no retrieval step involved. Fastest at inference, least reliable on facts.

The trend in 2026 is hybrid: retrieve the best few passages, then prompt a generative model to answer grounded in them. That's RAG, and lesson 14 covers the retrieval half in depth. This lesson builds the QA half.

Warm-up0/3
1. If a friend hands you a printed article and asks a question whose exact answer is stated word-for-word somewhere in the text, what's the most reliable way to answer?Warm-up
2. You don't know the answer to a trivia question offhand. Which approach is more likely to get you the right answer: guessing immediately, or looking it up in a reliable source first?Warm-up
3. Two students get the same exam question about an obscure fact. One has the right textbook page open, the other works from memory alone. Who is more likely to state the fact wrongly with full confidence?Warm-up
Check: The Problem0/4
1. What does an extractive QA model produce as its answer?Define
2. What defines open-domain QA?Define
3. What is retrieval-augmented generation (RAG)?Define
4. What is SQuAD?Define

The Concept

QA architectures: extractive, retrieval-augmented, generative

Extractive. Encode question and passage together with a transformer (BERT family), then train two heads that predict the start and end token indices of the answer. Loss is cross-entropy over valid positions, and the output is a span lifted straight from the passage. It never hallucinates, by construction, and it never handles a question the passage can't answer, by construction either.

Retrieval-augmented (RAG). Two stages. First, a retriever finds the top-k passages from a corpus. Second, a reader, extractive or generative, produces the answer using those passages. Splitting retriever from reader lets you train and evaluate each one independently, and modern RAG usually adds a reranker (a smaller model that re-scores the retrieved passages before the reader sees them) between the two.

Generative. A decoder-only LLM (GPT, Claude, Llama) answers from learned weights with no retrieval step at all. It's excellent on common knowledge and catastrophic on rare or recent facts, because the hallucination rate is inversely correlated with how often a fact showed up in the pretraining data.

Check: The Concept0/5
1. In QA, what is a hallucination?Define
2. What determines how likely a closed-book generative QA model is to hallucinate?Explain
3. Why can an extractive reader never hallucinate, yet never handle a question its passage cannot answer?Explain
4. What does a reranker add between the retriever and the reader in modern RAG?Explain
5. What do you gain by splitting a RAG system into a retriever and a reader?Explain

Build It

Step 1: extractive QA with a pretrained model

python
from transformers import pipeline
 
qa = pipeline("question-answering", model="deepset/roberta-base-squad2")
 
passage = (
    "Apple Inc. released the first iPhone on June 29, 2007. "
    "The device was announced by Steve Jobs at Macworld in January 2007."
)
question = "When was the first iPhone released?"
 
answer = qa(question=question, context=passage)
print(answer)
python
{'score': 0.98, 'start': 40, 'end': 53, 'answer': 'June 29, 2007'}

deepset/roberta-base-squad2 is trained on SQuAD 2.0, which includes unanswerable questions. That doesn't mean the pipeline refuses to guess: by default it returns the highest-scoring span even when the model's null score wins, so it does not automatically hand back an empty answer. Pass handle_impossible_answer=True if you want explicit "no answer" behavior; the pipeline then returns an empty answer only when the null score beats every span score. Check the score field regardless.

Step 2: a retrieval-augmented pipeline (sketch)

python
from sentence_transformers import SentenceTransformer
import numpy as np
 
encoder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
 
corpus = [
    "Apple Inc. released the first iPhone on June 29, 2007.",
    "Macworld 2007 featured the iPhone announcement by Steve Jobs.",
    "Android launched in 2008 as Google's mobile operating system.",
    "The first iPod was released in 2001.",
]
corpus_embeddings = encoder.encode(corpus, normalize_embeddings=True)
 
 
def retrieve(question, top_k=2):
    q_emb = encoder.encode([question], normalize_embeddings=True)
    sims = (corpus_embeddings @ q_emb.T).squeeze()
    order = np.argsort(-sims)[:top_k]
    return [corpus[i] for i in order]
 
 
def answer(question):
    passages = retrieve(question, top_k=2)
    combined = " ".join(passages)
    return qa(question=question, context=combined)
 
 
print(answer("When was the first iPhone released?"))

It's a two-stage pipeline: a dense retriever (Sentence-BERT) finds relevant passages by semantic similarity, and an extractive reader (RoBERTa-SQuAD) pulls the answer span out of the combined top passages. This works fine on small corpora. Once you're past a million documents, reach for FAISS (a library built for fast nearest-neighbor search over embeddings) or a vector database instead.

Step 3: generative with RAG

python
def rag_generate(question, llm):
    passages = retrieve(question, top_k=3)
    prompt = f"""Context:
{chr(10).join('- ' + p for p in passages)}
 
Question: {question}
 
Answer using only the context above. If the context does not contain the answer, say "I don't know."
"""
    return llm(prompt)

The prompt pattern matters more than people expect. Telling the model explicitly to ground its answer in the context, and to say "I don't know" when the context doesn't cover it, cuts hallucination rates by 40-60% compared to naive prompting. More elaborate patterns go further and add citations, confidence scores, and structured extraction.

Step 4: evaluation that reflects the real world

SQuAD uses Exact Match (EM) and token-level F1. EM is a strict match after normalization (lowercase, strip punctuation, remove articles): either the prediction matches exactly or it scores 0. F1 is computed over token overlap between prediction and reference and gives partial credit. Both under-credit paraphrases. "June 29, 2007" vs "June 29th, 2007" typically gets 0 EM, since the ordinal breaks normalization, but still earns substantial F1 from overlapping tokens.

For production QA:

  • Answer accuracy (LLM-judged or human-judged, since metrics don't capture semantic equivalence).
  • Citation accuracy. Does the cited passage actually support the answer? That's trivial to check automatically: string-match the generated citations against the retrieved passages.
  • Refusal calibration. When the answer isn't in the retrieved passages, does the system correctly say "I don't know"? Track the false confidence rate.
  • Retrieval recall. Before you evaluate the reader at all, measure whether the retriever gets the right passage into the top-k. A reader can't fix a passage that was never retrieved.

RAGAS: the 2026 production eval framework

RAGAS is purpose-built for RAG systems, and it's the shipping default in 2026. It scores four dimensions without needing gold references:

  • Faithfulness. Does each claim in the answer come from the retrieved context? Measured by NLI-based entailment (natural language inference: whether the context logically supports the claim, or contradicts it, or says nothing about it). This is your primary hallucination metric.
  • Answer relevance. Does the answer address the question? Measured by generating hypothetical questions from the answer and comparing them to the real one.
  • Context precision. Of the retrieved chunks, what fraction were actually relevant? Low precision means noise sitting in the prompt.
  • Context recall. Did the retrieved set contain everything needed to answer? Low recall means the reader never had a chance.

Reference-free scoring means you can evaluate live production traffic without curated gold answers. Layer an LLM-as-judge on top for open-ended questions where exact-match metrics fall apart.

pip install ragas, plug in your retriever and reader, and you get four scalars per query to alert on.

Check: Build It0/21
1. On SQuAD, what does Exact Match (EM) measure?Define
2. What does refusal calibration mean for a QA system?Define
3. What does training on SQuAD 2.0, as deepset/roberta-base-squad2 was, make possible?Explain
4. Which RAGAS dimension targets hallucinations specifically?Explain
5. Besides faithfulness, which three dimensions does RAGAS score?Explain
6. What does low context precision tell you about a RAG system?Explain
7. Why does it matter that RAGAS scores need no gold references?Explain
8. Why should you measure retrieval recall before evaluating reader accuracy?Explain
9. Which prompt pattern reduces hallucinations in RAG generation?Explain
10. What do citation accuracy and refusal calibration measure in production QA evaluation?Explain
11. A SQuAD2-trained pipeline gets a question its passage cannot answer, and you call it with default arguments. What does it return?Apply
12. The reference answer is "June 29, 2007" and the prediction is "June 29th, 2007". What do EM and F1 report?Apply
13. In the Step 2 answer() function with top_k=2, what context string does the reader receive?Apply
14. rag_generate calls retrieve with top_k=3. How does the context appear in its prompt?Apply
15. Your Step 2 pipeline works on a small corpus, and the corpus is now growing past a million documents. What is the lesson's fix?Apply
16. A RAG service shows low faithfulness but high context recall. What is the most likely problem?Analyze
17. A team reports excellent reader scores, but live users get many wrong answers and nobody has measured the retriever. Which step was skipped?Analyze
18. A demo bot answered with total confidence about a topic absent from the documents, yet its SQuAD EM and F1 looked fine. Which metric would have exposed this?Analyze
19. A QA model scores 41 EM but 73 F1 on SQuAD, and reviewers judge most of its answers correct. What best explains the gap?Analyze
20. A live RAG service has no gold answers, and you need alerts on hallucination and on missing context. What should you set up?Design
21. You can ship only one guardrail before launching a RAG assistant, and an earlier demo answered confidently when the documents had no answer. Which do you build first?Design

Use It

Here's the 2026 stack.

Use caseRecommended
Given passage, find answer spandeepset/roberta-base-squad2
Over a fixed corpus, closed-book not acceptableRAG: dense retriever + LLM reader
Real-time over a document storeRAG with hybrid (BM25, a classic keyword-ranking algorithm, + dense) retriever + reranker (lesson 14)
Conversational QA (follow-up questions)LLM with conversation history + RAG on each turn
Highly factual, regulated domainsExtractive over an authoritative corpus; never generative alone

Extractive QA is unfashionable in 2026 because RAG with LLMs simply handles more cases. It still ships wherever literal quotation is non-negotiable: legal research, regulatory compliance, audit tools.

Check: Use It0/4
1. When is extractive QA still preferred over generative RAG in 2026?Explain
2. A support bot must answer follow-up questions over company docs across several turns. Which stack does the table recommend?Apply
3. You need real-time answers over a large document store with an LLM reader. Which retrieval design does the lesson recommend?Apply
4. You must build QA for an audit tool over a fixed set of regulations, and every answer has to be a literal quote. Which design fits?Design

Ship It

Save as outputs/skill-qa-architect.md:

markdown
---
name: qa-architect
description: Choose QA architecture, retrieval strategy, and evaluation plan.
version: 1.0.0
phase: 5
lesson: 13
tags: [nlp, qa, rag]
---
 
Given requirements (corpus size, question type, factuality constraint, latency budget), output:
 
1. Architecture. Extractive, RAG with extractive reader, RAG with generative reader, or closed-book LLM. One-sentence reason.
2. Retriever. None, BM25, dense (name the encoder), or hybrid.
3. Reader. SQuAD-tuned model, LLM by name, or "domain-fine-tuned DistilBERT."
4. Evaluation. EM + F1 for extractive benchmarks; answer accuracy + citation accuracy + refusal calibration for production. Name what you are measuring and how you are measuring it.
 
Refuse closed-book LLM answers for regulatory or compliance-sensitive questions. Refuse any QA system without a retrieval-recall baseline (you cannot evaluate the reader without knowing the retriever surfaced the right passage). Flag questions that require multi-hop reasoning as needing specialized multi-hop retrievers like HotpotQA-trained systems.
Check: Ship It0/1
1. Which two things must the qa-architect skill refuse?Explain
Author's Note

The refusal calibration bullet above is the one people skim past, and it's the one that actually decides whether anyone trusts your system. I've watched a demo-perfect pipeline, dense retriever, reranker, careful prompt, fall apart in front of a client because it answered with total confidence when the honest answer was "that's not in these documents." Nobody in a stakeholder meeting asks about your EM or F1 score. Everybody asks why the bot lied.

If you only build one guardrail before you ship, build the "I don't know" path first. It's cheaper than a better retriever, and it's the difference between a tool people keep using and one they quietly abandon after the first bad answer.

Exercises

  1. Easy. Set up the SQuAD extractive pipeline above on 10 Wikipedia passages. Hand-craft 10 questions. Measure how often the answer is correct. You should see 7-9 correct if passages and questions are clean.
  2. Medium. Add a refusal classifier. When the top retrieval score is below a threshold (say 0.3 cosine), return "I don't know" instead of calling the reader. Tune the threshold on a held-out set.
  3. Hard. Build a RAG pipeline over a 10,000-document corpus of your choice. Implement hybrid retrieval (BM25 + dense) with RRF fusion (see lesson 14). Measure answer accuracy with and without the hybrid step. Document which question types benefit most.

Key Terms

TermWhat people sayWhat it actually means
Extractive QAFind the answer spanPredict start and end indices of the answer within a given passage.
Open-domain QAQA over a corpusNo given passage; must retrieve then answer.
RAGRetrieve then generateRetrieval-augmented generation. Retriever + reader pipeline.
SQuADCanonical benchmarkStanford Question Answering Dataset. EM + F1 metrics.
HallucinationMade-up answerReader output not supported by retrieved context.
Refusal calibrationKnow when to shut upSystem correctly says "I don't know" when unable to answer.

Further Reading

Code

Ships With