Lesson 1 · AI Evaluation · Foundation

Evaluation Fundamentals: Offline & Online

~14 min · 3 modules · why measurement is the moat, the offline/online split, and the loop that gates every ship

Published

Offline evalOnline evalLLM-as-judgeGolden setsEval loop

Your bar: explain why evaluation — not the model — is the real moat, draw the line between offline eval (a fixed dataset, repeatable, run before you ship) and online eval (live traffic, A/B and shadow, measured after you ship), and walk the loop that turns a production failure into a permanent regression test. By the end you can answer the question every AI team eventually faces: how do you know a change made the system better instead of just different? 1

The whole discipline reduces to four moves. Each chip is one of them:

You can’t improve what you can’t measure

score offline against a fixed golden set before you ship

score online on live traffic after you ship

feed every failure back into the golden set

1 · Collect golden cases 2 · Score prog / human / judge 3 · Diff vs baseline 4 · Ship / roll back decide on the number 5 · Feed failures back into the golden set — the loop closes OFFLINE — before you ship fixed dataset · repeatable · runs in CI · gates the merge same inputs every run ONLINE — after you ship live traffic · A/B + shadow real distribution The model is a commodity. The dataset of what 'good' means for your task is the moat. Offline tells you it's safe to ship. Online tells you it actually worked. You cannot improve what you cannot measure.
The eval loop in one frame. Collect cases, score them, diff against a baseline, ship or roll back, and feed failures back. Offline runs the loop on a fixed dataset before ship; online runs it on live traffic after.1
1

Why Evaluation Is the Moat

The model is a commodity — your competitor can call the same API. What you can’t copy is a curated dataset of what good means for your task and a measured baseline of how well you hit it. You cannot improve what you cannot measure. 2

Vibes don’t aggregate — they collapse at scale

Why "looks good to me" breaks ✗ Vibes-based a reviewer reads ~5 outputs "yeah, looks good" → ship no number to compare to last week a 3% regression is invisible — and silent across millions of calls ✓ Measured score every change on a golden set diff vs baseline → ship or roll back 82% → 79% = a blocked regression every change is a before/after diff — CI blocks it like a failing test 5 examples fit in a human's head. Millions of calls do not. (numbers illustrative)
Eyeballing a handful of outputs works at demo scale and quietly fails in production, where a small quality drop is thousands of bad answers nobody reads. Measurement is the only thing that scales with traffic.2

Is Evaluation = systematically scoring an AI system’s outputs against defined success criteria, so a change becomes a measured before/after instead of a guess. You evaluate the system, not just the model.

Why it exists Every prompt, model, retrieval, or tool change can silently help or hurt. Without a score you can’t tell which, can’t compare to last week, and can’t prove progress.

Like (world) A thermometer for a fever. You don’t argue about whether the patient “feels warm” — you read a number, treat, and read it again to see if the treatment worked.

Like (code) A regression test suite. Code without tests “works on my machine”; a green suite is the contract that a refactor didn’t break behavior. Eval is that contract for AI.

✗ “Our model is great, so the product is great — the model is the moat.”

✓ The model is a commodity anyone can call. The moat is your dataset of what “good” means for your task plus a measured baseline — that’s what a competitor can’t copy.

✗ “We reviewed a few outputs by hand; quality is fine.”

✓ Vibes work at 5 examples and collapse at scale. A 3% regression you’d never spot by eye is thousands of bad answers in production. (illustrative)

📥 Memory rule: You cannot improve what you cannot measure. The model is a commodity; the eval is the moat.

Memory check
  • Why is the model NOT the moat? → anyone can call the same API; the curated dataset of what's "good" for your task is the asset they can't copy
  • What does a score buy you that eyeballing doesn't? → a before/after diff — you can prove a change helped or blocked a regression, and it scales past what a human can read
  • What do you evaluate — the model or the system? → the whole system (prompt + retrieval + tools + model), because any of those can move quality

M1 — Your team ships LLM changes on “looks good to me.” Convince them evaluation is worth building.

