πŸ“Š LLM Evaluation β€” Master Guide

🎯 AI Product Manager βš™οΈ Staff Engineer Why eval matters, eval types, LLM-as-judge, datasets, metrics, regression testing, production monitoring, and a live eval lab

Why LLM Evaluation Is the Foundation of Everything
Without evaluation, you cannot improve. You cannot safely change a prompt. You cannot compare models. You cannot detect regressions. You cannot measure product quality. Evaluation is not a nice-to-have β€” it's the prerequisite for every other improvement activity.
🎯 PM Perspective
Eval is how you answer "is this AI feature ready to ship?" without relying on gut feel. It's how you measure whether a prompt change was an improvement or a regression. It's how you hold engineering accountable to quality standards and how you prioritize what to fix next. Invest in evals early β€” they compound over time.
βš™οΈ Engineer Perspective
Eval is your test suite for non-deterministic systems. Traditional unit tests don't apply β€” you can't write `assertEqual(llm_output, expected)`. Instead you measure dimensions of quality across a representative dataset. The discipline is similar: define expected behavior before writing code, run tests automatically, block deploys on regression.
🚨
The "vibe check" trap: The most common eval strategy is manual testing by the team β€” running 10-20 examples and deciding it "feels right." This fails because (1) small samples miss tail failures, (2) team members are biased toward their own work, (3) you can't track quality over time, and (4) it doesn't scale.

πŸ“Š What Good Eval Enables

Confident Shipping
Run eval before every deploy. If score drops, don't ship. If score holds, ship with confidence. No more "seems fine" as the gate criterion.
Model Comparison
GPT-4o vs Claude vs Llama β€” evaluated on YOUR task, not benchmarks. Generic benchmarks don't predict performance on your specific use case.
Prompt Optimization
Make a prompt change β†’ run eval β†’ see exact score delta. Turn "this feels better" into "this is 7% better on accuracy, 3% worse on brevity."
Regression Prevention
A model update silently broke a feature. Eval catches it immediately. Without eval, users find the regression first β€” in production.
Failure Analysis
Which input types fail most? Which prompt elements help most? Eval data answers these questions with evidence, not anecdote.
PM Decision Support
Is this feature good enough to ship? Is the quality improvement worth the cost increase? Eval provides the data to answer these product questions.

⏱️ When to Build Evals

StageEval ActivityWhy Now
Before writing the first promptDefine 5-10 test cases with expected outputsForces clarity on what "good" means before you build
During prompt developmentRun eval after every significant prompt changeMeasures improvement, prevents accidental regression
Before every deployFull eval suite as CI/CD gateCatches regressions before users see them
After model upgradesFull eval suite + new capability testsModel updates can change behavior unpredictably
In production (continuous)Sample + score live outputsCatches real-world failure patterns not in test set
πŸ“‹ Types of Evaluation
Not all evaluation is the same. The right eval type depends on what you're measuring, how much ground truth you have, and how much scale you need. Most production systems use a combination.

πŸ“Š The Eval Spectrum

TypeHow It WorksProsConsBest For
Exact MatchLLM output == expected output (string match)Fast, cheap, deterministicToo strict; "yes" β‰  "Yes" failsClassification, extraction with fixed labels
Regex / Rule-basedPattern matching on outputFast, zero costBrittle; doesn't capture semantic qualityFormat compliance, field presence checks
Semantic SimilarityCosine similarity between output and reference embeddingCatches paraphrasesDoesn't measure factual accuracySummarization, paraphrase detection
Human EvaluationHumans rate outputs on defined dimensionsHighest quality signalExpensive, slow, doesn't scale, inconsistentCalibration, new task types, final validation
LLM-as-JudgeLLM scores outputs against rubricScalable, nuanced, cheapBiases, needs calibrationMost production eval tasks
Reference-based LLM JudgeLLM compares output to reference answerBetter than semantic similarityNeeds reference answersRAG accuracy, factual QA
Reference-free LLM JudgeLLM scores output without referenceNo ground truth neededMore subjective; needs strong rubricStyle, tone, coherence, safety

