PROMETHEUS OS
NATIVE AI OPERATING SYSTEM
[INIT] Prometheus OS loading...
[CORE] Neural interface initializing...
[AI] LLM router connecting...
[MEM] Memory graph loading...
[AGT] Agent chains on standby...
[SEC] Security protocols active...
[NET] Provider mesh established...
[UI] Workspace rendering...
[DONE] All systems nominal.
Welcome to PROMETHEUS OS.
READY · OFFLINE · SECURE · PRIVATE
🎨 THEME ENGINE
PROMETHEUS OS · 23 THEMES
Trial version: Dark + Light themes only.
Full theme access with PROMETHEUS OS license.
Dark theme active
Experience all 23 themes in PROMETHEUS OS

Evaluating AI Systems

Advanced 14 min· 4 exercises

How to tell whether an AI feature actually works: building test sets, scoring with golden answers and LLM judges, regression-testing prompt changes, tracking cost and latency, red-teaming and monitoring in production.

By the end of this lesson you will be able to
  • Design a representative test set with held-out cases, golden answers and per-capability suites.
  • Calculate confidence intervals for eval scores and the number of cases needed for a target margin of error.
  • Compare two system versions with paired methods (McNemar's test and the paired bootstrap) on the same cases.
  • Validate an LLM judge against human labels using agreement and Cohen's kappa, and mitigate its known biases.
  • Build an evaluation and monitoring loop that tracks quality, cost and latency together and turns failures into tests.

Before this: APIs, Tokens and Pricing, Probability and Statistics for AI, Benchmarks and Evaluation

AI features fail quietly. A prompt tweak that fixes one complaint can break ten cases nobody rechecked, and a model update can shift behaviour overnight. Evaluation, often shortened to evals, is how you replace "it seemed fine when I tried it" with evidence.

Start with a test set

A test set is a collection of realistic inputs that represent what your system will face. Good sources:

  • Real user requests (with personal data removed).
  • Known hard cases and past failures.
  • Edge cases: empty input, very long input, other languages, ambiguous questions, requests that should be refused.

Start with 50 to 200 cases; a small set you actually run beats a large one you don't. Keep some cases aside that you never look at while tuning prompts, so you can detect overfitting to your own test set.

Golden answers and how to score

For each case, decide what "good" means. A golden answer (or reference answer) is the expected output, written or approved by someone who knows the domain. Scoring methods, from most to least objective:

MethodExampleStrengthWeakness
Exact or rule-based checkCategory label matches; JSON parses; answer contains the order numberCheap, deterministicOnly works for constrained outputs
Reference comparisonKey facts from the golden answer are presentFlexibleNeeds careful rubric
LLM-as-judgeA model grades against a rubricScales to open-ended textBiased; must be validated
Human reviewExperts rate outputsMost trustworthySlow and costly

Use the most objective method that captures what matters. Many systems combine them: code checks for format, a judge for quality, and periodic human review to keep the judge honest.

For RAG systems, evaluate retrieval separately (did the right passage appear in the top results?) from generation (was the answer faithful to the passages?).

LLM-as-judge and its biases

An LLM judge is a model prompted to grade another model's output against a rubric, or to pick the better of two answers. Research on this approach found strong judges can agree with human preferences about as often as humans agree with each other, but also documented systematic biases:

  • Position bias: when comparing two answers, favouring whichever is shown first (or second).
  • Verbosity bias: favouring longer answers even when they aren't better.
  • Self-enhancement bias: favouring outputs written by the same model or model family.
  • Limited ability to grade maths and reasoning it cannot itself do reliably.

Mitigations: swap the order and judge twice; use specific rubrics ("Does the answer state the refund deadline? yes/no") rather than "rate 1 to 10"; ask for a short justification before the score; use a different model family as judge where practical; and check the judge against a sample of human ratings before trusting it.

Regression-testing prompts

Treat prompts, model choices and retrieval settings like code. Every change runs the whole test set, and you compare scores before and after. This is regression testing: making sure fixes don't break what used to work. Keep prompts in version control and store each run's outputs so you can see exactly which cases changed.

Beware of noise. Worked example: prompt A scores 172 of 200 (86%) and prompt B scores 181 of 200 (90.5%). With 200 cases, the margin of error on each score is roughly plus or minus 4.5 percentage points at 95% confidence (using the standard approximation of 1.96 × √(0.88 × 0.12 ÷ 200) ≈ 0.045). So a 4.5-point gain is suggestive, not proof. Look at which specific cases flipped, run variable outputs more than once, and grow the test set where decisions hinge on small differences.

Measure cost and latency too

A more accurate answer that costs five times as much or takes 30 seconds may be worse overall. For every eval run, record:

  • Tokens and cost per task, including all tool-loop steps and retries.
  • Latency: time to first token and total time, reported as the median and the 95th percentile (the time within which 95% of requests finish), because averages hide slow outliers.
  • Failure rate: timeouts, invalid outputs, tool errors.

Then compare options on all three axes: quality, cost and speed.

Red-teaming

Red-teaming means deliberately trying to make the system misbehave, the way an attacker or a careless user might. Typical targets:

  • Prompt injection through documents, web pages or emails the system reads.
  • Extracting the system prompt, other users' data or secrets.
  • Getting tools to act outside their intended scope.
  • Producing harmful, biased or off-brand content.

Turn every successful attack into a permanent test case so the fix stays fixed.

Monitoring in production

Test sets cannot anticipate everything users do. In production, log inputs, outputs, tool calls, costs and latency (respecting privacy rules), and watch for:

  • Quality signals: thumbs up or down, edits users make to drafts, escalations to a human, repeated rephrasing.
  • Drift: changes in the kinds of questions asked, or behaviour changes after a provider updates a model.
  • Cost and latency spikes, often from runaway agent loops or bloated context.

Sample production conversations regularly for review, and feed interesting failures back into the test set. That cycle (collect, evaluate, fix, re-test) is how AI systems get steadily better instead of randomly different.

Going deeper

An eval score is an estimate

Suppose your system has some true success rate pp on the kind of traffic your test set represents. Running nn independent cases and observing ss successes gives the estimate p^=s/n\hat{p} = s/n, whose standard error is

SE(p^)=p^ (1−p^)n.\text{SE}(\hat{p}) = \sqrt{\frac{\hat{p}\,(1 - \hat{p})}{n}}.

The familiar 95% interval p^±1.96 SE\hat{p} \pm 1.96\,\text{SE} is what the earlier worked example used. It behaves poorly when p^\hat{p} is near 0 or 1 or nn is small, so a safer default is the Wilson interval, which the code below computes. For 172 of 200 it gives about 80.5% to 90.1%; for 181 of 200, about 85.6% to 93.8%. The intervals overlap heavily, which matches the earlier conclusion that the gap is suggestive, not proven.

How many cases do you need? Rearranging the standard error gives the sample size for a desired margin EE:

n≈1.962 p (1−p)E2.n \approx \frac{1.96^2\, p\,(1 - p)}{E^2}.

To measure a system near 85% accuracy to within ±3 points: n≈3.8416×0.85×0.15/0.0009≈545n \approx 3.8416 \times 0.85 \times 0.15 / 0.0009 \approx 545 cases. For ±5 points, about 196. This is why 50 to 200 cases is a good start for catching big regressions but not enough to resolve small differences.

Compare on the same cases: paired analysis

When two prompts are run on the same test cases, most cases come out the same for both. Only the cases where they disagree carry information about which is better. Count bb = cases only A got right and cc = cases only B got right. Under the null hypothesis that A and B are equally good, each disagreement is equally likely to go either way, so min⁡(b,c)\min(b, c) follows a binomial distribution with b+cb + c trials and probability one half. That is McNemar's test, and it is usually much more sensitive than comparing two independent intervals.

Worked example. In the 172 versus 181 comparison, suppose 166 cases were right for both, 13 wrong for both, b=6b = 6 and c=15c = 15. The net gain is c−b=9c - b = 9 cases, which is the 4.5 points. The exact two-sided McNemar p-value is about 0.08, so even the paired test does not reach the conventional 0.05 threshold, but it tells you precisely where to look: read the 21 flipped cases. If the 15 wins are real improvements and the 6 losses are noise or label errors, ship B; if the 6 losses are severe (for example, wrong refund amounts), the average hides a real regression.

import math, random

def wilson_ci(successes, n, z=1.96):
    p = successes / n
    denom = 1 + z**2 / n
    centre = (p + z**2 / (2 * n)) / denom
    half = z * math.sqrt(p * (1 - p) / n + z**2 / (4 * n**2)) / denom
    return centre - half, centre + half

def mcnemar_exact(b, c):
    """Two-sided exact p-value; b, c = discordant pair counts."""
    n, k = b + c, min(b, c)
    tail = sum(math.comb(n, i) for i in range(k + 1)) / 2**n
    return min(1.0, 2 * tail)

def paired_bootstrap(a, b, iters=10_000, seed=0):
    """a, b: per-case 0/1 scores on the SAME cases. 95% CI of mean(b - a)."""
    rng, n = random.Random(seed), len(a)
    diffs = []
    for _ in range(iters):
        idx = [rng.randrange(n) for _ in range(n)]
        diffs.append(sum(b[i] - a[i] for i in idx) / n)
    diffs.sort()
    return diffs[int(0.025 * iters)], diffs[int(0.975 * iters)]

print(wilson_ci(172, 200), wilson_ci(181, 200))
print(mcnemar_exact(6, 15))                      # about 0.078
a = [1]*166 + [1]*6 + [0]*15 + [0]*13            # prompt A per case
b = [1]*166 + [0]*6 + [1]*15 + [0]*13            # prompt B, same cases
print(paired_bootstrap(a, b))                    # roughly (0.0, 0.09)

The paired bootstrap resamples test cases with replacement and recomputes the score difference each time; the middle 95% of those differences is a confidence interval that works for any metric, including judge scores and costs, not just pass or fail. Here its lower end sits at about zero, consistent with the McNemar result.

Is the judge trustworthy? Measuring agreement

Before relying on an LLM judge, have humans label a sample of the same outputs and measure agreement. Raw agreement overstates quality when one label dominates, so use Cohen's kappa, which corrects for agreement expected by chance:

κ=po−pe1−pe,\kappa = \frac{p_o - p_e}{1 - p_e},

where pop_o is the observed agreement and pep_e is the agreement expected if the judge and the human labelled independently at their own base rates. Worked example on 100 outputs: both say "pass" on 40, both say "fail" on 45, the judge passes 10 that the human fails, and fails 5 that the human passes. Then po=0.85p_o = 0.85. The judge passes 50% of outputs and the human 45%, so pe=0.5×0.45+0.5×0.55=0.50p_e = 0.5 \times 0.45 + 0.5 \times 0.55 = 0.50, and κ=(0.85−0.50)/(1−0.50)=0.70\kappa = (0.85 - 0.50)/(1 - 0.50) = 0.70. That is substantial agreement, but notice the direction of the errors: the judge is more lenient than the human (10 false passes versus 5 false fails). Tighten the rubric where false passes cluster, then re-measure.

Behavioural tests, not just averages

A single average can hide systematic failures. Borrowing from software testing, write small suites that each check one capability or invariance:

  • Minimum functionality tests: simple cases that must always pass (a refund question must mention the refund window).
  • Invariance tests: changes that should not change the answer (swapping a customer's name, adding a typo).
  • Directional tests: changes that should move the answer in a known direction (adding "urgent" should not lower priority).

Report pass rates per suite. A model can improve its overall score while getting worse on one suite that matters, and per-suite reporting makes that visible.

Common pitfalls

  • Testing on what you tuned on. If you edited prompts while looking at every test case, the score is optimistic. Keep a held-out set.
  • Comparing runs with different settings. Changing temperature, model version or retrieval index between runs confounds the comparison; record the full configuration with each result.
  • Single runs of stochastic systems. At non-zero temperature, run each case several times or accept wider error bars.
  • Unvalidated judges. A judge that has never been compared with human labels may be measuring length or style, not correctness.
  • Averages only. Look at failures by category and at the individual cases that flipped.
  • Forgetting cost and latency. A quality gain that doubles p95 latency may be a net loss for users.

In practice

  • Build a 50 to 200 case test set from real usage before changing anything.
  • Score with code checks where possible, a validated LLM judge where necessary, and humans periodically.
  • Run the full set on every prompt, model or retrieval change, and inspect the cases that flipped.
  • Track cost and p95 latency alongside quality.
  • Red-team before launch, monitor after, and keep turning failures into tests.

Key takeaways

  • Evals replace impressions with evidence: a realistic test set, clear criteria and repeatable scoring.
  • Prefer objective checks where possible; use LLM judges for open-ended output but validate them against humans.
  • LLM judges show position, verbosity and self-enhancement biases, which swapping order and tight rubrics reduce.
  • Run the full test set on every change and remember small score differences on small sets can be noise.
  • Quality, cost and latency must be measured together, and production monitoring should feed new test cases.

Terms in this lesson

Eval
A repeatable test that measures how well an AI system performs on a defined set of cases.
Test set
A collection of representative inputs used to evaluate a system.
Golden answer
An expert-approved reference output for a test case.
LLM-as-judge
Using a language model to grade or compare outputs according to a rubric.
Regression testing
Re-running existing tests after a change to make sure previously working behaviour still works.
95th percentile latency
The response time within which 95% of requests complete.
Red-teaming
Deliberately attacking a system to find ways it can be made to fail or misbehave.
Drift
A gradual change in inputs or model behaviour that makes past evaluation results less representative.
McNemar's test
A test for paired binary outcomes that judges whether two systems differ using only the cases on which they disagree.
Cohen's kappa
A measure of agreement between two raters that subtracts the agreement expected by chance, ranging up to 1 for perfect agreement.
Bootstrap
Estimating the uncertainty of a statistic by repeatedly resampling the data with replacement and recomputing the statistic.

Check your understanding

  1. 1.

    An LLM judge comparing two answers keeps preferring the first one shown. What is the best mitigation?

  2. 2.

    Prompt B beats prompt A by 3 percentage points on a 100-case test set. What is the most reasonable conclusion?

  3. 3.

    Why report 95th percentile latency rather than only the average?

  4. 4.

    Roughly how many test cases do you need to estimate an accuracy near 80% to within ±4 percentage points at 95% confidence?

  5. 5.

    A judge and a human agree on 90% of 200 outputs. Each labels 90% of outputs 'pass', so the agreement expected by chance is 0.9 × 0.9 + 0.1 × 0.1 = 0.82. What is Cohen's kappa?

Exercises

Work each problem before opening the solution.

  1. Exercise 1Core

    Your classifier gets 138 of 150 test cases right. (a) Compute the simple 95% interval p^±1.96 SE\hat{p} \pm 1.96\,\text{SE}. (b) How many cases would you need for a margin of ±2 points at this accuracy?

    Show solution

    (a) p^=138/150=0.92\hat{p} = 138/150 = 0.92. SE=0.92×0.08/150=0.0004907≈0.02215\text{SE} = \sqrt{0.92 \times 0.08 / 150} = \sqrt{0.0004907} \approx 0.02215. Margin =1.96×0.02215≈0.0434= 1.96 \times 0.02215 \approx 0.0434. Interval ≈ 87.7% to 96.3%.

    (b) n≈1.962×0.92×0.08/0.022=3.8416×0.0736/0.0004≈707n \approx 1.96^2 \times 0.92 \times 0.08 / 0.02^2 = 3.8416 \times 0.0736 / 0.0004 \approx 707 cases.

  2. Exercise 2Core

    Prompts A and B are run on the same 300 cases. 240 are right for both, 30 wrong for both, 8 right only for A and 22 right only for B. (a) What are the two accuracies? (b) Which cases should you read first, and why? (c) Using the exact McNemar test, is the difference significant at the 0.05 level? (You may use the mcnemar_exact function from the lesson.)

    Show solution

    (a) A: (240+8)/300=82.7%(240 + 8)/300 = 82.7\%. B: (240+22)/300=87.3%(240 + 22)/300 = 87.3\%.

    (b) The 30 discordant cases (8 + 22). The 270 concordant ones say nothing about which prompt is better.

    (c) b=8b = 8, c=22c = 22, n=30n = 30. The exact two-sided p-value is 2×P(X≤8)2 \times P(X \le 8) for X∼Binomial(30,0.5)X \sim \text{Binomial}(30, 0.5), which mcnemar_exact(8, 22) gives as about 0.016. So yes, B's improvement is significant at 0.05, though you should still read the 8 cases B lost to make sure none is a serious regression.

  3. Exercise 3Core

    Write a Python function cohens_kappa(judge, human) for two equal-length lists of binary labels (1 = pass, 0 = fail). Check it on the lesson's example (40 both pass, 45 both fail, 10 judge-pass/human-fail, 5 judge-fail/human-pass).

    Show solution
    def cohens_kappa(judge, human):
        n = len(judge)
        p_o = sum(j == h for j, h in zip(judge, human)) / n
        pj, ph = sum(judge) / n, sum(human) / n          # pass rates
        p_e = pj * ph + (1 - pj) * (1 - ph)
        return (p_o - p_e) / (1 - p_e)
    
    judge = [1]*40 + [0]*45 + [1]*10 + [0]*5
    human = [1]*40 + [0]*45 + [0]*10 + [1]*5
    print(round(cohens_kappa(judge, human), 3))   # 0.7
    

    po=85/100=0.85p_o = 85/100 = 0.85; judge pass rate 0.50, human pass rate 0.45; pe=0.225+0.275=0.50p_e = 0.225 + 0.275 = 0.50; κ=0.35/0.50=0.70\kappa = 0.35/0.50 = 0.70. (If pe=1p_e = 1, kappa is undefined; handle that edge case in production code.)

  4. Exercise 4Challenge

    You run a RAG-based customer-support assistant. Design its evaluation plan: the test set (size and composition), the metrics for retrieval, answers, safety, cost and latency, how you will validate any LLM judge, the release gate a change must pass, and what you monitor in production.

    Show solution

    Test set. About 400 to 600 cases, enough for roughly ±3 to 4 points on headline metrics: real anonymized questions sampled by topic frequency; known past failures; edge cases (empty, very long, non-English, ambiguous); questions the knowledge base cannot answer (expect "I don't know"); and an adversarial suite (prompt injection in retrieved documents, attempts to extract other customers' data). Each case has labelled relevant passages and a golden answer or key facts. Hold out about 20% that prompt authors never see.

    Metrics.

    • Retrieval: recall@5 and MRR against labelled passages.
    • Answers: key-fact coverage (code or judge), faithfulness to retrieved passages (judge), citation validity (code: every cited ID was retrieved), correct refusal rate on unanswerable questions.
    • Safety: adversarial suite pass rate (should be 100% on known attacks), PII leakage checks (code).
    • Cost and latency: tokens and cost per conversation, median and p95 time to first token and total time.

    Judge validation. Have two support experts label about 150 outputs; compute their agreement with each other and Cohen's kappa between judge and the experts per metric; require kappa of roughly 0.6 or more before relying on the judge, and inspect where it is lenient. Re-check after changing the judge model or rubric.

    Release gate. A change ships only if: no drop beyond the noise level on any headline metric (paired comparison on the same cases, reading all flipped cases); no new failures in the safety suite; p95 latency and cost per conversation within agreed budgets; and a reviewer signs off on the flipped-case review.

    Production monitoring. Thumbs up and down, escalation rate, repeated rephrasing, citation-click rates; drift in topic mix; cost and latency dashboards with alerts; weekly human review of a random sample plus all escalations; every confirmed failure becomes a new test case.

Further reading

Go further

Sources

Fact-checked and last reviewed 2026-11-05

Stay in the loop
Prometheus OS™ · Native AI OS · Built for the future © 2025 - 2026