Hit these points: you cannot improve what you cannot measure — without a score, every prompt or model change is a coin flip you can’t compare to the last one → vibes don’t aggregate: a reviewer eyeballs 5 outputs, a system serves millions, and “looks good” hides a small regression that’s thousands of bad answers → evaluation is the moat because the model is a commodity everyone can call; the asset is your dataset of what good looks like for your task → the minimum viable eval is a golden set of ~50 cases plus one grader plus a baseline number to diff against → the payoff: every change becomes a measured before/after, and CI can block a regression the way it blocks a failing unit test.

2

Offline Evaluation

Offline eval scores the system against a fixed dataset — the golden set — before you ship. Same inputs every run, so it’s reproducible, runs in CI, and gates the merge. It’s the integration test suite for AI behavior. 3

The harness: dataset → runner → grader → report

The eval harness Golden dataset (input, expected) Runner execute per case Grader score each output Report aggregate score programmatic / exact-match LLM-as-judge (calibrated) human (gold labels) diff vs baseline better? ship · worse? block Same inputs every run → reproducible → lives in CI → a drop below baseline blocks the merge.
An eval harness is just a test framework for AI: a dataset, a runner that executes the system per case, a grader that scores each output, and a report you diff against the baseline. The golden set is your fixtures.3

Three ways to score a case

GraderHow it worksUse it when
ProgrammaticDeterministic check: exact-match, regex, JSON schema, tool succeededOutput is structured or has one right answer — cheapest, most reliable
LLM-as-judgeAn LLM scores / compares outputs against a rubricOpen-ended quality at scale — cheap, but biased; calibrate first
HumanA person applies a rubricGold labels & audits — the trusted source, but slow and costly

Golden set vs benchmark — don’t confuse them

DimensionGolden set (yours)Benchmark (public)
Purpose

Is the system right for your task?

Compare models against each other
DataPrivate, curated, your real inputsShared, public (MT-Bench, HELM)
TrustHigh — you hand-checked itRots: contamination, saturation
RoleGates your shipShortlists candidate models

Is Offline eval = scoring the system against a fixed golden set before shipping. Reproducible, gated in CI. A golden set is a versioned set of (input, expected / acceptance-criteria) cases, changed only by deliberate review.

Why it exists You need a repeatable, pre-ship signal that a change helped or hurt — one you can re-run on every commit and block a merge on, exactly like a unit test.

Like (world) A drug trial against a fixed cohort: same patients, same protocol, run again after each formulation change so the only variable is the change itself.

Like (code) Snapshot / golden-file tests: a curated set of fixtures with expected outputs; CI fails the build when the new output diverges from the approved snapshot.

✗ “A bigger golden set is always better — dump in every log line.”

✓ Small and hand-checked beats large and noisy. The golden set is fixtures: representative, labeled, versioned, changed only by review — not a raw traffic dump.

✗ “We scored high on the public benchmark, so we’re good.”

✓ Benchmarks measure a generic task and rot via contamination (test data leaked into training = memorization, not skill). A private golden set predicts your production.

📥 Memory rule: Offline = fixed dataset, repeatable, pre-ship, gates the merge. Build the harness once; diff every change vs the baseline.

Memory check
  • What makes offline eval reproducible? → a fixed dataset — same inputs every run, so the only variable is your change
  • What are the four parts of an eval harness? → dataset + runner + grader + report; you diff the report against a baseline
  • Golden set vs benchmark? → golden = your private curated fixtures that gate your ship; benchmark = shared public data to compare models, and it rots
M2 — Walk me through building an offline eval for a support assistant from scratch.

Hit these points: define success criteria per task before writing cases — what’s a pass, what’s a fail, in measurable terms → collect a golden set of real, representative inputs paired with expected outputs or acceptance criteria; keep it small, hand-checked, versioned like test fixtures → pick a grader per case: exact-match / programmatic where structured, LLM-as-judge where open-ended, humans for the gold labels → run the harness (dataset → runner → grader → report) → establish a baseline number, then every change is a diff vs that baseline → wire it into CI so it gates the merge → name the limit: a fixed dataset can’t catch what you didn’t think to put in it — which is why you also need online eval.

