# LLM as Judge

Using a model to score another model's output against a rubric, making open-ended evaluation scalable.

**Rests on:** Benchmarking

**Leads to:** Evals Gap, Evaluator Drift, Skill Testing and Evals

*LLMs and Generative AI · LLM Evaluation*


## Why learn this

This concept turns you from someone who can only *use* an LLM into someone who can *verify* it. Once you can build a judge, you can compare two prompts, two models, or two versions of your own app and know which is better — without reading hundreds of outputs yourself. It unlocks the rest of the evaluation stack: building evaluation datasets, catching regressions before users do, and eventually shipping with confidence. From here you can move into automating quality checks that prevent bad updates from reaching your customers, and understanding how to measure text similarity precisely.


## The intuition

Imagine you have hired a new assistant. You don't want to read every email they write, but you do want to make sure they aren't making mistakes. So you give a senior colleague a few sample emails and a checklist: 'Does this answer the customer's question? Is it polite? Is it clear?' The senior colleague reads each email, ticks or crosses each item on the checklist, and gives an overall score. That's what an LLM-as-judge does — except the senior colleague is another AI model, and the checklist is called a *rubric*. Instead of you reading a thousand outputs, the judge model reads them all and gives you a score for each. This is useful because modern AI systems generate a huge amount of text — answers, summaries, emails — and checking each one by hand is slow and expensive. The judge makes evaluation *scalable*: you can score a thousand outputs in minutes, not days. But the judge isn't perfect. It has its own opinions, its own biases, and it can change over time. So you have to treat it carefully, just like you would treat a human reviewer who has preferences you need to understand.


## An analogy

Think of a food critic who visits restaurants and writes reviews. You want to know if a new restaurant is good, but you can't visit every restaurant yourself. So you read the critic's review. The critic has a rubric in mind: food quality, service, ambience, value for money. They give each aspect a score and then an overall rating. That's the LLM-as-judge. Now, the critic has preferences — maybe they love spicy food, or they are annoyed by slow service. Those preferences are like the *biases* of the judge model. If the critic changes their taste over time — maybe they become a vegan — their future reviews won't be comparable to their old ones. That's *evaluator drift*. The analogy breaks down because a human critic can explain their reasoning in detail, and you can challenge them. An LLM judge gives you a score and maybe a short explanation, but you can't interrogate it for hidden assumptions. Also, a critic visits one restaurant at a time; an LLM judge can score millions of outputs in parallel — it is far faster but also more opaque.


## Definition

LLM-as-judge is the practice of using one large language model to evaluate the output of another model (or itself) by comparing the output against a written rubric and producing a score or verdict, instead of relying on human review.


## How it connects

This concept sits inside the broader topic of **LLM Evaluation**. You already know **Deterministic Validators** — code that checks if a specific condition is met, such as verifying a number falls within a set range or that a required field is present. The judge is different: it handles open-ended quality like tone or clarity that code cannot easily check. You also know **BLEU and Reference Metrics** — methods that measure how closely one piece of text matches another by counting shared words, which works well for exact matches but fails when the meaning is the same but the wording differs. The judge is more flexible in this regard. Your notes on this topic mention that the judge is a 'versioned dependency' — just like the model you're evaluating, the judge model gets updated, and you need to track that. This connects to **Evaluator Drift** — the phenomenon where the judge's scoring behavior shifts over time as its underlying version changes, silently breaking your comparisons. And finally, the judge is what powers **Regression Gates** — automated safety checks that block a new version of your app from launching if the judge determines quality has dropped below an acceptable threshold.


## The mathematics

This concept does not rest on heavy mathematics — no calculus or linear algebra. It rests on a simple but essential idea from **statistics and measurement**: the idea of turning a judgement into a number so that you can compare two things fairly. When you ask a judge to score an answer, you are performing a *measurement*: you are assigning a number to something that is not obviously numeric, like clarity or usefulness. The key mathematical operation is the **average** (arithmetic mean). You will collect many scores — one for each test input — and then take the average to compare two models. The average tells you which model performs better on average. But averages hide important details: a model could be great on most inputs but terrible on a few. So you also need to look at the *distribution* — how spread out the scores are. To do that, you calculate the **minimum**, the **maximum**, and maybe the **standard deviation**. The standard deviation measures how much the scores vary around the average. If the scores are tightly clustered, the model is consistently good or bad; if they are spread out, it is erratic. That's the mathematics: not complex equations, but careful measurement — collecting numbers, averaging them, and looking at the spread.

Let us define the list of scores you have collected. Let n be the number of test questions. Let s sub i (read 's sub i') be the score given by the judge for the i-th question. Here, i is just a counter that runs from 1 to n. So s sub 1 is the first score, s sub 2 is the second, and so on.

The average score is calculated by adding all the scores together and dividing by how many there are. In symbols:

mean = (s sub 1 + s sub 2 + ... + s sub n) divided by n

