learn-prompt-engineering-with-phoebe / Builder session 8 of 10
Learn Prompt Engineering with Phoebe · Builder track · Session 8 of 10

Evals I: from vibes to numbers

You have spent seven sessions making TriageBot better. Better according to whom? Today the guessing stops: golden sets, grading methods, and your first eval harness. This is the skill that separates prompt tinkerers from prompt engineers.

🟠 Builder track Practitioners Any model or API 35 min self-read · 45 min live
0-3 · Welcome 3-20 · Vibes, grading, promptfoo 20-42 · Build-along 42-45 · Q&A
Part 0

Why this session exists

Back in session 1 you saw Anthropic's funnel: success criteria, then evals, then - and only then - prompt engineering. We deliberately broke that order so you could build intuition first. Now we pay the debt. Sessions 8 and 9 turn "the v4 prompt feels better" into "v4 scores 91% category accuracy against 20 real tickets, v2 scores 78%". One of those sentences survives a meeting with your boss.

Live - presented in session Self-study - read after class ★ Build-along - TriageBot gets its eval Any model · any API
★ What you walk out with today The argument for why looks-good-to-me fails at scale, Anthropic's full grading taxonomy (three code-graded methods, three LLM-graded methods) and the volume-over-grading-quality principle, the anatomy of a promptfoo eval config, and a real golden set of 20 Meridian tickets with assertions that grade TriageBot v2 against v4 - with baseline scores logged for session 9's CI gate.
Part 1 · the case

Why vibes fail 5 min live

Every prompt you have shipped so far was graded the same way: you read a few outputs and nodded. That works for 5 test tickets. It does not survive contact with 1,000 real ones - and Meridian's queue does 1,000 a week.

LiveLooks-good-to-me is not a metric3 min▶

Three reasons eyeballing collapses at scale, all of which have already bitten the Meridian team:

  • You sample the easy cases. The tickets you test with are the ones you remember - clean, typical, polite. Production sends you the drunk 2am ticket in three languages with an order number in the subject line.
  • Your memory is not a baseline. When you "improved" the prompt in session 6, did shipping-delay accuracy go up or just refund handling? You genuinely cannot know without numbers from before the change.
  • Prompt changes are code changes. They alter production behaviour, so they need what code changes need: regression tests. A one-word edit to a prompt can silently break a category that used to work - and nobody reads 1,000 outputs to check.
Real world

The Meridian incident that started this. A well-meaning edit in session 7's vendor-variant work reworded one line of the Gemini variant. Refund tickets started coming back tagged SHIPPING. Nobody noticed for four days, because everyone checked the same three sample tickets - none of them refunds.

Self-studyThe whole industry converged on this2 min read▶

This is not one vendor's opinion. Recall the session 1 funnel: Anthropic's prompt engineering overview lists success criteria and empirical evals as prerequisites - things you do before prompt engineering, not after. Anthropic's own API course on Skilljar goes further and puts the evals module before the prompt engineering module, a deliberate ordering choice. OpenAI's reasoning guidance keeps hammering explicit success criteria. The message from everyone who ships this stuff: a tips-and-tricks practice without evals is a 2023 practice.

The honest framing for your team: evals are not the boring homework after the fun prompting. Evals are the instrument panel. Prompting without them is flying by feel in clouds.

Part 2 · the toolbox

The grading taxonomy 7 min live

Anthropic's eval docs give six ways to grade an output, and they sit on a ladder: cheap and rigid at the bottom, flexible and costly at the top. The craft is picking the lowest rung that can grade your criterion.

1 · Exact match Cheap, deterministic, rigid 2 · Similarity Cosine similarity ROUGE-L for summaries 3 · LLM binary + Likert Pass or fail, or a 1-5 scale, graded by a model 4 · LLM ordinal rubric Flexible, costly, needs bias care (session 9) code-graded: cheap, run thousands model-graded: flexible, costs per run Climb only as high as the criterion forces you. Category labels never need a judge.
🔍 Click to zoom - the grading ladder, from exact match to LLM-graded rubrics
LiveSix methods, one table4 min▶
MethodGraded byGrades whatTriageBot use
Exact matchCodeIs the output exactly X?Category label equals REFUND
Cosine similarityCodeIs it semantically close to a reference?Summary close to a gold summary
ROUGE-LCodeSummary overlap with a referenceSame, word-overlap flavour
LLM LikertModel1-5 rating on a quality dimensionTone appropriateness, 1-5
LLM binaryModelYes or no against a criterion"Is this summary actionable?"
LLM ordinalModelGraded scale with a rubricEscalation-note quality, 1-3