πŸ—οΈ Practical Eval Stack β€” What Most Teams Should Use

Layer 1: Deterministic Checks (Free)
Run first on every output β€” fast and zero cost.

β€’ Valid JSON / XML format
β€’ Required fields present
β€’ Output length in bounds
β€’ No forbidden strings (PII patterns, profanity)
β€’ Classification label is valid enum value
Layer 2: LLM Judge (Scalable)
Run on all cases β€” nuanced quality assessment.

β€’ Relevance (did it answer the question?)
β€’ Faithfulness (grounded in provided context?)
β€’ Accuracy (factually correct?)
β€’ Tone / style compliance
β€’ Completeness (did it cover key points?)
Layer 3: Human Eval (Calibration)
Run on a sample β€” ground truth source.

β€’ Calibrate your LLM judge (compare human vs judge scores)
β€’ Review cases where judge is uncertain
β€’ Identify failure categories the judge misses
β€’ Quarterly benchmark against human standards
βš–οΈ LLM-as-Judge β€” The Workhorse of Production Eval
Using a separate LLM to evaluate your system's outputs is the most scalable and practical approach for most AI products. Done right, it correlates strongly with human judgment. Done wrong, it introduces systematic biases that mislead your entire evaluation process.
🎯 PM View
LLM-as-judge lets you evaluate 10,000 outputs overnight for a few dollars β€” something human eval teams can't match. The output is structured scores you can track over time, compare across versions, and slice by input type. It makes quality a measurable KPI, not a feeling.
βš™οΈ Engineer View
The judge is just another LLM call with a carefully designed rubric prompt. Use a more capable model as judge (Claude Sonnet or GPT-4o judging Haiku outputs works better than Haiku judging itself). Always return structured scores, not prose judgments. Validate judge calibration against human labels before trusting it.

πŸ“‹ The LLM Judge Prompt β€” What a Good One Looks Like

System: You are an expert evaluator for an AI customer support system. Evaluate responses on the dimensions below. Be critical and calibrated β€” a score of 8+ should be genuinely excellent, not just acceptable. User: <task>Answer customer questions about our software product accurately and helpfully.</task> <question>{{CUSTOMER_QUESTION}}</question> <response>{{AI_RESPONSE}}</response> <reference_answer>{{REFERENCE_ANSWER}}</reference_answer> Evaluate on these dimensions (1-10 each): 1. ACCURACY: Is every factual claim in the response correct per the reference? 10 = all facts correct, 1 = major factual errors 2. RELEVANCE: Does the response directly address what the customer asked? 10 = fully on-point, 1 = misses the question entirely 3. COMPLETENESS: Does it cover all key points from the reference? 10 = all key points covered, 1 = major omissions 4. CLARITY: Is the response clear and easy for a non-technical user to understand? 10 = crystal clear, 1 = confusing or technical jargon without explanation 5. TONE: Is the tone appropriate β€” professional, helpful, not condescending? 10 = excellent tone, 1 = inappropriate tone Respond ONLY in this JSON format: { "accuracy": N, "relevance": N, "completeness": N, "clarity": N, "tone": N, "overall": N, "reasoning": "2 sentences max explaining the scores", "failure_category": "none | factual_error | incomplete | off_topic | tone_issue | format_issue" }

⚠️ LLM Judge Biases β€” Know Them Before You Trust the Scores

BiasWhat HappensMitigation
Verbosity biasLonger responses score higher even if less usefulInclude length calibration examples; penalize padding explicitly in rubric
Self-preferenceGPT-4o judges favor GPT-4o outputs; Claude favors Claude outputsUse a different model family as judge than the one being evaluated
Position biasIn A/B comparisons, the first option wins more oftenRun comparisons twice with positions swapped; average the scores
SycophancyJudge gives high scores to confidently-written but wrong answersExplicitly test factual accuracy; add "penalize confident errors heavily" to rubric
Anchoring on referenceAny answer similar to reference scores high even if it adds errorsSeparate "similarity to reference" from "factual accuracy" as distinct dimensions
Score inflationJudges tend to score 7-9; rarely use 1-4Provide calibration examples with known human scores; use relative ranking instead of absolute scores for high-precision comparisons

