Startseite / Artikel

Bewertungen für GenAI und Agenten: Einzel-Schritt- versus Mehr-Schritt-Testing in CI

Vergleichen Sie trace-basierte Ein-Schritt-Bewertungen mit simulatorgesteuerten Mehr-Schritt-Bewertungen und berücksichtigen Sie dabei Goldens, LLM-Judys, Agentenmetriken, CI-Gates sowie sieben Arbeitspraktiken.

Verlag: REACTAPP.TOP8 Min. Lesezeit1800 Wörter

Quellen: End-to-End Evals for Gen AI and Agentic AI: A Practitioner’s Guide to Single-Turn and Multi-Turn Evaluation

„Es funktioniert bei meinem Prompt“ ist kein ingenieurtechnisches Standard. Ein herkömmlicher Unit-Test bestätigt sich entweder eindeutig oder nicht, während generative Systeme offene, probabilistische Antworten liefern. Ein RAG-Pipeline kann größtenteils richtig sein, und ein Agent kann eine Aufgabe auf eine Weise abschließen, die auf dem Papier als Erfolg gilt, in der Praxis jedoch unsicher ist. Deshalb bilden Bewertungen, im Gegensatz zu Bauchgefühl oder einem Chatkanal voller Aussagen wie „Mir scheint alles in Ordnung zu sein“, heute die Grundlage für seriöse ML-Entwicklung im Bereich Generative KI und Agentensysteme. Im Folgenden wird erläutert, was gemessen werden sollte, wie sich Einzel- und Mehrschritt-Bewertungen unterscheiden, welche Kompromisse damit verbunden sind sowie Python-Muster, die in eine CI-Pipeline passen.

Warum Bewertungen nicht optional sind

Drei Eigenschaften von LLM-Anwendungen machen sie notwendig:

  1. Nichtdeterminismus. Identische Anfragen können bei verschiedenen Ausführungen, Modellversionen oder Temperaturwerten unterschiedliche Ergebnisse liefern.
  2. Kumulative Fehler bei Agenten. Während ein einfacher Chatbot nur eine Chance hat, falsch zu liegen, kombiniert ein Agent zwischen 10 und 50 Modellaufrufe, Toolaufrufe sowie Entscheidungen miteinander. Eine geringe Fehlerquote pro Schritt führt so zu häufigen Fehlern im gesamten Ablauf.
  3. Stille Regressionen. Eine kleine Anpassung der Anfrage, ein Modulupdate oder eine Neindeckung des Vektorstores kann die Qualität verschlechtern, ohne dass ein Ausnahmefall ausgelöst wird.

Durch eine Bewertung wird „es fühlt sich besser an“ in eine Zahl umgewandelt, die im Laufe der Zeit verfolgt werden kann, zur Steuerung von Deployments genutzt sowie zwischen verschiedenen Versionen verglichen wird.

Zwei Formen der Bewertung

Nahezu jedes Framework, darunter DeepEval, Ragas, LangSmith, Braintrust und OpenAI Evals, folgt letztendlich einem von zwei Mustern.

Einzugangsschleife, trace-basiert

Die Schleife ist einfach: Nehmen Sie jeden Fall, rufen Sie die Anwendung einmal auf und bewerten Sie den Trace.

Open a test run with trace-level metrics
  for each golden:
    yield golden
    call app with golden.input
    capture trace
    build a test case from the trace
    score test case with metrics
  upload test run (traces + scores)

Ein golden ist ein beschriftetes Beispiel: die Eingabe, die Antwort, die es liefern soll, sowie oft der Kontext oder die Tool-Aufrufe, die berücksichtigt werden müssen. Der Trace dokumentiert die gesamte Vorgangsabfolge einer Ausführung – einschließlich der abgerufenen Teile, der verwendeten Tools, der dazwischenliegenden Überlegungen, der Latenzzeit und der Token-Zahlen – und nicht nur den Endtext. Die Bewertung dieses Protokolls anstelle der bloßen Antwort zeigt die fehlerhafte Stufe auf: Die Datenerfassung, die Generierung oder ein Tool-Aufruf unterwegs?

Mehrfachschritte, simulationsbasiert

Das ist das schwierigere und realistischere Muster für Agenten und Chat-Assistenten.

def simulate(conversational goldens)
  for each golden:
    loop until expected outcome OR max turns:
      simulator model generates a user turn
      ask app for next reply
      capture assistant turn
    build a ConversationalTestCase from the full transcript
  evaluate(test cases, metrics)   # metrics run concurrently
    -> pass/fail + reason per metric

