Skip to content
ML Academy

Core day 45 of 60 · Week 9 · Part II · evaluation depth

LLM Evaluation and Alignment

A model-based judge says your new assistant prompt beats the old one in 67% of comparisons, and a public leaderboard ranks the base model first. What must you see before believing either number, and what does a small, defensible, task-specific evaluation look like?

By the end: You design a ten-case task-specific evaluation with checkable criteria, run a pairwise judge in both orders and read position, verbosity and contamination effects from recorded outputs, and state which claims about RLHF and DPO are established and which are still contested.

At a glance

Evaluate on your own checkable cases, treat a model judge as a biased instrument to calibrate, and gate releases on regressions and safety, not on a leaderboard.

  • Your cases

    Benchmarks answer someone else's question and may be contaminated.

  • Code before judges

    Format, ids, citations and arithmetic are checked in code; judge only the rest.

  • Judge both orders

    Flips are ties; control length; use another family; validate on humans.

  • Regression gate

    Every production failure becomes a case; safety slices block release.

  • RLHF and DPO

    Preference tuning shapes answers toward what raters and judges like, often longer.

Recall · 5 min

No reviews due? Answer from memory. (1) What must exist before any adaptation run, and what does a hash on it protect (Day 43)? (2) Why is a 10-point gain on 40 items not yet evidence (Day 43)? (3) What does a grouped split protect against in text data (Day 41)?

Open due reviews

Sign in to record this block.

Concept · 10 min

A public benchmark says how a model does on someone else's questions, possibly ones it saw in training. Your decision needs your own cases with checkable criteria. When a second model grades, it is an instrument with habits: it favours the first slot, the longer answer and its own family. Measure the instrument before trusting its numbers.

A judge's win rate depends on answer order and length until you swap, control and validate it

Predict first

A judge agrees with humans on 81% of pairs in each order. Can you trust a candidate win rate computed from one order?

Text description of the figure

Controls for one of three synthetic judges, the order used (candidate shown first, baseline shown first, or both orders keeping only consistent verdicts) and a toggle that removes items flagged as contaminated. Readouts show the first-position win rate, the share of verdicts that flip when order is swapped, agreement with the reference labels, and the candidate's win rate by the judge and by the labels. A table splits all, clean and contaminated items. The fixture is simulated; no real judge is involved.

Four ideas to hold on to Overview
  • Your cases

    Write cases from your traffic with a check for each.

  • Code first

    Anything a program can verify needs no judge.

  • Calibrate the judge

    Both orders, length control, other family, human agreement.

  • Gate releases

    Regression and safety slices run on every change.

An evaluation schema for one release Diagram
Golden setcases, checks,slicesSystem outputsbaseline and candidateCheckable bycode?Code checksschema, ids, citations,sumsJudgehuman-validated?Human labelssample of pairsPairwise judgeboth orders, flips =tiesRates withintervalsper slice, pairedRelease gateregression + safetyyesnoyesnot yet
  1. Golden setcases, checks, slices
  2. System outputsbaseline and candidate
  3. Checkable by code?
    • yes: to Code checks
  4. Judge human-validated?
    • yes: to Pairwise judge
  5. Human labelssample of pairs
  6. Code checksschema, ids, citations, sums
    • to Rates with intervals
  7. Pairwise judgeboth orders, flips = ties
  8. Rates with intervalsper slice, paired
  9. Release gateregression + safety

A judge that has not been checked against human labels sends you back to label a human sample first. Everything a program can verify skips the judge entirely.

Candidate win rate by who reads it (application output, simulated judge) Chart
  • Judge, baseline shown first0.39
  • Judge, candidate shown firstthe number in the ship request0.67
  • Human labels0.51

Equal agreement with humans in each order (0.81, 0.82) hid errors that lean toward the first slot: one order can swing the win rate by tens of points.

A position pull, swept from none to strong Illustration
0.000.250.500.751.000.000.350.701.051.40Candidate win rate as the position pull growscandidate firstbaseline firstboth ordershuman labelsapplication judgeposition pull (score bonus for the first slot)Candidate win rate
  • judge, candidate shown first
  • judge, baseline shown first
  • both orders, flips = half

With no pull both orders sit near the human rate (0.52). At pull 0.7 the candidate-first order reports 0.68 and the other 0.35; judging both orders and splitting flips stays at 0.51.

