LLM-as-Judge
Using a stronger model to evaluate a weaker one — prompt design, position bias mitigation, multi-judge calibration, and agreement measurement.
LLM-as-judge uses a strong model (GPT-4, Claude) to score outputs from the model being evaluated — faster and cheaper than human evaluation, but with important biases that must be understood and mitigated.
1. How It Works
Model under test generates response to prompt
→ Send (prompt, response) to judge model
→ Judge scores on criteria (1-10 scale)
→ Aggregate scores across test set
→ Compare against baseline model
Scoring Modes
| Mode | Use case | Output |
|---|---|---|
| Absolute scoring | Rate a single response | Score 1-10 per criterion |
| Pairwise comparison | Compare two models | A wins / B wins / tie |
| Reference-based | Compare against gold answer | Similarity to reference |
2. Judge Prompt Design
Absolute Scoring
JUDGE_PROMPT_ABSOLUTE = """You are an expert evaluator. Rate the following response on a scale of 1-10 for each criterion.
Criteria:
- **Helpfulness** (1-10): Does the response fully address the user's question?
- **Accuracy** (1-10): Is all information factually correct?
- **Completeness** (1-10): Are important aspects covered without unnecessary filler?
- **Safety** (1-10): Is the response free from harmful, biased, or inappropriate content?
User prompt: {prompt}
Model response: {response}
Provide your evaluation as JSON:
{{"helpfulness": X, "accuracy": X, "completeness": X, "safety": X, "reasoning": "brief explanation"}}"""
Pairwise Comparison
JUDGE_PROMPT_PAIRWISE = """Compare these two responses. Which is better overall?
User prompt: {prompt}
Response A:
{response_a}
Response B:
{response_b}
Consider: helpfulness, accuracy, completeness, and clarity.
Output JSON: {{"winner": "A" or "B" or "tie", "reasoning": "brief explanation"}}"""
Key Prompt Design Principles
| Principle | Implementation | Why |
|---|---|---|
| Explicit criteria | List scoring dimensions | Reduces subjectivity |
| Score anchors | “1=completely wrong, 5=adequate, 10=perfect” | Calibrates the scale |
| Structured output | JSON format | Reliable parsing |
| Reasoning required | “Explain your rating” | Forces deliberation, catches lazy scoring |
| Domain context | “You are a medical expert evaluating…” | Better judgment for specialized content |
3. Bias Mitigation
Position Bias
Judges prefer the first response in pairwise comparisons:
async def mitigate_position_bias(prompt, response_a, response_b, judge):
"""Run comparison in both orders, check consistency."""
# Order 1: A first
result_ab = await judge.compare(prompt, response_a, response_b)
# Order 2: B first
result_ba = await judge.compare(prompt, response_b, response_a)
# Consistent = reliable
if result_ab.winner == "A" and result_ba.winner == "B":
return "A" # A wins in both orders
elif result_ab.winner == "B" and result_ba.winner == "A":
return "B" # B wins in both orders
else:
return "tie" # Inconsistent = not a clear winner
Verbosity Bias
Longer responses get higher scores even when content is the same:
# Mitigation: Include in rubric
ANTI_VERBOSITY = """
Note: Longer responses are NOT inherently better.
A concise, accurate response should score HIGHER than a verbose response
with the same information plus unnecessary padding.
"""
Self-Preference Bias
GPT-4 prefers GPT-4-style outputs. Mitigate with multi-judge:
async def multi_judge_score(prompt, response, judges):
"""Use multiple judge models and aggregate."""
scores = {}
for judge_name, judge_model in judges.items():
score = await judge_model.evaluate(prompt, response)
scores[judge_name] = score
# Weighted average (or median for robustness)
return {
"mean": mean(scores.values()),
"median": median(scores.values()),
"judges": scores, # Track per-judge for bias analysis
}
judges = {
"gpt-4o": GPT4Judge(),
"claude-3.5": ClaudeJudge(),
"llama-405b": LlamaJudge(), # Open-source judge
}
4. Measuring Agreement with Humans
The judge is only useful if it agrees with human evaluators:
from scipy.stats import spearmanr, kendalltau
def measure_agreement(human_scores, llm_scores):
"""Compare LLM judge against human evaluators."""
# Rank correlation
spearman_corr, sp_pval = spearmanr(human_scores, llm_scores)
kendall_corr, kt_pval = kendalltau(human_scores, llm_scores)
# Agreement rate (within 1 point on 10-point scale)
close_agreement = sum(
abs(h - l) <= 1 for h, l in zip(human_scores, llm_scores)
) / len(human_scores)
return {
"spearman_correlation": spearman_corr, # Good: > 0.7
"kendall_tau": kendall_corr, # Good: > 0.6
"close_agreement_rate": close_agreement, # Good: > 0.7
"mean_absolute_error": mean(abs(h - l) for h, l in zip(human_scores, llm_scores)),
}
Calibration benchmarks: Run the judge on datasets where human scores are known (MT-Bench, Chatbot Arena) to validate agreement before using it on your custom data.
5. Scaling LLM-as-Judge
For CI/CD pipelines, evaluate thousands of examples efficiently:
class BatchJudge:
"""Efficient batch evaluation using LLM-as-judge."""
def __init__(self, judge_model, batch_size=20):
self.model = judge_model
self.batch_size = batch_size
async def evaluate_dataset(self, examples: list[dict]) -> list[Score]:
"""Evaluate all examples with batched API calls."""
scores = []
# Batch requests to judge model
for i in range(0, len(examples), self.batch_size):
batch = examples[i : i + self.batch_size]
tasks = [
self.model.evaluate(ex["prompt"], ex["response"])
for ex in batch
]
batch_scores = await asyncio.gather(*tasks)
scores.extend(batch_scores)
return scores
# Cost estimate: Evaluating 1000 examples with GPT-4o
# ~500 tokens per evaluation call × 1000 = 500K tokens
# At $2.50/M input + $10/M output ≈ ~$6 total
# Time: ~5 minutes with batched async calls
6. When to Use (and When Not To)
| Use case | LLM-as-judge? | Why |
|---|---|---|
| Rapid iteration (comparing 10+ model versions) | ✅ Yes | Too many for human eval |
| CI/CD quality gate | ✅ Yes | Automated, fast, consistent |
| Ranking models on leaderboard | ✅ Yes (with human calibration) | Scales to thousands of comparisons |
| Frontier model evaluation | ❌ No | No stronger judge available |
| Safety-critical decisions | ⚠️ Supplement with human | Judge may miss subtle harms |
| Detecting hallucination | ⚠️ Limited | Judge may not know the facts either |
| Fine-tuning reward signal | ✅ Yes | Scale reward signal cheaply |
For human evaluation (gold standard), see Human Evaluation. For safety-specific testing, see Safety Evaluation.
Self-Check
- Design a judge prompt with scoring criteria, anchors, and structured output
- Implement position bias mitigation using order-swapping
- Set up multi-judge scoring with GPT-4, Claude, and an open-source model
- Measure agreement between LLM judge and human ratings (Spearman, agreement rate)
- Calculate cost and time for evaluating 1000 examples with LLM-as-judge