Kapitel

kontinent / evalsKapitel 10

Online- und Produktions-Evaluation

Was Sie am laufenden System messen können, und was zu tun ist, wenn das Ihren Testergebnissen widerspricht.

Offline-Evaluation sagt Ihnen, wie Ihr System mit Eingaben umgeht, die Sie ausgewählt haben. Produktion sagt Ihnen, wie es mit Eingaben umgeht, die Ihre Nutzer stellen. Das sind zwei verschiedene Fragen, und sie liefern regelmäßig verschiedene Antworten.

Offline-EvalOnline-Eval
Wer hat die Eingabe geschrieben?SieEin echter Nutzer
Wann läuft es?Vor dem AusliefernDanach, auf echtem Verkehr
Kennen Sie die richtige Antwort?Ja, Sie haben sie aufgeschriebenNein
Hat ein Nutzer die Ausgabe schon gesehen?NeinJa

Die letzte Zeile ändert alles. Offline fangen Sie einen Fehler ab, bevor er jemanden trifft. Online zählen Sie Fehler, die schon passiert sind, um die nächsten zu verhindern. Nur offline können Sie eine Änderung prüfen, bevor Sie sie ausliefern. Nur online erfahren Sie, was Ihre Nutzer wirklich fragen. Und das ist nie ganz das, was Sie angenommen haben.

Dieses Kapitel sagt, was Sie dafür bauen: vier Dinge, in dieser Reihenfolge. Danach, was Sie tun, wenn Online und Offline sich widersprechen, und wie Sie Änderungen in Produktion vergleichen.

Guardrails und Evals sind nicht dasselbe

Ein Guardrail ist eine Prüfung zwischen Ihrem Modell und Ihrem Nutzer. Sie darf eine Antwort aufhalten. Verstößt die Antwort gegen eine Regel, bekommt der Nutzer sie nie zu sehen, sondern eine Ablehnung, eine umgeschriebene Fassung oder einen Menschen. Ein Online-Eval sieht denselben Verstoß und schreibt ihn auf. Der Nutzer bekommt die Antwort trotzdem.

Konkret: Ihr Modell entwirft eine Antwort, in der die vollständige Kreditkartennummer eines Kunden steht. Ein Guardrail erkennt das und blockiert die Nachricht. Ein Online-Eval erkennt es und zählt es. Dieselbe Erkennung, entgegengesetzte Aufgabe.

GuardrailOnline-Eval
LäuftBevor der Nutzer die Ausgabe siehtDanach, aus den gespeicherten Traces
Bei FehlerBlockiert, schreibt um oder leitet an einen Menschen weiterErfasst eine Zahl
LatenzbudgetInnerhalb der Anfrage, also einige Dutzend MillisekundenKeines
AbdeckungJede AnfrageEine Stichprobe
Optimiert aufPrecision: Eine falsche Blockade ist ein kaputtes ProduktRecall: Ein übersehener Fehler ist ein blinder Fleck

Ein Guardrail, das 2 % der legitimen Antworten blockiert, ist ein ernster Vorfall. Ein Judge, der 2 % der gezogenen Traces falsch labelt, ist ein Rundungsfehler. Bauen Sie beide als getrennte Komponenten mit getrennten Schwellwerten. Lassen Sie nie eine Prüfung, die zum Messen gebaut wurde, Verkehr blockieren, ohne sie vorher auf Precision neu abzustimmen.

Was Sie bauen: vier Dinge

  1. Traces, die sich abfragen lassen. Jeder Aufruf schreibt einen Datensatz mit festen Feldnamen.
  2. Billige Prüfungen auf jedem Trace. Dieselben Funktionen wie offline, jede Nacht über den ganzen Tag.
  3. Der Judge auf einer Stichprobe. Derselbe Judge wie offline, nachträglich, über einen kleinen Teil.
  4. Ein Wochenbericht, den ein Mensch liest. Zahlen mit Spanne, dazu 20 bis 30 Traces zum Lesen.

Die vier Abschnitte unten folgen diesem Raster: Was Sie tun, die Datei, was Sie sehen.

1. Traces speichern, die sich abfragen lassen

