
LLM Evaluation With Golden Datasets: The Only Way to Ship With Confidence
How to build a golden dataset, when to use LLM-as-judge vs rules vs humans, and the CI setup that catches regressions before your users do.
A golden dataset — a small, hand-curated set of inputs with known correct behavior — is the single artifact that turns 'LLM development' into engineering. Build it early, grow it every incident, run it in CI. Every LLM feature I've shipped without one has embarrassed me.
- Start with 20 examples, not 2000. A small careful set beats a large sloppy one.
- Categorize examples by scenario — 'easy happy path', 'edge case', 'known past bug', 'adversarial'.
- Rule-based checks first (regex, exact match, JSON schema), LLM-judge only when necessary.
- Every production incident becomes a new golden example. That's how the set grows meaningfully.
- Run evals on every prompt/model change. Block deploys on regressions past a threshold.
The core artifact
A golden dataset is a versioned file — YAML, JSONL, or a database table — where each row is: an input, one or more assertions about what a correct output looks like, and metadata (category, priority, source). Nothing more.
- id: refund_simple
category: happy_path
input: 'Can I get a refund for order 12345 shipped last week?'
assertions:
- kind: mentions_order
value: '12345'
- kind: intent
value: 'refund_request'
- kind: no_hallucinated_policy
forbidden_phrases: ['30-day guarantee', 'lifetime warranty']
- id: refund_expired_ambiguous
category: edge_case
input: 'This is old — bought it a year ago, hardly used it, want money back'
assertions:
- kind: escalate_to_human
required: trueRules first, LLM-judge second
The instinct is to grade every output with GPT-5. It's slow, expensive, and noisy. Ninety percent of assertions can be checked with deterministic rules:
- Exact match / substring — 'response contains order ID'.
- JSON schema — 'response parses to {intent: string, confidence: number}'.
- Regex — 'response contains a valid ISO date'.
- Forbidden list — 'response does not mention competitor names'.
- Length bounds — 'response is 50-500 tokens'.
Use LLM-as-judge only for genuinely subjective assertions — tone, factuality against a source doc, semantic equivalence. When you do, pin the judge model (don't 'use the latest') and periodically calibrate against human labels.
The 20-example starter
Don't wait for a labeling budget. Start with 20 examples you write yourself:
- 5 easy happy-path cases (the demos you'd show your CEO).
- 5 edge cases you already know are tricky.
- 5 real user inputs from logs or beta.
- 3 adversarial cases (prompt injection attempts, weird formatting, empty inputs).
- 2 'never do this' cases (things the last version regressed on).
Twenty examples take an afternoon. They will catch 80% of the regressions the next big prompt change would have shipped. Everything after this is refinement.
The CI pipeline
# .github/workflows/llm-evals.yml
on: pull_request
jobs:
evals:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements.txt
- run: python -m evals.run --dataset golden.yaml --out results.json
- run: python -m evals.compare --baseline main --results results.json
# fails if pass rate drops more than 2% on any category
- uses: actions/upload-artifact@v4
with: { name: eval-report, path: results.json }On every PR that touches a prompt, a model choice, or the retrieval stack, the workflow runs the golden set, compares to the baseline on main, and posts a comment. Regressions past a threshold block the merge.
Growing the dataset from incidents
Every production incident where the LLM did something wrong becomes a new row in the golden set — with the fix as an assertion. This is the single practice that turns a 'nice to have' eval suite into an ever-improving safety net.
Set a runbook step: 'after every LLM incident, add the offending input as a golden example within 48 hours'. Assign the on-call. In a year you'll have 200-500 examples covering exactly the failure modes your users actually hit — infinitely more valuable than a benchmark someone else designed.
What LLM-as-judge is actually good at
Reserve LLM judges for the assertions rules can't check:
- Factuality against a specific source document ('does this response state anything not in the doc?').
- Semantic equivalence for open-ended responses ('does this convey the same answer as the gold reference?').
- Tone and register ('is this professional but warm?').
- Multi-turn coherence.
Use structured judges: prompt the judge for a JSON verdict with a rubric, temperature 0. Calibrate weekly by having a human label 30 random cases and comparing agreement. When it drops below 85%, retune the judge prompt or swap the model.
Frequently asked
How big should the golden set get?
300-1000 examples is plenty for most production apps. Past that, marginal value drops fast and CI time balloons.
Should I share the golden set with the model in the prompt?
Never. That's data leakage — you'll get artificially high scores that don't generalize.
How often should I refresh it?
Add on every incident. Prune when an example stops distinguishing between prompt versions (everyone passes it) — replace it with something harder.
Building something similar?
I help teams ship production-grade AI agents, n8n workflows, and data platforms. Let's talk about what you're building.
Work with me
Islam Gamal
AI, Data & Automation Engineer. I design and ship production AI agents, n8n workflows, and cloud data platforms — with a focus on reliability, cost, and measurable business impact. Founder of Tashghil and Tek bil Arabi.
More from Islam Gamal
Evaluating LLMs and Classical ML: A Practical Metrics Guide
The metric you pick decides the model you ship. A deep field guide to choosing, computing, and defending metrics for classification, ranking, generation, RAG, and agents — with the traps that catch senior teams.
Defending LLM Apps Against Prompt Injection: A Practical Playbook
Direct and indirect prompt injection, tool-use exploits, data exfiltration — and the layered defenses that actually work in production.
Agentic RAG: When Your Retriever Should Think Before It Searches
Query rewriting, sub-question decomposition, tool routing, and self-correction — the patterns that turn a static RAG pipeline into an agent that reasons about retrieval.
Browse every article by Islam Gamal on the author page.