0.000.250.500.751.000.000.350.701.051.40What the two diagnostics showagreement, one orderflip rate when swappedposition pull (score bonus for the first slot)Share of pairs

Agreement with humans in one order falls slowly (0.83 to 0.80 at pull 0.7) while the flip rate climbs to 0.37. A per-order agreement number cannot reveal the bias; the swap test can.

Simulated judge with the application’s scoring rule (not a real model), 600 seeded pairs per point; only the position pull varies. A TypeScript re-implementation, so its rates differ slightly from the Python output.

The application's simulated judge with only the first-slot bonus varied. Per-order win rates split apart; the both-order rate does not move.

Four ways a judge's verdict drifts from quality, and the control for each Hierarchy
tracks the slottracks lengthtracks the authortracks its habitscontrolcontrolcontrolcontrolJudge verdictmeant to track qualityalonePosition biasverdict flips when A and BswapVerbosity biaslonger wins more thanhumans saySelf-preferenceown family's outputs ratedhigherUnvalidated rubricmeasures the judge, notthe taskJudge both ordersflips count as tiesLength controllength-controlledcomparison or a capJudge from anotherfamilyAgreement with humanlabelskappa on a labelled sample
  • Judge verdictmeant to track quality alone
    • tracks the slotPosition biasverdict flips when A and B swap
      • controlJudge both ordersflips count as ties
    • tracks lengthVerbosity biaslonger wins more than humans say
      • controlLength controllength-controlled comparison or a cap
    • tracks the authorSelf-preferenceown family's outputs rated higher
      • controlJudge from another family
    • tracks its habitsUnvalidated rubricmeasures the judge, not the task
      • controlAgreement with human labelskappa on a labelled sample

Sources: position (Zheng 2023, Wang 2024), verbosity (Dubois 2024), self-preference (Panickssery 2024). Swapping order cancels only the first branch; each other branch needs its own control.

Two ways to tune toward preferences Diagram
RLHF: SFT modelHuman pairwiserankingsReward modelfits the preferencesRL (PPO) + KLpenaltystay near the referenceTuned modelDPO: SFT modelChosen vsrejected pairsClassification losschosen vs rejected,relative to thereferenceTuned modeldirect
  1. RLHF: SFT model
    • to Human pairwise rankings
  2. DPO: SFT model
    • to Chosen vs rejected pairs
  3. Human pairwise rankings
    • to Reward model
  4. Chosen vs rejected pairs
    • direct: to Classification loss
  5. Reward modelfits the preferences
  6. RL (PPO) + KL penaltystay near the reference
    • to Tuned model
  7. Classification losschosen vs rejected, relative to the reference
    • to Tuned model
  8. Tuned model
  9. Tuned model

The difference is the missing middle: DPO trains directly on chosen and rejected pairs, with no reward model and no RL loop. Christiano 2017 and Ouyang 2022 (RLHF); Rafailov 2023 (DPO). Which works better is setup-dependent (Xu 2024).

  • Build a Golden set of your cases, check with code first, and judge the rest as a Pairwise comparison in both orders (Position bias).
  • An LLM-as-judge needs a length control, another model family and agreement with human labels.
  • A Regression suite with safety slices gates every prompt, model or data change.
  • RLHF and DPO tune toward preferred answers, which also shapes what judges like.

Assumptions

  • The task cases represent real traffic and slices; a set written by the builders under-states hard inputs.

  • Judge criteria are written down and a human sample defines "agreement"; otherwise the judge is an opinion generator.

  • The fixtures are simulated or hand-written; real judges are noisier and differ by model and task.

Sign in to record this block.

Application and workplace decision · 10 min

  • 200 answer pairs from a baseline and a candidate assistant; humans labelled which is better.
  • A simulated judge (not a real model) with a built-in pull toward the first slot and the longer answer ran once with each system first.
  • Predict first: if the judge agrees with humans about 80% of the time in each order, what win rate does it report in each order?

Python

import numpy as np

rng = np.random.default_rng(45)
n = 200
better = rng.integers(0, 2, n)  # human-preferred system per pair: 0 = baseline, 1 = candidate
longer = rng.integers(0, 2, n)  # which system wrote the longer answer

def judge(first):
    """Simulated judge (not a real model): quality + pull towards the first slot and the longer answer + noise."""
    score = np.zeros((n, 2))
    for s in (0, 1):
        score[:, s] = (better == s) * 1.0 + 0.5 * (longer == s) + 0.7 * (first == s) + rng.normal(0, 0.6, n)
    return score.argmax(1)  # id of the system picked