This means you sum every single score in your list, then divide that total by the count of questions.

The minimum is simply the smallest number in the list S. We write this as min(S).
The maximum is simply the largest number in the list S. We write this as max(S).

The standard deviation measures how far the scores typically are from the average. It is a single number that summarizes the spread. To calculate it, you follow these steps:

1. Find the difference between each score and the average. For example, take s sub 1 minus the mean.
2. Square that difference. This makes sure negative differences do not cancel out positive ones.
3. Do this for every score in the list.
4. Add all those squared differences together.
5. Divide that sum by n (the number of questions). Note: In some contexts, you divide by n minus 1, but for a complete set of test results like this, dividing by n is standard.
6. Take the square root of that result.

In symbols:

sigma = the square root of [ (1 divided by n) times the sum of (s sub i minus mean) squared, for i from 1 to n ]

Here, sigma (read 'sigma') is the symbol we use for standard deviation. The phrase 'sum of ... for i from 1 to n' means you perform the calculation inside the parentheses for every question and add them all up.

Symbol glossary:
s sub i = the score for the i-th question; n = the number of questions; mean = the average score; sigma (sigma) = the standard deviation, a measure of how spread out the scores are.


## A worked example

``` 
Suppose you have a test set of 5 questions. You ask two models — Model A and Model B — to answer each question. Then you ask an LLM judge to score each answer on a scale of 0 to 10, where 10 is perfect.

Step 1: Model A scores: [8, 6, 9, 7, 8]   # These are the judge's scores for Model A's answers to the 5 questions.
Step 2: Sum of Model A scores: 8 + 6 + 9 + 7 + 8 = 38   # Add up all the scores.
Step 3: Average for Model A: 38 ÷ 5 = 7.6   # Divide by the number of questions to get the mean.
Step 4: Model B scores: [7, 8, 6, 9, 5]   # Scores for Model B's answers.
Step 5: Sum of Model B scores: 7 + 8 + 6 + 9 + 5 = 35   # Sum for Model B.
Step 6: Average for Model B: 35 ÷ 5 = 7.0   # Mean score for Model B.
Step 7: Minimum for Model A: 6; Minimum for Model B: 5   # The worst score for each model — shows what happens on the hardest question.
Step 8: Maximum for Model A: 9; Maximum for Model B: 9   # The best score for each model.

Result: Model A has a higher average (7.6 vs 7.0), but Model B has the same maximum and a lower minimum. So Model A looks better on average, but you should check why Model B scored a 5 on one question — that might be an important failure.
```


## From scratch, in Python

```python
# We'll build a simple LLM-as-judge system from scratch.
# First, we need a model to evaluate. We'll use a tiny mock model that returns a canned answer.

def mock_model(question):
    """A stand-in for a real LLM. It ignores the question and returns a fixed string."""
    return "The capital of France is Paris. It is known for the Eiffel Tower."

# Now, we need a judge. We'll use another mock model that scores an answer against a rubric.
# In real life, this would be a call to a powerful LLM like GPT-4.

def mock_judge(answer):
    """Returns a score from 0 to 10 based on a simple rubric.
    
    Rubric: Does the answer mention France? If yes, 10 points. If not, 0 points.
    """
    if "France" in answer:
        score = 10
    else:
        score = 0
    return score

# Now we can evaluate the mock model on a list of questions.

questions = ["What is the capital of France?", "What is the capital of India?"]

scores = []
for q in questions:
    answer = mock_model(q)
    score = mock_judge(answer)
    scores.append(score)

print("Scores:", scores)
print("Average:", sum(scores) / len(scores))

# This is the core pattern: model -> answer -> judge -> score -> average.
```


## The same thing, with a framework

```python
In practice, you'd use a library like OpenAI's API. The judge call would look like this:

import openai

def judge_with_api(answer, rubric):
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "You are a strict judge. Score the answer against: " + rubric},
            {"role": "user", "content": answer}
        ]
    )
    # Extract the score from the response (assuming the model returns a number)
    return int(response.choices[0].message.content)

# Underneath, this is doing the same thing as our mock_judge: parsing the answer and applying a rubric.
```


## What the code does

The from-scratch code builds a simple simulation. `mock_model` stands in for the LLM you're evaluating — it returns a fixed answer. `mock_judge` stands in for the evaluator model — it applies a simple rubric (does the answer contain 'France'?). We then loop over a list of questions, generate answers, score them, and collect the scores. We print the list and the average. This shows the core pattern: generate → judge → score → aggregate. The framework version uses the OpenAI API to do the same thing, but the point is that the judge is just a function that takes text and returns a number, just like our mock. The key takeaway: the judge is a function, and you can replace it with any model or even a deterministic rule.


## Common misconceptions

**The judge is always right** — The judge is a powerful model, so its scores are accurate and unbiased.