Rule of thumb from the docs and from everyone's scars: code-graded beats model-graded whenever the criterion allows it. Code grading is free, instant, and deterministic - the same output always gets the same grade. A model judge costs money per run and can change its mind. Save it for what code truly cannot see: tone, helpfulness, reasoning quality. That is session 9's whole first act.

Self-studyThe volume principle - Anthropic's counterintuitive advice2 min read▶

The single most useful line in Anthropic's eval docs: prioritise volume over grading quality. Many test cases with slightly crude grading beat a handful of cases with exquisite hand-grading.

  • A 100-case eval with blunt exact-match assertions will catch a regression that a 5-case artisanal eval sails past - because the regression lives in case 47.
  • Crude grades average out. One mis-graded case in 100 shifts your score 1%. One missing case in 5 hides 20% of reality.
  • Volume is also cheaper to grow: every production failure becomes one more test case (session 9 makes this a formal loop).

So when you feel the pull to perfect ten test cases, resist it and write thirty rough ones instead. You can always upgrade the grading later. You cannot upgrade coverage you never wrote.

Part 3 · the harness

Your first eval harness with promptfoo 8 min live

You could write an eval loop in 40 lines of Python - Anthropic's course literally does. But the field standardised on a tool: promptfoo, an open-source eval CLI with 20k+ GitHub stars, used inside Anthropic's own prompt evaluations course. One YAML file in, a results grid out. Today is conceptual; no install needed in session.

prompts triagebot_v2.txt · triagebot_v4.txt providers the models you want in the race tests + assertions 20 golden tickets, each with checks the matrix every prompt x every provider x every test, graded v2 · ticket 07 · pass v4 · ticket 07 · pass v2 · ticket 12 · fail v4 · ticket 12 · pass ... 20 rows per prompt scores per column One config file declares the whole experiment. The grid is your before-and-after photo, per ticket.
🔍 Click to zoom - promptfoo anatomy: prompts x providers x tests become a graded grid
LiveThe config, annotated4 min▶

A promptfoo config is one YAML file with three lists. Here is a trimmed TriageBot version - read it top to bottom and notice it is just the SVG above in text form:

promptfooconfig.yaml - the shape to stealprompts: - file://prompts/triagebot_v2.txt - file://prompts/triagebot_v4.txt providers: - anthropic:messages:claude-sonnet-5 tests: - description: "plain refund request" vars: ticket: "Order 4471 arrived smashed. I want my money back." assert: - type: is-json - type: contains value: '"category": "REFUND"' - type: javascript value: JSON.parse(output).summary.split(" ").length <= 30 - description: "vague complaint, should not guess" vars: ticket: "your app is broken again, sort it out" assert: - type: is-json - type: contains value: '"category": "UNSURE"'

The four assertion types you will use constantly: contains (substring present), equals (exact match), is-json (parses cleanly - your session 3 schema work finally gets policed), and llm-rubric (a model judges against a written criterion - we hold this one until session 9, where it gets the care it needs). Anything custom, like the word count above, drops into a javascript assertion.

Self-studyRunning it, and reading the grid2 min read▶

When you do install it at your desk (one npm command, or use the hosted runner), the loop is: promptfoo eval runs the matrix, promptfoo view opens the grid in a browser. Each row is a test case, each column a prompt-provider pair, each cell green or red with the raw output on click.

  • Read columns to compare prompts: v4's column should be greener than v2's, and the score at the top says by how much.
  • Read rows to find hard cases: a ticket that fails in every column is either genuinely hard or wrongly labelled in your golden set. Both are worth knowing.
  • Add a second provider line and the same tests grade a vendor swap for free - your session 7 multi-vendor variants suddenly have a scoreboard.
Build-along

TriageBot gets its eval ★ 22 min · build it live