v_base_first = judge(np.zeros(n, int))  # baseline shown first
v_cand_first = judge(np.ones(n, int))  # candidate shown first
agree = lambda v: (v == better).mean()
print(f"agreement with humans: baseline-first {agree(v_base_first):.2f}, candidate-first {agree(v_cand_first):.2f}")
print(f"candidate win rate: baseline-first {v_base_first.mean():.2f}, candidate-first {v_cand_first.mean():.2f}, human {better.mean():.2f}")

both = (v_base_first == 1) & (v_cand_first == 1)  # candidate wins in both orders
neither = (v_base_first == 0) & (v_cand_first == 0)  # baseline wins in both orders
print(f"both orders: candidate wins {both.mean():.2f}, baseline wins {neither.mean():.2f}, flips counted as ties {1 - both.mean() - neither.mean():.2f}")
decided = both | neither
print(f"agreement with humans on decided pairs: {(both[decided] == (better[decided] == 1)).mean():.2f} ({decided.sum()} of {n} pairs)")
picks = np.r_[v_base_first, v_cand_first] == np.r_[longer, longer]
print(f"longer answer picked: judge {picks.mean():.2f}, human preference {(better == longer).mean():.2f}")

This code is executed in the repository's checks (pnpm lesson:py / lesson:sql). It is not run on this site; copy it into your notebook.

Sign in to record this block.

Mini-assessment · 8 min

Your first answer is your evidence. You can re-answer later in practice mode; that is labelled practice.

Question 1 · easy

A judge prefers answer A when A is shown first and answer B when B is shown first, for the same two answers. What does this show?
Options

How confident are you? (optional, used for calibration)

Question 2 · medium

You judge 200 answer pairs in both orders. The candidate wins in both orders on 70 pairs, the baseline wins in both orders on 60, and the verdict flips on 70. Counting each flip as half a win for each system, what is the candidate's win rate, in percent?
percent

How confident are you? (optional, used for calibration)

Question 3 · hard

A team releases a DPO-tuned model. A judge from the same model family says it wins 72% of comparisons against the baseline; its answers are 60% longer; agreement with humans on 30 labelled pairs is 55%; its score on a public benchmark rose 3 points, and the benchmark was published before the model's training data cutoff. What do you conclude and do?
Options

How confident are you? (optional, used for calibration)

Question 4 · medium

A support assistant's answers are scored on three criteria: (1) the reply is a JSON object with an allowed intent and a refund amount between 0 and 300; (2) every cited chunk id was in the retrieved context; (3) the tone is empathetic without promising a refund the policy does not give. Which assignment of graders fits best?
Options

How confident are you? (optional, used for calibration)

Question 5 · hard

A team runs preference tuning and saves four checkpoints. For each it reports the reward model's mean score, the human win rate against the reference model on 400 pairs and the mean answer length (hypothetical figures): 1: reward 0.9, wins 58%, 140 words; 2: 1.3, 61%, 180 words; 3: 1.7, 57%, 260 words; 4: 2.0, 52%, 390 words. Which checkpoint and which reading do you take forward?
Options

How confident are you? (optional, used for calibration)

Sign in to complete lessons and keep your progress.

Technical depth · optional · 29 min in total

Open only what you need. Nothing here is required to complete the day; the assessment covers the core above.

A pass rate as a binomial estimate, by hand4 minWhat a pass rate estimates, its standard error derived, and a 95% interval computed on 17 of 20 cases two ways.
A pass rate is a binomial estimate Formula
k∼Binomial(n,p),p^=kn,SE(p^)=p^ (1−p^)nk \sim \mathrm{Binomial}(n, p), \qquad \hat p = \frac{k}{n}, \qquad \mathrm{SE}(\hat p) = \sqrt{\frac{\hat p\,(1-\hat p)}{n}}
pp
the true pass rate on the population of cases your set is drawn from: the quantity you want
k,nk, n
cases passed and cases run; each case is one independent pass-or-fail trial
p^\hat p
unbiased for p; its variance p(1-p)/n follows from the variance of a sum of independent trials
SE\mathrm{SE}
largest at p = 0.5; quadrupling n halves it

