all writing

LLM Evaluation

How to Evaluate LLM Applications: Building Evals That Catch Regressions

2026-09-17 · by Talha Jaleel

How to evaluate LLM applications guide cover

Almost every guide to building LLM features, including the ones on this site, ends with the same instruction: test it against a fixed evaluation set. This post is the one that explains how to actually do that. Evaluation is what turns LLM quality from a subjective 'seems better' into a number you can move, defend, and protect from regressions, and it is the discipline that most separates production LLM systems from demos that quietly degrade. Here is how to build evals that earn their keep.

Why 'It Looks Good' Is Not an Evaluation

The default way teams judge an LLM feature is to try a few prompts by hand and eyeball the results. This feels like testing but is not, because it is not repeatable, it does not cover the cases that actually break, and it gives you no way to tell whether a change helped or hurt. A prompt tweak that fixes the three examples you happen to test can silently break twenty you did not.

LLM systems fail in a way traditional software does not: they degrade silently. A model update, a prompt edit, or drift in your underlying data can make outputs worse without throwing a single error, so nothing alerts you until a user complains. The only defense is a repeatable evaluation you run before and after every change, the same observability mindset covered in the LLM integration guide, applied to quality rather than uptime.

The goal of evaluation is not a perfect quality score. It is a consistent measurement that reliably moves in the right direction when you improve the system and drops when you break it. Once you have that, prompt engineering, model selection, and retrieval tuning stop being guesswork and become experiments you can actually run.

Start With an Eval Set, Not a Metric

The foundation of any evaluation is a fixed set of representative test cases: inputs your system will really see, paired with either a known correct answer or a clear description of what a good answer looks like. This set is the single most valuable artifact in an LLM project, and it is worth building carefully from real or realistic examples rather than a handful of easy cases you invented.

Build the set from the failure modes you actually care about. Include the common happy-path cases, the known hard cases, the edge cases that have burned you before, and examples that cover the range of inputs real users produce. A set of 50 to a few hundred well-chosen cases is usually enough to start catching regressions, and it grows naturally: every time a bad output slips through, you add it as a new case so it can never regress silently again.

This is exactly the artifact a proper RAG or LLM proof of concept should produce, not as a one-time gate but as a living asset the production system keeps using. Without it, every other technique below has nothing to measure against, which is why building the eval set comes before choosing how to score it.

Deterministic Checks vs. LLM-as-Judge

Some things you can check with plain code, and you should, because it is cheaper, faster, and perfectly reliable. Does the output parse as valid JSON, contain the required fields, stay under a length limit, avoid forbidden content, or exactly match a known answer for factual lookups? These deterministic checks catch a surprising share of real failures at zero model cost, so reach for them first wherever the correctness criterion is objective.

Many LLM outputs, though, are open-ended: a summary, an explanation, a support reply. There is no single correct string to match against, and whether the output is good is a judgment about relevance, accuracy, and tone. This is where LLM-as-judge comes in: you use a capable model to score the output against criteria you define, which has become the default method for evaluating open-ended LLM applications at scale precisely because it handles the cases exact-match cannot.

The right design uses both. Run the cheap deterministic checks as hard gates (an output that is not valid JSON fails outright, no judgment needed), and reserve the LLM judge for the qualitative dimensions that genuinely need it. Structuring evals this way keeps cost down and reserves the expensive judgment calls for where they add value, which also keeps your evaluation cost in check as the eval set grows.

Making LLM-as-Judge Trustworthy

An LLM judge is only useful if its scores track what a human expert would say, and that is not automatic. The way you establish it is to validate the judge against human labels: take a couple hundred representative cases, have a human score them, then measure how well the judge agrees. A well-tuned judge can reach agreement with human reviewers around the mid-80s percent, which is often higher than two humans agree with each other, but only after you have tuned the judge's prompt and examples to get there.

The tuning matters because LLM judges have known, systematic biases. They exhibit position bias (favoring whichever answer comes first in a comparison), verbosity bias (rating longer answers higher regardless of quality), and self-enhancement bias (scoring outputs from the same model family more generously). If you do not account for these, your judge produces confident scores that are subtly wrong in consistent ways, which is worse than no score at all.

Practical countermeasures: give the judge a specific rubric rather than a vague 'rate this,' ask it to reason through the criteria before scoring, randomize answer order in comparisons to cancel position bias, and for high-stakes evaluations, run several judge models and take a majority vote to average out any single model's biases. Then re-validate the judge against fresh human labels periodically, because model updates on the judge's own API can shift its behavior over time.