Es gibt hier kein festes Eingabepaar und Ausgabepaar. Ein Simulationsmodell spielt die Rolle eines Benutzers mit einem Ziel, wie zum Beispiel die Kündigung eines Abonnements oder die Rückerstattung für eine bestimmte Bestellung, und passt jede Nachricht an die Antworten des Assistenten an – genauso wie es ein Mensch tun würde. Das System wird anhand der gesamten Vorgehensweise beurteilt: Bleibt es beim Thema? Wird es die Tools über die verschiedenen Schritte hinweg richtig einsetzen? Löst es am Ende das Ziel? Erfindet es bereits nach drei Schritten Details zu den Richtlinien?

Agenten, mehrschrittige Assistenten sowie alles, was über Gedächtnis oder Zustände verfügt, benötigen diesen Ansatz. Eine Bewertung nach nur einem Schritt kann nicht erkennen, ob ein Agent sich im vierten Schritt widerspricht oder in einer Schleife fünfmal denselben Tool aufruft.

Messgrößen auswählen

Messgrößen lassen sich in vier Gruppen einteilen, und es ist ratsam, sie zu mischen – schließlich gibt keine einzige die vollständige Geschichte wieder.

Ein nützliches mentales Modell: Einzelturn-Metriken liefern einen Momentaufnahme-Bewertung, während agierende Metriken eine Entwicklungslinie bewerten.

LLM als Richter

Die meisten heutigen metriken ohne Referenzdaten arbeiten nach dem Prinzip „LLM als Richter“. Ein leistungsstarkes Modell – oft ein anderes und leistungsfähigeres als das getestete Modell – bewertet eine Ausgabe anhand eines Bewertungskriteriums und erklärt seine Punktzahl.

from dataclasses import dataclass

JUDGE_PROMPT = """
You are evaluating an AI assistant's response for FAITHFULNESS.
A response is faithful if every factual claim it makes is supported
by the provided context. It is unfaithful if it adds unsupported
claims, contradicts the context, or fabricates details.
Context:
{context}
Response:
{response}
Return JSON: {{"score": <0.0-1.0>, "reason": "<short explanation>"}}
"""

@dataclass
class TestCase:
    input: str
    actual_output: str
    retrieval_context: list[str]

def faithfulness_metric(test_case: TestCase, judge_llm) -> dict:
    prompt = JUDGE_PROMPT.format(
        context="\n".join(test_case.retrieval_context),
        response=test_case.actual_output,
    )
    result = judge_llm.generate(prompt, response_format="json")
    return {"score": result["score"], "reason": result["reason"], "passed": result["score"] >= 0.7}

Bei den Bewertern gibt es Fallstricke:

  • Selbstpräferenzbias. Modelle bewerten ihre eigenen Ausgaben oder solche in ihrem eigenen Stil gnädiger. Nutzen Sie bei Möglichkeit einen Bewerter aus einer anderen Modellfamilie.
  • Sensitivität gegenüber Anfragen.Kleine Änderungen in der Formulierung der Bewertungskriterien beeinflussen die Punktzahlen. Halten Sie die Anfragen an die Bewerter wie Code unter Versionskontrolle.
  • Kosten und Latenz.Auch die Nutzung von Bewertern kostet Geld. Bei knappen Budgets testen Sie den Produktionsverkehr mit Beispielen, anstatt alles zu bewerten.
  • Positionierungs- und Ausführlichkeitbias.Bewertende neigen dazu, längere, selbstsicherere Antworten zu geben – unabhängig davon, ob sie richtig sind. Kalibrieren Sie gelegentlich anhand einer kleinen Menge von von Menschen beschrifteten Beispielen.

Einzugangsbewertung in der Praxis

Ein ideales Datensatz kann bereits aus einer Liste von Wörterbüchern bestehen, die eine Eingabe sowie eine erwartete Ausgabe enthalten.

goldens = [
    {
        "input": "What's our refund policy for digital products?",
        "expected_output": "Digital products are refundable within 14 days if unused.",
        "expected_tools": [],
    },
    {
        "input": "Cancel order #48213",
        "expected_output": None,  # open-ended, judged not matched
        "expected_tools": ["lookup_order", "cancel_order"],
    },
]

Der Ausführende befolgt den oben beschriebenen Ablauf: Er startet einen Testlauf, durchläuft jede „goldene“ Testfall-Konfiguration, ruft die App auf, erfasst den Ablaufverlauf, bewertet ihn und lädt ihn hoch.