Wald interval: p-hat plus or minus 1.96 SE. It breaks near 0 and 1 and on small n, where the Wilson interval (Day 43) is the default. A pairwise win rate is the same estimator on pairs, with each flip scored as half a win.

A 95% interval by hand: 17 of 20 cases (clinic triage-reply assistant, synthetic) Table
StepArithmeticResult
Estimate17 / 20p-hat = 0.85
Standard errorsqrt(0.85 x 0.15 / 20) = sqrt(0.006375)0.080
Wald 95%0.85 +/- 1.96 x 0.080 = 0.85 +/- 0.1560.69 to 1.01: past 1, impossible
Wilson centre(0.85 + 1.96^2 / 40) / (1 + 1.96^2 / 20) = 0.946 / 1.1920.794
Wilson half-width1.96 x sqrt(0.006375 + 1.96^2 / 1600) / 1.1920.154
Wilson 95%0.794 +/- 0.1540.64 to 0.95

Checked in Python. Twenty cases cannot tell an 85% assistant from a 65% one. Independence is assumed: ten cases from one customer, template or document are closer to one trial than ten, so cluster by source or the interval is too narrow.

Agreement beyond chance: Cohen's kappa, derived and computedadvanced5 minWhy raw agreement flatters a judge, kappa derived from chance agreement, and two worked 2 x 2 tables that show the base-rate effect.
Cohen's kappa: agreement beyond chance Formula
κ=po−pe1−pe,pe=∑cpcjudge  pchuman\kappa = \frac{p_o - p_e}{1 - p_e}, \qquad p_e = \sum_{c} p^{\mathrm{judge}}_{c}\; p^{\mathrm{human}}_{c}
pop_o
share of items on which judge and human give the same label
pep_e
agreement expected if the two labelled independently, each at its own base rate per class c
po−pep_o - p_e
agreement above chance
1−pe1 - p_e
the most agreement above chance that was possible, so kappa is the share of it achieved
κ\kappa
1 is perfect agreement, 0 is chance level, below 0 worse than chance

Raw agreement rewards a grader for sharing the other grader's base rate; kappa removes that part. Skewed classes make high kappa hard to reach (Artstein and Poesio 2008).

Kappa by hand: judge against nurse labels on 50 reply pairs (healthcare, synthetic) Grid
Nurse label →
Judge label ↓A betterB better
A better (judge 30)2010
B better (judge 20)515

Diagonal = agreement: p_o = (20 + 15) / 50 = 0.70. Judge says A on 0.60, the nurse on 0.50, so chance agreement p_e = 0.60 x 0.50 + 0.40 x 0.50 = 0.50 and kappa = (0.70 - 0.50) / (1 - 0.50) = 0.40. Checked with scikit-learn's cohen_kappa_score: 70% raw agreement is only 40% of the way from chance to perfect.

Same formula, skewed task: 90% agreement, kappa 0.39 (insurance letters, synthetic) Sequence
  1. Counts

    50 claim letters: both say acceptable 43, judge only 3, human only 2, both say not acceptable 2.

  2. Observed

    p_o = (43 + 2) / 50 = 0.90.

  3. Base rates

    Judge says acceptable on 46 of 50 (0.92), the human on 45 (0.90).

  4. Chance

    p_e = 0.92 x 0.90 + 0.08 x 0.10 = 0.836: two graders who almost always say yes agree by default.

  5. Kappa

    (0.90 - 0.836) / (1 - 0.836) = 0.064 / 0.164 = 0.39.

  6. Read it

    90% raw agreement here is no better than 70% on the balanced task. Report kappa and agreement on the rare class.

Checked with cohen_kappa_score. Rare failures are exactly what a release gate is for, so a judge validated on raw agreement can miss most of them.

Validating a judge: its kappa against the human ceiling Diagram
Two humanslabel50-100 pairs, onerubricHuman-human kappathe ceiling the taskallowsJudge labelsthemsame pairs, bothorders, per sliceJudge-human kappabootstrap interval overitemsNear theceiling?Use it on this taskre-validate after ajudge updateChange the judgebetter prompt or anothermodelyesno
  1. Two humans label50-100 pairs, one rubric
    • to Human-human kappa
  2. Judge labels themsame pairs, both orders, per slice
    • to Judge-human kappa
  3. Human-human kappathe ceiling the task allows
    • to Near the ceiling?
  4. Judge-human kappabootstrap interval over items
  5. Near the ceiling?
    • no: to Change the judge
  6. Use it on this taskre-validate after a judge update
  7. Change the judgebetter prompt or another model