Evaluating RAG and Agents Specifically

RAG systems need their two stages evaluated separately, because a wrong answer can come from either. Measure retrieval on its own (did the correct chunk appear in the retrieved results) and generation on its own (given the retrieved context, was the final answer correct). Separating them tells you exactly which stage a regression came from and stops a retrieval fix from being masked by a generation problem, the diagnostic approach covered in depth in the guide to improving RAG accuracy.

Agents are harder to evaluate because success is a whole trajectory, not a single output. The questions that matter are whether the agent completed the task, whether it used the right tools in a sensible order, how many steps it took, and how much it cost to get there. Logging the full step trace of each run is what makes this measurable, and it doubles as the debugging record when a task fails.

For both, resist the urge to collapse everything into one score. Track task success rate, and alongside it the operational metrics (latency, cost per task, tool-call counts) that determine whether the system is viable in production, not just accurate. A production agent that answers correctly but takes fifteen steps and costs a dollar per request has an evaluation problem your quality score alone would never surface.

Running Evals Continuously in CI

An eval set that lives on someone's laptop and gets run occasionally provides a fraction of its potential value. The payoff comes from running it automatically: on every prompt change, every model version bump, and every retrieval tweak, ideally wired into your CI pipeline so a regression fails the build the same way a broken unit test would. This is what turns evaluation from an occasional audit into a guardrail.

In practice that means treating your prompts, model versions, and eval set as versioned artifacts, running the eval suite on each change, and comparing the score against the previous baseline. A meaningful drop blocks the change until you understand it. This is the same CI/CD discipline teams already apply to application code, extended to cover the AI components, and it is the difference between catching a regression in a pull request and hearing about it from a user.

None of this requires a heavy platform to start. A scripted eval set, a judge with a validated rubric, and a CI step that runs them and compares scores is enough to get most of the benefit. If you are setting this up for the first time and want the architecture right from the start, that groundwork is exactly what a principal AI engineer builds in early, because evaluation is far cheaper to design in than to retrofit onto a system that has already drifted.

Frequently Asked Questions

How do I evaluate an LLM application?

Start by building a fixed evaluation set of representative inputs paired with known correct answers or a clear definition of a good answer. Score each output with deterministic checks where the criterion is objective (valid JSON, required fields, exact match) and with an LLM-as-judge for open-ended qualities like relevance and tone. Run the whole set before and after every change so you can tell whether a change helped or hurt.

What is LLM-as-a-judge?

LLM-as-a-judge is using a capable language model to score, classify, or compare another LLM's outputs against criteria you define. It has become the default method for evaluating open-ended LLM applications at scale, because it can assess qualities like relevance and coherence that exact-match checks cannot. It must be validated against human labels to be trustworthy, since LLM judges have systematic biases.

How accurate is LLM-as-a-judge?

A well-tuned LLM judge can agree with human reviewers around the mid-80s percent of the time, which is often higher than the agreement between two human reviewers on the same task. That accuracy is not automatic: it requires a specific rubric, tuning the judge's prompt against human-labeled examples, and controlling for known biases like position bias and verbosity bias.

What biases do LLM judges have?

Common ones include position bias (favoring the first answer in a comparison), verbosity bias (rating longer answers higher regardless of quality), and self-enhancement bias (scoring outputs from the same model family more generously). Countermeasures include randomizing answer order, using a specific rubric, having the judge reason before scoring, and running multiple judge models with a majority vote for high-stakes evaluations.

How do I evaluate a RAG system?

Evaluate retrieval and generation separately. For retrieval, measure whether the correct chunk appears in the retrieved results; for generation, measure whether the final answer is correct given the retrieved context. Separating the two identifies which stage a regression came from and prevents a retrieval fix from being hidden by a generation problem, or vice versa.

Should LLM evals run in CI?

Yes. Wiring your eval set into CI so it runs on every prompt, model, and retrieval change catches regressions before they reach users, the same way a unit test suite does for application code. Version your prompts, models, and eval set, run the suite on each change, and compare against the previous baseline so a meaningful score drop blocks the change until it is understood.

Sources

Further Reading

Building something like this?

I build custom operations software for home service contractors: field ops platforms, AR dashboards, permit pipelines, and local SEO.If you're scoping a project, I can tell you what it would take for your setup in a quick call.