from deepeval import evaluate
from deepeval.metrics import FaithfulnessMetric, AnswerRelevancyMetric
from deepeval.test_case import LLMTestCase

def run_eval_suite(goldens, app_callback, metrics):
    test_cases = []
    for golden in goldens:
        trace = app_callback(golden["input"])   # your traced LLM/RAG app
        test_case = LLMTestCase(
            input=golden["input"],
            actual_output=trace.final_output,
            retrieval_context=trace.retrieved_chunks,
            expected_output=golden.get("expected_output"),
        )
        test_cases.append(test_case)
    results = evaluate(test_cases, metrics)  # runs metrics concurrently
    return results
metrics = [FaithfulnessMetric(threshold=0.7), AnswerRelevancyMetric(threshold=0.7)]
results = run_eval_suite(goldens, my_rag_app, metrics)

Eine Aussage wandelt die Werte in eine Schleuse um.

def assert_eval_gate(results, min_pass_rate=0.9):
    passed = sum(1 for r in results if r.success)
    pass_rate = passed / len(results)
    assert pass_rate >= min_pass_rate, f"Eval pass rate {pass_rate:.2%}
    below gate {min_pass_rate:.0%}"

Binden Sie es in den PR-Pipeline ein, genauso wie pytest eingebunden ist. Wenn eine Änderung bei der Anfrage oder beim Abrufen die Genauigkeit unter den Schwellenwert senkt, sollte der Merge blockiert werden und nichts unbemerkt veröffentlicht werden.

Mehrfachgespräche in der Praxis

Anstelle einer festen Eingabe erhält der Simulator ein Benutzerprofil und ein Ziel, mit dem er das Gespräch lenkt.

class ConversationSimulator:
    def __init__(self, simulator_model, max_turns=8):
        self.simulator_model = simulator_model
        self.max_turns = max_turns

    def simulate(self, golden, chatbot_callback):
        transcript = []
        user_turn = self.simulator_model.generate_opening(golden["scenario"])
        for _ in range(self.max_turns):
            transcript.append({"role": "user", "content": user_turn})
            assistant_turn = chatbot_callback(transcript)
            transcript.append({"role": "assistant", "content": assistant_turn})
            if self.simulator_model.is_goal_met(golden["expected_outcome"], transcript):
                break
            user_turn = self.simulator_model.generate_next_turn(transcript, golden)
        return transcript

Das entstehende Gespräch wird anschließend mit agierenden Metriken bewertet.

from deepeval.test_case import ConversationalTestCase, Turn
from deepeval.metrics import (
    TaskCompletionMetric,
    ToolCorrectnessMetric,
    ConversationCompletenessMetric,
)

def build_conversational_test_case(transcript, tools_called):
    turns = [Turn(role=t["role"], content=t["content"]) for t in transcript]
    return ConversationalTestCase(turns=turns, tools_called=tools_called)
    metrics = [
    TaskCompletionMetric(threshold=0.8),          # did it accomplish the user's goal?
    ToolCorrectnessMetric(threshold=1.0),          # right tools, right args, right order
    ConversationCompletenessMetric(threshold=0.7), # did it address everything raised?
    ]
    test_case = build_conversational_test_case(transcript, tools_called=agent_trace.tool_calls)
    result = evaluate([test_case], metrics)

Typische Überprüfungen auf Agentenebene umfassen:

  • Richtigkeit der Tool-Aufrufe: das richtige Tool mit den richtigen Argumenten in der richtigen Reihenfolge – mehr als nur „ein Tool wurde aufgerufen“.
  • Effizienz der Schritte und Erkennung von Schleifen: wiederholte Aufrufe desselben Tools ohne Fortschritt.
  • Befolgung von Rolle und Richtlinien: Beibehaltung der definierten Persona sowie Grenzen während des gesamten Gesprächs, nicht nur im ersten Schritt.
  • Fehlerbehebung: sinnvoller Neuanlauf nach einem fehlgeschlagenen Tool-Aufruf anstelle eines erfundenen Ergebnisses.
  • Weitergabe des Kontexts: sich daran erinnern, was der Benutzer drei Schritte zuvor gesagt hat.

Abschätzung der Abwägungen