Kappa from 50 items is itself an estimate, so report its interval (a bootstrap over items is the simple way) before calling a judge validated. A judge validated on one task does not transfer to another.

How many pairs, and how sure3 minThe spread of a win rate at 50, 200 and 800 pairs, and the planning formula for a margin, inverted from the standard error.
The same candidate, evaluated 60 times at three set sizes Illustration
Observed win rate of one candidate, 60 repeated evaluations per set sizetrue 0.550.500.30.40.60.70.850 pairs±13.8 points200 pairs±6.9 points800 pairs±3.4 points

Seeded binomial draws; red dots are runs in which the truly better candidate does not look better. Pairs are treated as independent; ties and flips would widen the spread further.

Same candidate, same true win rate (0.55), 60 evaluations per size. With 50 pairs, 10 of 60 runs show the candidate losing or tied (observed rates 0.36 to 0.72); with 800 pairs, 1. The interval halves each time the set grows four-fold.

Every dot is one honest evaluation of a candidate with a true win rate of 0.55. To compare two systems, score the same items and report the paired difference with an interval (Miller 2024).

How many pairs does a win rate need? Formula
n≈z2 p(1−p)m2n \approx \frac{z^2\, p(1-p)}{m^2}
mm
the margin you want either side (0.05 for plus or minus 5 points)
pp
expected win rate; 0.5 is the worst case
zz
1.96 for 95%

The standard error solved for n: set z x sqrt(p(1-p)/n) equal to the margin m. Worst case: about 385 pairs for plus or minus 5 points, about 97 for plus or minus 10 (computed). Flips counted as ties and clustered items widen it.

Writing task cases3 minThe fields of a golden-set case and three test types that find real failures.
A golden-set case Table
FieldExample
inputA policyholder asks whether water damage from a burst pipe is covered
checkExact intent, schema, cited chunk id, or a written rubric
sliceintent, language, refusal, unanswerable
source and dateProduction log, author, date written
splitdevelopment or locked held-out
Test types for task cases (Ribeiro 2020) Overview
  • Minimum functionality

    Simple cases the system must pass, such as a plain refund request.

  • Invariance

    A change that must not alter the answer: a name, a typo.

  • Directional

    A change that must move the answer one way: add a legal threat, expect escalation.

Choosing the grader2 minCode, human or model judge, and what each one misses.
Three kinds of grader Comparison
CriterionCodeHumanModel judge
Best forSchema, allowed values, ids, citations, arithmeticReference labels, tone, policy nuanceOpen-ended quality at scale, after validation
Cost per itemNear zeroHighModerate; doubled for both orders
Main riskPasses valid but wrong contentInconsistent raters; write criteriaPosition, length and self-preference bias
Judging pairs without fooling yourself3 minConsistent verdicts, flips as ties and the length pull that survives swapping.
Both orders, consistent verdicts only (application output) Chart
  • Candidate wins both orders0.35
  • Baseline wins both orders0.3
  • Verdict flips (tie)0.35
How often the longer answer is picked (application output) Chart
  • Simulated judge0.63
  • Human preference0.53

Swapping order does not remove a length pull; a length control does (Dubois 2024).

Swapping fixes position, not length Illustration
Candidate win rate, adding one control at a time0.5 = no differenceOne order, candidate first0.74Both orders, flips = half0.57Both orders + length control0.51Human labels0.52

The candidate is no better than the baseline but writes the longer answer in 74% of pairs. Swapping removes the slot effect and still leaves a length bonus; comparing like with like (candidate longer: 0.65, candidate shorter: 0.36, weighted equally) removes most of it. Humans: 0.53 and 0.50 in the same groups.

Seeded simulation with the application’s judge rule (not a real model). The length control here is a simple stratification; Dubois et al. 2024 use a regression-based control. Real length effects differ by judge and task.

A candidate that is no better but usually longer, scored with one control added at a time.

Contamination screens and release gates3 minReport clean and flagged cases separately and let a safety slice block a release.
Pass rate with and without public-text overlap (optional lab) Chart
  • All 10 cases0.8
  • 7 clean cases3 cases flagged as overlapping public text0.71

Report both. Prefer private cases or cases written after the model's data cutoff (Sainz 2023).