The judge has its own biases and can be fooled. It might prefer verbose answers, or it might give higher scores to answers that match its own style. The books note that judges exhibit position bias (preferring the first answer) and self-preference (preferring outputs from itself). In fact: The judge is a useful but imperfect tool. You need to validate it against human judgments and control for known biases.

**Scores are absolute** — A score of 8 means the answer is good, regardless of context.

Scores are relative and depend on the rubric and the judge's calibration. A 7 from one judge might be a 5 from another. What matters is comparison under the same conditions. In fact: Use judges for relative comparison — same judge, same rubric, same test set — not absolute quality measurement.

**The judge is a one-time tool** — I can write the judge once and use it forever.

Your judge model gets updated, the rubric might change, and the distribution of inputs might shift. The book *Practical LLM Evaluation* states: 'the judge is a dependency that must be versioned and monitored like any other.' If the judge changes, your scores change, and you can't compare old and new results. In fact: Pin the version of the judge model, log the rubric version, and periodically re-run a frozen reference set to check for drift.

**Judge bias is the same as fairness** — If I notice the judge prefers long answers, that's a fairness issue.

Bias in this context is a measurement artefact, not a social bias. It's about the judge's preferences affecting scoring, not about discrimination. In fact: This bias is a confound to control for (e.g., by ensuring answers are similar length), not a moral judgement.

**One judge is enough** — I can just use one judge model and trust it.

A single judge can have blind spots. Using multiple judges and averaging can reduce variance, but also adds cost and complexity. In fact: For high-stakes evaluations, consider using multiple judges or validating the judge against a small human-reviewed set.

**The judge can replace human review entirely** — Since the judge is scalable, I don't need humans anymore.

The judge is not perfect and can drift. Human review is needed periodically to recalibrate and catch things the judge misses. In fact: Use judges for scale, but keep a human-in-the-loop for edge cases and initial rubric design.


## In short

LLM-as-judge is a way to automatically score model outputs against a rubric, making evaluation scalable. Key points: (1) It's a function that takes text and returns a score. (2) The judge is a dependency — version it and monitor it. (3) Control for biases like position and verbosity. (4) Use averages, but also look at the spread. (5) This is the foundation for regression gates and production evaluation.


## Where this is used

LLM-as-judge is used in many places across AI engineering.

**In large language models:** Companies like OpenAI and Anthropic use LLM-as-judge to compare candidate responses during training and evaluation. For example, when training a model to be helpful, they might generate two responses and ask a judge which is better. That preference data is then used to align the model (RLHF). Developers also use it to compare prompt versions — e.g., 'Does adding 'be concise' make the output better?' — by running both prompts on a test set and having a judge score them.

**In small models on devices:** On a phone or laptop, you can't run a huge judge model. Instead, you might use a small, quantised judge that runs locally. The mechanism is the same: the judge scores the output against a rubric, but the rubric is simpler and the judge is faster. This is common in TinyML keyword spotters — the judge checks if the keyword was detected correctly, and the rubric is just 'did it output the right word?' It's also used in on-device translation to check if the translation is in the correct language.

**In retrieval-augmented generation (RAG):** In RAG, the model retrieves relevant documents and generates an answer based on them. The judge is used to evaluate whether the answer is grounded in the retrieved documents (relevancy and correctness). The rubric might include: 'Does the answer use facts from the context?' The judge checks each output against this rubric. Developers routinely use LLM-as-judge to measure RAG quality — for example, testing different chunking strategies or embedding models to see which yields better grounded answers.

**In agentic systems:** Agents that plan and call tools need to be evaluated on whether they complete the task. The judge scores the final result and also the intermediate steps. For example, if an agent is supposed to book a flight, the judge checks if the booking details are correct — the rubric includes 'the date must be in the future', 'the destination must match the request'. LLM-as-judge is essential here because the outputs are long and complex, and a simple validator can't catch semantic errors.

**In everyday applied ML:** Recommendation systems use judges to score whether recommended items are relevant — the judge looks at the user's query and the recommended item and gives a relevance score. Forecasting systems use judges to score the quality of the forecast explanation. Fraud detection uses judges to evaluate whether the explanation of a fraud alert makes sense to a human.

**What a developer actually writes:** In practice, they use a library like `mlflow.evaluate` (from the book *Practical MLflow for Generative AI on Databricks*) or the OpenAI API directly. The code snippet above shows the pattern. They also set up a pipeline to run the judge on every new version of the model, compare the average scores, and block deployment if the score drops below a threshold.

**What breaks when done badly:** If the judge is biased — e.g., prefers longer answers — you'll get inflated scores for verbose models. If the judge isn't versioned, a model update could silently change the scores, making old comparisons meaningless. If you don't control the temperature of the judge (set it to 0), the scores may be noisy and non-reproducible. The books emphasise: 'Evals, not vibes' — treat scoring as core engineering.


---

Read this on the web: https://basavapurushottam.com/learn-ai/llm-as-judge
