Three ways to grade, one budget to spend 7 min live
Every LLM metric is only as good as its grader. Faithfulness 0.92 sounds precise - but something read the answer and produced that number, and that something has strengths, blind spots, and a price. Anthropic's and OpenAI's taxonomies agree on the lineup: code-based graders, model-based graders (the LLM judge), and human graders. The craft is not picking one - it is spending each where it is strong.
| Grader type | Strengths | Weaknesses | Use for |
|---|---|---|---|
| Code-based exact match, string check, schema checks, text similarity (BLEU / ROUGE / METEOR / cosine) |
Fast, cheap, objective, perfectly repeatable | Brittle - misses paraphrase, rewards surface overlap | Format checks, exact answers, regression gates that must never flake |
| Model-based an LLM judge scoring with a rubric |
Flexible, handles nuance and open-ended answers | Non-deterministic, biased in documented ways, costs per call | Quality, tone, faithfulness - anywhere "correct" has many shapes |
| Human expert or crowd labels |
The gold standard - the definition of correct | Slow, expensive, does not scale | Spend it CALIBRATING the other two, not grading everything |
LiveAnthropic's volume doctrine4 min▶
Anthropic's develop-tests guidance is blunt: "prioritize volume over quality" - a larger set of questions with automated grading beats a small set graded by hand. The reasoning is statistical: eval scores are noisy estimates, and 500 automated verdicts pin down a model's behavior better than 30 artisanal ones, even if each automated verdict is individually less trustworthy.
That doctrine only works if the automated grader is trustworthy ON AVERAGE - which is exactly why the human budget goes to calibration. The division of labor:
- Code graders run on every commit - thousands of checks, zero marginal cost.
- The LLM judge grades the open-ended bulk - hundreds of answers per run.
- Humans label a small fixed anchor set once, and the judge is measured against it. The demo below makes this concrete.
LiveThe taxonomy outlives the product3 min▶
OpenAI's graders guide names the same families from the other direction: string check, text similarity (BLEU / ROUGE / METEOR / cosine and friends), score model (the judge), and python (arbitrary code). Two vendors, one shape: deterministic checks, model judgment, custom code, humans above them all.
The four documented judge failures 8 min live
LLM judges were not benchmarked on vibes. Zheng et al. 2023 (the MT-Bench paper, NeurIPS 2023) measured judge verdicts against human preferences and documented exactly four failure modes. Learn them as a checklist - every judge you ever deploy should be audited against all four.
- Position bias - verdicts flip when you swap the order of the two answers being compared. Mitigation from the paper: run both orders, keep only consistent verdicts.
- Verbosity bias - longer answers get rated better, independent of substance. The demo below is built on this one.
- Self-enhancement bias - a judge favors outputs from its own model family. Never let a model judge itself uncross-checked.
- Limited reasoning - a judge cannot reliably grade math or reasoning it cannot do itself. A judge is not smarter than its base model.
LiveThe 80% bar, read correctly4 min▶
Zheng et al. also measured the ceiling: GPT-4-class judges reach "over 80% agreement" with human preferences. Two readings of that number, one wrong and one right:
- Wrong reading: "the judge is 20% wrong - humans would do better."
- Right reading: 80% EQUALS the agreement rate between two humans. The judge has hit the ceiling of the thing it approximates - a judge cannot beat the humans it is calibrated against, because human preference IS the target, disagreements and all.
The habit this buys you: demand the agreement number with every judge score. "Faithfulness 0.92" alone is a model output. "Faithfulness 0.92, and this judge agrees with our human labels 85% of the time on the anchor set" is a measurement.
The judge that loved its own answers. A team A/B-tested two assistants and let a judge from the same model family as assistant A pick winners. A won decisively. A month later a cross-family judge and a small human panel both reversed the result - self-enhancement bias had picked the winner, not quality. The fix cost nothing: a judge from a different family, plus order-swapping. The un-fix cost a month of building on the wrong model.
Calibrate the judge: 58% to 88% ★ 20 min · everyone runs it
Below: 24 answers, each with a human label (good / bad) and a judge verdict. The judge has a scripted verbosity bias - it is a simulation of the Zheng et al. failure, so you can catch it red-handed. Your job is the full calibration loop, the same one you will run on real judges at work.
Run the raw judge: 58% agreement with the human labels, and 10 bad-but-long answers rated good. Read the individual rows - do not just take the number. Every miss has the same shape: wordy, empty, approved.
Name the pattern out loud before clicking anything: the judge is paying per word. That is verbosity bias - bias number two on tonight's checklist, found by reading rows, not by intuition.
Switch to the length-controlled judge: 88% agreement, 1 residual miss plus a few borderline calls no grader escapes. One systematic bias corrected, thirty points of agreement recovered.
Say the method, because the method IS the lesson: fixed human-labeled anchor set -> measure agreement -> find the systematic bias -> correct or constrain it -> re-measure. That loop, repeated whenever the judge or the task changes, is judge calibration in its entirety.
Price it: the anchor set is ~25 labels of human effort - an afternoon, once. It is the cheapest insurance in LLM evaluation, and it is the difference between a judge score you can defend and one you just hope about.
Self-studyMeasure agreement yourself, 15 lines3 min read▶
The loop from the demo, as the code you would actually run. No framework required - agreement is a mean of matches:
import json
anchors = json.load(open("anchor_set.json")) # ~25 human-labeled answers
def agreement(judge_fn, anchors):
verdicts = [judge_fn(a["question"], a["answer"]) for a in anchors]
hits = [v == a["label"] for v, a in zip(verdicts, anchors)]
misses = [a for a, h in zip(anchors, hits) if not h]
return sum(hits) / len(hits), misses
score, misses = agreement(raw_judge, anchors)
print(f"agreement: {score:.0%}") # 58% -> now READ the misses
for m in misses:
print(len(m["answer"].split()), m["label"]) # every miss: long + bad
The last loop is the part teams skip: the misses are where the systematic bias lives. In the demo every miss was long-and-bad - once you SEE that, the fix names itself. The number tells you whether to trust the judge; the misses tell you how to improve it.
Judge prompt hygiene ◐ read after class
Calibration finds the bias; hygiene prevents half of them showing up at all. Five habits for any judge prompt you write:
Self-studyThe five habits5 min read▶
- Rubric-anchored scales. Never ask for "a score 1-5" bare - define what a 2 and a 4 MEAN, with a short example of each. An unanchored scale drifts with the judge's mood; an anchored one is a checklist in disguise.
- Pairwise over pointwise where possible. "Which of these two is better?" is a more reliable judgment than "score this one" - comparison is easier than absolute calibration, for models and humans alike.
- Temperature 0. A grader that gives different verdicts on identical input is measurement noise you chose to add. Determinism first.
- Version-pin the judge model. A judge upgrade silently moves every score on your dashboard - pin the exact version, treat changes as breaking.
- Re-calibrate when it changes. New judge model, new rubric, new task distribution: re-run the anchor set and re-measure agreement before trusting a single new number. The ~25 labels keep paying rent.
Where this connects: learn-ai-evals-with-phoebe owns the harness that wires judges into pipelines and CI; tonight you learned what must be true about the judge before any of that machinery is worth running.
Try it yourself - this week ◐ 20-30 min total
- Re-run the demo and, before switching judges, predict which specific rows will flip. Check yourself against the residual - the borderline calls that survive are worth staring at.
- Find one judge-scored metric in your org (or a vendor deck) and ask for its agreement number against human labels. If nobody has one, you have found this week's cheapest high-impact task: ~25 labels.
- Audit any judge prompt you can access against the five hygiene habits. Score it out of five; fix the cheapest gap.
- Optional: skim Zheng et al. 2023 sections 3-4 (arXiv 2306.05685) - the bias measurements are short, readable, and the primary source for everything in Part 2.
Official sources covered
This session teaches the grader taxonomy both major vendors agree on and the judge-bias findings from the primary paper, with the calibration loop run live in your browser. This page covers:
Three questions before you go 🎯 ◐ 90 seconds
1 · Your pairwise judge prefers answer A - until you swap the order, and then it prefers B. Which documented bias is this, and what is the paper's mitigation?
Verdicts that flip with answer order are position bias, the first of the four Zheng et al. failures. The paper's own mitigation: present both orderings and only trust verdicts that agree across them. The other two options are real biases - with the wrong symptoms.
2 · GPT-4-class judges reach "over 80% agreement" with humans. What does that number actually mean?
Two humans agree with each other about 80% of the time on these preferences - so a judge at 80% is not 20% short, it is at the ceiling. A judge cannot beat the humans it approximates. The takeaway habit: demand the agreement number with every judge score.
3 · Put the calibration loop in order.
The anchor set comes first - without human labels there is nothing to measure agreement against, and without measurement you cannot find the bias or prove your fix worked. In the demo that loop took the judge from 58% to 88%, and the anchor set cost ~25 labels.