Was Sie tun. Bei jedem Aufruf Ihres Systems schreiben Sie eine Zeile in eine Trace-Datei oder Ihre Trace-Datenbank. Die Zeile enthält alles, was ein Judge oder ein Mensch später braucht, um die Antwort zu beurteilen. Das sind mindestens diese Felder:

FeldInhaltStandardname
trace_idEindeutige Kennung
timestampZeitpunkt
modelModell samt Versiongen_ai.request.model
inputDie Anfrage des Nutzersgen_ai.input.messages
retrievedWas die Suche geliefert hat, mit Kennung und Text
outputDie Antwortgen_ai.output.messages
tokens_in, tokens_outVerbrauchgen_ai.usage.input_tokens, gen_ai.usage.output_tokens
latency_msDauer
customerWas das System über den Nutzer wusste, etwa Tarif und Sprache
flagsWas Guardrails oder billige Prüfungen schon markiert haben
signalsWas der Nutzer danach tat: Daumen, neu generiert, eskaliert, Entwurf geändert

Die Spalte „Standardname“ verweist auf eine vereinbarte Liste von Feldnamen, damit jedes Werkzeug Ihre Traces lesen kann, nicht nur das, für das Sie sie geschrieben haben:

Befund: Dafür gibt es inzwischen einen herstellerneutralen Standard: die OpenTelemetry GenAI Semantic Conventions. Entwickelt hat sie die GenAI Special Interest Group. Diese Gruppe wurde im April 2024 unter der Semantic-Conventions-SIG gegründet und wird von der CNCF getragen. Der Standard definiert gen_ai.*-Span-Attribute: gen_ai.request.model, gen_ai.usage.input_tokens und gen_ai.usage.output_tokens, gen_ai.response.finish_reasons sowie die strukturierte Erfassung von Inhalten über gen_ai.input.messages / gen_ai.output.messages. Der Geltungsbereich ist gewachsen: von reinen LLM-Aufrufen auf Agenten-Orchestrierung, MCP-Tool-Aufrufe und Qualitätsbewertung. Umgesetzt wird der Standard unter anderem von Google Cloud, AWS, Azure und Datadog.

Das ist die wirkungsvollste Einzelentscheidung in der Produktions-Evaluation. Und sie ist gar keine Evaluationsentscheidung. Instrumentieren Sie nach dem Standard. Dann überleben Ihre Traces jede Eval-Plattform, für die Sie sich dieses Jahr entscheiden. Siehe Die Tooling-Landschaft zu den Ausstiegskosten.

Quelle: OpenTelemetry GenAI Semantic Conventions

Die Datei. Eine Zeile aus traces/2026-09-04.jsonl, für den Support-Assistenten aus dem Praxisbeispiel:

{"trace_id":"tr-88a1","timestamp":"2026-09-04T09:12:31+02:00","model":"<anbieter>/<modell>@2026-07-11","customer":{"plan":"pro","locale":"de"},"input":"Was kostet ein zusätzlicher Platz im Monat?","retrieved":[{"ref":"pricing#plans","text":"Starter: 39 € pro Platz und Monat. Pro: 45 € pro Platz und Monat."}],"output":"Ein zusätzlicher Platz kostet 45 € pro Monat [doc:pricing#plans].","tokens_in":2310,"tokens_out":41,"latency_ms":1840,"flags":[],"signals":{"escalated":false,"edit_distance":0.04}}

Die Felder customer, retrieved und output sind dieselben drei Dinge, die der Judge im Praxisbeispiel sieht. Deshalb kann derselbe Judge ohne Änderung über Produktions-Traces laufen.

Was Sie sehen. Noch nichts. Aber ab jetzt lässt sich jede Frage dieses Kapitels mit einer Abfrage über diese Datei beantworten.

2. Billige Prüfungen auf jedem Trace

Was Sie tun. Die deterministischen Prüfungen aus Ein Eval in fünf Dateien laufen jede Nacht über alle Traces des Tages. In Produktion gibt es keine erwartete Antwort, also fallen Prüfungen weg, die expect brauchen. Die Regelprüfungen bleiben:

  • Jede Quellenangabe verweist auf ein Dokument, das die Suche wirklich geliefert hat
  • Jeder Geldbetrag hat eine Quellenangabe
  • Die Ausgabe hält das Schema ein
  • Kein Stück des System-Prompts, kein Wettbewerbername, keine personenbezogenen Daten in der Antwort

