Golden set
A fixed, versioned set of realistic inputs with known-good answers or relevant documents, used to score every change the same way.
A golden set is your answer key. It is a list of real-looking questions, each paired with what a correct result looks like: the documents that should be found, the facts the answer must contain, or a rubric. Every time you change a prompt, a model or the retrieval, you rerun the same set and compare scores, so you know whether you improved things or broke them.
A chef's tasting menu that never changes, cooked after every kitchen change, so you can taste whether the new oven made things better or worse.
Writing the golden set yourself from the documents. Author-written questions reuse the documents' wording, so lexical retrieval looks great and real user phrasing fails.
Build from real traffic first (sampled logs, support tickets, search queries), then add synthetic items only to fill gaps you can name. Each item carries: input, expected relevant chunk ids (for retrieval metrics like Recall@k and nDCG), expected answer facts or a Rubric, and tags (intent, difficulty, language, answerable/unanswerable, facts-needed). Size it from the confidence interval you need: at accuracy p ≈ 0.8, the 95% CI half-width is 1.96·√(p(1−p)/n): ±5.5 points at n = 200, ±3.5 at n = 500, ±2.5 at n = 1,000. Version it in git, freeze a held-out split nobody tunes on, and refresh quarterly from new failure clusters found in Error analysis. Leakage is the silent killer: if items are also in few-shot examples or fine-tuning data, scores inflate (Benchmark contamination).
200–500 items sampled from production logs, stratified by intent, 10–15% unanswerable; two labellers on 20%+ of items with κ reported; JSONL in git with a schema and a version tag; 70/30 dev/holdout split; quarterly refresh from error-analysis clusters.
Code-search assistant for a 3M-line monorepo. v1 golden set: 320 items from six weeks of search logs, stratified across 'where is X defined' (90), 'how do I call Y' (110), 'why does Z fail' (70), cross-repo (30) and unanswerable (20). Each lists 1–4 relevant file paths plus required answer facts. Two engineers labelled independently; disagreements on 11% were adjudicated. A dev split of 220 is used for tuning; 100 are held out and only run before releases.
Say: I start from 200–300 items sampled from real logs, stratified by intent, with 10–15% unanswerable, labelled by two people, and I size it by the CI I need to detect the change I care about. Expect: 'how do you keep it from going stale?' Quarterly refresh from production failure clusters, plus a frozen holdout to catch overfitting to the dev split.
| Query (from logs) | Relevant files | Must mention | Tags |
|---|---|---|---|
| where is retry backoff set | net/retry.go | maxDelay 30s | where-defined |
| call billing svc from py | sdk/billing.py | idempotency key | how-to-call |
| why does make test hang | ci/README.md | docker socket | why-fails |
| deploy to mars region | — | abstain | unanswerable |
Numbers worth knowing
- 95% CI half-width
- ±5.5 / ±3.5 / ±2.5 pointsn = 200 / 500 / 1,000 at p ≈ 0.8
- Labelling time
- 3–6 min per itemretrieval ids + answer facts, domain-literate labeller
- Refresh cadence
- quarterly, 10–20% new itemsproducts with changing corpus or users
How to decide
| When | Do this |
|---|---|
| No production traffic yet | Write 100 items with domain experts, mark them provisional, replace with log samples within a month |
| Need to detect a 2-point change | n ≈ 1,500+ or a paired test on the same items |
| Multiple tenants or languages | Stratify and report per slice; a global mean hides regressions |
Cost maths
Labelling cost = n × minutes per item × hourly rate. 400 items × 5 min × $60/h = $2,000, plus 20% double-labelling = $2,400. Quarterly refresh of 15% ≈ $360. Compare with one bad release that a 3.5-point CI would have caught.
Operating it
- Release decisions hinge on differences inside the CI: grow n
- A new intent or tenant > 10% of traffic is not represented
- Dev-split score rising while holdout is flat: overfitting, refresh dev
- Dev vs holdout score gap; alert > 3 points
- Age of newest item; alert if > 120 days
- Share of production intents with < 20 golden items; review monthly
When it goes wrong
Golden-set accuracy rose from 81% to 89% over three months; user thumbs-down rate did not move
Quarterly holdout run: 80%, unchanged from the start
Prompt tweaks and few-shot examples had been tuned on the dev split for 40 iterations; several golden items had been copied into few-shot examples
Removed leaked items, rotated a fresh dev split from recent logs, and added a CI check that fails if any golden input appears in prompts or training data
Related terms
Where it shows up
Sources
- Your AI Product Needs Evals — Husain, 2024blog
- BEIR: A Heterogenous Benchmark for Zero-shot Evaluation of Information Retrieval Models — Thakur et al., 2021paper
- Introduction to Information Retrieval (ch. 8, Evaluation) — Manning, Raghavan & Schütze, 2008book
Check yourself
Three questions. Every option is explained once you answer.