AI Engineering (Applied) · Evaluating AI Systems

Evaluating AI Systems

You cannot improve what you do not measure. When a feature is powered by a foundation model, “it seemed to work when I tried it” is not evidence — it’s a vibe. This lesson is the door into the AI-engineering craft, and the craft begins here: an AI engineer measures everything. Evals are how you prove a feature is good, catch it the moment it stops being good, and ship changes without crossing your fingers.

☺ Explain it like I’m 10

Imagine you’re making the best sandwich in the world. If you only ever taste one bite and say “yum, good enough,” you’ll never know if tomorrow’s batch is worse. So instead you build a little taste-test with the same ten sandwiches every time, and a scorecard. Now you can prove the new recipe is better — and catch the day it goes bad before your customers do.

🐢Your host for this topic: Timmy the Turtle — Timmy never trusts a result until it’s been checked, re-checked, and measured against last week’s, which is exactly what evals are.

Why “it looks good” is not good enough — the eval gap

☺ Like you’re 10: Trying a chatbot once and saying “nice, it works” is like tasting one spoon of soup and declaring the whole pot perfect. One spoon can’t tell you the pot is too salty, or that yesterday’s pot was better.

When you build a normal feature, you know it works because you wrote a test: add(2, 2) returns 4, always, forever. Foundation-model features break that comfort in two ways. First, the model is non-deterministic — ask it the same thing twice and you may get two different wordings. Second, and worse, “correct” is fuzzy. There’s rarely one right answer to “summarize this ticket” or “draft a friendly reply.” There are many good answers, many mediocre ones, and many confidently-wrong ones that read just fine.

Contrast this with the classical ML you may have met: there, a model predicts a house price or a spam label, and you have the true answer sitting in a column, so you compute a clean number — accuracy, precision, RMSE, loss. Even evaluating a fine-tune leans on a held-out set with known-good labels. Generative output has no such column. “Is this summary good?” doesn’t reduce to a subtraction. That gap — between how obviously-scorable classical ML is and how slippery generative quality is — is the eval gap, and closing it is the whole job of this lesson.

The failure mode this creates is seductive. You demo the feature, it dazzles, everyone ships. Then real users send inputs you never tried, the model drifts when the provider updates it, someone tweaks the prompt to fix one bug and silently breaks three others — and nobody notices, because there was never a scorecard. Vibes don’t catch regressions. Measurement does.

A generative feature has no “correct answer” column to diff against. So you must manufacture a measurement: fixed examples, an explicit grader, and a score you track over time. No score, no engineering — just hoping.

The eval dataset — golden sets & regression sets

☺ Like you’re 10: A golden set is your special box of practice questions where you already know the best answers. Every time you change the recipe, you re-run the same box — so you’re comparing apples to apples, not to whatever you happened to type today.

An eval needs something fixed to run against. That’s the eval dataset (often called a golden set or golden dataset): a curated collection of representative inputs, each paired with what a great output looks like — an exact expected answer, a reference to compare against, or at minimum a rubric describing what “good” means. The golden set is the ruler you hold up to every version of your system.

Where do the examples come from? The best source is real production traffic, not your imagination:

The second flavor is the regression set. Every time you find a bug — the model mishandled a date, leaked a system instruction, botched a currency — you distill that failure into a small, permanent test case and add it to a set that must always pass. Regression tests lock in fixes: they’re your guarantee that a bug you squashed last month can never quietly crawl back in when you change a prompt or swap a model.

◆ Key idea

Your golden set is a living asset, not a one-time chore. Grow it from real traffic, and every production bug becomes a permanent regression case. A team’s eval dataset is often more valuable than its prompts — prompts are cheap to rewrite; a well-curated set of scored examples is not.

Graders — how a machine scores a fuzzy answer

☺ Like you’re 10: A grader is the thing that marks the test. Some questions have one right answer, so a simple checker works. Others need judgment, so you either write a checklist — or you ask a second smart friend to grade the first friend’s work. But that grader-friend has quirks you have to watch.

Once you have inputs and expected outputs, you need a grader: something that turns each output into a score. Graders come in a spectrum, from rigid and cheap to flexible and tricky.

Model output one answer to grade Rule-based exact match · regex valid JSON? · contains? cheap · strict · certain Rubric checklist of criteria score each · sum structured · needs a judge LLM-as-judge a model grades the output flexible · has biases Score → tracked over time

The two biases that bite hardest with LLM-as-judge:

A powerful trick is pairwise comparison: instead of asking “rate this answer 1–10” (models are wobbly at absolute scores), ask “which of these two answers is better, A or B?” Relative judgments are far more reliable than absolute ones. You run your new version against the old one head-to-head across the golden set and report a win rate. And crucially — you calibrate the judge itself: have humans grade a sample, then check the judge agrees with them. If your judge doesn’t match human judgment on cases you already trust, its scores are noise.