Diese Prüfungen kosten nichts und laufen auf 100 % des Verkehrs.

Die Datei. Ein Skript, das die Prüfungen aus checks.py über die Traces des Tages laufen lässt und je Prüfung zählt:

# evals/online_checks.py
import json
import pathlib
import sys

from checks import CHECKS

ONLINE = ["zitate_loesen_auf", "keine_zahl_ohne_beleg"]      # Prüfungen ohne expect

tag = sys.argv[1]                                             # z. B. 2026-09-04
traces = [json.loads(z) for z in pathlib.Path(f"traces/{tag}.jsonl").read_text().splitlines()]
verstoesse = {name: 0 for name in ONLINE}

for trace in traces:
    for name in ONLINE:
        if not CHECKS[name](trace["output"], trace):
            verstoesse[name] += 1
            trace["flags"].append(name)

pathlib.Path(f"traces/{tag}.jsonl").write_text("".join(json.dumps(t, ensure_ascii=False) + "\n" for t in traces))
print(f"{tag}  {len(traces)} Traces")
for name, anzahl in verstoesse.items():
    print(f"  {name:24} {anzahl:5}  ({anzahl / len(traces):.1%})")

Die Prüfungen lesen trace["retrieved"], genau wie sie im Offline-Eval fall["retrieved"] lesen. Das ist der Grund, warum die Felder in Schritt 1 so heißen, wie sie heißen.

Was Sie sehen. Jede Nacht eine Zusammenfassung:

2026-09-04  3.412 Traces
  zitate_loesen_auf           31  (0.9%)
  keine_zahl_ohne_beleg       88  (2.6%)

Ein Trace mit Verstoß bekommt den Namen der Prüfung in flags, und die Datei wird mit diesen Markierungen zurückgeschrieben. Das ist die Markierung, die Schritt 3 benutzt.

Was der Nutzer danach tat, zählt in derselben Nacht mit. Diese Signale sind kostenlos, kommen in großer Menge und sind auf bekannte Weise verzerrt:

SignalLiest sich alsVorbehalt
Daumen runterUnzufriedenheitNicht dasselbe wie falsch; wird viel zu selten genutzt
Neu generieren / umformulierenDie Antwort kam nicht anKann auch Neugier sein
Kopieren oder exportierenDie Antwort war nützlichNur wo die Oberfläche das anbietet
Eskalation an einen MenschenAufgabe gescheitertDas sauberste Signal, das die meisten Produkte haben
Abbruch mitten in der SitzungEtwas ging schiefVermischt mit allem anderen
Änderungen am Entwurf vor dem VersandWie viel vom Entwurf brauchbar warNur wo ein Mensch dazwischensitzt; dort das beste Signal überhaupt

Die Eskalationsrate ist meist die ehrlichste Produktmetrik, die ein Support-Produkt hat. Sie braucht keine Labels.

3. Der Judge auf einer Stichprobe

Was Sie tun. Der Judge, den Sie offline gegen menschliche Labels gemessen haben, läuft jede Nacht über einen Teil der Traces. Nicht über alle, weil das zu teuer wäre. Nehmen Sie an, Sie haben täglich 100.000 Gespräche und lassen den Judge über 5 % davon laufen. Dann sind 5.000 bewertet und 95.000 nicht. Sie wissen weniger. Dafür bekommen Sie eine Rechnung, die Sie bezahlen können.

Welche Traces gezogen werden, entscheiden drei Regeln:

  • Eine Grundquote von 1 bis 10 %, zufällig gezogen. Sie liefert die unverzerrte Zahl für „wie gut sind wir insgesamt“.
  • Alle Traces mit einer Markierung in flags, zu 100 %. Die sind die interessanten.
  • Mehr aus den Ecken, die Sie beobachten wollen. Neue Funktionen, seltene Sprachen, lange Dialoge, wertvolle Kunden. Sind 2 % Ihres Verkehrs italienisch, liefert eine Zufallsstichprobe von 500 nur 10 italienische Gespräche. Das reicht für keinen Schluss. Ziehen Sie absichtlich 100. Halten Sie diese gezielt gezogenen Traces im Bericht getrennt von der Grundquote, sonst ist die Gesamtzahl weder das eine noch das andere.