3

Online Evaluation & Closing the Loop

Offline only measures the distribution you captured. Online eval measures quality on live traffic after you ship — in two shapes: A/B (real users see the variant, you compare outcomes) and shadow (run the new system in parallel, discard its output, zero user risk). 4

Shadow vs A/B — safety vs signal

Two shapes of online eval Shadow live traffic old → user new (parallel) output discarded zero user risk no live conversion signal A/B test split users 50% → old (control) 50% → new (variant) real outcome signal (conversion) some users see a worse experience Common sequence: shadow first to confirm no regressions → then A/B to measure the real lift.
Shadow buys safety (no user ever sees the new output) but gives no business signal; A/B buys a real outcome signal but exposes some users to a possibly-worse variant. Run shadow first, then A/B.4

LLM-as-judge — a cheap sensor you must calibrate

LLM-as-judge: scale, but biased Known biases position (favors 1st) verbosity (favors longer) self-preference (own family) a preference may be an artifact calibrate Calibrate vs humans measure judge–human agreement on a labeled slice randomize order · force a rubric ~80% agreement is illustrative Then trust it use as a cheap sensor to scale scoring confirm close calls with humans
A judge is a noisy, cheap sensor that scales human judgment — not a replacement for it. A strong judge can reach roughly human-level agreement on some tasks, but that's dataset-dependent; calibrate before you let it gate anything.5

Offline ↔ online — complementary, not rivals

DimensionOfflineOnline
DataFixed golden setLive production traffic
WhenBefore ship (gates the merge)After ship (measures reality)
Repeatable?Yes — same inputs every runNo — traffic drifts constantly
Blind spotOnly what you put in the setCan’t gate a deploy that hasn’t happened

Is Online eval = measuring quality on live traffic after shipping. A/B splits real users between old and new and compares outcomes; shadow runs the new system in parallel and discards its output.

Why it exists A fixed dataset can’t cover what you never imagined. Real traffic drifts and surfaces failure classes the golden set missed — online is the only honest signal of production quality.

Like (world) Crash-test dummies (offline, repeatable lab) vs real-world accident data (online, messy but true). You need both: the lab to gate the design, the road to find what the lab missed.

Like (code) Tests in CI (offline) vs production observability / canary releases (online). Green CI lets you deploy; metrics and canaries tell you it actually worked under load.

✗ “Offline eval is green, so we’re done — ship and move on.”

✓ Green offline + unhappy users = a coverage gap, not a broken eval. Add online signals and fold the failing live cases back into the golden set.

✗ “The LLM judge scored the new prompt higher, so it’s better. Ship it.”

✓ An uncalibrated judge has biases (position, verbosity, self-preference). Measure its agreement with humans first; otherwise it ships regressions confidently.

📥 Memory rule: Offline gates the ship; online proves it worked. Feed every production failure back into the golden set — the loop closes.

Memory check
  • Shadow vs A/B in one line each? → shadow = run new in parallel, discard output, zero user risk; A/B = split real users, they see the variant, you get an outcome signal
  • Why must you calibrate an LLM judge? → it has position / verbosity / self-preference bias; measure its agreement with human labels before trusting it to gate
  • How does the loop close? → harvest failing live cases, label them, fold them into the golden set so the next offline run catches that class
M3 — Offline eval is green but users complain after you ship. What happened and what do you add?

Hit these points: offline eval only measures the distribution you captured in the golden set — real traffic drifts and hits inputs you never fixtured → green offline + unhappy users = a coverage gap, not a broken eval → add online evaluation: A/B split real users between old and new and compare outcomes, or run the new system in shadow (same traffic, output discarded) to compare safely with zero user risk → instrument production signals: thumbs-down, regenerate-rate, escalation-to-human, task completion → close the loop: harvest the failing live cases, label them, fold them into the golden set so the next offline run catches that class → the two are complementary — offline is repeatable and pre-ship, online is real and post-ship.

