Fehleranalyse und Golden Set

Track KI · M3 Evaluation, Bausteine 01 und 02 · ca. 50 Min.

Worum es geht

Du hast in M2 ein RAG-System gebaut und merkst: manche Antworten sind schlecht. Der Reflex ist, am Prompt zu schrauben. Das ist der häufigste Fehler beim Verbessern einer LLM-Anwendung (Quelle). Besser: erst zählen, welche Art von Fehler überwiegt (Fehleranalyse, error analysis), dann einen festen Satz Testfälle bauen (Golden Set), an dem du jede Änderung misst. Das ist M3 im Lernplan (Evaluation und Guardrails). Die Quelle nennt es das beste Aufwand-Marktwert-Verhältnis im Plan: Nach M3 reicht es für ein erstes verkaufbares Format (“LLM Eval Audit”).

In dieser Lektion läuft kein echtes LLM. Die Fälle sind kleine Listen von Beobachtungen, die du von Hand gelesen hättest. Alle Fälle in dieser Lektion sind erfunden, um die Technik zu zeigen. In deinem Projekt (Projektaufgabe in Teil b) nimmst du echte Antworten, denn die Quelle verlangt ausdrücklich echte, nicht erfundene.

Zur Orientierung: “(Quelle)” im Text meint das Kursbuch quellen/kursbuch-lerninhalte.md. Zeitplan: etwa 20 Minuten Lesen und 30 Minuten für die vier Übungen, zusammen rund 50 Minuten. Die Metriken (Accuracy, Precision, Recall, Recall@k, MRR) und die Projektaufgabe folgen in Teil b.

Was du am Ende dieses Teils kannst:

  • Fehler in wenige Kategorien einsortieren, zählen und die häufigste bestimmen
  • ein Golden Set als Datenstruktur bauen und auf Lücken prüfen
  • erklären, warum ein Set aus einfachen Fällen oder aus Prompt-Beispielen lügt

Von JS/TS her gedacht

Idee JS/TS Python
Häufigkeiten zählen arr.reduce((m, k) => ({...m, [k]: (m[k] ?? 0) + 1}), {}) Counter(kategorien)
Nach Häufigkeit sortieren Object.entries(m).sort((a, b) => b[1] - a[1]) zaehler.most_common()
Schema mit Zod z.object({ frage: z.string() }) class Fall(BaseModel): frage: str
Nur bestimmte Texte erlaubt z.enum(["typisch", "randfall"]) Literal["typisch", "randfall"]
String oder null string \| null str \| None

Konzept

Schritt 1: Fehler lesen und in Kategorien sortieren

Die Quelle sagt: 20 bis 50 echte Antworten des Systems durchlesen, jeden Fehler in eine kurze, wiederverwendbare Kategorie einsortieren. Beispiele aus der Quelle: “falscher Chunk gefunden”, “Chunk gefunden, aber falsch zitiert”, “Halluzination trotz korrektem Chunk”, “Format falsch”. Die Übung der Quelle verlangt höchstens 5 selbst gewählte Kategorien.

Damit du das üben kannst, halten wir pro Antwort vier Beobachtungen fest (ja oder nein): Wurde der richtige Chunk gefunden? Stimmt die Aussage der Antwort? Stimmt das Zitat? Stimmt das Format? Daraus ergibt sich die Kategorie, und zwar in dieser Reihenfolge: Ist schon der Chunk falsch, sind die übrigen Mängel meist Folgefehler, also zählt zuerst der Chunk.

Lies die Liste einmal durch. Fall 4 hat sowohl einen falschen Chunk als auch eine falsche Aussage: Er landet wegen der Reihenfolge bei falscher_chunk. Zwei Fälle (3 und 10) sind in Ordnung und haben None.

Schritt 2: Zählen, dann entscheiden

Jetzt zählen. Counter macht aus einer Liste eine Häufigkeitstabelle, most_common() sortiert absteigend. Wichtig: None (kein Fehler) darf nicht mitgezählt werden, sonst könnte “kein Fehler” die häufigste “Kategorie” sein.

Ergebnis: falscher_chunk 5 mal, falsch_zitiert 3 mal, halluzination und format je 1 mal. Der spektakulärste Fall war Fall 1 (die Halluzination). Aber sie kam nur einmal vor. Der Merksatz der Quelle: Häufigkeit vor Dramatik. Hier liegt der größte Hebel im Retrieval (Chunking, Suche, Reranking aus M2), nicht im Sprachmodell oder im Prompt. Die Quelle sagt dazu: Oft ist es Retrieval, nicht das Sprachmodell selbst.

Eine Einschränkung, die du kennen solltest: Mit 12 Fällen ist die Zahl grob. Sie zeigt eine Richtung, keinen Beweis. Darum verlangt die Quelle 20 bis 50 Fälle.

Schritt 3: Das Golden Set als Datenstruktur