πŸ”¬ Judge Calibration β€” Validating Your Judge

Before trusting your LLM judge at scale, validate it against human judgment on a calibration set. This is non-negotiable for any eval system you'll use in production decisions.

# Calibration process calibration_set = 100 # examples labeled by humans # Score both human and judge human_scores = [human_eval(ex) for ex in calibration_set] judge_scores = [llm_judge(ex) for ex in calibration_set] # Measure alignment from scipy.stats import pearsonr, spearmanr pearson_r, _ = pearsonr(human_scores, judge_scores) spearman_r, _ = spearmanr(human_scores, judge_scores) # Interpret: # pearson_r > 0.8 β†’ strong alignment β†’ trust the judge # pearson_r 0.6-0.8 β†’ moderate alignment β†’ use with caution # pearson_r < 0.6 β†’ poor alignment β†’ revise rubric before trusting # Also check: where do they disagree most? disagreements = [(ex, h, j) for ex, h, j in zip(calibration_set, human_scores, judge_scores) if abs(h - j) > 2] # large gaps # Review these cases β†’ update rubric to address systematic gaps
πŸ“¦ Eval Datasets β€” Building Your Ground Truth
Your eval is only as good as your dataset. A dataset that doesn't represent real production traffic will give you false confidence. A dataset that's too small will miss systematic failures.

πŸ—οΈ Dataset Construction Principles

  • βœ“
    Start with 50-100 examples. Enough to be statistically meaningful, small enough to annotate by hand.
  • βœ“
    Represent the real distribution. If 20% of real queries are edge cases, your dataset should have 20% edge cases.
  • βœ“
    Include known hard cases. Deliberately add inputs you know are difficult β€” they're most valuable for measuring improvement.
  • βœ“
    Cover failure modes. Once you identify a failure pattern in production, add examples of it to your eval set.
  • βœ“
    Never include eval examples in training/prompts. Your eval set is sacrosanct β€” contamination invalidates everything.
  • βœ“
    Version your dataset. v1.0, v1.1 etc. When you add examples, create a new version.
  • βœ“
    Add new examples over time. As you discover production failures, add them to the eval set so they never regress.
  • βœ“
    Separate dev/test sets. Dev set for experimentation; test set only for final evaluation before ship.
  • βœ“
    Human-annotated labels as ground truth. Synthetic reference answers are acceptable; AI-generated labels without human review are not.
  • βœ“
    Track provenance. Know where every example came from β€” synthetic, production, manual creation.

πŸ“‹ Dataset Schema β€” What to Store

