SQuAD 2.0
Tests whether a model can find the answer to a question in a Wikipedia paragraph, or recognise when the paragraph does not contain it.
At a glance
What it tests
SQuAD 1.1 was the dataset that made extractive QA a mainstream task: read a Wikipedia paragraph, highlight the span that answers the question. Models passed human performance on it within two years, largely because every question had an answer and the answer was always a span.
SQuAD 2.0 adds questions that are plausible but unanswerable from the paragraph — same entities, same wording style, but the paragraph does not actually say. A model now has to decide whether to answer at all, which is a very different skill from locating a span.
GPT-3 evaluated it few-shot and reached 69.8 F1, far below fine-tuned systems. The benchmark has since been saturated by fine-tuned ensembles.
Examples
Items from the dataset (or representative items where the originals are not freely redistributable).
Reported results
Scores reported on this benchmark, with the evaluation setting each one used.
| Setting | Reported | Context |
|---|---|---|
| Few-shot (16 examples) | 69.8 F1 | Zero-shot 59.5; fine-tuned SOTA then 93.0 |
State of the art
Source: rajpurkar.github.io ↗ · checked October 2026.
Quickstart
Load the benchmark and score a Hugging Face causal LM on it in a few lines.
pip install -U datasets transformers evaluate lm-eval sacrebleu rouge-score scikit-learn
context, question, answers (text list, answer_start list — empty lists mean unanswerable)
from datasets import load_dataset ds = load_dataset("rajpurkar/squad_v2", split="validation") print(ds) # columns: context, question, answers (text list, answer_start list — empty lists mean unanswerable) print(ds[0])
Two helpers cover every benchmark in this collection: loglik for anything multiple-choice (score each option, pick the highest) and generate for anything free-form. Swap MODEL for whatever you are evaluating.
import torch from transformers import AutoTokenizer, AutoModelForCausalLM MODEL = "gpt2" # or "Qwen/Qwen2.5-1.5B", "meta-llama/Llama-3.2-1B", … tok = AutoTokenizer.from_pretrained(MODEL); model = AutoModelForCausalLM.from_pretrained(MODEL, torch_dtype=torch.bfloat16).eval().to("cuda") @torch.no_grad() def loglik(context, continuation): """Sum of log-probs of `continuation` tokens given `context` — the standard multiple-choice scorer.""" ids = tok(context + continuation, return_tensors="pt").input_ids.to(model.device) n_ctx = len(tok(context).input_ids) logp = model(ids).logits.log_softmax(-1)[0, :-1] return logp.gather(1, ids[0, 1:, None])[n_ctx - 1:].sum().item() @torch.no_grad() def generate(prompt, max_new_tokens=32, stop=None): ids = tok(prompt, return_tensors="pt").input_ids.to(model.device) out = model.generate(ids, max_new_tokens=max_new_tokens, do_sample=False, pad_token_id=tok.eos_token_id) text = tok.decode(out[0, ids.shape[1]:], skip_special_tokens=True) return text.split(stop)[0] if stop else text
import evaluate metric = evaluate.load("squad_v2") # for DROP use the official drop_eval.py from allenai/allennlp-reading-comprehension preds, refs = [], [] for ex in ds: p = f"{ex['context'] if 'context' in ex else ex['passage']}\nQuestion: {ex['question']}\nAnswer (or 'unanswerable'):" out = generate(p, max_new_tokens=32, stop="\n").strip() preds.append({"id": ex["id"], "prediction_text": "" if out.lower().startswith("unanswerable") else out, "no_answer_probability": float(out.lower().startswith("unanswerable"))}) refs.append({"id": ex["id"], "answers": ex["answers"]}) print(metric.compute(predictions=preds, references=refs))
Task name(s): squadv2. The harness reproduces the GPT-3 prompt formats and reports the standard metric.
lm_eval --model hf --model_args pretrained=gpt2,dtype=bfloat16 \
--tasks squadv2 --num_fewshot 0 --batch_size auto --output_path results/Pitfalls
- Report HasAns and NoAns F1 separately; a model that always abstains gets ~50 F1 overall.
- Use `evaluate.load('squad_v2')` — it needs a `no_answer_probability` per prediction.
- Few-shot prompting needs an explicit 'unanswerable' verbalisation; GPT-3 used the text 'unanswerable'.
References
- Paper (arXiv 1806.03822)https://arxiv.org/abs/1806.03822
- Leaderboardhttps://rajpurkar.github.io/SQuAD-explorer/
- Hugging Facehttps://huggingface.co/datasets/rajpurkar/squad_v2