LLM Evals in Practice: Making LLM Application Quality Measurable
Non-deterministic outputs, subjective correctness, and hard-to-track regressions make traditional unit testing ineffective for LLM applications. This article introduces LLM evaluation (LLM Evals) as a systematic way to make quality measurable. It explains what evals are and how they differ from unit tests, defines six core quality dimensions—relevance, faithfulness, conciseness, format correctness, safety, and semantic similarity—and compares three evaluation methods: metric-based checks, LLM-as-a-judge, and human review. It also covers building versioned evaluation datasets, integrating evals into CI/CD pipelines as automated quality gates, and practical guidance for rolling out an eval system while avoiding common pitfalls such as overfitting the eval set.
1. Why LLM Applications Need an Evaluation System
A chatbot starts giving terse, unhelpful replies; a summarizer produces “facts” that appear nowhere in the source text; a RAG system answers confidently based on irrelevant retrieved documents; an engineer tunes a prompt to fix one use case while three others quietly regress—these are everyday occurrences in LLM application development. On the surface it looks like “model instability,” but the root cause is that three engineering properties have fundamentally changed:
- Non-deterministic output: The same prompt can produce drifting output due to the temperature parameter, sampling strategy, or silent upgrades to the model backend. The traditional exact assertion of
output == expected stringfails completely here. - Subjective correctness: “Is this summary good?” and “Is this answer helpful?” have no single correct answer. You cannot decide them with a boolean; you must first define criteria, then quantify a score.
- Invisible blast radius: A prompt behaves like a “global variable”—modifying it in one place can ripple through every use case that depends on it. Teams without regression testing can only firefight reactively after user complaints.
So if you want to build enterprise-grade software on top of LLMs, the way forward is not to hope the model becomes more stable, but to apply the same engineering discipline as with traditional software: automated, reliable, repeatable testing—that is, LLM evaluation (LLM Evals)—integrated directly into your CI/CD pipeline, so that quality degradation is intercepted before merge and release.
2. What LLM Evals Are: Unit and Integration Testing for AI
LLM evaluation is a framework for measuring the quality and performance of LLM outputs against a set of predefined criteria. A well-formed eval case typically contains four components:
- Input: the user question or the full prompt;
- Context (optional): RAG-retrieved documents, conversation history, system instructions, etc.;
- Reference criteria: a golden reference answer, a rubric, or executable assertions;
- Scoring function: rule checks, statistical metrics, or a judge model.
Compared with traditional unit tests, the key differences are:
| Dimension | Traditional Unit Tests | LLM Evals |
|---|---|---|
| Verdict | Exact assertion, binary result | Score/threshold, continuous result |
| Output determinism | Deterministic and reproducible | Non-deterministic, requires statistical treatment |
| Source of correctness | Objective logic | Subjective criteria + explicit rubrics |
| Pass criteria | All tests pass | Score meets threshold with no regression |
Once you understand these differences, it becomes clear that LLM evals are not “unit tests written differently.” They are a quality system redesigned around scores and thresholds.
3. Six Core Evaluation Dimensions
- Relevance: Does the answer actually address the user’s question? Common failure modes include dodging the question, being vague, or over-expanding the topic. You can score this with a judge model against a rubric, or use semantic similarity as a first-pass filter.
- Faithfulness / Groundedness: The lifeline of RAG scenarios. Every factual statement in the answer must be supported by the given context. The standard engineering approach is to split the answer into atomic statements, verify each one against the context, and quantify the hallucination rate.
- Conciseness: Is the answer clear and to the point, without filler pleasantries? It can be approximated with rule-based checks such as output length constraints and repetition detection.
- Format Correctness: When the output is required to be JSON, SQL, or a fixed template, is it parseable, are all fields present, and are the values valid? This is the easiest dimension to express as rules and the first one that should go into CI.
- Safety (Toxicity / Safety): Does the output contain harmful or inappropriate content, leak sensitive information, or fall for prompt injection? Enterprise applications must cover this before launch, typically with a “one-strike veto” policy.
- Semantic Similarity: How close the output is to the golden reference answer in vector space—suitable for cases where “the answer isn’t unique, but its meaning should be.” Note that it measures “similarity,” not “correctness,” and should be combined with other dimensions.
For specific tasks, you can also add task-specific metrics: classification accuracy, field recall for extraction tasks, retrieval hit rate for RAG, and so on.
4. Three Evaluation Methods and How to Choose
1. Metric-Based Evals (fast, precise, cheap)
Use classic NLP metrics (such as BLEU, ROUGE) or custom programmatic checks (such as is_json(), contains_word(), length ranges, regex matching). BLEU and ROUGE suit tasks closely aligned with reference text (translation, summarization) but are insensitive to paraphrasing; programmatic assertions excel at format and hard constraints. A unit-test-style example:
import jsondef test_extract_output_format():raw = call_llm(EXTRACT_PROMPT, SAMPLE_INPUT)assert is_valid_json(raw), "Output must be valid JSON"data = json.loads(raw)assert {"company", "amount", "date"} <= set(data.keys())assert len(data["company"]) > 0
The pros: deterministic, low cost, completes in milliseconds. The cons: narrow coverage—unable to judge semantic quality.
2. LLM-as-a-Judge Evals
Use a stronger, more stable model as the “judge” that scores the output under test against a rubric. Key practices include:
- Decompose “good” into individually judgeable items and write them as an explicit rubric, instead of vaguely asking for “a score”;
- Require the judge to return structured results (score + reason) to support statistics and auditing;
- Set the judge’s temperature to 0 or use deterministic decoding to reduce scoring jitter;
- Decouple the judge model from the model under test to avoid “self-preference” bias;
- Periodically sample for human review to verify agreement between the judge and human judgment.
A sample judge prompt:
JUDGE_PROMPT = """You are a strict QA inspector. Rate the "answer" (1-5) against these criteria:1) Uses only the given context, with no fabricated facts;2) Directly addresses the question itself;3) Contains no filler or boilerplate.Output JSON only: {"score": integer, "reason": "one-sentence rationale"}Context: {context}Question: {question}Answer: {answer}"""
Be aware of its limitations: judge calls cost money, and judges can exhibit position bias and length preference, so they must be continuously validated against a calibration set.
3. Human Evaluation
Subjective experience, style, and brand tone still ultimately need a human. The recommended combination is “run everything automatically, review a sample manually”: for example, sample 5–10% of cases, always review all bad cases, and feed human conclusions back as new eval cases, forming a closed loop.
5. Evaluation Datasets: The Foundation of the Entire System
- Golden set sources: high-frequency questions and bad cases from real production traffic (highest value); boundary and adversarial cases (overlong input, ambiguous questions, hallucination-inducing prompts, prompt injection); typical scenarios and expected key points written by domain experts.
- Layered management: a smoke set (a few dozen cases, runs in seconds, executed on every commit); a core set (covering the main functional paths, executed before merge); a full set (thousands of cases, executed nightly or before release).
- Versioning: manage eval sets in version control just like prompts and code. Every production quality incident should be captured as a new case—the regression case library only grows, never shrinks.
6. Integrating into CI/CD: Automating Quality Gates
Evals should be triggered whenever: prompts or system instructions change, the model version is upgraded or switched, RAG retrieval strategy or chunking parameters change, or output post-processing logic changes. An example gate policy: the smoke set’s average score must not fall below the baseline with no significant drop in any single dimension; zero tolerance on safety cases; 100% pass rate on format cases. A sample pipeline configuration (pseudocode):
pipeline:- stage: unit_testsrun: run_tests ./tests/unit- stage: llm_smoke_evalsrun: python run_evals.py --suite smoke --min-score 0.85- stage: report_archiverun: python report.py --uploadnightly:- run: python run_evals.py --suite full --min-score 0.90
The core loop of an eval runner:
results = []for case in load_suite("smoke"):output = call_llm(case.prompt, case.variables)scores = {"format": rule_check(output, case.rules),"faithfulness": judge(case.context, case.question, output),"similarity": cosine(embed(output), embed(case.gold)),}results.append({**scores, "case_id": case.id})avg = mean(r["faithfulness"] for r in results)assert avg >= THRESHOLD, f"Faithfulness average {avg:.2f} below gate {THRESHOLD}"
You should also build observability for your evals: persist every score, per-case detail, and the version under test (prompt hash, model version) to storage, and turn them into trend dashboards. These capabilities can be self-built on generic cloud services such as logging, monitoring and alerting, and object storage—or you can use LLM services and the accompanying evaluation and observability components offered by platforms such as Baidu AI Cloud.
7. Rollout Advice and Common Pitfalls
- Start small: cover high-frequency paths and high-risk scenarios (safety, format, hallucination) first; there is no need to build everything at once.
- Watch out for overfitting the eval set: repeatedly tuning prompts against the same batch of cases will degrade performance on the real production distribution. Refresh the eval set regularly from production traffic.
- Put scores in context: averages mask tail risk—also track the performance of the worst 10% of cases.
- Evaluate the evaluator: regularly measure the agreement between judge results and human labels (e.g., the Kappa coefficient). When agreement drops, update the rubric or adjust the judge strategy.
- Control costs: judge calls are the biggest expense. Compress them by caching results for identical inputs and running tiered execution (rules first, then judges).
8. Conclusion
The chaos of LLM application development fundamentally comes from “correctness” turning from a deterministic proposition into probability and subjective judgment. LLM evals put that ambiguity back into the engineering cage: define quality with explicit dimensions, make quality regression-testable through automation, and intercept degradation before merge with CI/CD gates. When the eval system is versioned and managed alongside prompts, models, and retrieval strategies, “prompt tuning” finally turns from alchemy into engineering.