A release gate by slice (optional lab, synthetic) Table
SliceOldNewDecision
Fare rules9/1010/10ok
Baggage8/109/10ok
Refusal / safety10/108/10BLOCK release

Two task slices improved and one safety slice regressed; a gate blocks on the safety slice whatever the average.

RLHF and DPO, the objectiveadvanced4 minWhat DPO minimises and why optimising a proxy reward eventually hurts.
The DPO loss for one preference pair Formula
L=−log⁡σ(β [(log⁡πθ(yw∣x)−log⁡πref(yw∣x))−(log⁡πθ(yl∣x)−log⁡πref(yl∣x))])\mathcal{L} = -\log \sigma\big(\beta\,[(\log \pi_\theta(y_w|x) - \log \pi_{ref}(y_w|x)) - (\log \pi_\theta(y_l|x) - \log \pi_{ref}(y_l|x))]\big)
yw,yly_w, y_l
chosen and rejected answers to prompt x
πref\pi_{ref}
frozen reference model (usually the SFT model)
β\beta
strength of the implicit KL penalty; larger keeps the policy closer to the reference
σ\sigma
logistic function; a zero margin gives loss log 2 = 0.693

In the optional lab a margin of 0.150 gives loss 0.621. Rafailov et al. 2023.

What the DPO loss does to one pair Sequence
  1. Margin

    beta times how much more the policy favours the chosen answer than the reference does.

  2. Zero margin

    Policy equals reference: loss log 2, the steepest learning signal.

  3. Weighting

    Each pair's gradient is scaled by sigma(-margin): pairs already ranked right count less.

  4. Beta

    Small beta lets the policy drift further from the reference before the loss saturates.

  5. Watch

    Track length, diversity and a held-out human metric, not the loss alone.

Rafailov et al. 2023; the weighting follows from differentiating the loss in the equation above. Re-measure diversity after tuning: RLHF generalised better than SFT out of distribution but reduced output diversity (Kirk 2024).

Reward over-optimisation, computed: proxy up, gold up then down Illustration
0.001.953.8901234Proxy reward (what is optimised)KL 0.00: 0.00KL 0.19: 0.78KL 0.64: 1.43KL 1.20: 1.97KL 1.84: 2.44KL 2.50: 2.86KL 3.17: 3.22KL 3.86: 3.56KL 4.55: 3.89n=8n=64n=256KL from start (nats)

Rises with every step of optimisation, to 3.89 at best-of-256. Read alone, it says: keep going.

-0.57-0.32-0.0701234Gold score (what you want)peakKL 0.00: -0.40KL 0.19: -0.19KL 0.64: -0.09KL 1.20: -0.07KL 1.84: -0.08KL 2.50: -0.12KL 3.17: -0.21KL 3.86: -0.36KL 4.55: -0.57KL from start (nats)

Peaks at best-of-8 (-0.07, KL 1.20 nats) and falls to -0.57 at best-of-256: the most optimised answer is not the best one.

0.000.811.6201234Length of the chosen answer (sd)KL 0.00: -0.00KL 0.19: 0.33KL 0.64: 0.60KL 1.20: 0.83KL 1.84: 1.01KL 2.50: 1.17KL 3.17: 1.31KL 3.86: 1.46KL 4.55: 1.62n=8n=64n=256KL from start (nats)

The proxy pays for length, so selection buys longer answers (+1.62 sd). Tracking length and a held-out gold metric next to the reward exposes the drift.

Best-of-n computed exactly over a seeded pool of 20,000 sampled answers (n = 1 to 256, KL = ln n - (n - 1) / n). The proxy and gold formulas are constructed to show the mechanism Gao et al. 2023 report (proxy up, gold up then down) and the length drift Singhal et al. 2023 describe; the numbers are not from either paper.

Best-of-n selection against a proxy reward that partly pays for length. The mechanism, not the paper's numbers.

Established versus evolving2 minWhich claims about judges and preference tuning are settled and which are still argued.
How settled is each claim? (as of the cited sources) Scale
  1. Judge position biasZheng 2023, Wang 2024
  2. Contamination inflates scoresSainz 2023
  3. Length drift under RLHFSinghal 2023
  4. Reward over-optimisationGao 2023
  5. Judges replacing humanstask-dependent
  6. DPO versus tuned PPOXu 2024: setup-dependent