Einzelschritt Mehrschritt
Kosten Ein Aufruf pro Schritt – günstig und schnell
Jeder Durchlauf ist ein mehrfach aufrufbares Gespräch, das durch Turns und Metriken erweitert wird Datensatz Große „goldene“ Datensätze sind einfach verfügbar, sei es aus Logs oder durch synthetische Erzeugung Simulatoren erreichen Randfälle sowie feindselige Benutzer, die niemand manuell programmieren würde Signal Trennt sauber Fehler bei der Informationsabrufung von Fehlern bei der Erzeugung und ist nahezu deterministisch für die CI-Prüfung Fängt sich kumulative Fehler ein, die zu echten Vorfällen führen, und testet das gesamte System einschließlich Tools, Orchestrierung, Zustand und Schutzmechanismen Schwachstellen Überseht Drift, Widersprüche und Gedächtnisverlust über die Turns hinweg sowie führt zu Overfitting am „goldenen“ Datensatz Höhere Varianz, da der Simulator Zufälligkeit hinzufügt; schwierigeres Debuggen, weil ein Fehler im Turn 6 bereits im Turn 2 beginnen kann, und die Bewertung wird durch lange Transkripte erschwert

Weil die Ergebnisse mehrerer Schritte rauschig sind, sollten sie statistisch interpretiert werden. Führen Sie den gesamten Prozess N Mal aus und betrachten Sie die Verteilungen, anstatt sich auf eine einzige Bewertung zu konzentrieren.

Praktiken, die halten

  1. Fangen Sie mit einer kleinen, sauberen „Gold-Gruppe“ von 30 bis 100 Beispielen an. Eine rauschige Gruppe von 1.000 Beispielen ist schlimmer als eine ordentliche Gruppe von 50, da fehlerhafte Etiketten das Signal verfälschen.
  2. Bewerten Sie im RAG-Verfahren das Abrufen und Erzeugen von Inhalten getrennt voneinander. Treue gegenüber dem Originaltext und das Erinnern an den Kontext beantworten unterschiedliche Fragen – ihre Kombination verdeckt den wahren Problembereich.
  3. Bewerten Sie mit einem stärkeren, unabhängigen Modell und überprüfen Sie gelegentlich dessen Ergebnisse anhand menschlicher Bewertungen. Schon 20 bis 30 Beispiele pro Monat können eine Abweichung in der Bewertung aufzeigen.
  • Verfolgen Sie alles nachvollziehbar. Bewerten Sie die aus den erfassten Spuren gewonnenen Daten (heruntergeladene Dokumente, Toolaufrufe, Zwischenschritte) – und nicht nur den endgültigen Text. Deshalb erfolgt die Erfassung der Spuren vor dem Erstellen des Testfalls.
  • Simulieren Sie Agenten vor dem Einsatz. Führen Sie Gespräche mit realistischen Personas sowie unter adversären Bedingungen durch, wie zum Beispiel ein wütender Benutzer, eine unklare Anfrage oder ein Randfall in der Richtlinie – und zwar vor dem Veröffentlichen, nicht erst nach einem Incident.
  • Betrachten Sie die Bewertungen als lebendige Ressourcen. Führen Sie den gesamten Testumfang nach jeder Änderung der Anfragen, jedem Modulupdate oder jeder Neubildung des Index wieder durch und legen Sie in den CI-Prozessen Schwellenwerte für die Bestehensrate fest, ähnlich wie bei den Abdeckungsprozentsätzen.
  • Achten Sie auf die Entwicklung im Laufe der Zeit. Ein einziger Bewertungsvorgang ist nur eine Stichprobe, keine absolute Wahrheit. Wiederholen Sie wichtige Testserien und verfolgen Sie die Trends.
  • Die Schlussfolgerung

    Die Bewertung generativer KI begann als Randnotiz, als eine Zelle in einem Notizbuch, die vor einer Demonstration ausgeführt wurde. Agentenbasierte Systeme haben das bereits übertroffen. Sobald Software mehrfach handeln kann, Tools aufrufen und den Zustand von Runde zu Runde beibehalten kann, ist die Bewertung nicht mehr nur Qualitätskontrolle – sie ist das wichtigste Instrument, um das tatsächliche Verhalten des Systems zu erfassen.

    evals, die auf der Nachverfolgung von Abläufen basieren und nur eine Runde umfassen, liefern schnelle, kostengünstige Prüfungen der Ausgabequalität. evals, die durch Simulatoren gesteuert werden und mehrere Runden umfassen, liefern die zuverlässigste Einschätzung dafür, ob ein Agent im gesamten Interaktionsverlauf wie vorgesehen handelt – und für die meisten produktiven Agenten ist genau diese Einschätzung am wichtigsten. Entwickeln Sie beide Arten von evals und automatisieren Sie sie. Vertrauen Sie keiner von ihnen blind und lassen Sie immer einen Menschen die Ergebnisse überprüfen.