No new prompt today - we build the thing that judges the prompts. By the end, v2 versus v4 is a number, not an argument.

Assemble the golden set: 20 real tickets with expected categories. This is the hardest step and it is a team sport, not a solo one. Pull 20 real Meridian tickets, spread across categories, and agree the correct label for each - out loud, as a group. The arguments you have here ("is a late refund a REFUND or a SHIPPING?") are the product decisions your prompt was silently making alone. Write the agreed answers down; that document outlives every prompt version.

Write the code-graded assertions. Four checks per ticket, all cheap: category exact-match against the golden label; output is-json (the session 3 schema, enforced at last); summary under 30 words via a javascript word count; and no invented order numbers - this one is beautifully checkable: any order id appearing in the output must also appear in the input ticket. Hallucination detection in one line of code.

Sketch the promptfoo YAML. Take the config from Part 3 and extend it: two prompt files (v2 and v4), one provider, 20 test blocks. Keep descriptions human ("angry refund, order id in subject") - future you reads the grid by them.

Run v2 versus v4 - mentally, together. Before any real run, predict: which tickets does v2 fail? The team's guesses tend to cluster on the vague tickets and the multi-issue tickets - exactly where v4's grounded policy manual and lookup tool should win. Writing predictions down first is what makes the real numbers educational instead of just decorative.

Log the baseline. Whatever the scores are, record them: date, prompt version, model, score per assertion type. This row of numbers is the whole point of today - session 9 wires a gate to it, so no future "improvement" can quietly score below it again.

Why the golden set is the asset Prompts are cheap and disposable; you have rewritten TriageBot's four times already. The golden set is the opposite: it appreciates. Every ticket you add makes every future prompt, model swap, and vendor migration cheaper to judge. If you build one artifact from this whole track that outlives the course, make it this one.
Homework

Before session 9 ◐ 30 min total

Source material

What this session covers

Builder-level coverage of the sources below. Official notebooks and course videos stay with the vendors; links live in the course map.

✓Anthropic docs - success criteria + grading taxonomyPart 2 · six methods, volume principle (platform.claude.com develop-tests)
✓Anthropic Prompt Evaluations course - lessons 1-4Parts 1-3 · evals 101, code-graded, classification (anthropics/courses)
✓promptfoo - intro and config anatomyPart 3 + build-along · the harness Anthropic's own course uses
✓Building Systems with the ChatGPT API - eval arcPart 1 · prompt-to-system bridge, evals as the system's tests (DeepLearning.AI)
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · Anthropic's volume principle for evals says...

Coverage catches regressions; grading precision only refines them. One crude grade wrong shifts your score a little - one missing case can hide a whole failure mode. Write thirty rough cases, not ten perfect ones.

2 · When should you reach for a model-graded check instead of a code-graded one?

Code-graded checks are free, instant, and deterministic - the same output always gets the same grade. Climb the ladder to a model judge only when the criterion forces you. Category labels and JSON validity never do.

3 · The hardest and most valuable part of building TriageBot's eval was...

The config is twenty minutes of typing. The golden set forces the team to agree what correct even means, ticket by ticket - and it appreciates in value with every prompt, model, and vendor change you ever make.

Builder session 8 cheat sheet · pin this

Vibes fail at volumeYou test the easy cases and your memory is not a baseline. 1,000 real inputs need numbers, not nods.
Prompts are codeA prompt edit changes production behaviour, so it needs regression tests. Every vendor now teaches criteria + evals before techniques.
The grading ladderExact match, cosine similarity, ROUGE-L (code) · Likert, binary, ordinal (LLM). Climb only as high as the criterion forces.
Code beats model gradingCheap, instant, deterministic. Save LLM judges for what code cannot see: tone, helpfulness, reasoning.
Volume over grading qualityMany ok-graded cases beat few perfectly-graded ones. Regressions live in case 47.
promptfoo anatomyOne YAML: prompts x providers x tests with assertions (contains, equals, is-json, llm-rubric, javascript). Run, view the grid.
The golden set is the assetReal inputs + agreed answers, built as a team. Prompts are disposable; the golden set appreciates.
Checkable hallucinationsAny order id in the output must appear in the input. Grounding checks can be one line of code.