Ein Golden Set ist ein fester Satz Fragen mit bekannt richtiger Antwort. Ohne ihn lässt sich “besser geworden” nie zuverlässig behaupten, weil du Änderungen sonst nur an den zwei, drei Beispielen prüfst, an die du gerade denkst (Quelle). Die Quelle zeigt ein Pydantic-Modell mit frage, erwartete_quelle und erwartete_kernaussage. Wir ergänzen ein Feld art, damit wir später zählen können, wie viele Randfälle drin sind (das Feld ist eine Ergänzung dieser Lektion, nicht aus der Quelle).

Zwei Entscheidungen stecken darin. Erstens str | None ohne Default: Wer einen Fall anlegt, muss ausdrücklich None hinschreiben, wenn es keine Antwort gibt. Ein vergessenes Feld wird damit zum Fehler statt zu einem stillen “keine Antwort”. Zweitens Literal: Ein Tippfehler wie "randfal" wird abgelehnt.

Was die Quelle über den Inhalt eines guten Golden Sets sagt: Es mischt typische Fragen mit bewusst schwierigen Randfällen. Die Quelle nennt drei Arten: mehrdeutige Frage, Frage ohne Antwort im Korpus, Frage mit veralteter erwarteter Antwort. Es wächst mit jedem echten Fehler aus der Fehleranalyse, der es wert war, festgehalten zu werden. Die Zielgröße der Quelle: 20 Fälle (15 typische, 5 Randfälle, davon mindestens eine Frage ohne Antwort im Korpus). Im Code-Beispiel der Quelle steht dazu der Kommentar “20-40 weitere”, das Set soll also über die 20 Übungsfälle hinaus wachsen.

Falle

Falle 1: Sofort am Prompt schrauben. Ohne Fehleranalyse optimierst du gegen ein Gefühl statt gegen echte Fälle (Quelle). Zuerst zählen, dann den Hebel wählen.

Falle 2: Dramatik statt Häufigkeit. Die eine spektakuläre Halluzination bleibt im Kopf, die drei unscheinbaren falschen Zitate nicht. Eine Kategorie, die dreimal auftaucht, ist wichtiger als eine, die einmal spektakulär auffällt (Quelle).

Falle 3: Ein Golden Set nur aus einfachen Fällen. Es zeigt eine Erfolgsquote, die in der Praxis nie erreicht wird. Randfälle gehören von Anfang an rein, nicht erst wenn sie live aufgefallen sind (Quelle).

Falle 4: Ein Golden Set, das zu klein ist. Die Rechnung dazu ist einfach. Eine einzelne Frage verschiebt die Quote bei 5 Fällen um 20 Prozentpunkte, bei 40 Fällen um 2.5:

Eine feste Mindestgröße nennt die Quelle nicht, nur 20 Fälle als Übungsziel. Eine “ab N sicher”-Regel gibt es hier nicht (bitte prüfen, falls du eine brauchst, und sie bei deinem Kunden mit Zahlen begründen).

Falle 5: Golden Set aus Prompt-Daten (über die Quelle hinaus, allgemeines Fachwissen). Stehen deine Testfragen als Beispiele im Prompt (few-shot) oder wurden daran Regeln angepasst, misst du Auswendiglernen. Bei einem Test gilt: Der Prüfstoff darf nicht der Übungsstoff sein.

Übungen

Übung 1: Selbst schreiben (mittel, ca. 10 Min.)

kategorie, fall und Counter stehen dir zur Verfügung (Schritt 1). Schreibe haeufigste_fehlerkategorie(faelle). Sie gibt (kategorie, anzahl) der häufigsten Fehlerkategorie zurück. Regeln:

  • Fälle ohne Fehler (kategorie(fall) ist None) zählen nicht mit.
  • Bei Gleichstand gewinnt die Kategorie, die alphabetisch zuerst kommt.
  • Gibt es keinen einzigen Fehler (auch bei leerer Liste), kommt None zurück.

Baue zuerst die Kategorienliste ohne die None-Einträge. Wenn sie leer ist, bist du fertig. Überlege, wie du bei Gleichstand eindeutig entscheidest. Ein Sortierschlüssel muss nicht aus einem einzigen Wert bestehen.

def haeufigste_fehlerkategorie(faelle):
    zaehler = Counter(k for k in map(kategorie, faelle) if k is not None)
    if not zaehler:
        return None
    return min(zaehler.items(), key=lambda kv: (-kv[1], kv[0]))
haeufigste_fehlerkategorie

Übung 2: Modell bauen (mittel, ca. 8 Min.)

Ergänze das Pydantic-Modell TestFall (Schritt 3), diesmal mit einem zusätzlichen Feld: erwartete_quelle ist ein Text oder None und muss immer angegeben werden (kein Default). art darf nur "typisch" oder "randfall" sein. Neu ist erwartete_seite: die Seite in der Quelle als ganze Zahl oder None (wenn es keine einzelne Seite gibt). Auch erwartete_seite muss immer angegeben werden, ein vergessenes Feld soll ein Fehler sein. Literal und BaseModel stehen dir zur Verfügung.

Ein Feld ohne = ... ist Pflicht, auch wenn sein Typ None erlaubt. Für “nur diese Texte” gibt es einen Typ, der die erlaubten Werte aufzählt, ähnlich z.enum in zod. Für erwartete_seite gilt dasselbe Muster wie für die Quelle, nur mit einem anderen Grundtyp.