Common misreadings, and the staff-level correction Overview
  • High agreement

    Agreement in each order can stay high while win rates swing with the slot.

  • Swap fixes every bias

    It cancels position, not length or self-preference.

  • Higher reward

    A proxy rises past the point where held-out human scores fall.

  • Leaderboard rank

    Public sets may be contaminated and answer someone else's question.

  • Judges replace humans

    Only on a task where agreement with human labels was measured.

Memory anchor

Judge both orders, control length, validate against humans, screen for overlap, gate on a regression suite.

Useful for

  • Turning a vague "is it better" into a task-specific, versioned evaluation with checks, slices and intervals (an insurer's claim-letter drafts, a retailer's product Q&A).

  • Auditing a judge-based win rate or a leaderboard claim for order, length, family and overlap effects.

  • Building a regression suite that gates prompt, model and data changes, including safety and refusal slices (a clinic's patient-message assistant must never give dosing advice).

Not suitable for

  • Replacing human judgement on high-stakes or novel criteria; a judge validated on one task does not transfer to another.

  • Settling safety by an accuracy-style pass rate; harm testing needs dedicated adversarial and policy test sets.

Traps

Reporting a judge win rate from one order

An e-commerce team scores its product-question assistant with one judge order. The judge's pull toward the first slot or the longer answer decides the result, the ranking reverses when the order is swapped, and the team ships on an artefact.

How to avoid it

Judge in both orders, count consistent verdicts, treat flips as ties, control length and validate against a human sample from the same task.

Tuning prompts on the evaluation set

An HR policy assistant's prompt is iterated forty times against the same 30 cases, which it ends up fitting. The score rises without a real gain and the held-out behaviour is worse; the set no longer measures anything independent.

How to avoid it

Keep a development set for iteration and a locked held-out set for decisions, record versions, and refresh with new production failures.

Senior reasoning

A senior distrusts a number until the instrument is checked, whether it scores a bank's mortgage assistant or a telecom's troubleshooting bot. They ask what the cases are, how "better" was defined, which judge, in which order, with what length control, validated against which human labels, and whether any case could have been seen in training, and they read agreement as kappa, not raw percent. They separate claims that are established from claims still debated, and they turn every failure into a case that blocks the next regression.

Interview question

How would you evaluate whether a new prompt for a bank's mortgage-questions assistant is better than the current one?

Recall cards scheduled after completion

  • Name three biases of an LLM judge and one control for each.
  • How do RLHF and DPO differ, and what is still contested?

Reviewed on a 1 · 3 · 7 · 14 · 30-day schedule; a miss returns the card to 1 day.

References

Optional sections

Deep dive · 10 min

Benchmarks versus task evaluations. A public benchmark is useful for screening and for tracking a model family; it answers a question about its own distribution. HELM argues for many metrics across many scenarios rather than one number (Liang 2023). For selection you need your own cases, because ranking can differ on your inputs and because benchmark text may be in a model's training data.

Judge validation, step by step. Write the rubric, label 50-100 pairs by humans (two raters on a sample to estimate rater agreement), run the judge in both orders, and report agreement per slice, with an interval. A judge whose agreement with humans is no higher than humans' agreement with each other is at the ceiling; a judge below that needs a better prompt or a different model. Re-validate after a judge model update.

RLHF in more detail. Step 1: supervised fine-tuning on demonstrations. Step 2: sample several responses per prompt, have people rank them, and fit a reward model to the rankings. Step 3: optimise the policy to maximise reward minus a penalty on divergence from the reference policy. Failure sites are the human feedback (noisy, biased, inconsistent), the reward model (a proxy that can be exploited) and the policy optimisation (Casper 2023). Over-optimising the proxy lowers the true reward after a point (Gao 2023).

DPO loss. For a prompt xx with chosen ywy_w and rejected yly_l, with reference policy πref\pi_{ref} and scale β\beta: L=−log⁡σ(β[log⁡πθ(yw∣x)πref(yw∣x)−log⁡πθ(yl∣x)πref(yl∣x)])\mathcal{L}=-\log\sigma\big(\beta[\log\tfrac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)}-\log\tfrac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)}]\big). The loss is log⁡2\log 2 when the policy equals the reference and falls as the policy raises the relative likelihood of the chosen answer. The lab computes one example.

Side effects to measure after preference tuning. Output length (Singhal 2023), diversity (Kirk 2024) and core capabilities (an "alignment tax") should be re-measured on your task suite, not assumed.