{ "id": "eval_001", "version": "v1.2", "input": "What is your refund policy for digital products?", "reference_output": "Digital products are non-refundable within 30 days of purchase unless they are defective. To request a refund for a defective product, contact support@company.com with your order number.", "tags": ["policy", "refund", "digital"], "difficulty": "medium", // "easy" | "medium" | "hard" | "edge_case" "category": "policy_questions", "provenance": "production_logs_2025-01", "human_label": { "annotator": "jane_doe", "quality_score": 9, "notes": "Reference is clear and complete. Key test: does model include the contact email?" }, "added_date": "2025-01-15", "added_reason": "Production failure on 2025-01-10: model hallucinated 14-day policy" }

⚑ Golden Set vs Held-Out Set

SetSizePurposeHow Used
Golden Set (dev)50-200 examplesPrompt development, quick iteration feedbackRun after every prompt change; track scores over time
Held-Out Set (test)200-500 examplesPre-release validation onlyRun only before major releases; never use for prompt tuning
Production Sample1% of live trafficCatch real-world failures not in test setsContinuous sampling + scoring; alert on score drops
πŸ“ Eval Metrics β€” What to Measure and Why
Different tasks need different metrics. Choosing the right metric β€” and understanding what it does and doesn't capture β€” is as important as running the eval itself.

πŸ“Š Core Metrics by Task Type

Task TypePrimary MetricSecondary MetricsWhat to Watch
ClassificationAccuracy / F1Precision, Recall per classClass imbalance; F1 is better than accuracy for unbalanced datasets
Information ExtractionExact Match, F1 on spansCoverage (recall of key fields)Partial matches β€” exact match is too strict if paraphrases are acceptable
SummarizationFaithfulness (LLM judge)Coverage, Relevance, ROUGE (if reference available)ROUGE correlates poorly with human quality; prefer LLM judge
RAG / Q&AAnswer CorrectnessContext Recall, Context Precision, FaithfulnessRAGAS framework covers all four RAG-specific metrics
Code GenerationPass@k (unit tests pass)Code quality (complexity, style), CorrectnessRunning actual tests is the only reliable signal; don't use LLM judge for code correctness
Open-ended GenerationLLM judge (multi-dim)User satisfaction (if AB test available)Define dimensions before scoring; avoid single "overall quality" score only
Safety / Content ModerationPrecision + Recall on violationsFalse positive rate (important for UX)Cost of false negative (missed violation) vs false positive (blocked good content)

πŸ“ˆ The Eval Dashboard β€” What to Track Over Time

Quality Metrics
β€’ Overall quality score (composite)
β€’ Per-dimension scores
β€’ Pass rate (% above threshold)
β€’ Failure rate by category
β€’ Score distribution (not just average)
Performance Metrics
β€’ Latency p50/p95/p99 per endpoint
β€’ Token usage (input + output)
β€’ Cost per query
β€’ Cost per successful output
β€’ Cache hit rate
Business Metrics
β€’ Task completion rate
β€’ User satisfaction / thumbs rating
β€’ Escalation rate (to human)
β€’ Retry / regeneration rate
β€’ Feature adoption (do users trust it?)
⚠️
The metric-gaming trap: Optimizing a single metric almost always degrades others. An agent optimized purely for accuracy might become verbose. One optimized for brevity might drop critical details. Always track a balanced scorecard, not a single KPI.
πŸ” Regression Testing β€” Never Break What Works
A regression is when a change that was supposed to improve one thing silently breaks another. In LLM systems, regressions are especially insidious because the model's non-determinism makes them hard to detect without systematic testing.

πŸ”„ CI/CD for Prompt Changes

Engineer changes prompt β†’ pushes to git branch
↓
CI pipeline triggers
↓
πŸƒ Run golden set (50 examples) against new prompt
↓
πŸ“Š Compare scores: new_score vs baseline_score
↓ if score_delta > -0.05 (5% regression threshold)
βœ… PASS β€” PR can be merged
↓ if score_delta ≀ -0.05
❌ FAIL β€” PR blocked. Show which examples regressed.
πŸ’‘
Make this automatic. Engineers should never have to manually decide if a prompt change is safe β€” the pipeline decides. Treat a failing eval the same way you'd treat a failing unit test: fix it before merging.

πŸ“‹ Regression Test Implementation

# eval/regression_test.py β€” run in CI/CD import json from anthropic import Anthropic client = Anthropic() def run_regression_eval( new_prompt: str, eval_dataset: list[dict], baseline_score: float, regression_threshold: float = 0.05, # 5% allowed drop ) -> dict: scores = [] failures = [] for example in eval_dataset: # Get model output with new prompt response = client.messages.create( model="claude-haiku-4-5", max_tokens=500, system=new_prompt, messages=[{"role":"user","content":example["input"]}] ) output = response.content[0].text # Score it with LLM judge score = llm_judge( input=example["input"], output=output, reference=example["reference_output"] ) scores.append(score) if score < 0.7: # below quality threshold failures.append({ "id": example["id"], "score": score, "output": output[:200] }) new_score = sum(scores) / len(scores) delta = new_score - baseline_score passed = delta >= -regression_threshold return { "passed": passed, "new_score": new_score, "baseline_score": baseline_score, "delta": delta, "failure_count": len(failures), "failed_examples": failures, }
πŸš€ Production Monitoring β€” Eval That Never Stops
Your eval dataset captures what you thought to test. Production catches what you didn't think to test. Running eval continuously on a sample of real traffic is the only way to catch the long tail of real-world failures.

πŸ“Š Production Eval Architecture

Live Traffic
100% of requests
β†’
Sampler
1-5% sample
β†’
Async Eval Queue
no latency impact
β†’
LLM Judge
scores each sample
β†’
Dashboard
+ alerts
πŸ’‘
Keep the eval pipeline asynchronous β€” it must never add latency to the user request. Sample β†’ queue β†’ score β†’ dashboard. Alert only when rolling averages cross a threshold, not on individual low-score samples (noise).

🚨 When to Alert

SignalAlert ThresholdAction
Rolling quality score drop5% below 7-day average (sustained for 30 min)Page on-call; investigate recent deploys
Error rate spikeError rate 2x above p95 baselineImmediate alert; check model API status
Latency spikep95 latency 50% above baseline for 5 minAlert; check for context window overflow
Cost anomalyToken cost 3x median for 15 minAlert; check for prompt injection / runaway agent loops
Failure category spikeAny failure category 2x above baselineInvestigate that specific failure category
⚠️ Eval Pitfalls β€” What Goes Wrong
Evaluation is hard to do wrong in obvious ways β€” it fails quietly, giving you false confidence in a system that has real problems. These are the most common ways eval programs break down.

❌ Dataset Contamination

Including eval examples in your few-shot prompts or fine-tuning data. The model "memorizes" the eval and scores artificially high.

🚨
Symptoms: eval scores much higher than production quality. Fix: strict separation β€” eval examples are never used in prompt engineering.

❌ Distribution Mismatch

Your eval dataset is too clean, too short, or too representative of easy cases. You score 95% in eval but production quality is 70%.

⚠️
Fix: sample your eval set directly from production logs. Include the messy, ambiguous, poorly-phrased real inputs users send.

❌ Single Metric Optimization

Prompt-tuning to maximize one eval score causes another dimension to collapse. Users complain about the same feature you just "improved."

⚠️
Fix: balanced scorecard of 3-5 dimensions. An improvement must improve at least one dimension without degrading others by more than a threshold.

❌ Stale Eval Dataset

You built the eval set 6 months ago. Your product evolved. New features, new user patterns, new failure modes β€” none of them are in the eval set.

⚠️
Fix: every production failure category gets added to the eval set. Review and refresh the dataset quarterly. Tag examples by date added.

❌ No Baseline

You have scores but no context. Is 0.82 good? Is it an improvement? Without a baseline and history, scores are meaningless.

⚠️
Fix: record every eval run with timestamp, prompt version, model version. Always show delta from previous version and from 30-day baseline.

❌ Judge Without Calibration

You deploy an LLM judge without ever validating it against human scores. It may have systematic biases that consistently mislead your decisions.

🚨
Fix: calibrate against 50-100 human-scored examples before trusting the judge. Pearson r > 0.8 is the minimum bar for production use.
πŸ§ͺ

Live Eval Lab β€” Build and Run an LLM Judge

Define a task, provide reference answers, and run a multi-dimensional LLM evaluation on real responses. See structured scores with reasoning for each dimension. This is exactly how production eval pipelines work.

Step 1: Define Your Eval Task

Step 2: Eval Cases

Each case: a question, a reference answer, and 1-2 model responses to evaluate. The judge will score each response on all dimensions.