Children's Book Test

Children's Book Test (CBT-CN / CBT-NE)

Tests whether a model can fill a missing word in a sentence from a children's book after reading the twenty sentences before it.

Released Nov 2015 Metric test accuracy SOTA 93.3 (CN) · 89.1 (NE) · GPT-2 1.5B (2019)
01

At a glance

Task
10-way cloze
Size
~670k train questions; 2,000 validation and 2,500 test per word type
Metric
Accuracy, reported separately for Common Nouns (CN), Named Entities (NE), verbs and prepositions
Source
108 children's books from Project Gutenberg
Note
GPT-2 found one test book (The Jungle Book) in its training data and excluded it
The Goldilocks Principle: Reading Children's Books with Explicit Memory Representations
Hill, Bordes, Chopra, Weston · ICLR 2016
Read the paper ↗ Hugging Face ↗
02

What it tests

CBT shows a model 20 sentences of a children's story, then a 21st sentence with one word removed and ten candidate words taken from the context. The question is which candidate fits.

The authors split results by the kind of word removed. Verbs and prepositions are easy for any language model (local syntax decides). Named entities and common nouns need the story — who is in the scene, what object was mentioned — so CN and NE are the numbers people report.

GPT-2 scored each candidate by the probability of the full sentence with that word filled in, reaching 93.3% on CN and 89.1% on NE zero-shot, above the human baseline of ~82%. It has rarely been used since.

03

Examples

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

CBT-NE
Context (last of 20 sentences)
…"I will give you a kingdom," said the King, "if you can find her." So the Prince set out on his travels…
Query
Then the ______ said to his servant, "Bring me my horse."
Candidates
King · Prince · servant · kingdom · horse · travels · …
AnswerPrince (representative item, paraphrased)
CBT-CN
Query
She put the ______ on the table and went to fetch the milk.
Candidates
bowl · door · cat · window · road · …
Answerbowl (representative)
04

Reported results

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

SettingReportedContext
Zero-shot (1.5B); candidate scored by full-sentence probabilityCN 93.30NE 89.05Prior SOTA 85.7 / 82.3; human 81.6 (CN) / 81.6 (NE)
05

State of the art

Best known · test accuracy
93.3 (CN) · 89.1 (NE)
✓ saturated · at or above human level
Model
GPT-2 1.5B (zero-shot)
2019
Human baseline
~81.6

Benchmark effectively retired after GPT-2; later models do not report it. Source: cdn.openai.com ↗ · 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

sentences (list of 20), question (contains 'XXXXX'), answer, options (10 candidates). Configs: CN, NE, V, P, raw.

python · load
from datasets import load_dataset

ds = load_dataset("cam-cst/cbt", "CN", split="test")
print(ds)            # columns: sentences (list of 20), question (contains 'XXXXX'), answer, options (10 candidates)
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
acc = 0
for ex in ds:
    ctx = " ".join(ex["sentences"]) + " "
    s = [loglik(ctx, ex["question"].replace("XXXXX", o)) for o in ex["options"]]
    acc += int(ex["options"][s.index(max(s))] == ex["answer"])
print("accuracy", acc / len(ds))
07

Pitfalls

  • Score the full query sentence with each candidate substituted, not just the candidate token.
  • Check for overlap with your pre-training data (Project Gutenberg is in most corpora).
  • Report CN and NE; V and P are near-ceiling for any LM.
08

References