LLM Evals From Zero  Chapter 1 of 9
01 / 20
Chapter 1 · Foundations

Why Your App Is Already Broken
(And Demos Won't Tell You)

LLM Evals From Zero: build an eval suite that blocks bad releases. This chapter sets up the problem the whole course solves: a change that looks better in a demo and is measurably worse in production.

Learning objectives

  • Explain why "looks good" fails as a quality signal for LLM systems
  • Define an evaluation formally: dataset, system, scorers, gate
  • Distinguish evals from unit tests, observability, and guardrails
  • Read an eval report and make a merge or block decision from it

How this lecture runs

  • 20 minutes, 20 slides: one core concept every 45 to 60 seconds
  • One running example throughout: a support RAG assistant
  • Every claim is backed by an artifact: a diff, a dataset, a report, a pipeline
  • No tooling tour. Plain concepts first, tools later in the course
Audience: engineers with a working RAG app or agent Prereqs: Python · basic RAG · one LLM API key Setup: laptop only, no GPU
SG
Saloni GargSenior Machine Learning Engineer, Adobe
SLIDE 01 / 20PACE 0:00
Slide 02 · The core problem

Why "looks good" is not a metric

A metric is a number you can compare across two versions of a system and act on. A vibe check produces none of the properties a release decision needs.

Property a release decision needsVibe checkMeasured evaluation
ReproducibleDifferent reviewer, different verdict. Mood, order, and recency all leak in.Same dataset, same scorers, same result. Anyone can rerun it.
ComparableNo baseline. "Better than last week" is unrecorded memory.Candidate is diffed against a saved baseline run, per category.
CoverageWhoever demos picks the examples, so the sample is biased by construction.Dataset is stratified on purpose: easy, hard, adversarial, out of scope.
ActionableOutput is an opinion. Nothing in CI can consume an opinion.Output is a score against a threshold. A gate can merge or block on it.
Attributable"Quality feels off" names no component and no fix.Failures cluster by cause: retrieval, generation, refusal, citation.

Engineering question: what exactly am I measuring, and could a script act on the answer?

SLIDE 02 / 20PACE 1:00
Slide 03 · Running example

The system under test: Support RAG

One system, used for the entire course. It answers support questions from product docs, cites its sources, and must refuse when the answer is not in the docs.

User Query
Support question in natural language
→
Retriever
Embed query, search index, return top-k chunks
→
Context Assembly
Chunks plus system prompt plus citation instructions
→
LLM
Generates a grounded answer from context only
→
Answer
Answer with citations, or a refusal

Contract

  • Answer only from retrieved docs
  • Every claim carries a citation
  • No source in docs means refuse, do not guess

Change surfaces

  • Prompt revisions
  • Chunking and embedding model swaps
  • Model upgrades and provider changes

Failure surfaces

  • Retriever returns the wrong chunk
  • Model answers beyond the context
  • Model refuses a question it could answer
SLIDE 03 / 20PACE 2:00
Slide 04 · The change

A prompt change that appears to improve quality

Prompt v13 asks for warmer, more complete answers. In the demo the answers read better: fuller, friendlier, more confident. Nothing about the demo tells you what it cost.

prompts/support_v12.txt → support_v13.txt
# system prompt diff - Answer using only the provided context. - If the context is silent, say you do not know. - Cite the source for every claim. + Be a warm, helpful support expert. + Give complete answers. Fill small gaps + with your general product knowledge. + Keep citations where they fit naturally.

What the change really does

  • Removes the grounding constraint. "Fill small gaps" is a license to hallucinate.
  • Weakens refusal. A warm, complete answer is the opposite of "I do not know."
  • Makes citations optional. "Where they fit" means unverifiable claims ship.
  • Improves surface quality. Longer, warmer text reads better in a spot check, which is exactly why the demo passes.

Engineering question: which behavior did this diff trade away, and who measured it?

SLIDE 04 / 20PACE 3:00
Slide 05 · The spot check

Manual spot-check: 5 examples, 5 passes

The team tries v13 on five familiar questions before merging. Every one looks good. This is the exact moment most bad releases get approved.

#Queryv13 behavior observedVerdictHidden property
1How do I reset my password?Correct steps, warm tone, citedPASSEasy, in docs, high frequency
2Where is my invoice?Correct steps, citedPASSEasy, in docs
3How do I add a team member?Correct, fuller than v12PASSEasy, in docs
4Can I export to CSV?Correct, citedPASSMedium, in docs
5What is the refund window?Correct number, citedPASSMedium, in docs

What the sample contains

Five answerable, in-scope, previously seen questions. Zero refusals, zero adversarial phrasing, zero missing-doc cases.

What a pass here proves

Almost nothing. With n = 5 drawn from the easiest slice of traffic, even a badly regressed system passes most of the time.

SLIDE 05 / 20PACE 4:00
Slide 06 · The measurement

500 production queries expose the regression

Run the same v13 against a 500 query dataset drawn from real support traffic, scored the same way as the v12 baseline. The demo result does not survive contact with the distribution.

EXAMPLE EVALUATION REPORT · candidate v13 vs baseline v12 · n = 500
Faithfulness91.2%  ↓ 4.8%
Citation Accuracy96.8%  ↓ 7.1%
Refusal Correctness88.5%  ↓ 9.4%
Latency1.8 s  ↑ 0.3 s
✕ BUILD FAILED Gate decision: block the release. Every quality metric regressed; the warm tone was paid for with grounding, citations, and refusals.

Engineering question: how do I detect regressions before users do? Run the candidate on the full distribution and diff it against a baseline.

SLIDE 06 / 20PACE 5:00
Slide 07 · Failure analysis

Failure taxonomy: name it to measure it

A single accuracy number hides everything. Split failures by cause and each one gets its own scorer, its own owner, and its own fix.

Hallucination

Answer asserts facts absent from the retrieved context.

Signal: claims with no supporting chunk.

Scorer: faithfulness judge plus citation check.

Retrieval failure

The right chunk never reaches the model, so no prompt can save the answer.

Signal: expected source missing from top-k.

Scorer: recall@k, deterministic.

Refusal error

Answers what it should refuse, or refuses what it could answer.

Signal: behavior mismatch on should-refuse set.

Scorer: confusion matrix, next visual.

Citation error

Citation present but wrong, stale, or not supporting the claim.

Signal: cited chunk does not entail the sentence.

Scorer: citation accuracy check.

Refusal confusion matrix, example run (refusal slice, n = 200 of 500)

Predicted: answer
Predicted: refuse
Should answer
143answered, correct behavior
17false refusals
Should refuse
6answered anyway: highest risk
34refused, correct behavior

Refusal correctness = (143 + 34) / 200 = 88.5%, matching the report on slide 6.

Failure clusters among failed cases, example run

Retrieval miss41
Hallucination33
Refusal error27
Citation error19

Read the clusters, not the score. Retrieval is the top fix here, not prompt wording.

SLIDE 07 / 20PACE 6:00
Slide 08 · Sampling bias

Why demos systematically miss these failures

Demo failure is not bad luck. Four structural biases guarantee the demo sample looks nothing like production traffic.

1 · Selection bias

The presenter picks examples the system is known to handle. The sample is filtered by the outcome before it is shown.

2 · Distribution bias

Demo queries are short, clean, and in scope. Production adds typos, ambiguity, multi-part asks, and out-of-scope requests, which is where refusals and retrieval break.

3 · Sample size

Five examples cannot reveal a failure mode that fires on 5 to 10 percent of traffic. Rare per query, certain per day at production volume.

4 · No baseline, no memory

A demo compares the new version against a feeling about the old one. Regressions on categories nobody re-tests are invisible by definition.

Demo sampleProduction distribution
Query sourceChosen by the teamReal user traffic, logged
Should-refuse casesAlmost never shownA fixed slice of the golden set
Verdict"Looked good live"Scored, diffed, gated
SLIDE 08 / 20PACE 7:00
Slide 09 · Definition

What is an evaluation? A formal definition

An evaluation is a repeatable procedure that runs a system over a fixed dataset, scores the outputs against defined criteria, and compares the result to a decision rule.

Eval = D dataset × S system under test × M scorers → report → G gate

D · Dataset

Fixed, versioned inputs with expected behavior per item.

S · System

The exact candidate: model, prompt, retriever, config, all pinned.

M · Scorers

Deterministic checks, reference scoring, and judges, per category.

G · Gate

Pre-agreed thresholds that turn a report into a merge or block call.

evals/run_eval.py · the whole idea in 10 lines
def run_eval(dataset, system, scorers, baseline): results = [] for case in dataset: # fixed, versioned inputs output = system.run(case.query) # candidate, fully pinned scores = {s.name: s.score(case, output) for s in scorers} # per category, never one number results.append({"id": case.id, **scores}) report = diff(aggregate(results), baseline) return gate(report) # PASS or BLOCK, nothing vaguer
SLIDE 09 / 20PACE 8:00
Slide 10 · Two loops

Offline vs. online evaluation

Offline evals answer "should this ship?" before release. Online evals answer "is it still true?" after release. You need both; they catch different things.

DimensionOffline evaluationOnline evaluation
WhenPre-release, on every candidate changePost-release, continuously on live traffic
DataGolden dataset: fixed, labeled, versionedSampled production traffic, often weakly labeled
Ground truthExpected answers, sources, and refusal labelsUser signals, judge scores, human spot review
Decision it drivesMerge or block the releaseRollback, canary promotion, dataset updates
Blind spotCannot see queries nobody anticipatedCannot run a controlled A/B against a baseline build
Failure it catchesThe v13 regression on slide 6Drift: new products, new phrasing, stale docs

The loop between them: every real failure found online becomes a permanent case in the offline golden set. The dataset is a growing memory of everything production has taught you.

SLIDE 10 / 20PACE 9:00
Slide 11 · Boundary 1 of 3

Evals vs. unit tests

Unit tests verify code behaves as specified. Evals measure how a probabilistic system behaves across a distribution. Related discipline, different object.

DimensionUnit testsEvaluations
Unit under testA function or componentThe whole system: prompt, retrieval, model, config
OutputDeterministic: same input, same outputProbabilistic: same input, a distribution of outputs
OracleExact expected valueCriteria, references, rubrics, and judges
Pass conditionBinary: pass or fail per testAggregate scores vs. thresholds, plus per-category gates
FlakinessA bug: tests must never flakeManaged: fixed seeds where possible, noise bands, rerun rules
Cost per runMilliseconds, freeReal API calls: budget it, cache it, subset it in CI

Rule of thumb: if the expected output can be written exactly, write a unit test. If quality is a matter of degree across many inputs, write an eval. Most LLM systems need deterministic checks inside the eval suite too, which is Chapter 4 of this course.

SLIDE 11 / 20PACE 10:00
Slide 12 · Boundary 2 of 3

Evals vs. observability

Observability tells you what the system did in production. Evaluation tells you whether what it did was good. Traces without scores are surveillance, not measurement.

DimensionObservabilityEvaluation
QuestionWhat happened? Latency, tokens, errors, tracesWas the output correct, grounded, and safe?
WhenLive traffic, after releaseBefore release on datasets, and sampled live
DataLogs, spans, metrics from real requestsInputs paired with expected behavior and scores
ComparisonAgainst time: yesterday vs. todayAgainst a baseline build on identical inputs
ActionAlert, debug, roll backMerge or block, promote or hold a canary

Worked example

Observability shows latency up and zero errors after v13 ships. Everything looks healthy. Only the eval report shows faithfulness and refusal correctness down, because wrong answers return HTTP 200.

How they compose

Traces feed evals: sampled production traces become scored cases and, once labeled, golden dataset entries. Observability is the supply chain; evaluation is the judgment.

SLIDE 12 / 20PACE 11:00
Slide 13 · Boundary 3 of 3

Evals vs. guardrails

Guardrails intervene on a single live request. Evals decide whether the system as a whole is fit to ship. One is a runtime control; the other is a release control.

DimensionGuardrailsEvaluations
ScopeOne request or response at a timeThe full system across a dataset
TimingInline, in the request path, adds latencyOffline in CI, plus sampled checks online
ActionBlock, redact, rewrite, or refuse that responseBlock or approve the release itself
What it cannot doDetect a slow quality regression across thousands of allowed responsesStop a single harmful response in real time
ExamplePII filter on outputs; a refusal classifier in the pathRefusal correctness scored over the should-refuse set before merge

And guardrails themselves need evals. A guardrail is a model or ruleset with its own false positives and false negatives. You measure those with the same machinery: a labeled dataset, a confusion matrix, and thresholds, exactly like slide 7.

Engineering question: where does this fit into my deployment pipeline? Next three slides.

SLIDE 13 / 20PACE 12:00
Slide 14 · Pipeline architecture

The evaluation pipeline, end to end

The PR is the trigger, the pipeline is the judge, and the gate is the decision. This is the architecture the course builds, piece by piece.

Pull Request
Prompt, model, chunking, or config change
Candidate Prompt
The exact build under test, pinned and versioned
Evaluation Pipeline
  • Golden Dataset
  • Retrieval Metrics
  • LLM Judge
  • Deterministic Checks
Pass Threshold
No critical regression vs. baseline
Merge
Regression
Any gated category drops beyond its band
Block Release
SLIDE 14 / 20PACE 13:00
Slide 15 · Inside one run

Dataset → Model → Scorers → Report → Gate

1 · Dataset
Golden JSONL, versioned
→
2 · Model
Candidate system runs every case
→
3 · Scorers
Deterministic, retrieval, judge
→
4 · Report
Diff vs. baseline, per category
→
5 · Gate
Thresholds decide merge or block
data/golden_v1.jsonl · one line per case
{"id": "q-001", "query": "How do I reset my password?", "expected_sources": ["docs/account/reset.md"], "must_refuse": false, "category": "easy"} {"id": "q-214", "query": "What is the CEO's home address?", "expected_sources": [], "must_refuse": true, "category": "should-refuse"} {"id": "q-377", "query": "Refund window for annual plans?", "expected_sources": ["docs/billing/refunds.md"], "must_contain": ["30 days"], "category": "hard"}

What each stage guarantees

  • Dataset: the questions never change mid-comparison. Version it like code.
  • Model: one pinned candidate per run. No silent provider drift inside a run.
  • Scorers: cheap deterministic checks first, judge only where judgment is needed.
  • Report: a diff, not a score. Baseline vs. candidate, per category, with failing case IDs.
  • Gate: thresholds agreed before the run, so the decision is not negotiated after it.
SLIDE 15 / 20PACE 14:00
Slide 16 · Deployment pipeline

Where evaluation fits into CI/CD

Two speeds keep the gate affordable: a fixed subset on every PR for a fast signal, and the full suite nightly for the complete picture.

PR Opened
Lint and unit tests first
→
Eval Subset
Fixed slice of the golden set, runs in minutes
→
Report Comment
Baseline vs. candidate diff posted on the PR
→
Gate
Block on critical regression, warn on cost drift
→
Merge + Nightly
Full suite nightly, canary before full rollout
.github/workflows/evals.yml
on: [pull_request] jobs: eval-gate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install -r requirements.txt - run: python -m evals.run --subset pr - run: python -m evals.report --post-pr-comment - run: python -m evals.gate --baseline main # exits non-zero on a gated regression

Gate policy used in this course

  • Block on any critical category regression: refusal, faithfulness, safety.
  • Block on an overall drop beyond the suite noise band.
  • Warn, do not block, on cost and latency drift. Page a human, not the pipeline.
  • When the gate fires, read the failures, not the score. The report links every failing case.

Engineering question: how do I know whether to block a release? The gate policy answers it before the PR exists.

SLIDE 16 / 20PACE 15:00
Slide 17 · The build

What this course will build

One project, built in order: a versioned eval suite in a repo that runs on every PR, compares candidates against a baseline, and fails the build when quality regresses.

The artifacts you will own

  1. Golden dataset: stratified JSONL with expected answers, sources, and refusal labels
  2. Scorer library: deterministic checks, retrieval metrics, citation checks
  3. Calibrated LLM judge: a rubric validated against your own hand labels
  4. Eval report: baseline vs. candidate diff, per category, with failing cases
  5. CI gate: GitHub Actions workflow that merges or blocks on the report

The skills behind the artifacts

  • Failure analysis: cluster failures into causes before touching a prompt
  • Judge calibration: measure judge vs. human agreement and fix the rubric, not the labels
  • Threshold setting: separate real regressions from run to run noise
  • Suite maintenance: fold production failures back into the dataset, re-baseline deliberately

Tooling stays boring on purpose: plain Python, pytest, JSONL, GitHub Actions. Tracing and dashboards appear as an optional layer, never as the core idea.

SLIDE 17 / 20PACE 16:00
Slide 18 · Repository preview

Repository structure: one suite, one home

Everything the pipeline needs lives in the repo and is versioned with the code it judges: dataset, scorers, judge prompts, baselines, and the workflow.

llm-evals-from-zero/
llm-evals-from-zero/ ├── app/ │ ├── rag.py # the support RAG system │ └── prompts/ # v12, v13, ... pinned ├── evals/ │ ├── run_eval.py # dataset x system x scorers │ ├── scorers.py # deterministic + retrieval │ ├── judge.py # rubric + judge prompts │ ├── report.py # baseline diff, PR comment │ └── gate.py # thresholds, exit codes ├── data/ │ ├── golden_v1.jsonl # the golden dataset │ └── baselines/ # saved reference runs ├── tests/ # unit tests for scorers └── .github/workflows/ └── evals.yml # the CI gate

Versioning rules that keep it honest

  • Dataset changes are PRs too. Editing the golden set to make a failing build pass is the one unforgivable move.
  • Judge prompts are code. Changing the judge changes the measurement, so judge changes re-baseline the suite.
  • Baselines are saved runs, not remembered numbers. Every report names the baseline it diffed against.
  • Broken variants ship in the repo on purpose, so each chapter can break the system and watch the suite catch it.
SLIDE 18 / 20PACE 17:00
Slide 19 · Roadmap

Course roadmap: nine chapters, one suite

Part 1 · Foundations

  • 1. Why your app is already broken YOU ARE HERE
  • 2. Anatomy of an eval suite: the four scorer layers
  • 3. Build the golden dataset

Part 2 · Scoring

  • 4. Score what you can without an LLM first
  • 5. LLM-as-judge, done properly: rubrics and judge bias
  • 6. Calibrate the judge against humans

Part 3 · Shipping

  • 7. RAG and agent evals, where averages lie
  • 8. Put it in CI: the suite that blocks bad releases
  • 9. Keep it alive: online evals, drift, maintenance

How the chapters compound

Each chapter ends with a failure the suite catches that it could not catch before. Chapter 3's dataset makes Chapter 4's scorers meaningful; Chapter 6's calibration is what makes Chapter 8's gate trustworthy; Chapter 9 keeps the whole thing true after launch. Downloads for the course: repo template with the sample RAG app and broken variants, golden dataset template, judge rubric template, failure analysis worksheet, and the CI workflow file.

SLIDE 19 / 20PACE 18:00
Slide 20 · Takeaways

Key takeaways, and what comes next

Five things to keep

  1. "Looks good" is not a metric. If a script cannot act on it, it cannot gate a release.
  2. Demos are biased samples. Small, cherry picked, and missing exactly the cases that fail in production.
  3. An eval is dataset, system, scorers, report, gate. Drop any one and you have an opinion again.
  4. Measure by category. Faithfulness, retrieval, refusal, and citations fail for different reasons and need different fixes.
  5. The gate is the point. Thresholds agreed in advance turn measurement into a deployment decision.

Next video · Chapter 2

Anatomy of an Eval Suite. The four scorer layers: deterministic checks, reference based scoring, LLM-as-judge, and human review, and how to evaluate by capability instead of chasing a single average score.

Bring: your running RAG app and one change you are afraid to ship. Chapter 2 gives it a measurement.

SG
Saloni GargSenior Machine Learning Engineer, Adobe
SLIDE 20 / 20PACE 19:00 · END 20:00