# PSEUDOCODE — an LLM-as-judge grader with position-bias defense
def judge_pairwise(question, answer_a, answer_b, rubric):
    # ask BOTH orders to cancel position bias
    v1 = judge_model(prompt(question, rubric, first=answer_a, second=answer_b))
    v2 = judge_model(prompt(question, rubric, first=answer_b, second=answer_a))
    if v1.winner == "first" and v2.winner == "second":
        return "A wins"          # judge agreed A is better, both orders
    if v1.winner == "second" and v2.winner == "first":
        return "B wins"
    return "tie / inconsistent"  # disagreed → don't trust it

# CALIBRATE before you rely on it
assert agreement(judge_model, human_labels) > 0.8   # else the judge is noise

What to measure — the metrics that matter

☺ Like you’re 10: A good answer isn’t just “right.” It also has to stick to the facts you gave it, come out in the shape you asked for, stay safe, and not cost a fortune or take forever. So you keep score on all of those at once, not just one.

“Is it good?” is really several questions. A production eval tracks a handful of dimensions, and it’s a mistake to collapse them into one number. The core set:

MetricQuestion it answersHow you grade it
Task successDid it actually do the job the user asked for?Rule-based when there’s a right answer; rubric or judge when open-ended
Faithfulness / groundednessIs every claim supported by the sources given, with nothing invented?Judge or rubric that checks each claim against the provided context
Format adherenceIs the output the shape you demanded (valid JSON, required fields, length)?Rule-based — the ideal case for exact checks
SafetyDid it refuse what it should, and avoid harmful or leaked content?Rules + classifiers + judge; overlaps with guardrails
CostHow many tokens / dollars did this answer take?Measured directly per call — a first-class metric, not an afterthought
LatencyHow long did the user wait?Measured directly; track the tail (p95/p99), not just the average

Faithfulness (also called groundedness) deserves special attention because it’s the direct measure of hallucination. In any retrieval or document-based feature, the question isn’t just “is the answer plausible?” but “does every statement trace back to the sources we provided?” You grade it by giving the judge the answer and the source context and asking it to flag any claim that isn’t supported. High faithfulness is the number that tells you your RAG system is trustworthy rather than merely fluent.

And note the last two rows. Cost and latency are first-class metrics, measured on every eval run right alongside quality. A version that’s 1% more accurate but twice as expensive and twice as slow is often a worse engineering choice — and you can only see that tradeoff if you’ve been measuring all three together. The cost & latency lesson goes deep on tuning them.

◆ Key idea

Never reduce quality to a single score. A model can ace “task success” while quietly hallucinating (low faithfulness), returning malformed JSON (low format adherence), or costing 3× as much. You measure several dimensions because they trade off against each other.

🎬 At the AI Academy
🦫

Benny the Beaver: Great news — I rewrote the support-bot prompt and it answered my test question way better. Shipping it!

🐢

Timmy the Turtle: Hold on. One question you liked isn’t evidence. Run it against the golden set — all 200 real tickets, with the answers we agreed are good.

🐿️

Nutty the Squirrel: I pulled those 200 straight from last month’s real traffic — including the nasty edge cases people actually sent.

🐬

Delphi the Dolphin: Running both prompt versions… old prompt wins 61% of head-to-head comparisons. And the new one invented a refund policy that isn’t in the docs — faithfulness dropped.

🐢

Timmy the Turtle: There it is. Your one good answer hid a regression on the other 199. The scorecard caught what the vibe missed — new prompt stays out until the win rate goes up, not down.

🦫

Benny the Beaver: …okay, fair. Adding that hallucinated-refund case to the regression set right now so it can never sneak back.

Offline vs online — evals in CI, then A/B tests in production

☺ Like you’re 10: First you test the sandwich in your kitchen before anyone eats it (offline). Then, once it passes, you serve it to a few real customers and watch whether they actually like it more than the old one (online). Both matter — the kitchen test can’t tell you everything real people will do.

There are two arenas for evals, and mature teams use both.

Offline evals run against your fixed golden set, before any user is involved — typically in CI (continuous integration), the automated pipeline that runs on every code or prompt change. This is where evals become a release gate: you set pass-rate thresholds (“task success ≥ 90%, faithfulness ≥ 95%, zero regression failures”) and the pipeline blocks the deploy if a change drops below them. This is the single highest-leverage habit in AI engineering — it turns “I hope this prompt change didn’t break anything” into a hard, automatic guarantee, exactly like a unit-test suite gates normal code.

