Evaluation Fundamentals
Why eval, golden sets, metrics, and the eval-driven development loop.
What is LLM evaluation?
LLM evaluation (eval) is the systematic measurement of LLM application quality. A golden set is a curated dataset of (input, expected output) pairs. Metrics quantify quality: faithfulness (is the answer supported by context?), answer relevance (does it address the question?), retrieval recall (did we find the right chunks?).
Eval-driven development: write the eval BEFORE the feature, run it on every change, gate deploys on eval scores. This is the AI engineer's test suite.
Why eval matters
Without eval, you're flying blind. Prompt changes 'feel' better but regress quality. Model upgrades ship regressions. You can't tell if your RAG is good or bad. Eval turns vibes into numbers, enables confident iteration, and catches regressions before users do. Every production LLM system needs an eval pipeline.
Eval architecture
Golden set (curated, versioned) → eval runner (generates answers, scores) → metrics (faithfulness, relevance, recall) → report (per-example + aggregate) → gate (block deploy if regression > threshold) → online eval (sample production traffic, score, detect drift).
A golden-set eval
from dataclasses import dataclass
from typing import Callable
@dataclass
class GoldenExample:
query: str
expected_keywords: list[str] # must appear in answer
expected_sources: list[str] # must be cited
context_relevant: bool # should retrieval find relevant context
@dataclass
class EvalReport:
total: int
faithfulness: float
answer_relevance: float
retrieval_recall: float
failures: list[dict]
def run_eval(golden: list[GoldenExample], prompt_version: str) -> EvalReport:
results = []
for ex in golden:
# Generate answer with current prompt
retrieved = retrieve(ex.query)
answer = generate(ex.query, retrieved, prompt_version)
# Score
faith = score_faithfulness(answer, retrieved)
rel = score_relevance(answer, ex.query)
recall = score_recall(retrieved, ex.expected_sources)
results.append({
"query": ex.query,
"faithfulness": faith,
"relevance": rel,
"recall": recall,
"answer": answer,
})
n = len(results)
return EvalReport(
total=n,
faithfulness=sum(r["faithfulness"] for r in results) / n,
answer_relevance=sum(r["relevance"] for r in results) / n,
retrieval_recall=sum(r["recall"] for r in results) / n,
failures=[r for r in results if r["faithfulness"] < 0.7],
)
def gate_deploy(baseline: EvalReport, candidate: EvalReport, threshold: float = 0.05) -> bool:
"""Block deploy if candidate regresses > threshold on any metric."""
for metric in ["faithfulness", "answer_relevance", "retrieval_recall"]:
if getattr(candidate, metric) < getattr(baseline, metric) - threshold:
print(f"REGRESSION: {metric} {getattr(baseline,metric):.2f} → {getattr(candidate,metric):.2f}")
return False
return TrueExperiment: eval-driven dev
See how eval catches regressions that 'feel' fine.
What to observe
Changes that feel better often regress on faithfulness. Eval is the only reliable signal. Verbosity, model confidence, and removed safeguards all 'feel' fine but drop quality. Run eval on EVERY change before shipping.
Production eval
Production eval: golden set curated and versioned, runs in CI on every PR, gates deploy on regression threshold, online eval samples production traffic to detect drift, and a separate judge model (not the system model) scores outputs. Eval quality depends on golden set quality — invest in curation.
Challenge
Your eval passes (faithfulness 0.85) but users complain answers are wrong. What's wrong with your eval? (Hint: golden set doesn't represent real traffic.)
Production checklist
Production checklist
0 of 8 checked
Knowledge check
Your eval passes but users report wrong answers. Most likely cause?
Complete
You can now build a golden-set eval. Next: LLM-as-judge — using a model to score outputs at scale.
Mark this chapter as complete
Track your progress and unlock the next chapter.