M3 — Your LLM-as-judge gives a new prompt a higher score, so you ship. The judge was wrong. How do you prevent this?

Hit these points: an LLM judge is itself a model with biases — position (favors the first option), verbosity (favors longer answers), self-preference (favors its own family’s text) → never trust a judge you haven’t calibrated: measure its agreement against a human-labeled slice before letting it gate anything → a strong judge can reach roughly human-level agreement on some tasks, but that’s dataset-dependent and must be re-verified → mitigations: randomize option order, force a rubric / chain-of-thought, use a different model family as judge, anchor with reference answers → treat the judge as a cheap noisy sensor that scales human judgment, never a replacement for the gold labels it was calibrated against.

Retrieval-specific eval: RAG pipelines need their own metrics (faithfulness, context precision/recall). The retrieval-eval deep dive lives in Context Engineering · Lesson 6 — Retrieval Evaluation & Observability. This track generalizes evaluation to whole AI systems and agents.

Retrieval practice — test the three modules

Q1. The strongest argument that evaluation, not the model, is the moat is that…

Q2. What makes <em>offline</em> evaluation reproducible enough to gate a merge in CI?

Q3. The defining difference between a <em>shadow</em> deployment and an <em>A/B</em> test is that…

Q4. Before letting an LLM-as-judge gate a ship decision, you must first…

Q5. Offline eval is green but production users complain. The right next step is to…

Interview — pick your bar

Answer out loud in ~60s, then reveal. Core = recall · Senior = trade-offs & failure modes · Staff = synthesis under ambiguity · System Design = open design round (a different axis, not a harder level).