Die 5 % oben sind ein Beispiel, keine Empfehlung. Es gibt keine Studie, die eine richtige Quote festlegt. Die Werkzeuge, die Produktions-Traces speichern, etwa Langfuse oder Braintrust aus der Tooling-Landschaft, sind alle nach diesem Muster voreingestellt, mit einer Grundquote von 1 bis 10 %. Ihre eigene Grundquote rechnen Sie aus, wie Statistik es zeigt: groß genug, um die Änderung zu sehen, bei der Sie handeln würden, und das je Teilmenge, die Sie beobachten. Dazu kommt eine Kontrolle des Judges selbst: 5 bis 10 % seiner Urteile bekommt ein Mensch noch einmal vorgelegt. So fällt auf, wenn der Judge in der Produktion schlechter wird als auf dem versiegelten Stapel.

Die Datei. Ein Skript, das die Stichprobe zieht und den Judge aus run.py aufruft:

# evals/online_judge.py
import json
import pathlib
import random
import sys

from run import judge

tag, judge_modell, judge_name = sys.argv[1], sys.argv[2], sys.argv[3]
GRUNDQUOTE = 0.05

traces = [json.loads(z) for z in pathlib.Path(f"traces/{tag}.jsonl").read_text().splitlines()]
random.seed(tag)
stichprobe = [t for t in traces if t["flags"] or random.random() < GRUNDQUOTE]

out = pathlib.Path(f"runs/online-{tag}.jsonl")
with out.open("w") as f:
    for trace in stichprobe:
        fall = {"judge": judge_name, "customer": trace["customer"], "retrieved": trace["retrieved"]}
        bestanden = judge(trace["output"], fall, judge_modell)
        f.write(json.dumps({"trace_id": trace["trace_id"], "flagged": bool(trace["flags"]), "passed": bestanden}) + "\n")

grund = [json.loads(z) for z in out.read_text().splitlines()]
grund = [r for r in grund if not r["flagged"]]
durchgefallen = sum(1 for r in grund if not r["passed"])
print(f"{tag}  Grundquote: {len(grund)} Traces, {durchgefallen} durchgefallen ({durchgefallen / max(len(grund), 1):.1%})")

Der Judge läuft nachträglich über gespeicherte Traces, nie zwischen Anfrage und Antwort. Dort würde er jede Antwort um seine volle Latenz verzögern, und seine Ausfälle wären Ihre Ausfälle. Was er kostet, rechnen Sie vorher aus: 5 % von 100.000 Gesprächen sind 5.000 Judge-Aufrufe am Tag. Bei den Zahlen des Praxisbeispiels, rund 3.000 Token je Aufruf, sind das grob 20 € am Tag. Ist das zu viel, senken Sie die Grundquote oder lassen einen kleineren Judge vorsortieren und den großen nur über das laufen, was der kleine markiert.

Was Sie sehen. Eine Zeile je Nacht, und eine Ergebnisdatei je Trace:

2026-09-04  Grundquote: 168 Traces, 13 durchgefallen (7.7%)

Das Praxisbeispiel zeigt an Tag 31, was diese Zahl wert ist: Dort fielen im Betrieb 8 % durch, im Eval-Set 2 %. Der Unterschied war die Nachricht.

4. Der Wochenbericht, und das Lesen

Was Sie tun. Einmal die Woche fassen Sie die Nächte zusammen und lesen 20 bis 30 Traces selbst: alle, die der Judge und eine Prüfung markiert haben, dazu einige aus der Grundquote. Das ist dieselbe Tätigkeit wie die Fehleranalyse von Tag 1, nur ohne Ende. Sie hält alles andere ehrlich, denn nur so bemerken Sie Fehlermodi, für die es noch keine Prüfung und keinen Judge gibt.

Die Datei. Der Bericht hat eine feste Form. Jede Zahl steht neben der Vorwoche und mit ihrer Spanne, denn eine Zahl allein sagt nicht, ob sich etwas bewegt hat:

Woche 36                       diese Woche      Vorwoche     Spanne
Traces                         23.910           22.480
zitate_loesen_auf              0.8 %            0.9 %        ±0.1
keine_zahl_ohne_beleg          2.4 %            2.7 %        ±0.2
Judge, Grundquote              7.1 %            7.9 %        ±1.5      (n = 1.180)
Judge, italienisch             14.0 %           n/a          ±6.8      (n = 100, gezielt gezogen)
Eskalationsrate                3.1 %            3.0 %        ±0.2
Entwurf geändert (Median)      6 %              6 %

Gelesen: 28 Traces. Neu aufgefallen: 3 × „Kunde fragt nach Kündigung, Assistent
antwortet mit Preisliste". Noch keine Prüfung dafür. In die Taxonomie aufgenommen.

Was Sie sehen, und was Sie damit tun. Drei Regeln, was einen Alarm auslöst und was in den Bericht gehört:

  • Alarm bei deterministischen Prüfungen. Steigen Schemafehler oder nicht auflösbare Quellenangaben sprunghaft, ist das ein echter Vorfall mit einer echten Ursache. Das darf jemanden aus dem Bett holen.
  • Alarm bei der Eskalationsrate. Sie ist eine Produktmetrik, kein Ersatzmaß. Steigt sie, hat sich für Nutzer etwas geändert.
  • Kein Alarm beim Judge-Wert. Fällt er eine Stunde lang unter einen Schwellwert, ist das Rauschen. Liegt der Sieben-Tage-Trend außerhalb der Spanne, gehört das in den Bericht. Der Wert des Judges in Produktion ist Diagnose, nicht Alarm.

Wenn Online und Offline sich widersprechen

Das ist der aufschlussreichste Moment. Der Offline-Wert ist gut, der Online-Wert nicht, oder umgekehrt. Prüfen Sie die fünf Ursachen in dieser Reihenfolge, denn die ersten sind die häufigsten und die leichtesten zu prüfen.

1. Ihr Eval-Set sieht nicht aus wie Ihr Verkehr. Prüfung: Ziehen Sie 50 Produktions-Traces und 50 Eval-Fälle, mischen Sie sie, und versuchen Sie, sie auseinanderzuhalten. Gelingt das leicht, haben Sie die Antwort. Abhilfe: 100 frische Traces lesen und das Set nachziehen, wie das Praxisbeispiel an Tag 31.

2. Das System ist nicht das, was Sie offline bewertet haben. Prüfung: Vergleichen Sie Modellversion, Prompt-Hash, Suchindex und Kontextaufbau zwischen Harness und Produktion. Häufige Täter: eine Middleware, die Prompts kürzt, ein Rate Limiter, der auf ein kleineres Modell ausweicht, ein Index, der offline älter ist als online.

3. Der Judge ist in Produktion schlechter. Er wurde auf sauberen Beispielen gemessen und sieht jetzt unordentlichere. Prüfung: die 5 bis 10 % Judge-Urteile, die ein Mensch nachprüft. Abhilfe: den Judge erneut messen, diesmal auf gelabelten Produktions-Traces.

4. Überanpassung an das Eval-Set. Monate der Iteration gegen dasselbe Set. Das Muster: Der Offline-Wert steigt, die Nutzersignale bleiben flach. Abhilfe steht in Evals in der CI.

5. Das Eval misst etwas, das Nutzern nicht mehr wichtig ist. Die Faithfulness stieg, die Nutzer wollten Vollständigkeit. Das ist das schwerste Versagen, denn jede beteiligte Zahl verhält sich korrekt. Prüfung: Lesen Sie die eskalierten Gespräche der Woche und fragen Sie, ob Ihr Kriterium den Grund der Eskalation überhaupt sieht.

Häufiger Fehler: Bei Widerspruch dem Offline-Ergebnis mehr trauen, weil es die kontrollierte Messung ist. Produktion ist per Definition die Wahrheit, an der Sie sich messen. Wenn beide auseinanderlaufen, ist das Offline-Eval das, was repariert werden muss.

Änderungen in Produktion vergleichen