Change new prompt/model CI eval gate golden set · thresholds offline ✗ Blocked below threshold → back Canary small % of traffic online A/B test vs old version online Human review sample real outputs pass

Online evals happen once the change is live, because the fixed golden set can never fully predict the messy real world. The tools here:

Offline tells you a change is safe to try; online tells you it’s actually better. You need both. The operational machinery for canaries, rollouts, and monitoring lives in production & ops, and evals are a core stage of any real AI pipeline.

The habit that defines an AI engineer: no prompt or model change ships without passing the offline eval gate — and every change is then watched online. That single discipline is the difference between a demo and a product.

Pitfalls — how evals quietly lie to you

☺ Like you’re 10: Even the scorecard can trick you. If you practice on the exact same ten questions forever, you’ll memorize them and think you’re a genius. If the grader has a favorite, it’ll pick wrong. And ten questions is too few to trust anyway. So you have to check the checker.

Evals are powerful, but a badly-built eval gives you false confidence — which is worse than no eval at all. Watch for these:

The meta-lesson is Timmy’s creed: be suspicious of your own measurements. An eval that always passes may be too easy, leaking answers, or measuring the wrong thing. A good eval occasionally fails and catches real problems — that’s how you know it’s doing its job.

⚠ A green eval can still be a lie

A passing eval is only as trustworthy as the set it runs on and the grader that scores it. Overfit prompts, leaked answers, an uncalibrated judge, or a ten-item set can all produce a confident green checkmark on a system that’s actually broken. Audit your evals the way you audit your code.

◆ In practice you’ll reach for…

You rarely hand-roll all of this. Eval harnesses run a dataset through your prompt/model and score it — OpenAI Evals, promptfoo, Braintrust, LangSmith, or Ragas (RAG-specific). Most have LLM-as-judge built in; LangSmith and Langfuse also capture production traces you can promote into eval cases. Pick one, wire it into CI, and treat the names as “true at time of writing.”

🦫 Benny’s workshop · 5 min

Take any AI feature you use (a chatbot, a summarizer, a “write this email” tool). Write down five real inputs — including one weird edge case — and, for each, what a great answer would contain. Congratulations: that’s a tiny golden set. Now run all five through the tool and score each yourself against your own criteria. Notice how having written the criteria first makes you spot flaws you’d have hand-waved past on a single casual try.

🐢 Timmy’s checkpoint

(1) Why can’t you evaluate a text-generating feature the same way you check add(2,2)==4, and how is that different from scoring a classical-ML classifier? (2) What is a golden set, where should its examples come from, and how does a regression set differ from it? (3) Name the two big biases of an LLM-as-judge and one defense for each — and why do you calibrate the judge against humans? (4) What does it mean to use an offline eval as a CI release gate, and why do you also need online A/B tests and human review?

Check your answers
  1. Why generative output resists add(2,2)==4: A foundation model is non-deterministic (the same input can yield different wordings) and “correct” is fuzzy — there are many good answers to “summarize this ticket,” not one. A classical-ML classifier is scorable because the true label sits in a column, so you diff prediction against truth for a clean number like accuracy or RMSE; generative output has no such answer column, so you must manufacture the measurement. That missing column is the eval gap.
  2. Golden set vs regression set: A golden set (or golden dataset) is a curated, fixed collection of representative inputs each paired with what a great output looks like — an exact answer, a reference, or at least a rubric — and it’s the ruler you hold up to every version. Its examples should come mostly from real production traffic (scrubbed), deliberately covering easy, hard, ambiguous, adversarial, and “no good answer” cases, with a human curating the expected output. A regression set differs by being built from past bugs: each fixed failure becomes a small permanent test case that must always pass so the bug can’t crawl back.
  3. LLM-as-judge biases, defenses, and calibration: The two big biases are position bias (favoring whichever answer it sees first or last) — defended by running each comparison both orders, A-then-B and B-then-A, and only counting a win when the judge agrees both ways — and verbosity bias (over-rewarding longer answers) — defended by putting explicit length/conciseness criteria in the rubric. You calibrate the judge against human labels because a judge that doesn’t match human judgment on cases you already trust is producing noise, so its scores can’t be relied on to gate anything.
  4. Offline CI gate vs online checks: Using an offline eval as a CI release gate means running every prompt or model change against the fixed golden set in your continuous-integration pipeline with pass-rate thresholds (e.g. task success ≥ 90%, faithfulness ≥ 95%, zero regression failures), and automatically blocking the deploy if a change drops below them. You also need online A/B tests and human review because the fixed golden set can never fully predict the messy real world — offline tells you a change is safe to try, while online tells you whether real people are actually better served and surfaces new failure modes and drift.