Why is evaluation called the real moat for an AI product?
Hit these points: the model is a commodity — any competitor can call the same API → what you can't copy is a curated dataset of what "good" means for your task and a measured baseline → you cannot improve what you cannot measure: without a score, every change is a guess and progress is unprovable → "vibes-based" eval works at 5 examples and collapses at scale, where a small regression is thousands of bad answers no human will eyeball → evaluation turns model changes into measured before/after diffs — the only way to improve reliably.
What is the difference between offline and online evaluation?
Hit these points: offline = score the system against a FIXED dataset (the golden set) BEFORE shipping; reproducible, runs in CI, gates a deploy — same inputs every run, like an integration test suite → online = measure quality on LIVE production traffic AFTER shipping; real distribution, real users → online has two shapes: A/B (split real users, they see the variant, you compare outcomes) and shadow (run the new system in parallel but discard output — no user risk, no live signal) → they're complementary: offline is repeatable but only covers what you captured; online is real but can't gate a deploy that hasn't happened.
What is a golden set and how is it different from a benchmark?
Hit these points: a golden set is a versioned, curated set of (input, expected-output / acceptance-criteria) cases that is YOUR ground truth for offline eval — small, hand-checked, treated like test fixtures, changed only by deliberate review → a benchmark is a shared, public dataset + metric used to compare models against EACH OTHER (MT-Bench, HELM scenarios) → the benchmark is a standardized exam: good for cross-model comparison, weak as a proxy for your task → benchmarks rot via contamination (test data leaked into training = memorization, not capability) → a fresh private golden set beats a public leaderboard for trusting a result on your problem.
What are the three ways to score an eval case, and when do you use each?
Hit these points: programmatic / exact-match — deterministic checks (regex, JSON schema, equals-expected, tool-succeeded); cheapest and most reliable, use whenever the output is structured or has one right answer → human grading — a person applies a rubric; the gold standard and the source of your gold labels, but slow and expensive, so reserve it for the golden set and audits → LLM-as-judge — an LLM scores or compares against a rubric; scales cheaply for open-ended quality, but biased and must be calibrated against human labels first → the stack: programmatic where you can, judge where you must, human to anchor both.
Offline eval passes but production users complain. Diagnose.
Hit these points: the golden set only covers the distribution you thought to capture; live traffic drifts and hits inputs you never fixtured — green offline + unhappy users is a coverage gap → confirm by sampling the complaints and checking whether those inputs even exist in the golden set (usually they don't) → add online signals: thumbs-down rate, regenerate rate, escalation-to-human, task completion, plus a shadow or A/B comparison of old vs new on real traffic → close the loop: harvest the failing live cases, label them, fold them into the golden set so the next offline run catches that class → the fix isn't "trust offline less" — offline and online cover different risks and you need both.
When do you use shadow deployment vs an A/B test for online evaluation?
Hit these points: shadow = run the new system on real traffic in parallel and THROW THE OUTPUT AWAY; users never see it, so zero user risk — use it when the change is risky, hard to roll back, or you only need to compare behavior, not measure conversion → A/B = split real users between old and new; users SEE the variant, so you get a real outcome signal (conversion, completion, satisfaction) but you've exposed some users to a possibly-worse experience → the trade: shadow gives safety but no business signal; A/B gives the business signal at real user cost → common sequence: shadow first to confirm no regressions, then A/B to measure the real lift.
Your LLM-as-judge prefers the new prompt. Should you trust it? Argue both sides.
Hit these points: the judge is a model with documented biases — position, verbosity, self-preference — so a preference can be an artifact, not real quality → trust it ONLY to the degree you've calibrated it: measure agreement against a human-labeled slice; a strong judge can reach roughly human-level agreement on some tasks, but that's dataset-dependent and must be re-verified → mitigations before trusting a gate: randomize order, force a rubric/CoT, use a different model family as judge, include reference answers → synthesis: the judge is a cheap noisy sensor that lets you scale human judgment to thousands of cases — use it to flag, confirm close calls with humans, never let an uncalibrated judge alone decide a ship.
A teammate wants to grow the golden set by dumping in every production log line. Push back.
Hit these points: the golden set is fixtures, not a data lake — its value is that every case is representative, labeled, and hand-checked, so a score on it means something → raw logs are unlabeled, redundant, and noisy; dumping them in inflates the suite, slows every run, and dilutes the signal without adding coverage → it also breaks the "changed only by deliberate review" property — silent growth means you no longer know what your baseline measures → the right move: sample from logs, especially failures and edge cases, label them, and add the ones that cover a class you don't already test → quality and coverage of the set beat raw size every time.
Map the full eval loop end to end: from a failing user report to a regression test that protects against it.
Hit these points: collect — gather representative cases, including failures harvested from production → score — apply the right grader per case (programmatic / human / LLM-judge) → diff — compare the aggregate score against the baseline to see better or worse → decide — ship if it's a measured win, roll back if it's a regression; offline gates the merge, online (A/B / shadow) confirms on live traffic → feed back — every production failure becomes a new labeled case in the golden set, so the next offline run catches that class → the loop is the point: it converts one-off failures into permanent regression coverage and makes quality a ratchet, not a coin flip → measure each stage (coverage, judge-human agreement, regression catch-rate) so the loop itself is trustworthy.
One eval system, three forces — speed, trust, coverage — that pull against each other. How do you reason about the trade-offs?
Hit these points: name the three: programmatic/judge graders give SPEED, human labels give TRUST, online + golden-set growth give COVERAGE → the tension: the fast graders (judge) are the least trusted, the trusted grader (human) is the slowest, and the most realistic signal (online) can't gate a pre-ship decision → sequence it: gold-label a small golden set with humans (trust), automate the bulk with programmatic + calibrated judge (speed), grow coverage by folding online failures back in → never trade an unmeasured risk for a measured saving: a cheap but uncalibrated judge is worse than no gate because it ships regressions confidently → measure the loop itself — judge-human agreement, offline coverage of real traffic, regression catch-rate — so you know which force is weakest.
"We hit 90% on the public benchmark, so we don't need our own eval." Tear this apart as a system design.
Hit these points: two unsafe assumptions → "benchmark = our task" is false: a public benchmark measures a generic task on shared data — it's a capability proxy, not a measure of YOUR inputs and YOUR success criteria → "a high score = real skill" is suspect: contamination means leaderboard test data leaks into training, so the rank can be memorization; benchmarks also saturate and rot as new models arrive → the right design: a private golden set of your real inputs + your graders gates the ship; benchmarks only shortlist candidate models cheaply → then confirm with shadow/A/B on live traffic → the framing: the leaderboard says a model is generally capable; only your eval says it's right for the job — teach the method, not the rank.
Design-round framework — narrate an eval strategy in this order so the interviewer hears criteria-first, then offline gate, then online reality, then the loop:
  1. Clarify scope: what's the task, what's the cost of a wrong answer vs a missed answer, is there ground truth, who can label?
  2. Define success criteria per task first — measurable pass/fail, not "good."
  3. Build a small, versioned golden set of real, representative (input, expected) cases, hand-labeled by humans.
  4. Choose graders: programmatic where structured, calibrated LLM-as-judge where open-ended, human for gold labels and audits.
  5. Stand up the harness (dataset + runner + grader + report), set a baseline, and wire offline regression eval into CI to gate the merge.
  6. Ship behind shadow first (no user risk), then A/B to measure real lift; instrument production signals (thumbs-down, regenerate, escalation, task success).
  7. Close the loop: route live failures back into the golden set; name risks — benchmark contamination, judge bias, coverage gaps — and measure the loop, not just the model.
Design an evaluation strategy for a new LLM feature, from zero to a CI gate plus production monitoring.
A strong answer covers: define success criteria per task first — measurable pass/fail, not "good" → build a small versioned golden set of real, representative (input, expected) cases, hand-labeled by humans → choose graders: programmatic where structured, calibrated LLM-as-judge where open-ended, human for the gold labels and audits → stand up the harness (dataset + runner + grader + report) and establish a baseline number → wire offline regression eval into CI so a drop below baseline blocks the merge → ship behind shadow first (no user risk), then A/B to measure real lift → instrument production signals (thumbs-down, regenerate, escalation, task success) and route failures back into the golden set → map risks: benchmark contamination, judge bias, coverage gaps; measure the loop, not just the model.
A leader says "just use the public leaderboard score to pick our model." Tear this apart and propose what you'd do instead.
A strong answer covers: a public benchmark measures a generic task on shared data — it's a proxy for capability, not a measure of YOUR task → contamination: leaderboard test data leaks into training sets, so a high rank can be memorization, and leaderboards saturate and rot as new models arrive → the right move is a private golden set of your real inputs with your success criteria, scored by your graders — that's the number that predicts production → use benchmarks only to shortlist candidate models cheaply, then decide with your own offline eval and confirm with shadow/A/B on live traffic → the framing: the leaderboard says a model is generally capable; only your eval says it's right for the job — teach the method, not the rank.
Sources
1. Anthropic, "Create strong empirical evaluations" — docs.anthropic.com (Build with Claude → Test & evaluate). Building task-specific evals, grading methods, and evaluating the system not just the model.
2. Anthropic, "Define your success criteria" — docs.anthropic.com. Turning a fuzzy quality goal into measurable per-task pass/fail criteria before writing eval cases.
3. OpenAI, "Evals" framework — github.com/openai/evals. Reference eval-harness shape: a registry of evals, model-graded vs exact-match graders, datasets-as-code.
4. Liang et al., 2022, "Holistic Evaluation of Language Models" (HELM) — Stanford CRFM, arXiv:2211.09110. One number is never enough: evaluate across many scenarios and metrics and surface the trade-offs. Coverage / distribution numbers illustrative.
5. Zheng et al., 2023, "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena" — arXiv:2306.05685. Strong judges can approach human-level agreement; documents position, verbosity, and self-preference bias. Agreement figures illustrative and dataset-dependent.
Was this lesson helpful? Thanks — noted.

These notes reflect my current understanding and are updated as I learn, build, and discover better explanations.