A/B-Tests sind der Standard. Sie beantworten die Frage, die Sie tatsächlich haben: Hat diese Änderung das Ergebnis verändert, das Nutzer erleben? Drei Regeln: Teilen Sie die Nutzer pro Nutzer auf, nicht pro Anfrage, sonst wechselt ein Dialog mitten im Verlauf das System. Messen Sie die Produktmetrik, etwa die Eskalationsrate, nicht den Judge-Wert. Und rechnen Sie mit mehr Verkehr, als Sie erwarten, denn Produktmetriken sind verrauschter als Eval-Werte.

Interleaving ist die Alternative überall dort, wo der Nutzer aus einer Liste wählt. Ein A/B-Test zeigt der einen Hälfte Ihrer Nutzer die Ergebnisse von System A und der anderen Hälfte die von System B. Dann vergleicht er, wie oft jede Gruppe klickt. Das braucht viel Verkehr, denn die beiden Gruppen sind verschiedene Menschen mit verschiedenen Anliegen, und dieser Unterschied ist Rauschen. Interleaving zeigt stattdessen jedem Nutzer eine einzige Liste, in der die Ergebnisse beider Systeme gemischt sind: das erste von A, das erste von B, das zweite von A und so weiter. Gezählt wird, wessen Ergebnisse angeklickt werden. Jeder Nutzer vergleicht beide Systeme bei derselben Anfrage. Darum zeigt sich ein echter Unterschied mit weit weniger Nutzern.

Befund: Interleaving wurde in großem Maßstab validiert, von Chapelle, Joachims, Radlinski und Yue (TOIS, 2012). Die Studie umfasste zwei kommerzielle Suchmaschinen und ein Retrieval-System für wissenschaftliche Literatur. Die Zahl zur Empfindlichkeit, die üblicherweise dazu zitiert wird, stammt aus Radlinski und Craswell, Optimized interleaving for online retrieval evaluation (WSDM 2013). Über 38 großangelegte Online-Experimente und mehr als 3 Milliarden Klicks hielt optimiertes Interleaving eine Empfindlichkeit ein bis zwei Größenordnungen über A/B-Tests. Zugleich stieg die Übereinstimmung mit A/B-Metriken um bis zu 22 %.

Die belastbare Form ist „one to two orders of magnitude“, also ein bis zwei Größenordnungen. Das griffigere „10–100ד, das Ihnen begegnen wird, ist eine Rundung dieses Ergebnisses. Es ist keine unabhängige Bestätigung.

Quelle: Chapelle et al., TOIS 2012 · Radlinski & Craswell, WSDM 2013

Ein bis zwei Größenordnungen heißt: dieselbe Aussage mit zehn- bis hundertmal weniger Verkehr. Der Haken: Es funktioniert nur, wo der Nutzer aus einer Liste wählt. Suchergebnisse, Empfehlungen, die Dokumente, die ein RAG-System findet. Eine Chat-Antwort ist keine Liste. Die Suche eines RAG-Systems liefert aber genau so eine Liste. Dort wird Interleaving zu selten genutzt.

Shadow-Betrieb. Das neue System läuft auf echtem Verkehr mit, ohne dass Nutzer seine Antworten sehen. Sie speichern beide Antworten und vergleichen sie offline, mit denselben Prüfungen und demselben Judge wie oben. Kein Risiko für Nutzer, und die echte Verteilung der Anfragen. Das ist die beste Brücke zwischen beiden Welten. Nur eine Reaktion der Nutzer kann es nicht messen.

Umgang mit den Daten

Produktions-Traces enthalten Nutzerinhalte. Sie für die Evaluation zu ziehen ist ein Verarbeitungszweck. Der braucht eine Rechtsgrundlage, eine Aufbewahrungsfrist und eine Antwort auf die Frage, wer sie lesen darf. Nach DSGVO ist „wir behalten alles für immer, um das Modell zu verbessern“ keine solche Antwort.

Die praktische Form: Pseudonymisieren Sie beim Schreiben der Trace-Zeile. Behalten Sie Roh-Traces nur kurz. Bewahren Sie abgeleitete Labels und Kennzahlen länger auf. Trennen Sie die Oberfläche, in der Menschen Traces lesen, vom allgemeinen Zugriff auf Logs. Entscheiden Sie das, bevor Sie Schritt 4 bauen. Die Aufbewahrungsfrist bestimmt, was der Bericht zeigen darf. Sie nachträglich einzubauen ist viel schwerer, als von Anfang an dafür zu entwerfen.