Skip to content

    AI Architect

    Evaluating AI Systems: Metrics, Judges and Gates

    How AI architects evaluate LLM systems: golden sets, retrieval and generation metrics, judge bias and kappa calibration, and CI gates with confidence intervals.

    By Published 41 min read

    Share

    This lesson is part of AI Architect: From AI Engineer to Expert. Enroll for free, then sign in, to read it in full.

    What you'll learn: how to build a golden set and a regression gate a team can trust, how an LLM judge works and where it is biased, how to calibrate a judge against human labels with Cohen's kappa, how to measure retrieval (recall at k, MRR, nDCG) separately from generation (faithfulness, answer relevance), how to evaluate agents by outcome and trajectory, and what a pass/fail gate with a finite number of samples can and cannot detect.

    The real-world problem

    A team changes one sentence in the system prompt of its product-help assistant to make answers shorter. Five reviewers read twenty answers each, nobody sees a problem, and the change ships. Two weeks later the returns team reports confident but incomplete answers about one product category. The quality dashboard shows an average that moved by about a point. Nothing alerted, because nothing was measuring that category, and one point on the average was well inside the noise of the sample that produced it.

    The team did not lack effort. It lacked an evaluation design: a labelled set big enough to see the failure, a judge whose agreement with people was known, metrics that separate retrieval from generation, and a gate that states what size of drop it can and cannot detect. This page teaches that design.

    After this page you will be able to

    • Build a versioned golden set with slices, a rubric and a hold-out split, and say what each part is for.
    • Calibrate an LLM judge against human labels: compute raw agreement, Cohen's kappa and the judge's failure recall from a 2x2 table, and decide whether the judge may gate a release.
    • Compute recall at k, reciprocal rank and nDCG for a ranked list with graded relevance, and use them to locate a failure in retrieval rather than generation.
    • Compute a Wilson confidence interval for a pass rate and the number of samples needed to detect a stated drop, and explain why a gate on the point estimate misleads.
    • Design a CI gate for a prompt or model change, including slice reports, a position-swapped pairwise comparison and the outcome-versus-trajectory split for agents.

    Read page 2, the architect mindset first: it defines testable requirements and works one confidence-interval example (180 of 200 passing, and the zero-failures bound), which this page does not repeat. Retrieval concepts come from page 5, data and retrieval and agent concepts from page 6, agents, tools and MCP. Practitioner-level background is in Evaluating RAG systems with RAGAS, Testing AI applications and Output evaluation and validation. For the cost of judge calls use the site's LLM cost estimator and token counter; this page states no prices.

    Terms used on this page: golden set, regression gate, LLM as judge, position bias, verbosity bias, self-preference bias, Cohen's kappa, recall at k, mean reciprocal rank, nDCG, faithfulness, answer relevance, Wilson interval, pass at k, eval service, quality bar, SLI and SLO.

    Core concepts

    Figure 1. The evaluation loop around an AI system

    flowchart LR accTitle: The evaluation loop around an AI system accDescr: Offline, a versioned golden set and a rubric feed the eval service, which runs the candidate and asks a judge model to grade it. A gate passes or blocks the release. After release, the trace store feeds a human review sample whose findings grow the golden set. subgraph OFF["Offline, before release"] GS["Golden set (versioned)"] --> ES["Eval service"] RU["Rubric and judge prompt"] --> ES ES --> OR["Orchestrator (candidate version)"] OR --> ES ES --> JG["LLM provider (judge)"] JG --> ES ES --> GT{"Gate"} end GT -- pass --> RL["Release"] GT -- fail --> FX["Fix and re-run"] subgraph ON["Online, after release"] RL --> TS["Trace store"] TS --> HR["Human review of a sample"] end HR --> GS

    How to read this: the left box is what blocks a bad change, the right box is how production teaches the golden set about cases nobody imagined, and the arrow back into the golden set keeps the loop honest.

    Golden sets and how to build them

    A golden set is a versioned collection of inputs with what is needed to grade the outputs: a reference answer, facts that must appear, passages that should be retrieved, a rubric, or the end state an agent should reach. Anthropic's guidance says to "design evals that mirror your real-world task distribution" and to include edge cases, and that "more questions with slightly lower signal automated grading is better than fewer questions" (Anthropic, Define success criteria and build evaluations, as of 2026-10-22). Its agent-eval post says "20-50 simple tasks drawn from real failures is a great start" (Demystifying evals for AI agents, 9 January 2026). OpenAI recommends logging as you develop so real cases can be mined into new evals (Evaluation best practices, as of 2026-10-22). Working rules:

    1. Seed from real failures and real traffic, not from what the team can imagine. Every incident adds at least one item.
    2. Tag every item with slices: product category, language, document type, tenant, risk class, input length. Slices find the failure an average hides.
    3. Write the rubric before labelling, and label subjective items with two people, adjudicating disagreements.
    4. Split a hold-out set that nobody tunes prompts against. This is the course's recommendation, not a sourced rule: once you edit a prompt until the set passes, the set measures your editing.
    5. Version the set and record which version produced each score.
    NOTE

    Size is a statistical decision. Under the hood section 7 shows that 100 items detect only a drop of about 7.5 points from a 92% baseline, and a 30-item slice only about 16 points.

    Offline and online evaluation

    Offline evaluation runs a fixed set before release and answers "is this change safe to ship". Online evaluation looks at production traffic and answers "is the system still working on what users actually send". Offline is repeatable but sees only the past. Online sees the real distribution but has no ground truth for most requests, so it relies on user signals, sampled human review and a judge on a sample. Online findings flow back into the golden set (Figure 1), and canary and A/B mechanics (page 9) reuse the same metrics and intervals. Do not judge every production request unless the verdict changes what the user sees: a sampled score gives a rate with a known interval for a fraction of the spend.

    Regression gates in CI

    A regression gate blocks a merge when evidence shows quality dropped. Decide three things in advance: the metric (pass rate on a rubric, recall at k, faithfulness), the comparison (a fixed bar or the current production version), and the rule for noise (a confidence bound, not the point estimate). Anthropic's agent-eval post separates capability evals, which ask "what can this agent do well?" and "should start at a low pass rate", from regression evals, which "should have a nearly 100% pass rate". Keep them as separate suites with separate gates.

    Figure 2. A regression gate in CI, including its failure paths

    sequenceDiagram accTitle: Regression gate in CI accDescr: CI asks the eval service to run the golden set. For each item the eval service calls the candidate, then asks the judge model for a verdict. A verdict that is still malformed after one retry is stored as an error. The eval service computes slice pass rates with a lower confidence bound, stores everything in the trace store and tells CI to pass or block. participant CI as CI pipeline participant ES as Eval service participant OR as Orchestrator participant LP as LLM provider participant TS as Trace store CI->>ES: Run golden set for candidate version loop Each golden-set item ES->>OR: Input and test context OR-->>ES: Output, retrieved passages, tool calls ES->>LP: Judge prompt with rubric and output LP-->>ES: Verdict alt Verdict still malformed after one retry ES->>TS: Record eval error, not a pass else Verdict parses ES->>TS: Record score, trace, judge and prompt versions end end ES->>ES: Pass rate and lower bound per slice alt Every slice clears its bound and error rate is within limit ES-->>CI: Pass with report else Any slice fails or too many eval errors ES-->>CI: Block with failing slices and items end Note over CI,TS: A run with too many judge errors is invalid, not green.

    How to read this: the gate decides on a bound per slice and counts judge errors as failures of the evaluation, so a broken judge can never turn a run green.

    Human review and label quality

    Humans are the reference, but not perfectly consistent. In the TREC-8 question answering track each question was judged independently by three assessors, and the organisers concluded that "assessors have legitimate differences of opinion as to correctness even for fact-based, short-answer questions" (Voorhees and Tice, LREC 2000). In the MT-bench study, two human experts agreed 81% of the time when ties are excluded, against 85% for GPT-4 with humans (Zheng et al., Table 5a). So a judge cannot be held to a standard higher than your own reviewers reach: measure reviewer agreement first, and if two reviewers disagree often, repair the rubric before measuring anything else. Anthropic's documentation states the usual tradeoff: code-based grading is "fastest and most reliable" but lacks nuance, human grading is "most flexible and high quality, but slow and expensive", and LLM-based grading is "fast and flexible" and should be tested for reliability before scaling. Use all three: code checks for what code can check (schema, citation present, forbidden string absent), a calibrated judge for what needs reading, and humans for calibration and for cases the judge finds hard.

    Evaluating retrieval separately from generation

    A wrong answer from a retrieval-augmented system has at least four causes, and one end-to-end score cannot separate them: the passage was never retrieved, it was retrieved but dropped or buried during prompt assembly, the model ignored or contradicted it, or the passage itself is stale or wrong. Each has a different fix and owner.

    Figure 3. Locating the failing stage of a wrong answer

    flowchart TD accTitle: Locating the failing stage of a wrong answer accDescr: A decision tree for a wrong or unsupported answer. It asks whether a relevant passage was retrieved, whether it reached the prompt, whether every claim is supported by the passages, and whether the passage itself is correct and current. Each no leads to a named failing stage, and a final branch checks the label or judge. W["Wrong or unsupported answer"] --> Q1{"Relevant passage in the retrieved set?"} Q1 -- no --> R1["Retrieval failure: check recall at k, index, chunking, filters"] Q1 -- yes --> Q2{"Passage present in the final prompt?"} Q2 -- no --> R2["Context assembly failure: trimming, ordering, budget"] Q2 -- yes --> Q3{"Every claim supported by the passages?"} Q3 -- no --> R3["Generation failure: faithfulness"] Q3 -- yes --> Q4{"Passage correct and current?"} Q4 -- no --> R4["Source failure: stale or conflicting document"] Q4 -- yes --> R5["Check the label and the judge before changing the system"]

    How to read this: work down the tree in order, because the first "no" names the stage to fix, and the last branch reminds you that the evaluation itself can be wrong.

    This is why sections 5 and 6 below keep the metrics apart: retrieval metrics need labelled passages and no model call; generation metrics need the retrieved passages and a judge. Report both per slice, side by side.

    Evaluating agents: trajectory versus outcome

    Anthropic's post defines the transcript (trajectory) as "the complete record of a trial, including outputs, tool calls, reasoning, intermediate results" and the outcome as "the final state in the environment at the end of the trial", and advises that "it's often better to grade what the agent produced, not the path it took", because valid paths vary. The tau-bench benchmark does the same for tool-using agents: it compares the database state at the end of a conversation with an annotated goal state (Yao et al., arXiv 2406.12045).

    What to grade Example check Why
    Outcome The ticket is in the right state, the refund has the right amount, no other record changed It is what the business cares about, and many paths reach it
    Trajectory, policy steps only The approval step was not skipped, no forbidden tool was called Some paths are unacceptable even when the outcome is right
    Trajectory, efficiency Steps and tokens against a budget Cost and latency are requirements too

    Agent runs are stochastic, so one trial per task is not enough. Anthropic defines pass@k as "the likelihood that an agent gets at least one correct solution in k attempts" and pass^k as "the probability that all k trials succeed". If each trial succeeded independently with probability p (a simplification, since trials share task difficulty), pass@k is 1 - (1 - p)^k and pass^k is p^k: with p = 0.9, pass@3 is 0.999, pass^3 is 0.729 and pass^8 is 0.43. The tau-bench abstract reports that even the strongest function-calling agents tested succeeded on fewer than half the tasks, with pass^8 below 25% in the retail domain. Report pass^k for any agent that acts on the world (agent loop: page 6; event-driven designs: page 7).

    Case files

    • A prompt tweak that silently broke one product category. In a composite retail scenario, a prompt change lowered answer quality in one category while the average barely moved. Pattern: eval gates, with a golden set per category and a confidence interval on the gate.
    • A RAG assistant that was confident and wrong. In a composite healthcare scenario, a procedure-lookup assistant gave fluent, wrong answers, mostly because it retrieved a superseded passage and stayed faithful to it. Pattern: LLM judge and faithfulness checks, retrieval metrics kept apart from generation metrics, and abstention when evidence is weak.
    • Summarisation: nobody agreed what good meant. In a composite public-sector scenario, a summarisation feature could not be improved because there was no shared definition of quality. Pattern: eval design, with a rubric, a calibrated judge, human spot checks and pairwise comparison for model changes.

    Under the hood: How an LLM judge works

    Intuition

    An LLM judge is an ordinary model call that returns a grade instead of an answer. Its output depends on the judge model, the judge prompt, the rubric, the item and the sampling settings, so it is a measuring instrument with its own error. Treat it like any classifier you ship: version it, measure it against labelled data, and never assume its accuracy is fixed.

    Mechanism

    Zheng et al. studied "LLM-as-a-judge" and defined three variants: pairwise comparison (the judge sees a question and two answers and picks the better one or declares a tie), single answer grading (the judge scores one answer) and reference-guided grading (the judge is given a reference solution, used mainly for maths). Their default single-answer prompt (Figure 6 of the paper) shows the design. It tells the judge to "act as an impartial judge", to consider factors such as "helpfulness, relevance, accuracy, depth, creativity, and level of detail", to "begin your evaluation by providing a short explanation", and to rate from 1 to 10 in a strict format, "[[rating]]": a rubric, reasoning before the verdict, and a machine-parseable verdict.

    Figure 4. One judge call, including a malformed verdict

    sequenceDiagram accTitle: One judge call accDescr: The eval service builds a judge prompt from the rubric, question and candidate answer, sends it to the judge model and receives an explanation followed by a verdict. If the verdict parses it is stored with the prompt and judge model versions. If not, the eval service retries once and otherwise records an evaluation error. participant ES as Eval service participant LP as LLM provider participant TS as Trace store ES->>ES: Build judge prompt from rubric, question and answer ES->>LP: Judge prompt with output format LP-->>ES: Short explanation, then verdict alt Verdict parses ES->>TS: Store verdict, raw output, prompt version, judge model version else Verdict malformed ES->>LP: Retry once with a format reminder LP-->>ES: Second response ES->>TS: Store verdict if it parses, else store an evaluation error end Note over ES,TS: The judge output is stored raw so a human can audit any score.

    How to read this: the judge is one remote call with a parse step after it, and the parse step has a defined failure path.

    Both providers recommend narrow, structured outputs. Anthropic's guidance says to have "detailed, clear rubrics", to "be empirical or specific" (output only "correct" or "incorrect", or a score from 1 to 5) and to encourage reasoning before the score; OpenAI's says LLMs "are better at discriminating between options" and recommends pairwise comparison or pass/fail "for more reliability". The paper also shows the format has a cost: in its position-bias test, between 0% and 3.8% of judge outputs per configuration had a wrong output format (the "Error" column of Table 2). Parse failures are a measurable part of the pipeline.

    What this means for architects

    • Latency and cost. Every judged item is at least one extra model call, and a judge that reasons produces output tokens, which dominate latency (page 4). Run judges offline or on a sample unless the verdict changes what the user sees.
    • Pin and record versions. Store the judge model version, prompt version and raw output with every score. Zheng et al. note that absolute scores "are likely to fluctuate more than relative pairwise results if the judge model changes", so a changed judge breaks comparison with history: re-baseline.
    • Failure handling. A malformed verdict is an evaluation error, never a pass, and a run above an agreed error-rate limit is invalid.
    • Separation. Anthropic's example code carries the comment "Generally best practice to use a different model to evaluate than the model used to generate the evaluated output". Give the judge its own route behind the model gateway so its model can differ from the system under test.
    • Verify the judge. It is a model to be tested, which the next two sections cover.

    Under the hood: Judge biases

    Intuition

    A judge can prefer an answer for reasons unrelated to quality: where it sits in the prompt, how long it is, or who wrote it. These biases are systematic, so they do not average out like random noise, and they can line up with the change you are testing.

    Mechanism

    Zheng et al. define each bias and measure it on 2023-era models (GPT-4, GPT-3.5, Claude-v1). Read the numbers as evidence that the effects exist and can be large, not as properties of any model you use today.

    Bias Definition in the paper What they measured
    Position bias "when an LLM exhibits a propensity to favor certain positions over others" Two very similar answers per question, order swapped (default prompt): consistency GPT-4 65.0%, GPT-3.5 46.2%, Claude-v1 23.8%; Claude-v1 favoured the first position in 75.0% of cases
    Verbosity bias "when an LLM judge favors longer, verbose responses, even if they are not as clear, high-quality, or accurate as shorter alternatives" A "repetitive list" attack on 23 answers (rephrased items added, no new information): judge failure rate Claude-v1 91.3%, GPT-3.5 91.3%, GPT-4 8.7%
    Self-enhancement bias "LLM judges may favor the answers generated by themselves" GPT-4 favoured itself with a 10% higher win rate than humans gave it, Claude-v1 25%, GPT-3.5 not at all; the judges also favoured other models, and the authors state their "study cannot determine whether the models exhibit a self-enhancement bias"
    Limited reasoning Judges mis-grade maths and reasoning answers Failure on 10 maths questions (20 judgments): default prompt 14/20, chain-of-thought 6/20, reference-guided 3/20

    On self-preference the paper is inconclusive, but later work is not: Panickssery, Bowman and Feng report that LLM evaluators score their own outputs higher than other texts even when human annotators rate those texts as equal in quality, that GPT-4 and Llama 2 have non-trivial accuracy at telling their own text from other models' and humans', and that self-recognition and the strength of self-preference are linearly correlated (arXiv 2404.13076). Assume the effect is possible.

    The paper's mitigations, with their stated costs:

    • Swap positions. "A conservative approach is to call a judge twice by swapping the order of two answers and only declare a win when an answer is preferred in both orders." Inconsistent results are a tie. Swapping doubles the judge calls, so do it always for release decisions and on a sample for monitoring. Random position assignment is "effective at a large scale with the correct expectations".
    • Few-shot examples raised GPT-4's consistency from 65.0% to 77.5%, but "high consistency may not imply high accuracy", they may add new biases, and the longer prompts made API calls 4 times more expensive.
    • Chain-of-thought and reference-guided judging cut maths failures from 14/20 to 6/20 and 3/20. With chain-of-thought the judge often "makes exactly the same mistake as the given answers".
    • Length and family controls. OpenAI's guidance names position and verbosity bias and recommends controlling for response length; Anthropic's example recommends a different judge model from the generator.

    Figure 5. The position-swap mitigation

    sequenceDiagram accTitle: Position-swap mitigation for a pairwise judge accDescr: The eval service sends the same two answers to the judge in both orders. If the same answer wins in both orders the trace store records a win for it. If the verdicts disagree the result is recorded as a tie. participant ES as Eval service participant LP as LLM provider participant TS as Trace store ES->>LP: Prompt 1 with answer A first and answer B second LP-->>ES: Verdict 1 ES->>LP: Prompt 2 with answer B first and answer A second LP-->>ES: Verdict 2 alt Same answer preferred in both orders ES->>TS: Record a win for that answer else Verdicts disagree or both say tie ES->>TS: Record a tie end Note over ES,LP: Two judge calls per pair instead of one.

    How to read this: a preference counts only if it survives swapping the order, so a pure position effect becomes a tie rather than a false win.

    What this means for architects

    • Measure your own judge. The published rates are for old models. Run every pair in both orders and report the share of flips, and pad a few answers with redundant text to see whether the verdict moves. Both cost a small multiple of one run.
    • Bias that cancels and bias that does not. A constant bias applied equally to baseline and candidate largely cancels in an A/B comparison. A bias correlated with the change does not: a prompt edit that lengthens answers looks better to a verbosity-biased judge. This is the course's reasoning, not a measured result, and it is why you control length and spot-check with humans.
    • Judges cannot grade what they cannot do. For maths, code and facts the judge does not know, give it a reference or use code-based grading.

    Under the hood: Calibrating a judge against human labels

    Intuition

    Before a judge's pass rate counts, check how often its verdict matches a person's on the same items. Raw agreement is not enough, because two raters who both say "pass" most of the time agree often by chance. Cohen's kappa asks how much better than chance the agreement is.

    Mechanism

    The Stanford information retrieval textbook defines the statistic: kappa = (P(A) - P(E)) / (1 - P(E)), where P(A) is "the proportion of the times the judges agreed" and P(E) is "the proportion of the times they would be expected to agree by chance" (Manning et al., Assessing relevance). Cohen's original coefficient computes P(E) from each rater's own marginal proportions; the textbook pools the two raters' marginals. Artstein and Poesio describe the first as assuming prior distributions "unique to each coder" (2008, section 2.4.3). On the textbook's own example (400 judgments: 300 both yes, 20, 10, 70 both no) both versions give 0.776. The textbook reads the value so: above 0.8 is "good agreement", between 0.67 and 0.8 "fair agreement", below 0.67 "data providing a dubious basis for an evaluation", with the caveat that the precise cutoffs depend on the purpose.

    A worked example (illustrative counts). Take 200 items that a human reviewer and the judge both labelled pass or fail.

    Human pass Human fail Judge total
    Judge pass 150 20 170
    Judge fail 6 24 30
    Human total 156 44 200
    P(A) = (150 + 24) / 200 = 0.87
    judge says pass: 170/200 = 0.85     human says pass: 156/200 = 0.78
    P(E) = 0.85 x 0.78 + 0.15 x 0.22 = 0.663 + 0.033 = 0.696
    kappa = (0.87 - 0.696) / (1 - 0.696) = 0.174 / 0.304 = 0.572

    Raw agreement is 87%, yet kappa is 0.57, below the textbook's 0.67 line. The table shows why: of the 44 items humans failed, the judge caught only 24 (54.5%, with a 95% Wilson interval of about 40% to 68%), and it passes 85% of items where humans pass 78%, overstating the pass rate by 7 points. A gate built on this judge would wave bad answers through. A percentile bootstrap over the 200 items (5,000 resamples; a computation made for this page, not a sourced method) puts the kappa interval at roughly 0.42 to 0.71, a reminder that kappa from 200 items is itself an estimate.

    Skewed data distorts kappa the other way. Artstein and Poesio call it the prevalence problem: "if a disproportionate amount of the data falls under one category, then the expected agreement is very high", so chance-corrected agreement "may be low even though" observed agreement is high. With 200 items split 180 / 6 / 6 / 8, observed agreement is 94% and kappa only 0.54. Always report the judge's performance on the rare class, which for gates is the fail class.

    After tightening the rubric, measure again on a fresh sample, not the items used to edit it. Suppose a fresh 200 gives 146 both pass, 8 judge-pass-human-fail, 10 judge-fail-human-pass and 36 both fail: P(A) = 0.91, kappa = 0.742, the judge passes 77% against the humans' 78%, and it catches 36 of 44 failures. That is the textbook's "fair" band, usable for trend monitoring with spot checks. Whether it may gate a release alone depends on the bar the requirement sets and the cost of a missed failure.

    Figure 6. The life of a judge

    stateDiagram-v2 accTitle: Judge calibration life cycle accDescr: A judge starts as a draft prompt and rubric. It is calibrated against human labels. If agreement is below the agreed bar it returns to draft. If it meets the bar on fresh items it is trusted. A failed spot check or any change to the judge model or prompt sends it back to calibration. A retired judge is kept for the record. [*] --> Draft Draft --> Calibrating: rubric and prompt written Calibrating --> Draft: agreement below the bar Calibrating --> Trusted: meets the bar on fresh items Trusted --> Drifting: spot check disagrees or judge or prompt changes Drifting --> Calibrating: relabel a fresh sample Trusted --> Retired: task or rubric replaced Retired --> [*]

    How to read this: a judge is never trusted for good, because any change to the judge, prompt or task, and any failed spot check, sends it back to calibration.

    What this means for architects

    • Put the bar in the requirement. For example: "kappa of at least 0.67 and failure recall of at least 80% on a fresh 200-item sample, re-checked monthly and after any change to judge or prompt". The numbers are yours to set; what matters is that they exist.
    • Cost. Human labels are the expensive part. Label a stratified sample that over-represents failures and borderline cases, because the rare class decides the judge's usefulness; the 40% to 68% interval on 44 failures shows how few failures make failure recall hard to pin down. A sample that is not random changes the marginals, so weight each stratum back to its share of the population before computing kappa.
    • Hold-out discipline and slices. Calibration items must not be the items used to tune the rubric. A judge that agrees on easy items and not on hard ones looks fine in aggregate, so report agreement per slice.
    • Published figures in context. In MT-bench, GPT-4 agreed with human experts 85% of the time without ties, against 81% between humans, with 50% expected for random judges. Applying the kappa formula with 50% as the chance level gives (0.85 - 0.50) / (1 - 0.50) = 0.70. That illustrates the formula on the paper's own baseline; the paper does not report it, but it shows a headline "85% agreement" is 0.70 on the chance-corrected scale.

    Under the hood: Pairwise and absolute scoring

    Intuition

    You can ask a judge "is this answer good?" (absolute) or "which of these two is better?" (pairwise). Absolute scores can be tracked against a fixed bar over time. Pairwise judgments are usually more reliable for choosing between two versions but say nothing about whether either is good enough.

    Mechanism

    Zheng et al. state the tradeoff. Pairwise comparison "may lack scalability when the number of players increases, given that the number of possible pairs grows quadratically", while single answer grading "may be unable to discern subtle differences between specific pairs" and "absolute scores are likely to fluctuate more than relative pairwise results if the judge model changes". On MT-bench (Table 5a, first turn, non-tie votes) GPT-4 agreed with human experts 85% of the time in both modes, and the authors say single-answer grading "may sometimes perform slightly worse than pairwise comparison and give more tie votes" but "is a more scalable method".

    Call counts (illustrative). For k systems and Q questions, absolute grading needs k x Q calls. Pairwise grading with a position swap needs k(k - 1)/2 pairs, two orders each: k(k - 1) x Q calls. With 6 systems and 80 questions that is 480 calls against 2,400. For one candidate against the current version (k = 2) both need 2 x Q calls, but pairwise calls carry two answers each, so about twice the answer tokens.

    Reporting a pairwise result (illustrative). Run 400 items in both orders and count a win only when the candidate is preferred in both (the paper's conservative rule): 150 wins, 110 losses, 140 ties. Excluding ties, the candidate wins 150 of 260 decided items, 57.7%, with a 95% Wilson interval of about 51.6% to 63.5%, which excludes 50%. Two cautions: 140 of 400 items (35%) showed no judged difference, so the effect sits in a minority of items, and "better than the baseline" is not "good enough", so it does not replace an absolute bar.

    Figure 7. Choosing a scoring mode

    flowchart TD accTitle: Choosing between pairwise and absolute scoring accDescr: The decision determines the mode. Choosing between two versions uses position-swapped pairwise judging. Holding a quality bar over time uses absolute pass or fail on a rubric. Choosing among many candidates screens with absolute scores and then runs pairwise on the shortlist. All paths end in a human spot check. Q{"What decision is this?"} Q -- "Is version B better than version A" --> PW["Pairwise with position swap"] Q -- "Does the system still meet the bar" --> AB["Absolute pass/fail on a rubric"] Q -- "Which of many candidates" --> SH["Absolute screen, then pairwise on a shortlist"] SH --> PW PW --> R1["Report wins, ties, losses and an interval"] AB --> R2["Report pass rate with a lower bound"] R1 --> HC["Human spot check of ties and disagreements"] R2 --> HC

    How to read this: the decision picks the mode, and both modes end with a person reading a sample of the cases the judge found hard.

    What this means for architects

    • Default (an opinion). Pairwise with a position swap to choose between model or prompt versions; absolute pass/fail on a written rubric for the release bar and monitoring. OpenAI's guidance favours pairwise or pass/fail "for more reliability", while others prefer graded scores for diagnostics, so check your judge's calibration in each mode.
    • Cost. Pairwise cost grows with the number of candidates, so screen with absolute scores first when comparing many.
    • History. Absolute scores are comparable over time only while judge, prompt and rubric stay fixed. Pin all three, and run the baseline beside the candidate in every pairwise comparison.
    • Ties are data. A high tie rate says the change barely matters to the judge: good news for a refactor, bad news for an optimisation.

    Under the hood: Retrieval metrics

    Intuition

    For each query the retriever returns a ranked list. Three questions matter. Did the relevant documents appear in the top k (recall at k)? How early did the first one appear (reciprocal rank)? Are the most useful documents ranked above the less useful ones (nDCG)? They need labelled queries but no model call, so they are cheap and deterministic.

    Mechanism

    The Stanford IR book defines recall as "the fraction of relevant documents that are retrieved", tp / (tp + fn); restricted to the top k results it is recall at k. For graded relevance it defines normalised discounted cumulative gain, "designed for situations of non-binary notions of relevance" (Manning et al., section 8.4). With R(j, m) the grade assessors gave the document at rank m for query j, and Z the factor that makes a perfect ranking score 1:

    Recall@k = (relevant documents in the top k) / (all relevant documents)
    NDCG(Q, k) = (1/|Q|) * sum over queries j of  Z_kj * sum for m = 1..k of (2^R(j,m) - 1) / log2(1 + m)
    RR = 1 / (rank of the first relevant result), or 0 if none;  MRR = mean of RR over queries

    That section of the Stanford book does not define mean reciprocal rank. The TREC-8 question answering track scored a question as "the reciprocal of the rank at which the first correct response was returned, or 0 if none of the five responses contained a correct answer", and a submission as the mean over questions (Voorhees and Tice, LREC 2000). That track listed five responses; choose your own cutoff and state it.

    A worked example (illustrative). One query has four relevant documents with grades 3, 2, 2 and 1 (0 means not relevant). The retriever returns ten results; the relevant ones are at rank 2 (grade 3), rank 4 (grade 2) and rank 7 (grade 1). The other grade-2 document is never retrieved.

    Rank m 1 2 3 4 5 6 7 8 9 10
    Grade 0 3 0 2 0 0 1 0 0 0
    Recall@5  = 2/4 = 0.50          Recall@10 = 3/4 = 0.75          RR = 1/2 = 0.50
    DCG@10  = (2^3-1)/log2(3) + (2^2-1)/log2(5) + (2^1-1)/log2(8)
            = 7/1.585 + 3/2.322 + 1/3 = 4.4165 + 1.2920 + 0.3333 = 6.0419
    IDCG@10 = 7/log2(2) + 3/log2(3) + 3/log2(4) + 1/log2(5)
            = 7 + 1.8928 + 1.5 + 0.4307 = 10.8235
    nDCG@10 = 6.0419 / 10.8235 = 0.558

    For MRR take three queries whose first relevant results are at ranks 2, 1 and not in the top 10: reciprocal ranks 0.5, 1 and 0, so MRR = 1.5 / 3 = 0.5. Now put the grade-3 document at rank 1 and the grade-2 document at rank 3, leaving the grade-1 document at rank 7. Recall at 5 is still 0.50, but nDCG at 10 rises from 0.558 to 0.816. Recall at k ignores order inside the top k; nDCG rewards putting the most useful document first.

    Figure 8. From labelled queries to retrieval metrics

    flowchart LR accTitle: From labelled queries to retrieval metrics accDescr: Labelled queries go to the retriever, which searches the vector index and returns a ranked top k. The eval service compares the list with relevance labels from the document store and computes recall at k, reciprocal rank and nDCG. Results are reported per slice and checked against a gate. LQ["Labelled queries"] --> RT["Retriever"] VI["Vector index"] --> RT RT --> RK["Ranked top k"] DS["Document store (relevance labels)"] --> ES["Eval service"] RK --> ES ES --> M["Recall at k, reciprocal rank, nDCG"] M --> SG["Per-slice report and gate"]

    How to read this: the retriever output never touches a language model on this path, so the numbers are repeatable and any change comes from the index, the query or the ranking.

    What this means for architects

    • Recall at the k you feed the model is a ceiling. If a relevant passage is not among those placed in the prompt, the generator cannot ground its answer in it. Measure recall at the k you actually use, and revisit it when you change the context budget (page 4) or add a reranker (page 5).
    • Choose the metric by what is consumed. MRR when the first result matters, recall at k when a set of passages is consumed together, nDCG when grades differ and order matters.
    • Labels are incomplete. The IR book notes that for TREC, relevance judgments exist "only for the documents that were among the top k returned" for some participating system. A relevant document nobody labelled counts as a miss, so add labels when you change retrievers, or the new one is penalised for finding what the old one never showed.
    • Cost and slices. These metrics run in seconds on thousands of queries, so they are the fast gate for index, chunking and reranker changes, before slower judge-based checks. Slice them: per-tenant recall catches an access-filter or chunking bug that the mean hides.

    Under the hood: Generation metrics

    Intuition

    Once the right passages are in the prompt, the questions change. Is every claim in the answer supported by those passages (faithfulness)? Does the answer address the question asked (answer relevance)? These metrics are reference-free: they need the question, the retrieved context and the answer, not a gold answer.

    Mechanism

    The RAGAS paper defines them (Es et al., arXiv 2309.15217). Faithfulness: the answer is faithful "if the claims that are made in the answer can be inferred from the context". An LLM extracts a set of statements S from the answer, then judges for each whether it can be inferred from the retrieved context; with V the supported statements, F = |V| / |S|. Answer relevance: an LLM generates n questions from the answer, each is embedded, and the score is the mean cosine similarity to the original question, AR = (1/n) x sum of sim(q, q_i). The paper adds that this "does not take into account factuality, but penalises cases where the answer is incomplete or where it contains redundant information". Context relevance is the fraction of the retrieved context's sentences that an LLM judges crucial to answering the question.

    The library documentation, as of 2026-10-22, describes the same ideas: faithfulness is supported claims divided by total claims, and answer relevancy averages cosine similarities between the user input and questions generated from the response, 3 by default (faithfulness, answer relevancy). The documentation says the legacy interface will be deprecated in version 0.4, so pin the version you use.

    A worked example (illustrative). An answer splits into 5 statements and the verifier judges 4 supported: F = 4 / 5 = 0.80. For relevance, if three questions generated from the answer have cosine similarities 0.91, 0.88 and 0.79 with the original, AR = (0.91 + 0.88 + 0.79) / 3 = 0.86. The paper's own low-faithfulness illustration names the wrong director for a film when the context names the right one.

    Figure 9. Computing faithfulness for one trace

    sequenceDiagram accTitle: Computing faithfulness for one trace accDescr: The eval service reads a trace holding the question, retrieved passages and answer. It asks the judge model to split the answer into statements, then to verify each statement against the passages. It computes supported over total and flags low-scoring traces for review. participant ES as Eval service participant TS as Trace store participant LP as LLM provider ES->>TS: Fetch question, retrieved passages and answer TS-->>ES: Trace record ES->>LP: Split the answer into standalone statements LP-->>ES: Statements S1 to Sn ES->>LP: For each statement, is it supported by the passages LP-->>ES: Yes or No per statement, with a short reason ES->>ES: Faithfulness is supported statements divided by all statements alt Score below the slice threshold ES->>TS: Flag the trace for human review else Score meets the threshold ES->>TS: Store the score end Note over ES,LP: Two judge stages per answer, so cost grows with answer length.

    How to read this: faithfulness needs two model stages per answer, one to decompose and one to verify, and it checks the answer against the retrieved passages, not against the world.

    Limits to design around.

    1. Faithful is not true. The check asks whether the context supports the answer. A stale, wrong or conflicting passage yields a faithful answer that is wrong: the source-failure branch of Figure 3.
    2. Answer relevance ignores facts. By the paper's definition a fluent, on-topic, wrong answer can score well, so treat it as a check against evasive or padded answers, not a quality score. The paper does not say how an abstention ("the documents do not say") scores, so test that on your data before using the metric in a system designed to abstain.
    3. The metrics are model outputs. The paper used gpt-3.5-turbo-16k and text-embedding-ada-002. On its WikiEval dataset, where each instance compares two answers or two contexts, and where annotators agreed in about 95% of cases (about 90% for answer relevance), the metrics matched humans in pairwise comparisons at 0.95 for faithfulness, 0.78 for answer relevance and 0.70 for context relevance. The authors found context relevance "the hardest quality dimension to evaluate". This shows the metrics can pick the better of two answers when one is deliberately degraded; it does not show that a threshold such as "release at 0.9 or higher" is calibrated for your data.
    4. Decomposition and verification quality set the ceiling for long answers and hard claims. Calibrate against human labels as in the previous section.

    What this means for architects

    • Log the components per request: retrieved passage identifiers, the prompt as sent and the answer, so faithfulness can be recomputed after you improve the verifier.
    • Use it as a gate and a monitor, not as truth. Faithfulness per slice catches a prompt change that makes the model drift from its sources. Pair it with retrieval metrics and periodic human checks of source correctness.
    • Cost. Two judge stages per answer plus embedding calls for relevance: every item in CI, a sample in production.
    • Define the response to low faithfulness. The remedy is a behaviour, not a retry: abstain or answer with citations only, route to a human queue, record the case (approval steps: page 6).

    Under the hood: Confidence intervals and sample sizes for gates

    Intuition

    A pass rate measured on n items is an estimate. Run the same system on two different 400-item samples and the rates differ by chance. A gate that compares the point estimate with a threshold treats noise as signal in both directions: it blocks healthy changes and passes bad ones. The fix is to gate on an interval, and to know in advance how large a drop the gate can see.

    Mechanism

    Page 2 used the normal-approximation interval. This page uses the Wilson interval, whose limits cannot fall outside 0% to 100%. The NIST/SEMATECH e-Handbook gives it as the confidence interval for a proportion, calls an interval with an impossible lower limit "an inferior approach", and says one-sided limits use z for alpha instead of alpha/2 (NIST, section 7.2.4.1):

    Wilson limits = ( p + z^2/(2n)  +/-  z * sqrt( p(1-p)/n + z^2/(4n^2) ) ) / ( 1 + z^2/n )

    For 180 of 200 passing, the normal approximation on page 2 gives 85.8% to 94.2% and the Wilson interval 85.1% to 93.4% (z = 1.96).

    Sample size to detect a drop. NIST gives the sample size for testing whether a proportion has moved from p0 to p1, with delta = |p1 - p0|, significance alpha and power 1 - beta (NIST, section 7.2.4.2):

    N >= [ ( z_(1-alpha) * sqrt(p0(1-p0)) + z_(1-beta) * sqrt(p1(1-p1)) ) / delta ]^2     (one-sided; add 1/delta as a continuity correction)

    The handbook's example (10% to 20%, one-sided 5%, 10% risk of missing) gives 102, or 112 with the correction. For a quality gate with baseline p0 = 0.92, a drop to p1 = 0.88 (delta = 0.04), alpha = 0.05 one-sided and power 0.80 (z = 1.645 and 0.8416), N >= 323.8, so 324, or 349 with the correction. An exact binomial calculation agrees: at n = 349 the test rejects 5.0% of the time when the true rate is 0.92 and 81.1% when it is 0.88. That formula treats the 92% baseline as known exactly. If baseline and candidate are independent samples of equal size, the noise adds and the standard two-proportion extension needs about 695 items per run for 80% power (an exact enumeration of that two-sample test at 695 per run gives power 0.804 and a 5.0% false-alarm rate). Running both versions on the same items and analysing per-item differences can be tighter (see the worked example).

    What a gate can detect (baseline 92%, one-sided 5%, 80% power, baseline treated as known, no continuity correction):

    Golden-set size n 100 200 400 1,000 2,000
    Smallest drop detected (points) about 7.5 about 5.2 about 3.6 about 2.2 about 1.6

    Two different gates. A proof gate passes only when the lower bound clears the threshold, demonstrating the system meets the bar. A regression gate blocks on evidence of a drop against a baseline. The proof gate is demanding: with n = 400, a one-sided 95% Wilson lower bound and a threshold of 0.90, it needs at least 370 passes (92.5%). The chance it passes, by exact binomial arithmetic:

    True pass rate 0.90 0.92 0.94 0.95
    Gate passes, n = 200 5.7% 26.4% 68.5% 87.0%
    Gate passes, n = 400 5.2% 40.0% 91.1% 98.9%
    Gate passes, n = 1,000 4.9% 70.4% 99.9% 100%

    A system whose true rate is 0.92 fails a 0.90 proof gate 60% of the time at n = 400. That is the gate working as designed: 400 items cannot demonstrate 90% for a system two points above it.

    Figure 10. A gate decision with three outcomes

    flowchart TD accTitle: Gate decision with three outcomes accDescr: Run the golden set, count passes and compute the interval. If the lower bound meets the threshold the requirement is demonstrated. Otherwise, if the upper bound is below the threshold there is evidence of failure. If neither holds the result is inconclusive and the change is blocked by default pending more items or review. A["Run n golden-set items"] --> B["Count passes and compute the interval"] B --> C{"Lower bound at or above threshold?"} C -- yes --> P["Pass: requirement demonstrated"] C -- no --> D{"Upper bound below threshold?"} D -- yes --> F["Fail: evidence the rate is below the bar"] D -- no --> I["Inconclusive: not demonstrated"] F --> X["Block and report failing slices"] I --> X2["Block by default, add items or hold for review"]

    How to read this: there are three outcomes, not two, and "inconclusive" is a normal result for a small set, not a reason to rerun until it turns green.

    What a pass/fail gate cannot claim.

    • Slices. A 30-item slice tested alone detects only drops of about 16 points from a 90% baseline at 80% power. Slices need their own item counts.
    • Many slices at once. Test 10 independent slices each at a 5% false-alarm rate and the chance of at least one false alarm is 1 - 0.95^10 = 40.1%. Treat slice results as reports to review, or tighten the per-slice false-alarm rate.
    • Independent items. The formulas assume independence. Paraphrases of one question, or many questions about one document, are correlated, so the effective sample is smaller than n.
    • Noise beyond sampling. A stochastic model and a judge with its own error add variance the binomial formula omits. Repeat borderline runs and report judge agreement beside the pass rate.
    • Severity and shift. A pass rate says nothing about how bad a failure is, and a golden set samples the past; online evaluation covers what it cannot.
    • Zero failures. Page 2 shows that zero failures in 80 cases still allows a true rate near 3.7% at 95% confidence.

    What this means for architects

    • Write the detectable drop into the requirement. "The gate detects a drop of 4 points or more with 80% power" is checkable; "no regressions" is not. Choose n from it.
    • Choose the gate deliberately. A proof gate for a feature's first release against a stated bar; a regression gate for later changes, with the proof re-run less often.
    • Cost. Detecting half the drop needs roughly four times the items, because delta is squared in the denominator. Weigh judge and labelling cost against the cost of a missed regression.
    • Failure behaviour. Inconclusive blocks by default, and the owner chooses between adding items, improving the system or signing a documented risk acceptance. Design slices in from the start, with extra items where traffic is thin but risk is high.

    Decision framework

    1. If you have no labelled set, then start with 20 to 50 items from real failures and real traffic and add every incident, because a small set of real cases finds more problems than a large invented one; revisit when slices have enough items to give intervals you can act on.
    2. If a release decision rests on an LLM judge, then calibrate it on a fresh human-labelled sample and report kappa and failure recall, because raw agreement hides chance and prevalence; revisit when the judge model, rubric or task changes, or a monthly spot check disagrees.
    3. If you compare two versions, then use pairwise judging with a position swap on the same items for both, because swapping removes pure order effects and shared items tighten the comparison; revisit when the judge's flip rate rises.
    4. If the feature uses retrieval, then report retrieval and generation metrics separately per slice, because one end-to-end score cannot say which stage failed; revisit when the retriever, chunking, index or prompt assembly changes.
    5. If a gate blocks merges, then gate on a confidence bound and state the smallest drop it can detect, because a point estimate turns noise into false alarms and missed regressions; revisit when n, the baseline or the slice mix changes.
    6. If an agent acts on the world, then grade the end state first, check only policy-relevant steps of the trajectory and report pass^k over repeated trials, because paths vary legitimately while one success hides inconsistency; revisit when the agent gains a new tool or permission.

    Comparison of the main options

    Option Strengths Weaknesses Choose when Typical failure
    Code-based checks Fast, cheap, reproducible Brittle to valid variation; cannot judge quality The answer has a checkable form Valid answers fail on wording
    Human review Highest quality; the reference for calibration Slow, expensive, reviewers disagree Calibration, rare high-risk cases, rubric design Inconsistent labels with no agreement measure
    LLM judge, absolute pass/fail Scales; one number against a bar Biased; drifts with judge changes Release bar and monitoring Uncalibrated judge waves failures through
    LLM judge, pairwise with swap More reliable for choosing versions Twice the calls; no absolute quality Model or prompt changes A win read as "good enough"
    Retrieval metrics on labelled queries Deterministic, no model call Needs labels; incomplete labels penalise new retrievers Index, chunking, reranker changes Unlabelled relevant documents counted as misses
    Reference-free generation metrics No gold answers; per request Model outputs themselves; faithful is not true Gate and monitor RAG generation Faithful answer built on a wrong passage
    Online signals and sampled review The real distribution Sparse ground truth; slow After release; golden-set growth A vocal minority read as the average

    Failure scenarios to design for

    1. The judge returns malformed output. Behaviour: retry once with a format reminder, then record an evaluation error that counts against the run, not as a pass. A run whose error rate exceeds the agreed limit is invalid and cannot gate.
    2. The judge model is updated or deprecated by its provider. Behaviour: judge model and prompt versions are stored on every score; a new version triggers recalibration and a re-baseline before any comparison with history.
    3. The prompt is tuned until the golden set passes. Behaviour: gating uses a hold-out split nobody tunes against, refreshed from production on a schedule.
    4. The aggregate is green while one slice has regressed. Behaviour: the report lists every slice with its n and interval; a slice below the minimum item count is shown as "not measurable" and blocks a change that targets it.
    5. Retrieval labels go stale when documents change. Behaviour: labels are versioned with document versions, and labels for changed documents are quarantined and re-reviewed before they count.
    6. The judge shares a model family with the system and inflates scores. Behaviour: release decisions use a judge from a different family or a human-confirmed sample, and the gap between judge and human pass rates is tracked.
    7. The gate is inconclusive. Behaviour: the change is blocked by default; the owner adds items, improves the change or signs a risk acceptance. Re-running until green is not permitted.

    Worked example

    A support-answer assistant is gated on a 400-item golden set. The baseline (current production prompt) passes 368 of 400.

    1. Baseline interval. 368/400 = 92.0%; Wilson 95% interval (z = 1.96) 88.9% to 94.3%.

    2. Candidate interval. Prompt B passes 352/400 = 88.0%, interval 84.5% to 90.8%. The intervals overlap (88.9% to 90.8%), but overlap is not the test for a difference, so do not stop here.

    3. Paired comparison on the same items. On 30 items the baseline passed and B failed; on 14 items B passed and the baseline failed. The net difference is (30 - 14)/400 = 0.04. Treat each item's difference as +1, 0 or -1: the mean is 0.04, the sample variance 0.1087, and the standard error of the mean is the square root of 0.1087/400 = 0.0165, so z = 0.04 / 0.0165 = 2.43 and the one-sided p-value is about 0.008. Treating the runs as independent gives a standard error of 0.0212, z = 1.89 and p = 0.029. The paired analysis is tighter when the same hard items sit in both runs, as the counts assume. Decision: block B, since a 4-point drop is detected at the 5% level. This is a normal-approximation check on 44 discordant items, adequate for a gate and no substitute for reading the 30 items B lost.

    4. A regression the aggregate hides. A different candidate, C, passes 364/400 (91.0%), one point below baseline and far inside what 400 items can detect (about 3.6 points). All four extra failures fall in the "returns policy" category, which has 30 items: the baseline passed 27/30 and C passes 23/30 (76.7%). The Wilson intervals are 74.4% to 96.5% and 59.1% to 88.2%. With 30 items a one-sided test at 80% power detects only a drop of about 16 points from a 90% baseline, and this drop is 13.3 points, so a slice gate would probably miss it. Detecting 13.3 points from 90% takes about 41 items (49 with the continuity correction), so raise that slice to at least 50 items.

    Assumptions: all counts are illustrative; items are independent; one-sided alpha = 0.05 and power 0.80 unless stated; z = 1.96 for two-sided 95% intervals; the baseline is a sample, not a known constant; the discordant counts (30 and 14) are chosen for the example; normal approximations are used where stated. Every figure was recomputed with Python.

    Code sample: a CI gate with a confidence bound

    This gate fails the build when the one-sided lower confidence bound of a pass rate drops below a threshold, per slice. It needs only the standard library and implements the Wilson lower limit given above.

    import json
    import math
    import sys
    from statistics import NormalDist
    
    
    def wilson_lower(passes, n, confidence=0.95):
        """One-sided lower confidence bound for a pass rate (Wilson score method)."""
        z = NormalDist().inv_cdf(confidence)
        p = passes / n
        centre = p + z * z / (2 * n)
        margin = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n))
        return (centre - margin) / (1 + z * z / n)
    
    
    def gate(results, threshold, confidence=0.95):
        """results: one bool per golden-set item. Pass only if the lower bound clears the threshold."""
        lower = wilson_lower(sum(results), len(results), confidence)
        return lower >= threshold, lower
    
    
    def run(by_slice, threshold):
        """by_slice: {"all": [...], "category-a": [...]}. Returns the slices that fail."""
        failed = {}
        for name, results in by_slice.items():
            ok, lower = gate(results, threshold)
            if not ok:
                failed[name] = (len(results), round(sum(results) / len(results), 3), round(lower, 3))
        return failed
    
    
    if __name__ == "__main__":
        failed = run(json.load(open(sys.argv[1])), float(sys.argv[2]))
        for name, (n, rate, lower) in failed.items():
            print(f"FAIL {name}: n={n} rate={rate} lower bound={lower}")
        sys.exit(1 if failed else 0)

    Run it as python gate.py results.json 0.90, where the file maps each slice name to a list of true/false results; CI reads the exit code. Checked by running it: with 400 items, 370 passes (92.5%, lower bound 0.9004) print nothing and exit 0, while 369 (92.25%, lower bound 0.8976) print FAIL all: n=400 rate=0.922 lower bound=0.898 and exit 1, matching the table above. A slice with 27 of 30 passes prints lower bound=0.774 and fails the same threshold, because 30 items cannot demonstrate it.

    Two limits are built in. A "fail" covers both "evidence of failure" and "inconclusive" (the conservative default in Figure 10), so report the rate and n beside it. And it gates a bar, not a change: for a candidate against a baseline use the paired comparison in the worked example. Count a malformed judge verdict as False, or exclude the item and enforce the error-rate limit separately; never as a pass.

    Common mistakes

    • Reporting a judge's raw agreement as its quality. 87% agreement hid a kappa of 0.57 and a failure recall of 55%. Report kappa, failure recall and per-slice agreement.
    • Tuning and gating on the same items. Once prompts are edited until the set passes, it no longer measures generalisation. Keep a hold-out.
    • Reading overlapping intervals as "no difference". The baseline and candidate intervals overlapped while the paired test detected a drop.
    • Gating on the average. A one-point drop in the average hid a 13-point drop in a 30-item category. Report slices with their sample sizes.
    • Treating faithfulness as correctness. A faithful answer built on a stale passage is wrong, so evaluate retrieval and sources too.
    • Changing the judge and the system in one release. The movement cannot be attributed. Change one at a time, or run the old judge alongside the new.

    Try it

    Time: 20 to 40 minutes. Use an AI feature you work on, or a toy assistant that answers questions about a document you have.

    1. Write 30 golden-set items with at least two slices and a pass/fail outcome from you, and set 10 aside as hold-out.
    2. Run the feature twice on the 30 items. Compute the Wilson interval for both runs (the code sample's wilson_lower gives the lower limit; flip the sign for the upper, and pass confidence=0.975 for a two-sided 95% interval). Note how far the two runs differ.
    3. Have a colleague, or yourself a day later, relabel 20 items blind. Build the 2x2 table against your first labels and compute observed agreement and kappa by hand, following the worked example.
    4. Pick a baseline pass rate and a drop you care about, compute the sample size with the NIST formula above, and say in one sentence whether 30 items can detect it.

    Done when you have a table of your items with slices, two interval calculations, one kappa value from a 2x2 table, a sample-size number for a drop you named, and a sentence saying what your current set can and cannot detect.

    Key takeaways

    • A golden set is seeded from real failures, tagged with slices, labelled against a written rubric, versioned and split into tuning and hold-out parts.
    • An LLM judge is a model under test: pin its version, store its raw output, treat parse failures as errors, and calibrate it against human labels on fresh items.
    • Position, verbosity and self-preference effects are documented: swap positions for pairwise judgments, control length, prefer a different judge family, and measure your own judge, because the published rates come from 2023-era models.
    • Raw agreement misleads. Report Cohen's kappa and the judge's recall on the fail class, and remember that humans disagree too.
    • Measure retrieval (recall at k, MRR, nDCG) separately from generation (faithfulness, answer relevance); faithful does not mean true, and answer relevance ignores facts.
    • Gate on a confidence bound and write down the smallest drop the gate can detect: about 3.6 points at 400 items from a 92% baseline, about 16 points for a 30-item slice.
    • For agents, grade the outcome state first, check policy-relevant steps of the trajectory, and report reliability over repeated trials.

    Self-check

    1. A judge agrees with human reviewers on 87% of 200 items. Why is that not enough to let it gate releases?

    Agreement includes chance. Both raters say "pass" most of the time, so expected chance agreement is 0.696 and kappa is only 0.57, below the 0.67 line the Stanford textbook calls a dubious basis. The judge also caught only 24 of the 44 items humans failed (54.5%) and overstated the pass rate by 7 points, which is what matters for a gate.

    2. Two retrievers both place 2 of 4 relevant documents in the top 5, yet their nDCG at 10 is 0.558 and 0.816. Why?

    Recall at 5 ignores order inside the top 5, so both score 0.50. nDCG discounts each document's gain by log2(1 + rank) and weights grades, so putting the grade-3 document first scores higher. Gate on recall at the k you give the model for the grounding ceiling, and on nDCG or MRR when order and grades matter.

    3. A RAG answer scores faithfulness 1.0 and is still wrong. How, and which stage failed?

    Faithfulness checks that the claims can be inferred from the retrieved context, not that the context is right. A stale, wrong or conflicting passage yields a faithful but wrong answer: a source failure (the last branch of Figure 3), fixed by freshness, versioning and conflict handling in retrieval, not by editing the generator prompt.

    4. A proof gate uses n = 400, a one-sided 95% Wilson lower bound and a threshold of 0.90. The true pass rate is 92%. What happens?

    The gate needs at least 370 passes (92.5%) and passes only about 40% of the time at a true rate of 92%, so it blocks a healthy system most runs. That is correct: 400 items cannot demonstrate 90% for a system two points above it. Raise n (at 1,000 items it passes about 70% of the time), set the threshold lower, or use a regression gate against the baseline.

    5. Why swap positions in a pairwise judge, and what does it cost?

    Judges favour positions: with near-identical answers GPT-4 was consistent under swapping only 65.0% of the time in the MT-bench study, and weaker judges far less. Calling the judge twice with the order swapped and counting a win only when the same answer wins both times turns pure order effects into ties. The cost is two judge calls per pair, doubling judge latency and spend for pairwise runs.

    Further reading

    Last verified: 2026-10-22

    Next

    Part B ends here. Part C starts with LLMOps and Observability for AI Systems, which takes the metrics and gates from this page into prompt registries, tracing, canary releases and cost tagging.

    Enroll to keep reading

    Lesson 8 of 13 · AI Architect: From AI Engineer to Expert

    How AI architects evaluate LLM systems: golden sets, retrieval and generation metrics, judge bias and kappa calibration, and CI gates with confidence intervals.

    In the rest of this lesson

    • Under the hood: Calibrating a judge against human labels
    • Under the hood: Pairwise and absolute scoring
    • Under the hood: Retrieval metrics
    • Under the hood: Generation metrics
    • Under the hood: Confidence intervals and sample sizes for gates
    • Decision framework

    Enrolling is free. It unlocks every lesson in AI Architect: From AI Engineer to Expert, tracks your progress across devices and keeps your quiz scores. The newsletter is optional.

    Ask about this article

    Get answers grounded in this post. AI-generated — based on this article, and may be imperfect.

    Scaled AI Weekly

    Enjoyed this? Get more like it every Monday.

    Real architecture decisions, LLMOps patterns that survive production, and engineering leadership advice — from 12+ years of building at enterprise scale. Free. No spam. Unsubscribe anytime.

    Get new articles by email

    Free. We email a confirmation link first, and you can unsubscribe from any email.

    Join engineers building production AI systems

    Comments