Area 04 // EvalsLesson 69 / 14016 min read
LLM as a judge, pairwise comparison and rubrics
An LLM judge is a model prompted to grade another model's output, either against a rubric of clear criteria or by comparing two outputs side by side, which lets you evaluate open-ended answers at scale, as long as you check the judge agrees with humans.
Think of it like this
Analogy
A school uses teaching assistants to mark essays because the professor can't mark 500. Good TAs get a marking scheme ("thesis stated: yes/no; three pieces of evidence: yes/no"), not "give it a mark out of 10". The professor double-marks a sample to check the TAs agree with her. And when comparing two essays, a careful TA reads them in both orders, because whichever you read first can colour your judgement.
An LLM judge is the TA. The rubric is the marking scheme. Calibration is the professor's double-marking.
The problem it solves
Many AI outputs are open-ended: summaries, support replies, explanations, plans. There's no single correct string to compare against, so exact-match tests don't work. Human review is the gold standard but slow and expensive at hundreds of cases per change. You need scalable grading of free text that's still trustworthy.
How it works: LLM as a judge
- Pick a judge model: usually a strong model, ideally from a different family than the one you're testing (models tend to favour their own style).
- Write a judging prompt: the task, the inputs (question, sources, answer), the criteria, and examples of passes and fails.
- Ask for structured output: a verdict per criterion plus a short reason, as JSON (structured outputs). Reasons make results debuggable; asking for the reason before the verdict often improves consistency.
- Run it over your eval set and aggregate.
- Calibrate before trusting it: have humans label 50–200 cases; compare with the judge using agreement and Cohen's kappa (agreement corrected for chance); adjust the prompt and examples until agreement is high.
- Watch for biases: position (in pairwise), length (longer looks better), self-preference, leniency, and being fooled by confident tone.
- Re-check calibration when you change the judge model or prompt.
How it works: pairwise comparison
- Show the judge two outputs for the same input (A and B) and ask which is better against the criteria (or a tie).
- Swap the order and ask again to cancel position bias; count only wins that hold both ways, otherwise a tie.
- Aggregate win rates across cases: "version B wins 58%, loses 30%, ties 12%".
- Best for: comparing two prompts or models when absolute scores are hard to define. Relative judgements are often more reliable than absolute ones.
- Rank many versions with pairwise results (Elo-style ratings), like human-preference leaderboards (benchmarks).
How it works: rubric scoring
- List specific criteria that define a good answer for this product: grounded in the sources, answers every part of the question, follows the format, appropriate tone, no unsafe advice.
- Make each criterion binary (pass/fail) with a clear definition and examples. Binary criteria are applied far more consistently than 1–10 scales.
- Score each criterion separately, then combine (count of passes, weighted score, or "must pass all critical criteria").
- Report per criterion, not just the total, so you know what to fix.
- Grow the rubric from error analysis: each important failure mode becomes a criterion.
See it in code
- Install
pip install scikit-learn- Needs
- Python 3.10+. The judge's reply is written out here; in practice it comes from a model call with structured output.
A rubric prompt, parsing a judge's JSON verdict, swapped pairwise judging, and calibrating against humans.
import json
from sklearn.metrics import cohen_kappa_score
RUBRIC = {"grounded": "Every claim is supported by the sources.",
"complete": "Answers every part of the question.",
"concise": "No more than 4 sentences."}
def judge_prompt(question: str, answer: str, sources: str) -> str:
"""What you send to the judge model. Ask for JSON so code can read the verdict."""
criteria = "\n".join(f"- {k}: {v}" for k, v in RUBRIC.items())
return (f"Grade the answer. For each criterion reply pass or fail with a reason.\n{criteria}\n"
f"<sources>{sources}</sources>\n<question>{question}</question>\n<answer>{answer}</answer>\n"
'Reply as JSON: {"grounded": {"verdict": ..., "reason": ...}, ...}')
# A judge reply (a model writes this in practice) -> rubric score.
reply = '{"grounded": {"verdict": "pass", "reason": "matches [1]"}, "complete": {"verdict": "fail", "reason": "ignores carry-over"}, "concise": {"verdict": "pass", "reason": "2 sentences"}}'
verdicts = {k: v["verdict"] == "pass" for k, v in json.loads(reply).items()}
print("rubric:", verdicts, "-> score", f"{sum(verdicts.values())}/{len(verdicts)}")
# Pairwise: ask twice with the order swapped to cancel position bias; count only consistent wins.
def pairwise(first_run_winner: str, swapped_run_winner: str) -> str:
swapped_back = {"A": "B", "B": "A"}[swapped_run_winner]
return first_run_winner if first_run_winner == swapped_back else "tie (inconsistent)"
print("pairwise:", pairwise("A", "B"), "|", pairwise("A", "A"))
# Calibrate the judge against human labels before trusting it.
human = [1, 1, 0, 1, 0, 0, 1, 1, 0, 1]
judge = [1, 1, 0, 1, 1, 0, 1, 1, 0, 1]
agree = sum(h == j for h, j in zip(human, judge)) / len(human)
print(f"judge vs human: agreement {agree:.0%}, Cohen's kappa {cohen_kappa_score(human, judge):.2f}")rubric: {'grounded': True, 'complete': False, 'concise': True} -> score 2/3
pairwise: A | tie (inconsistent)
judge vs human: agreement 90%, Cohen's kappa 0.78In the second pairwise call the judge picked "A" both times, even though A and B had swapped places: that's position bias, so it counts as a tie. A kappa around 0.8 is generally considered strong agreement; below about 0.6, improve the rubric before relying on the judge.
A real example
Example
Grading 2,000 support replies a night
A support team generates thousands of AI replies a day. Each night, a judge grades a random sample of 2,000 against a five-criterion rubric (grounded in the help-centre sources, correct policy, answers the question, polite, no promises the agent can't keep). The judge was calibrated against two senior agents' labels on 300 replies (kappa 0.81). Criteria trends appear on a dashboard; a drop in "correct policy" one week was traced to an outdated help article.
When choosing between two new prompts, they run pairwise judging on 400 golden cases with swapped order; prompt B won 54% vs 31% (15% ties), and a human spot-check of 50 agreed.
The easy way
Start here
Write three pass/fail criteria for your feature. Ask a strong model to grade 30 answers against them in JSON with a reason. Grade the same 30 yourself. If you agree on most, use the judge for the rest; if not, sharpen the criteria and add examples.
When you grow: the production setup
Teams version judge prompts, use different-family judge models, include few-shot examples of passes and fails, request reasoning before verdicts, swap order in pairwise runs, periodically re-calibrate against fresh human labels, track judge cost, and use eval tools that run judges at scale (eval tools).
Trade-offs
What you gain
- Scalable grading of open-ended outputs.
- Rubrics make criteria explicit and results actionable.
- Pairwise comparison is reliable for choosing between versions.
What it costs you
- Judges have biases (position, length, self-preference, leniency).
- Costs tokens and time on every eval run.
- A judge is only as good as its calibration; uncalibrated scores mislead.
When not to use it
- A deterministic check exists (exact value, JSON validity, tests pass): use code, it's cheaper and exact.
- High-stakes final decisions (legal, medical): use judges to triage, humans to decide.
Common mistakes
- Vague 1–10 "quality" scores.
- Never comparing the judge with human labels.
- Using the same model to judge itself.
- Pairwise judging without swapping order.
- Treating judge reasons as ground truth instead of debugging hints.
Interview questions
Try answering out loud first, then open the model answer.
How do you build a reliable LLM-as-a-judge evaluator?
Model answer
Define specific, binary criteria grounded in error analysis; write a judging prompt with the inputs, criteria definitions and pass/fail examples; request structured output with reasoning and verdicts; use a strong judge, preferably a different model family; calibrate against human labels on a representative sample (agreement and kappa), iterating until acceptable; mitigate known biases (swap order, conciseness criteria); version the judge and periodically re-calibrate.
When is pairwise comparison better than absolute scoring?
Model answer
When deciding between two versions and absolute quality is hard to define, because relative judgements are more consistent for both humans and models. It directly answers "is B better than A?" It needs order swapping to cancel position bias and doesn't give an absolute quality level, so pair it with rubric scoring for tracking over time.
What biases do LLM judges have?
Model answer
Position bias (favouring the first or second answer), verbosity bias (preferring longer answers), self-preference (favouring outputs from the same model family), leniency and sycophancy, susceptibility to confident or authoritative tone, and inconsistency across runs. Mitigate with swapped comparisons, explicit criteria such as conciseness, different-family judges, few-shot calibration examples, multiple runs, and human calibration checks.
Quiz
Pick an answer to see whether it’s right and why.
0 of 6 answered
Key terms
- LLM as a judge
- Using a model, with a grading prompt and criteria, to score another model's outputs at scale.
- Rubric
- A list of specific criteria (ideally pass/fail) that define a good output, used by human or LLM graders.
- Pairwise comparison
- Judging which of two outputs for the same input is better, usually run twice with the order swapped.
- Position bias
- A judge's tendency to prefer the first (or second) of two options regardless of quality.
- Cohen's kappa
- A measure of agreement between two raters that corrects for agreement expected by chance; 1 is perfect.
Before and after
Progress is saved in this browser only.