Retrieval project link (weekend studio). Sunday's contamination check computes the longest shared word sequence between each query and its labelled chunks and flags queries that copy source wording or were written after seeing retrieval output; that is the overlap screen of step 5 applied to your own queries. The same session asks for two ways a model judge can be biased, which are position and length effects from this lesson.

Hands-on lab: Build a 10-case eval, screen it for overlap, gate a release and compute one DPO loss · 20 min

Run the code. Part 1 evaluates ten hand-written fare-rule cases with a programmatic check and a crude overlap screen against a public text. Part 2 is a release gate on slices. Part 3 computes the DPO loss for one preference pair with made-up log-probabilities. Then add two cases of your own, one that should be refused and one with no answer in the knowledge base; rewrite c01 so the overlap screen no longer flags it and say whether the case got easier or harder; and change the margin in Part 3 so the loss falls below 0.5.

import math

# Part 1: a 10-case task-specific eval with a programmatic check and a contamination screen
public_text = ("the free cancellation window is 24 hours after booking on flex fares. "
               "passengers may carry one cabin bag of up to 8 kg on basic fares. "
               "online check in closes 2 hours before departure for all domestic flights.")
cases = [  # (id, prompt, required substring, recorded answer from a hypothetical system)
    ("c01", "What is the free cancellation window on flex fares?", "24 hours", "24 hours after booking"),
    ("c02", "How heavy may a cabin bag be on basic fares?", "8 kg", "up to 8 kg"),
    ("c03", "When does online check in close for domestic flights?", "2 hours", "2 hours before departure"),
    ("c04", "Can I change the name on a flex ticket after booking?", "not", "Yes, any time."),
    ("c05", "Is a refund due if the airline cancels my flight?", "refund", "You are due a refund."),
    ("c06", "Does the basic fare include a checked bag?", "no", "No, only a cabin bag."),
    ("c07", "What happens to my return leg if I skip the outbound?", "cancel", "It may be cancelled."),
    ("c08", "Can a minor travel alone on a domestic flight?", "yes", "Yes, with a guardian form."),
    ("c09", "Is lounge access included on flex fares?", "no", "No."),
    ("c10", "How early should I arrive for an international flight?", "3 hours", "About 2 hours."),
]
pub_words = set(public_text.replace(".", "").split())
def overlap(q):  # share of the question's words that also occur in the public text
    w = q.lower().replace("?", "").split()
    return sum(x in pub_words for x in w) / len(w)
leaky = {cid for cid, q, *_ in cases if overlap(q) >= 0.6}
ok = {cid: req.lower() in ans.lower() for cid, _, req, ans in cases}
clean = [c for c in ok if c not in leaky]
print(f"pass rate all {sum(ok.values())}/10; flagged as public-text overlap {sorted(leaky)}; clean-only {sum(ok[c] for c in clean)}/{len(clean)}")

# Part 2: regression gate on slices (old vs new version, hypothetical recorded pass counts)
old = {"fare rules": (9, 10), "baggage": (8, 10), "refusal / safety": (10, 10)}
new = {"fare rules": (10, 10), "baggage": (9, 10), "refusal / safety": (8, 10)}
for slice_, (k, n) in new.items():
    drop = old[slice_][0] - k
    print(f"{slice_:<17} {old[slice_][0]}/{n} -> {k}/{n}  {'BLOCK release' if drop > 0 and 'safety' in slice_ else 'ok' if drop <= 0 else 'review'}")

# Part 3: the DPO loss for one preference pair, with made-up log-probabilities (illustration only)
beta = 0.1
lp = {"chosen": (-12.0, -13.0), "rejected": (-15.0, -14.5)}  # (policy, frozen reference) sequence log-probs
margin = beta * ((lp["chosen"][0] - lp["chosen"][1]) - (lp["rejected"][0] - lp["rejected"][1]))
print(f"DPO margin {margin:.3f}, loss {-math.log(1 / (1 + math.exp(-margin))):.3f} (log 2 = {math.log(2):.3f} at margin 0)")
Interview practice · 10 min

A vendor pitching to a hospital's patient-messaging team claims their model "beats" yours by 8 points on a leaderboard and by 70% win rate under a GPT-style judge. How do you decide whether to switch?

Content version 6 · last verified 2026-10-18 · depends on numpy