Natural Questions

Natural Questions (NQ / NQ-Open)

Tests whether a model can answer real Google search questions from memory, without being shown any document.

Released Jan 2019 Metric NQ-Open test exact match (retrieval-augmented) SOTA 60.4 · Atlas (2022)
01

At a glance

Task
Original: long answer (paragraph) + short answer (span) from a Wikipedia page. NQ-Open: short answer with no page given
Size
307k train / 7.8k dev / 7.8k test; NQ-Open 79k train / 3.6k test
Metric
Exact match (after normalisation) against up to 5 reference short answers
Source
Anonymised aggregated Google search queries; annotators find the answer in the top Wikipedia result
Licence
CC BY-SA 3.0
Natural Questions: A Benchmark for Question Answering Research
Kwiatkowski et al. (Google) · TACL 2019
Read the paper ↗ Hugging Face ↗
02

What it tests

Natural Questions are exactly that: questions real people typed into Google, with annotators marking where in the Wikipedia page the answer is. Unlike SQuAD, nobody wrote the question while looking at the passage, so the wording is natural and often sloppy.

The GPT papers use the closed-book flavour: give the model only the question and see if it produces the right short answer from what it memorised during pre-training. GPT-2 managed 4.1% exact match zero-shot; GPT-3 reached 29.9% few-shot, which at the time rivalled some retrieval systems.

That gap between 'answer from memory' (GPT-3, 29.9) and 'answer with retrieval' (Atlas, 60.4) is the clearest single argument for retrieval-augmented generation.

03

Examples

Items from the dataset (or representative items where the originals are not freely redistributable).

Question
who sings does he love me with reba
AnswerLinda Davis
Question
when was the last time the eagles won the superbowl
Answer2018 (Super Bowl LII, played February 2018 for the 2017 season)
Question
how many episodes are in chicago fire season 4
Answer23
04

Reported results

Scores reported on this benchmark, with the evaluation setting each one used.

SettingReportedContext
Zero-shot, question + 'A:', greedy4.1% EMThe 1.5B model answered 5.3× more questions correctly than the smallest; the paper lists its 30 most confident answers
Few-shot (64 examples), closed-book29.9 EMZero-shot 14.6, one-shot 23.0; open-domain SOTA then 44.5 (RAG), closed-book T5-11B 36.6
05

State of the art

Best known · NQ-Open test exact match (retrieval-augmented)
60.4
no human baseline
Model
Atlas (Izacard et al.)
2022
Human baseline
not standardised

Closed-book few-shot LLMs: Llama 3.1 405B 41.5 (5-shot), PaLM 540B 39.6. Retrieval remains worth ~20 points. Source: arxiv.org ↗ · checked October 2026.

06

Quickstart

Load the benchmark and score a Hugging Face causal LM on it in a few lines.

1Install
shell
pip install -U datasets transformers evaluate lm-eval sacrebleu rouge-score scikit-learn
2Load the data

question, answer (list of acceptable strings). The full NQ (`google-research-datasets/natural_questions`) is ~40 GB with HTML pages — use nq_open for closed-book evaluation.

python · load
from datasets import load_dataset

ds = load_dataset("google-research-datasets/nq_open", split="validation")
print(ds)            # columns: question, answer (list of acceptable strings)
print(ds[0])
3Score a model

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.

python · helpers
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
python · evaluate
import re, string
def norm(s):
    s = s.lower(); s = "".join(c for c in s if c not in string.punctuation)
    s = re.sub(r"\b(a|an|the)\b", " ", s); return " ".join(s.split())
FEW = "Q: who wrote the novel 1984?\nA: George Orwell\n\nQ: what is the capital of australia?\nA: Canberra\n\n"
em = 0
for ex in ds:
    golds = ex.get("answer") or ex.get("answers") or ex["answer"]["aliases"]
    pred = generate(FEW + f"Q: {ex['question']}\nA:", max_new_tokens=16, stop="\n")
    em += int(norm(pred) in {norm(g) for g in golds})
print("exact match", em / len(ds))
4Or use lm-evaluation-harness

Task name(s): nq_open. The harness reproduces the GPT-3 prompt formats and reports the standard metric.

shell
lm_eval --model hf --model_args pretrained=gpt2,dtype=bfloat16 \
        --tasks nq_open --num_fewshot 0 --batch_size auto --output_path results/
07

Pitfalls

  • Normalise before matching: lower-case, strip articles and punctuation (the standard SQuAD normaliser).
  • Many answers are time-sensitive ('who is the current …'); the gold is as of 2018–2019.
  • Closed-book numbers are only comparable at the same shot count and with the same answer-length cap (GPT-3 used a short-answer prompt).
08

References