class TestFall(BaseModel):
    frage: str
    erwartete_quelle: str | None
    erwartete_kernaussage: str
    art: Literal["typisch", "randfall"]
    erwartete_seite: int | None
TestFall

Übung 3: Golden Set auf Lücken prüfen (leicht bis mittel, ca. 8 Min.)

TestFall (mit art) steht dir zur Verfügung. Schreibe golden_set_probleme(faelle) für eine Liste von TestFall-Objekten. Sie gibt eine alphabetisch sortierte Liste von Problem-Codes zurück (leer, wenn alles passt). Die Regeln folgen der Übung der Quelle (20 Fälle, 5 Randfälle, mindestens eine Frage ohne Antwort):

  • "zu_klein": weniger als 20 Fälle insgesamt
  • "zu_wenige_randfaelle": weniger als 5 Fälle mit art == "randfall"
  • "keine_frage_ohne_antwort": kein einziger Fall mit erwartete_quelle is None

Drei unabhängige Prüfungen, jede hängt bei Bedarf einen Code an die Liste. Ein Fall mit erwartete_quelle=None ist nicht automatisch ein Randfall im Sinne des Feldes art: Zähle beides getrennt.

def golden_set_probleme(faelle):
    probleme = []
    if len(faelle) < 20:
        probleme.append("zu_klein")
    if sum(1 for f in faelle if f.art == "randfall") < 5:
        probleme.append("zu_wenige_randfaelle")
    if not any(f.erwartete_quelle is None for f in faelle):
        probleme.append("keine_frage_ohne_antwort")
    return sorted(probleme)
golden_set_probleme

Übung 4: Multiple Choice mit Begründung (leicht bis mittel, ca. 7 Min.)

Ein Team misst seinen RAG-Assistenten mit einem Golden Set aus 30 Fällen. Alle 30 Fragen sind leicht umformulierte Beispielfragen, die auch im Prompt als Beispiele stehen, und alle haben einen eindeutigen Treffer im Korpus. Die Messung zeigt 97 Prozent korrekte Antworten, im Betrieb beschweren sich Nutzer häufig. Was ist die wahrscheinlichste Erklärung und der beste nächste Schritt?

  • a) Das Modell ist zu schwach: sofort auf ein größeres Modell wechseln und mit demselben Set neu messen.
  • b) 30 Fälle sind zu wenig: dieselben Fragen in zehn weiteren Formulierungen vervielfachen, bis es mehr sind.
  • c) Die Bewertung ist zu streng: das Prüfkriterium so lange lockern, bis die Zahl zu den Beschwerden passt.
  • d) Das Set ist zu leicht und teilt Fälle mit dem Prompt: echte Fragen und Randfälle ergänzen.

Trage den Buchstaben als String ein.

Zwei Beobachtungen widersprechen sich: ein sehr gutes Messergebnis und viele Beschwerden. Frag dich, woher die Testfragen stammen und ob sie die Fragen der echten Nutzer abbilden.

antwort = "d"
antwort

Merksatz

Erst zählen, dann verbessern: Die häufigste Fehlerkategorie schlägt den spektakulärsten Fehler, und nur ein festes Golden Set mit Randfällen, das nicht aus dem Prompt stammt, macht “besser geworden” belegbar.

Prüfstein

Dein Kollege sagt: “Ich habe den Prompt umgeschrieben, die Antworten wirken jetzt besser, drei Beispiele haben es gezeigt.” Nenne drei Dinge, die du ihm vorschlägst, bevor ihr den Prompt-Wechsel übernehmt, und begründe jedes mit einem Ergebnis dieser Lektion.

Weiter geht es mit Teil b: Metriken.


Quelle: quellen/kursbuch-lerninhalte.md, Modul M3, Bausteine “01 Fehleranalyse kommt vor Verbesserung” und “02 Testdatensätze (Golden Set)” (Zeilen 611 bis 655). Aus der Quelle stammen: Fehleranalyse vor Verbesserung, 20 bis 50 echte Antworten, kurze Kategorien (die vier Beispielkategorien), Häufigkeit vor Dramatik, “oft ist es Retrieval”, das Pydantic-Modell TestFall mit frage, erwartete_quelle, erwartete_kernaussage, 20 bis 40 weitere Fälle im Code-Kommentar, Randfälle (mehrdeutig, ohne Antwort, veraltet), Wachstum aus Fehleranalyse, die Stolperfalle “nur einfache Fälle”. Über die Quelle hinaus (allgemeines Fachwissen): die Felder art und erwartete_seite, die Reihenfolge der Kategorie-Entscheidung, die Stolperfallen “Golden Set zu klein” (nur die Rechnung, keine Mindestgröße) und “aus Prompt-Daten”. Alle Fallbeispiele (Fälle, Quellen-IDs) sind von Hand ausgedacht und keine echten Messungen. Alle Python-Beispiele wurden mit Python 3.13 ausgeführt.