RAG-Evaluationsmetriken: Retrieval, Reranking, Generation
Automatische Übersetzung Dieser Artikel wurde automatisch aus der englischen Originalversion übersetzt.
Ein RAG-System mit fehlerhaften Filtern kann monatelang laufen, ohne einen operativen Alarm auszulösen. Es liefert weiterhin Antworten und erfüllt sein Latenzziel, doch die Antworten basieren auf unvollständigen Belegen. Recall@k gegenüber dem ursprünglichen Gold-Set macht den Verlust sichtbar. Latenz- und Availability-Dashboards tun das nicht.
Für Engineers, die Multi-Stage-RAG-Systeme betreiben oder evaluieren, ordnet diese Referenz Fehler beim Parsen von Dokumenten, Filtern, Retrieval, Reranking und bei der Generation der jeweiligen Metrik zu, die sie erkennt. Anschließend zeigt sie, wo diese Messung in einen Release- oder Monitoring-Gate gehört.
- Ein nützlicher Evaluierungs-Stack deckt Ingestion, Retrieval, Grounding der Generation, Ontologie-Konformität und Systemsignale ab. [RAGAS](https://docs.ragas.io/), [TruLens](https://www.trulens.org/), [DeepEval](https://deepeval.com/), [Arize Phoenix](https://phoenix.arize.com/) und der [TREC 2024 RAG Track](https://trec.nist.gov/data/rag2024.html) stellen dafür Tooling bereit. Die Auswahl der Metriken übernehmen sie jedoch nicht. - Bei metadata- und ontologiegestütztem RAG können ein falscher Tag oder ein fragiles hartes Prädikat den Recall auf null reduzieren. Standard-Recall@k erkennt den Verlust, wenn das ursprüngliche Gold-Set erhalten bleibt. Eine Metrik für False Exclusions durch Filter identifiziert die Ursache. Faithfulness kann Claims weiterhin gegenüber unvollständigem Kontext bewerten, aber die Ursache im Filter oder Retrieval nicht diagnostizieren. Eine leere Refusal kann je nach Implementierung keine Statements und `NaN` erzeugen.Direkt vorspringen und Code ausführen?
Das ausführbare
slavadubrov/rag-evals-demo-Repository wendet die Metriken auf SciFact an.make evalführt die Suite aus, undmake benchmarkvergleicht Chunking-, Embedding- und LLM-Konfigurationen. Die Notebooks 00–09 isolieren die einzelnen Metriken. Die Demo verwendet eingebettetes Qdrant und benötigt daher Docker nicht.
Die Abschnitte folgen der Reihenfolge der Pipeline. Beginnen Sie mit der Entscheidungstabelle und verwenden Sie die späteren Abschnitte anschließend als Referenz für die einzelnen Stages.
Entscheidungstabelle für RAG-Evaluierung
Verwenden Sie diese Tabelle als Ausgangspunkt, bevor Sie ein Framework auswählen. Die passende Metrik hängt vom Fehlermodus ab, den Sie erkennen möchten, nicht vom Namen des Tools.
| Frage | Metrikfamilie | Verwenden, wenn | Darauf achten |
|---|---|---|---|
| Hat das Parsing die Quelle erhalten? | Extraction Completeness, Table/Figure Coverage | PDFs, Slides, Scans und HTML-Seiten in den Korpus gelangen | Sauber wirkender Text kann Captions, Fußnoten oder Tabellenstruktur verlieren |
| Hat Retrieval die richtigen Belege gefunden? | Recall@k, nDCG@k, MRR, Context Precision/Recall | Sie relevante Chunks oder Dokumente labeln können | Ein harter Metadata-Filter kann das richtige Dokument entfernen, bevor das Ranking beginnt |
| Hat Reranking die Shortlist verbessert? | Reranker Uplift, Precision@1, nDCG Delta | Cross-Encoder oder LLM-Ranker nach Retrieval eingesetzt werden | Messen Sie Latency und Kosten gemeinsam mit dem Qualitätsgewinn |
| Hat die Antwort die Belege verwendet? | Faithfulness, Groundedness, Citation Support | Die Antwort Dokumente zitiert oder Fakten aus dem Kontext übernimmt | Faithfulness kann schlechtes Parsing oder schlechtes Retrieval nicht diagnostizieren |
| Ist das System in Production stabil? | Drift, Regeneration, Fallback, p95 Latency, Cost per Answer | Sich der Traffic nach dem Launch verändert | Production-Telemetrie benötigt stichprobenartige Human Reviews, um kalibriert zu bleiben |
Einen kürzeren Tool-Vergleich finden Sie unter Best RAG Evaluation Tools: Ragas, DeepEval, and TruLens.
Teil 1: Erfolg vor der Architektur definieren
Erstellen Sie das Eval Set vor dem Architekturdiagramm. Dadurch erhält jede spätere Entscheidung für eine Komponente ein messbares Ziel.
Sie können nicht zwischen BM25 und Dense Retrieval, rekursivem und semantischem Chunking oder Cohere Rerank und BGE wählen, bevor Sie wissen, was Sie optimieren. „Bessere Antworten“ ist keine Metrik. Ein beispielhafter Vertrag wäre: „Faithfulness ≥ 0,85 auf einem Golden Set mit 200 Queries, das unsere drei wichtigsten Intents abdeckt, bei einer p95 Latency < 1,5 s und einer False-Exclusion-Rate des Filters < 2 %.“ Die Zahlen sind Platzhalter; entscheidend ist, dass Qualität, Coverage, Latency und Filtering explizite Gates haben.
Definieren Sie das Harness, bevor Sie den Retrieval-Code schreiben. Das erste Harness wird falsch sein, und Sie werden es überarbeiten. Eine Metrik zu überarbeiten ist deutlich günstiger, als ein bereits ausgeliefertes System zu überarbeiten.
Drei Pipeline-Schichten und zwei Run-Modi
Modernes RAG ist eine Pipeline, daher muss auch die Evaluation eine Pipeline sein. Keine einzelne Zahl erfasst jeden Failure Mode.
Die Production-Evaluation umfasst drei Pipeline-Schichten. Ingestion Evaluation prüft, ob Korpus und Index die Quelle erhalten. Query-Time Evaluation prüft, ob Rewriting, Filtering, Retrieval, Reranking und Context Assembly die richtigen Belege gefunden haben. Answer and Production Evaluation prüft, ob die Antwort diese Belege verwendet hat und ob die Qualität unter Live-Traffic stabil bleibt. Wenn Sie die Schichten zu einem Score zusammenfassen, kann ein Normalisierungsfehler innerhalb eines akzeptablen Answer Scores verschwinden.
Diese Ebenen beschreiben, wo ein Fehler auftritt. Offline und online beschreiben, wann und anhand welcher Daten die Prüfung ausgeführt wird. Die Offline-Evaluierung verwendet ein festgelegtes Dataset mit bekannter Ground Truth; sie ist reproduzierbar und gehört in die Komponentenauswahl, A/B-Vergleiche und CI-Gates. Die Online-Evaluierung bewertet Stichproben aus dem Live-Traffic und erfasst Regeneration, Verweildauer, explizites Feedback und den tatsächlichen Query-Drift. Sie ist rauschbehafteter und schwieriger zu instrumentieren.
Jede Pipeline-Ebene kann Offline- und Online-Prüfungen beitragen. Ein festgelegtes Ingestion-Korpus erkennt Parser-Regressionen vor dem Release, während Monitore für Freshness und Parse-Fehler Live-Updates abdecken. Ein festgelegtes Query-Set misst das Retrieval vor dem Release, während Stichproben aus Live-Traces Drift in der Produktion sichtbar machen. Nur offline zu prüfen, übersieht Live-Änderungen; nur online zu prüfen, erschwert die Reproduzierbarkeit von Regressionen.
Komponentenebene vs. End-to-End
Es gibt zwei häufige Fehler. Eine ausschließlich End-to-End-Evaluierung zeigt, dass das System defekt ist, aber nicht, wo der Fehler liegt. Eine ausschließlich komponentenbasierte Evaluierung kann zeigen, dass jeder Teil besteht, während das Gesamtsystem weiterhin fehlschlägt. Die Lösung besteht aus einigen zentralen End-to-End-Metriken für Go/No-Go-Entscheidungen sowie Komponentenmetriken zur Diagnose. Retrieval-Metriken erkennen Retriever-Regressionen. Generierungsmetriken erkennen Generator-Regressionen. Die End-to-End-Korrektheit der Antwort erkennt Integrationsfehler.
Die Referenz-Frameworks (Meinungstour)
| Framework | Besonders geeignet für | Schwächen |
|---|---|---|
| RAGAS | Mein Auswahlkriterium: ein gemeinsames Vokabular für Faithfulness, Answer Relevancy sowie Context Precision/Recall (Metriken) | Kosten für den LLM-Judge; beim Debugging intransparente Score-Komponenten; Änderungen zwischen Versionen |
| ARES | Mein Auswahlkriterium: Ein aufgabenspezifischer Classifier-Judge rechtfertigt den Trainings- und Annotierungsaufwand (Paper); die angegebene Precision ist an den Benchmark gebunden | Aufwendigeres Setup; Modelle müssen tatsächlich trainiert werden |
| TruLens | Mein Auswahlkriterium: Trace-verknüpfte Feedback-Funktionen und OpenTelemetry-Integration sind wichtiger als ein RAG-Metrikkatalog (Projekt) | Weniger integrierte RAG-spezifische Metriken als RAGAS |
| DeepEval | Mein Auswahlkriterium: Test-Runner-Integration und Custom Metrics sind wichtiger als ein Framework-Default (Projekt) | Umfangreicher Einsatz von LLM-Judges führt zu Kostenspitzen |
| Arize Phoenix | Mein Auswahlkriterium: Tracing und Embedding-Visualisierungen helfen bei der Untersuchung einer Drift-Hypothese (Projekt) | Die Definitionen der Metriken müssen selbst mitgebracht werden |
| TREC 2024 RAG Track | Öffentlicher Benchmark für Nugget-Evaluation (AutoNuggetizer), Support-Evaluation und Fluency auf MS MARCO Segment v2.1 | Kein Runtime-Tool, sondern ein Benchmark zur Kalibrierung |
Mein Standard-Stack besteht aus RAGAS für das Metrikvokabular, DeepEval für CI-Gates, Phoenix für Production Tracing sowie eigenem Code für ontologiespezifische Metriken. Das Framework, mit dem du startest, wird dir irgendwann nicht mehr ausreichen. Wähle das Framework, mit dem sich Custom Metrics einfach implementieren lassen.
Für Benchmarks kannst du BEIR (Thakur et al., NeurIPS 2021) für die Zero-Shot-Generalisierung von Retrieval, MTEB für die allgemeine Qualität von Embeddings, MIRACL für multilingualen Retrieval und den TREC 2024 RAG Track für die End-to-End-Evaluation von RAG verwenden.
Teil 2: Evaluationspunkte auf die Pipeline abbilden
Ein Production-RAG-System ist größer als „Dokumente embedden, Chunks retrieven, ein LLM aufrufen“. Jede Phase zwischen der Dokumentbeschaffung und der Auslieferung der Antwort kann fehlschlagen.
Jede Stufe im Diagramm hat mindestens eine Metrik. Eine Stufe ohne Metrik kann ausfallen, ohne dass es jemand bemerkt.
Die drei Lanes entsprechen den Stellen, an denen Evidence verloren gehen kann. Die Ingestion-Lane umfasst Parsing, Cleaning, Chunking, Embedding und Indexing. Die Query-Time-Lane umfasst Rewriting, Filtering, Retrieval, Reranking und Context Assembly. Die Answer-and-Production-Lane umfasst Faithfulness, Citation Verification, User Signals, Drift, Latency und Cost.
Fehler verstärken sich entlang der Kette: Schlechtes Parsing begrenzt, was Chunking leisten kann; schlechtes Chunking begrenzt Retrieval; und schlechtes Retrieval begrenzt sowohl Reranking als auch Generation. Faithfulness misst nur die finale Antwort, niemals die vorgelagerte Ursache.
Teil 3: Ingestion-Evaluation
Viele RAG-Ausfälle in Production beginnen bei der Ingestion. Das System funktioniert mit sauberen Testdokumenten, scheitert dann aber an echten PDFs, Scans, Tabellen und unaufgeräumten Corpus-Seiten.
Dokumentbeschaffung und Parsing
Was gemessen werden sollte:
-
Vollständigkeit der Textextraktion:
extracted_chars / expected_charsauf einer gelabelten Stichprobe, berechnet pro Dokumentklasse. Es gibt kein kanonisches Package — schreibt ein kleines Harness, das die Parserausgabe mit einer manuell bereinigten Referenz vergleicht. Achtet auf fehlende Fußnoten, Header und Captions. -
OCR-Genauigkeit: CER (Character Error Rate) und WER (Word Error Rate), die Standardmetriken aus Speech/OCR:
Dabei sind , , Substitutionen, Löschungen und Einfügungen auf Zeichenebene, und ist die Anzahl der Referenzzeichen (Subskript für die Wortversion). Wendet nicht für jedes Corpus dieselbe CER-Grenze an. Kalibriert sie nach Dokumentklasse und dem nachgelagerten Answer Loss. Gedruckter Text, Handschrift und mehrsprachiges Material haben unterschiedliche Error Profiles. Berechnet die Werte mit
jiwer(jiwer.cer(refs, hyps),jiwer.wer(refs, hyps)) oder mitevaluatevon HuggingFace. Für Evaluation-Corpora sind FUNSD und SROIE öffentliche Benchmarks.from jiwer import cer, wer refs = ["Mars has two moons, Phobos and Deimos."] hyps = ["Mars has two m00ns, Phobos and Deirnos."] print(f"CER = {cer(refs, hyps):.3f}") # CER = 0.105 print(f"WER = {wer(refs, hyps):.3f}") # WER = 0.286 -
Fidelity der Table Extraction: TEDS (Tree-Edit-Distance-based Similarity) misst, wie nah ein vorhergesagter HTML-Table-Tree an der Referenz liegt, normalisiert anhand der Größe des größeren Trees. Nach Zhong et al., 2020 (PubTabNet):
TEDS berücksichtigt sowohl die Struktur (Zeilen, Spalten, Spans) als auch den Zellinhalt. TEDS-S entfernt den Inhalt und bewertet nur die Struktur. Referenzimplementierung:
teds.pyvon PubTabNet (verwendet internapted). Für Evaluation-Corpora siehe PubTabNet, FinTabNet und SciTSR. Naive Parser scheitern bei Tabellen häufig. Führt vor dem Vertrauen in sie einen Benchmark durch. -
Erhalt von Layout und Struktur: Reihenfolge von Überschriften und Listen sowie Lesereihenfolge in mehrspaltigen PDFs. Verwenden Sie DocLayNet als gelabelten Benchmark. Ein direkter Vergleich kann einen Element-Parser wie
unstructured, eine PDF-Bibliothek wiepymupdfund einen VLM-Parser wiedoclingumfassen.
Vergleichen Sie verschiedene Parser-Familien, zum Beispiel eine Tesseract-Baseline, ein VLM-basiertes OCR-Modell und den Kandidaten Ihres Vendors. Verwenden Sie eine stratifizierte Stichprobe realer Dokumentklassen mit einer festen DPI-Anzahl, darunter saubere Scans, Fotos, Tabellen, mehrsprachige Texte, Mathematik und Handschrift. Berichten Sie CER oder WER für jede Klasse sowie TEDS für Tabellenseiten.
Bereinigung und Normalisierung
-
Genauigkeit der Boilerplate-Entfernung: Precision/Recall gegenüber von Menschen gelabelten Boilerplate-Spans. Eine aggressive Entfernung löscht relevante Inhalte; eine zu zurückhaltende Entfernung verunreinigt Embeddings. Vergleichbare Tools sind
trafilatura,jusTextundResiliparse. Barbaresi (2021) führt einen direkten Benchmark dieser Tools durch. -
Unicode-Normalisierung: Der Prozentsatz der Dokumente, die identische NFC- und NFKC-Ausgaben erzeugen (berechnet mit dem Standardbibliotheksmodul
unicodedata.normalize), ist ein nützliches Signal für Drift. Abweichungen zeigen, wie Zero-Width-Joiner und ähnlich aussehende Zeichen den Retrieval-Recall beeinträchtigen. -
Genauigkeit der Spracherkennung: F1 auf einer gelabelten mehrsprachigen Stichprobe. Das ist für mehrsprachige Indizes entscheidend. Verwenden Sie
fasttext-langdetect(Facebookslid.176),lingua-pyodercld3. FLORES-200 stellt Evaluierungstexte in 200 Sprachen bereit. Für den Testausschnitt sollte jedoch die Sprachenverteilung in Ihrer Production maßgeblich sein. -
Effektivität der Deduplication (MinHash / LSH): Precision/Recall Ihres Near-Duplicate-Detektors gegenüber einer manuell gelabelten Menge. Die zugrunde liegende Idee besteht darin, die Jaccard-Ähnlichkeit zwischen Shingle-Mengen von Dokumenten anhand von Hashes zufälliger Permutationen zu schätzen (Broder, 1997) und Near-Duplicates mithilfe von LSH-Banding in Buckets einzuordnen (Indyk & Motwani, 1998). Variieren Sie die Hash-Anzahl und den Jaccard-Schwellenwert auf Ihrem Korpus. Erfassen Sie die False-Merge-Rate (verfälscht Antworten) getrennt von der Missed-Merge-Rate (verschwendet Index-Speicher).
datasketchstellt die unten verwendete Implementierung bereit; die Parameter dienen lediglich als Beispiele:from datasketch import MinHash, MinHashLSH def shingles(text: str, k: int = 5) -> set[str]: text = text.lower() return {text[i:i + k] for i in range(len(text) - k + 1)} def to_minhash(text: str, num_perm: int = 128) -> MinHash: m = MinHash(num_perm=num_perm) for s in shingles(text): m.update(s.encode("utf-8")) return m docs = { "d1": "Mars has two moons, Phobos and Deimos.", "d2": "Mars has two moons, Phobos and Deimos!", # near-dup "d3": "Curiosity rover landed on Mars in 2012.", } lsh = MinHashLSH(threshold=0.8, num_perm=128) for did, text in docs.items(): lsh.insert(did, to_minhash(text)) print(sorted(lsh.query(to_minhash(docs["d1"])))) # ['d1', 'd2'] -
PII-Scrubbing: Precision und Recall, jeweils getrennt nach Entitätstyp berechnet (E-Mail-Adressen, SSNs, Namen, Adressen). Recall-Fehler erzeugen Compliance-Risiken; Precision-Fehler beeinträchtigen die Qualität der Antworten. Legen Sie den Operating Point gemeinsam mit dem Legal-Team fest. Mögliche Tools sind Microsoft Presidio,
scrubaduboder ein Fine-Tuned-NER-Modell auf einer gelabelten Menge.
Chunking steuert die Retrieval-Qualität
Chunking kann eine mehrfache Recall-Lücke erzeugen, selbst wenn das Embedding Model unverändert bleibt. Im NVIDIA Vendor Benchmark von 2025 erzielte Chunking auf Seitenebene bei paginierten Dokumenten die höchste Genauigkeit und die geringste Varianz. Betrachte dieses Ergebnis als Evidenz für das getestete Korpus, nicht als universell beste Methode.
Semantic Chunking gruppiert aufeinanderfolgende Sätze anhand ihrer Embedding-Ähnlichkeit und setzt die Trennpunkte an unähnlichen Grenzen. LangChains SemanticChunker und LlamaIndex’ SemanticSplitterNodeParser implementieren diese Strategie. Sie kann den Recall gegenüber festen Fenstern verbessern, wenn thematische Grenzen relevant sind.
Recursive Character Splitting versucht zunächst Absatzumbrüche, dann Satzumbrüche und anschließend Wortumbrüche, bis jeder Chunk in die Zielgröße passt. LangChains RecursiveCharacterTextSplitter implementiert diese Abfolge. Wähle Kandidatenwerte für Fenstergröße und Overlap, die zu deiner Dokumentstruktur passen, und überlasse die endgültige Auswahl dem Golden Set.
Zu erfassende Metriken:
- Chunk-Kohärenz: , wobei Satz-Embeddings sind. Gesunde Chunks sind intern ähnlich und an ihren Grenzen unähnlich. Berechne dies mit
sentence-transformersund demcosine_similarityvonscikit-learn. - Grenzqualität: Von Menschen gelabelte Antwort auf „Ist dies ein sinnvoller Schnitt?“ für eine Stichprobe sowie eine strukturelle Prüfung, dass Chunks keine Tabellen, Listen oder nummerierten Abschnitte teilen.
- Optimale Chunk-Größe: Variiere die Token-Größen (128, 256, 512, 1024) und zeichne Recall@k gegenüber der Größe auf deinem Golden Set auf. Wähle den Knickpunkt. Nimm nicht einfach den Wert aus dem Tutorial.
- Wirksamkeit des Overlaps: Entferne testweise mehrere Overlap-Anteile und miss Recall@k. Erhöhe den Overlap nicht weiter, sobald die lokale Recall-Kurve abflacht oder die Duplikationskosten den Gewinn überwiegen.
- Fidelity der Chunk-Attribution: Anteil der Chunks, die einen überprüfbaren Source Pointer behalten (Seitennummer, Section Anchor, Doc ID). Auditierbarkeit setzt dies voraus.
- Late vs. Early Chunking: Late Chunking (Günther et al., 2024) bettet das vollständige Dokument ein und segmentiert es anschließend, wodurch der globale Kontext erhalten bleibt (Referenzimplementierung in
jina-embeddings-v3). Contextual Retrieval (Anthropic, 2024) stellt jedem Chunk von einem LLM generierten Kontext voran. Beides verursacht zusätzliche Kosten. Führe vor der Einführung einen Benchmark auf deinem Korpus durch.
Meine Einschätzung: Structural Chunking (Aufteilung anhand von Überschriften, Tabellen und Abschnitten – implementiert durch Parser wie unstructured.io oder durch das Durchlaufen des AST, den dein Parser bereits erzeugt hat) wird zu wenig genutzt. Wenn deine Dokumente strukturiert sind, nutze diese Struktur, bevor du Similarity-Heuristiken hinzufügst. Recursive Character Splitting ist der Baseline-Ansatz; Semantic Chunking rechtfertigt den Overhead hauptsächlich bei unstrukturiertem Fließtext.
Metadatenextraktion und -anreicherung
- NER-Precision/Recall/F1: pro Entitätstyp auf einem annotierten Subset. Standardmäßig im CoNLL-/MUC-Stil. Berechnen Sie die Werte mit
seqeval(from seqeval.metrics import f1_score) für die BIO-/IOB-Tag-aware-Variante oder mit scikit-learn für Vergleiche von Span-Mengen. CoNLL-2003 und OntoNotes 5.0 sind die maßgeblichen Referenzkorpora. - F1 der Relationsextraktion: für Ontology-grounded Systems noch wichtiger. Annotieren Sie eine nach Relationstyp und Dokumentklasse stratifizierte Menge. TACRED und DocRED sind öffentliche Benchmarks; mögliche Implementierungen umfassen
opennreundspaCyfür Relationsextraktions-Pipelines. - Genauigkeit der Titel-/Heading-Extraktion: Exact Match plus normalisierte Levenshtein-Ähnlichkeit () gegenüber der Ground Truth —
python-Levenshteinoderrapidfuzzliefern beides mit einem Aufruf. - Erhalt hierarchischer Metadaten: Prozentsatz der Chunks, die ihren übergeordneten Abschnitt, ihr übergeordnetes Dokument und ihren Pfad in der Hierarchie korrekt beibehalten. Diese Metrik entscheidet, ob Ihr RAG Fragen vom Typ „Was sagt das Kind von Richtlinie X?“ beantworten kann.
Embedding-Generierung
- Benchmarks zur Model-Auswahl: Verwenden Sie die Task-Ergebnisse von MTEB (nDCG@10 ist die zentrale Kennzahl; mit dem MTEB Python package können Sie die Bestenliste lokal reproduzieren), BEIR für Zero-Shot-Generalization und MIRACL für multilingualen Retrieval als Vergleichspunkte. Betrachten Sie die Übertragung von englischem MTEB auf eine Sprache mit geringeren Ressourcen als Hypothese, die Sie auf einem annotierten Set dieser Sprache testen müssen.
- Domain-spezifische Evaluation: Behandeln Sie einen allgemeinen Benchmark-Rang nicht als Ergebnis für eine bestimmte Domain. Stellen Sie anhand der Coverage-Matrix und der Unsicherheit, die Ihre Entscheidung tolerieren kann, ein Domain-Golden-Set zusammen. Anschließend können Sie die Kandidaten-Models darauf mit
ranxoderpytrec_evalneu ranken. Ein Domain-Set kann die Reihenfolge einer Bestenliste umkehren. Veröffentlichen Sie daher gemeinsam mit dem Ergebnis den Dataset-Ausschnitt, das Retrieval-Protokoll und das Konfidenzintervall. - Erkennung von Embedding Drift: Verfolgen Sie die distributionale KL-Divergenz oder den Model-based Drift zwischen einem festen Referenzfenster und rollierenden Production-Embeddings. Messen Sie außerdem die Stabilität der Nearest Neighbors für ein festes Probe-Set.
evidentlyundalibi-detectimplementieren Model-based und statistische Detektoren. Die vergleichende Studie von Evidently ist eine Evaluation eines Anbieters; vergleichen Sie die Methoden anhand bekannter Shifts in Ihren eigenen Embeddings. - Multi-Vector vs. Single-Vector: Late Interaction bewahrt Token-Level-Repräsentationen, statt jedes Dokument auf einen einzelnen Vektor zu reduzieren; ColBERT ist das maßgebliche Design, mit Referenzimplementierungen in RAGatouille und PyLate. Diese reichhaltigere Repräsentation erhöht die Kosten für Index und Retrieval. Vergleichen Sie Qualität, Speicherbedarf und Latenz mit einer Single-Vector-Baseline auf demselben Domain-Set, bevor Sie das Verfahren übernehmen.
Indexkonstruktion
- Recall@k unter Approximation: Vergleichen Sie den Approximate-Nearest-Neighbour-(ANN-)Index bei demselben k mit einer exakten Brute-Force-Baseline — in FAISS sind das
IndexHNSWFlat(oderIndexIVFFlat) gegenüberIndexFlatIP/IndexFlatL2. Legen Sie den akzeptablen Recall-Verlust anhand Ihres Downstream-Qualitätsbudgets fest. Das Projektann-benchmarkserfasst Recall–QPS-Pareto-Kurven über verschiedene Libraries hinweg. - HNSW-Tuning: HNSW (Hierarchical Navigable Small World) ist ein geschichteter Proximity-Graph; siehe Malkov & Yashunin, 2018. Implementiert ist er in
hnswlib, in FAISS alsIndexHNSWFlatsowie in den meisten Vector DBs. HNSW bietet drei Stellschrauben:M(Graph-Fan-out),efConstruction(Candidate-Breite beim Aufbau) undefSearch(Candidate-Breite zur Query-Zeit). Beginnen Sie mit den dokumentierten Defaults der Library und variieren Sie anschließend die Parameter, bis die Recall–Latency-Kurve die Anforderungen Ihres Evaluation-Sets erfüllt. - IVF-Tuning: IVF (Inverted File Index — Vektoren mithilfe von k-Means in
nlistZellen partitionieren und zur Query-Zeit dienprobenächstgelegenen Zellen durchsuchen; siehe FAISS’IndexIVFFlatundIndexIVFPQ). Variieren Sienlistundnprobeanhand von Recall und Latency der exakten Suche. Führen Sie für gefilterte Queries separate Benchmarks durch, da Indexfamilien und Vector DBs die Filter-Traversierung unterschiedlich implementieren. - Update-Freshness-Lag: Zeitspanne vom Commit eines Dokuments bis zu seiner Abrufbarkeit. Erfassen Sie p50 und p99. Bei Systemen mit regulatorischen Anforderungen sollten Sie zusätzlich den Prozentsatz der Queries erfassen, die gegen veraltete Indizes ausgeführt werden.
Teil 4: Evaluation zur Query-Zeit
Die Query-Zeit-Spur enthält die Metriken zur Diagnose eines Retrieval-Pfads. Recall@k allein zeigt nicht, ob Rewriting, Filtering, Reranking oder Context Assembly den Fehler verursacht hat.
Query-Verständnis und Rewriting
- Qualität der Query Expansion: Recall@k-Uplift auf deinem Golden Set, verglichen zwischen expandierter Query und Raw-Query. Definiere den minimalen nützlichen Gewinn und dessen Unsicherheit vor dem Test. Wenn die Expansion dieses lokale Gate nicht überschreitet, rechtfertigt sie weder ihre Latenz noch ihre Kosten. Klassische PRF-Baselines (Pseudo-Relevance Feedback) wie RM3 und Bo1 sind weiterhin nützliche Sanity Checks; LLM-basierte Expansion muss sie übertreffen.
- HyDE-Evaluation: HyDE (Gao et al., 2022) generiert mit dem LLM eine hypothetische Antwort, bettet sie ein und führt darauf basierend Retrieval durch. Dadurch kommen Generation-Latency und eine neue Failure Surface hinzu. Miss Recall@10 separat für In-Domain-, Out-of-Domain- und Low-Confidence-Slices und entscheide anschließend, ob HyDE in den Default Path, einen Fallback oder in keinen von beiden gehört.
- Multi-Query-Generierung: Recall@k der Union aus N Rewrites gegenüber einer einzelnen Query. Sweep N und wähle einen Punkt auf deiner Recall–Latency-Frontier. Implementierungen: LangChains
MultiQueryRetriever, LlamaIndex’QueryFusionRetriever. - Genauigkeit der Intent-Klassifikation: Standardmäßige Precision/Recall/F1 pro Intent (berechnet mit
sklearn.metrics.classification_report), aber die operative Metrik ist die Routing Correctness — wird die richtige nachgelagerte Pipeline aufgerufen? - Adaptives Routing: Adaptive-RAG (Jeong et al., NAACL 2024) zeigt, dass nicht jede Query dieselbe Retrieval-Strategie benötigt. Tracke die Router-Accuracy als Klassifikationsproblem anhand eines gelabelten Sets mit den Kategorien „kein Retrieval erforderlich / One-Shot / iterativ“.
Retrieval-Metriken
Das sind die Baseline-Metriken. Wenn du sie nicht trackst, kannst du nicht feststellen, ob sich das Retrieval verbessert.
| Metrik | Was sie misst | Wann sie verwendet wird |
|---|---|---|
| Recall@k | Anteil der relevanten Dokumente einer Query, die in den Top k zurückgegeben werden | verwenden, wenn das Fehlen eines beliebigen Teils des relevanten Sets relevant ist |
| Precision@k | Prozentsatz der Top-k-Dokumente, die relevant sind | nützlich, wenn das Context Window der Bottleneck ist |
| MRR | Durchschnitt von 1/Rang des ersten relevanten Dokuments | wenn User nur das Top-1- oder Top-3-Ergebnis betrachten |
| nDCG@k | positionsdiskontierter, nach Relevanzgraden gewichteter Gewinn | Standard-Retrieval-Metrik für abgestufte Relevanz |
| MAP | Mittelwert der Average Precision über alle Queries | wenn die gesamte gerankte Liste relevant ist |
| Hit Rate@k | ob mindestens ein relevantes Dokument in den Top k erscheint | binäres Ergebnis über alle Queries mitteln, um eine schnelle Sanity-Metrik zu erhalten |
| Coverage | Prozentsatz der Golden Docs, die über alle Queries hinweg jemals abgerufen wurden | erkennt systematische Lücken im Index |
Die Formeln zur Referenz (binäre Relevanz mit der relevanten Menge für Query und , falls das -te abgerufene Dokument in enthalten ist):
Für graded relevance gilt: ; binäres nDCG ist der im folgenden Code verwendete Sonderfall. MAP ist der Mittelwert über die Queries von . Herleitungen finden Sie in Manning, Raghavan, Schütze, Introduction to Information Retrieval, Kapitel 8.
Verwenden Sie für Production Code ranx, pytrec_eval oder ir_measures — sie implementieren die gesamte TREC-Metrikfamilie und behandeln graded relevance korrekt. Legen Sie Release-Ziele anhand eines realistischen Golden Sets, der nachgelagerten Answer Quality und der Kosten eines Fehlers fest. Übernehmen Sie keine Thresholds aus einem Tutorial.
Das Test-Harness für diese Metriken ist kurz. Sie können es in einem Notebook ausführen, noch bevor Sie sich für eine Vector Database entschieden haben.
from math import log2
from statistics import mean
# synthetic gold set: query_id -> set of relevant doc ids
gold = {
"q1": {"d3"},
"q2": {"d7", "d2"},
"q3": {"d11"},
"q4": {"d5"},
}
# ranked retrieval results: query_id -> ranked list of doc ids (top-10)
runs = {
"q1": ["d8", "d3", "d1", "d4", "d2", "d9", "d6", "d10", "d12", "d13"],
"q2": ["d2", "d6", "d4", "d7", "d1", "d3", "d8", "d11", "d5", "d9"],
"q3": ["d11", "d2", "d3", "d4", "d1", "d6", "d7", "d8", "d10", "d12"],
"q4": ["d1", "d2", "d3", "d6", "d8", "d9", "d10", "d12", "d13", "d14"],
}
def recall_at_k(ranked, gold_set, k):
if not gold_set:
return 0.0
hit = sum(1 for d in ranked[:k] if d in gold_set)
return hit / len(gold_set)
def reciprocal_rank(ranked, gold_set):
# MRR contribution per query: 1/rank of the first relevant doc.
for rank, d in enumerate(ranked, start=1):
if d in gold_set:
return 1.0 / rank
return 0.0
def ndcg_at_k(ranked, gold_set, k):
# binary relevance: rel ∈ {0, 1}
gains = [1.0 if d in gold_set else 0.0 for d in ranked[:k]]
dcg = sum(g / log2(i + 2) for i, g in enumerate(gains))
# ideal DCG: all gold docs ranked first, capped by k
n_gold_in_topk = min(k, len(gold_set))
idcg = sum(1.0 / log2(i + 2) for i in range(n_gold_in_topk))
return dcg / idcg if idcg else 0.0
K = 5
print(f"Recall@{K}: {mean(recall_at_k(runs[q], gold[q], K) for q in gold):.3f}")
print(f"MRR: {mean(reciprocal_rank(runs[q], gold[q]) for q in gold):.3f}")
print(f"nDCG@{K}: {mean(ndcg_at_k(runs[q], gold[q], K) for q in gold):.3f}")
# Recall@5: 0.750
# MRR: 0.625
# nDCG@5: 0.627
Das ist Ihr Retrieval-CI-Gate. Binden Sie es bei jedem PR an ein durch Coverage gesteuertes schnelles Subset und führen Sie das vollständige Golden Set im langsameren Release-Gate aus. Blockieren Sie einen Merge, wenn eine vorab registrierte Metrik ihr Regression Budget überschreitet.
Das begleitende Repo fixiert die exakten obigen Zahlen (Recall@5 = 0.750, MRR = 0.625, nDCG@5 = 0.627) als Unit Test in tests/test_retrieval_metrics.py; Notebook 01 variiert Recall@k / MRR / nDCG über einen realen SciFact-Index, und das Production-shaped Harness befindet sich in evaluation/retrieval.py.
Hybride Retrieval- und Reciprocal-Rank-Fusion
BM25 ist ein sparscher lexikalischer Scorer, der Exact-Term-Matching, Termgewichtung und Längennormalisierung kombiniert. Er ist in rank_bm25, Elasticsearch, OpenSearch und den meisten Search Engines verfügbar.
Reciprocal Rank Fusion (Cormack, Clarke und Buettcher, SIGIR 2009) kombiniert BM25- und dichte Rankings anhand ihrer Position. Das ursprüngliche k=60-Setting ist eine nützliche Baseline. RRF ist score-agnostisch und vermeidet dadurch die Cross-Lane-Normalisierung, die bei linearer Interpolation erforderlich ist. Testen Sie bei einem ausreichend großen gelabelten Set, mit dem sich ein stabiles Delta schätzen lässt, zusätzlich eine konvexe Kombination und tunen Sie α.
Meine Hypothese ist, dass hybrides Retrieval plus ein Cross-Encoder-Reranker bei technischen, logartigen und Code-Corpora helfen kann. Bei stark semantischen Corpora kann der Gewinn gering sein. Messen Sie gegen die Dense-only- und Sparse-only-Lanes, da eine schlechte Fusion-Konfiguration hinter jedem der beiden Inputs zurückbleiben kann. Das begleitende SciFact-Notebook ist ein begrenzter Test und kein allgemeingültiges Ergebnis.
Die Implementierung passt in wenige Zeilen.
from collections import defaultdict
# two retrieval lanes: dense embeddings and BM25.
dense = ["d3", "d7", "d1", "d4", "d2", "d9", "d10"]
sparse = ["d2", "d3", "d8", "d1", "d11", "d4", "d6"]
def rrf(rankings: list[list[str]], k: int = 60) -> list[tuple[str, float]]:
"""Reciprocal Rank Fusion (Cormack et al., SIGIR 2009).
score(d) = sum over rankings of 1 / (k + rank(d))
Score-agnostic: only rank position matters. k=60 is the canonical default.
"""
scores: dict[str, float] = defaultdict(float)
for ranking in rankings:
for rank, doc in enumerate(ranking, start=1):
scores[doc] += 1.0 / (k + rank)
return sorted(scores.items(), key=lambda kv: kv[1], reverse=True)
fused = rrf([dense, sparse], k=60)
for doc, score in fused[:5]:
print(f"{doc} score={score:.5f}")
# d3 score=0.03252 <- rank 1 dense, rank 2 sparse
# d2 score=0.03178 <- rank 5 dense, rank 1 sparse
# d1 score=0.03150
Beachten Sie, was RRF nicht tut: Es betrachtet niemals die Raw-Similarity-Scores. Ein Dense Retriever mit Cosine 0.98 und eine BM25-Lane mit Score 17.4 sind nicht direkt vergleichbar. Wenn Sie sie mit z-Scores oder Min-Max-Scaling normalisieren, können Sie am Ende die Lane mit der höchsten Varianz in diesem Batch bevorzugen.
RRF verwendet ausschließlich den Rang. Wenn ein Retriever ein Dokument auf Position 2 platziert, ist diese Stimme 1 / (60 + 2) wert — unabhängig vom Raw Score, der diese Position hervorgebracht hat.
Hybrid + RRF auf SciFact: Notebook 02 vergleicht Dense vs. BM25 vs. RRF mit Deltas pro Query. Der Production-shaped Fuser befindet sich in retrieval/hybrid_rrf.py; tests/test_rrf.py fixiert die kanonische d3 / d2 / d1-Reihenfolge bei k=60.
Reranking
- ΔnDCG / ΔMRR: Uplift gegenüber „ohne Reranking“ auf deinem Golden Set und bei der Tiefe, die deine Anwendung tatsächlich verwendet. Berechne den Wert, indem du deine Retrieval-Metriken mit und ohne Reranker auf identischen Candidate Sets ausführst.
- Cross-Encoder vs. Bi-Encoder: Ein Bi-Encoder bettet Query und Dokument unabhängig voneinander ein (je ein Vektor pro Seite) und bewertet sie per Dot Product; ein Cross-Encoder verkettet Query und Dokument und führt einen einzelnen Forward Pass aus, der gemeinsam über beide hinweg Attention berechnet. Cross-Encoder tauschen einen Forward Pass pro Candidate gegen eine reichhaltigere Query–Dokument-Interaktion. Referenzimplementierung:
sentence-transformersCrossEncoder. Benchmarke Relevanz und Latency auf spezifizierter Hardware, mit festgelegter Batch Size und Candidate Depth; übertrage nicht das Ergebnis eines Models oder Managed Services in eine andere Umgebung. - Listwise vs. Pointwise: Pointwise bewertet jedes (Query, Dokument)-Paar unabhängig; Listwise bewertet die gesamte Candidate List gemeinsam, sodass das Model Candidates miteinander vergleichen kann. Evaluiere beide Ansätze auf denselben Candidate Sets. Kalibriere jeden Score Threshold pro Model und Corpus, statt ein veröffentlichtes Beispiel als übertragbar zu behandeln.
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
query = "How do I rotate database credentials in production?"
candidates = [
"Production database credentials are rotated via Vault every 30 days.",
"The new logo was unveiled at the all-hands meeting.",
"To rotate prod DB creds, run the `rotate-secrets` GitHub Action.",
]
scores = reranker.predict([(query, c) for c in candidates])
ranked = sorted(zip(candidates, scores), key=lambda x: -x[1])
for doc, score in ranked:
print(f"{score:+.3f} {doc}")
Ein Reranker hilft häufig bei einer einfachen RAG-Pipeline, ist aber kein garantierter Gewinn. Miss ΔPrecision@1 und ΔnDCG auf deinem Golden Set und behalte ihn nur, wenn der Gewinn sein Latency- und Kostenbudget übersteigt. Vergleiche diesen gemessenen Gewinn mit kleineren Retrieval-Änderungen, bevor du die nächste Optimierung auswählst.
ΔnDCG und ΔPrecision@1 eines Cross-Encoders auf SciFact: Notebook 03; Modul: retrieval/reranker.py.
Context Construction und Lost-in-the-Middle
Viele Fehler nach dem Muster „gutes Retrieval, schlechte Antwort“ beginnen bei der Context Construction.
- Context Relevance: Relevanzscore pro Chunk aus RAGAS
ContextRelevanceoder einem Cross-Encoder, aggregiert als Mittelwert und als prozentualer Anteil der Chunks unterhalb eines Thresholds. - Context Utilization: Wie viele der in den Context aufgenommenen Chunks wurden tatsächlich in der Antwort zitiert oder verwendet? Berechne dies als über ein gelabeltes Sample. Leite den operativen Threshold aus Antwortqualität und Token-Kosten ab, statt einen universellen Prozentsatz zu verwenden.
- Lost-in-the-Middle Detection: Synthetische Eval, bei der du den Gold Chunk an den Positionen {first, middle, last} eines langen Contexts platzierst und die Korrektheit der Antwort misst. Die zitierte Studie von Liu et al. (TACL 2023) berichtet unter ihren Long-Context-Bedingungen eine U-förmige Verschlechterung. Behandle dasselbe Muster in einem aktuellen Model als Hypothese, die getestet werden muss. Mitigations: Zuerst Reranking durchführen, dann die Top-k-Chunks so umsortieren, dass der Chunk mit dem höchsten Score an erster oder letzter Stelle steht (LangChains
LongContextReordermacht genau das), oder Chunks in der Mitte aggressiv komprimieren. Miss dies mit einer positionsstratifizierten Eval und nicht nur mit einem aggregierten Score. Eine ausgearbeitete, ausführbare positionsstratifizierte Eval findest du in Notebook 06 (Modul:evaluation/lost_in_middle.py). - Context Compression: Berichte die Compression Ratio (Input-Tokens / Output-Tokens) zusammen mit der Antwortkorrektheit. Zu den Tools gehören LangChains
ContextualCompressionRetrieverund LongLLMLingua. Definiere vorab den größten akzeptablen Verlust an Korrektheit anhand des Risikos und Token-Budgets der Anwendung und verwerfe anschließend Konfigurationen, die diesen Grenzwert überschreiten.
Teil 5: Die False-Exclusion-Rate des Filters
Diese Metrik erhält einen eigenen Abschnitt, weil aggregierte Retrieval-Scores nicht zuordnen können, ob ein Fehltreffer durch den Filter verursacht wurde.
Ein harter Metadatenfilter wie tenant_id = X AND product = Y AND locale = en-US kann den effektiven Recall auf null senken. Korrekt implementierter Recall@k erfasst diesen Verlust, weil der Nenner weiterhin aus der ursprünglichen Menge relevanter Dokumente besteht. Er zeigt jedoch nicht, ob der Filter, der Retriever oder der Ranker den Fehltreffer verursacht hat. Faithfulness bewertet Claims anhand des abgerufenen Kontexts. Es kann weiterhin Claims bewerten, die durch diesen unvollständigen Kontext gestützt werden, aber die Ursache im Filter oder Retrieval nicht diagnostizieren. Eine leere Verweigerung kann je nach Implementierung keine Aussagen und NaN erzeugen; behandeln Sie dies nicht als Beleg dafür, dass Faithfulness die Verweigerung bestätigt hat.
Der hervorgehobene Pfad ist der häufigste Fehler: Das richtige Dokument existiert, aber der Filter entfernt es vor dem Retrieval. Recall@k registriert den Rückgang; nur die Exclusion Rate ordnet ihn dem Prädikat zu.
Die Metrik
filter_false_exclusion_rate =
(# queries where all gold docs were excluded by metadata filter) /
(# queries with at least one gold doc)
Diese Definition auf Query-Ebene zählt katastrophale Ausschlüsse: Kein relevantes Dokument bleibt übrig. Bei Queries mit mehreren Gold-Dokumenten zeigt der Standard-Recall@k weiterhin partielle Verluste; ergänzen Sie eine dokumentweise Exclusion Rate, wenn diese Grenze relevant ist. Für die Berechnung einer der beiden Raten benötigen Sie (a) Ground-Truth-Dokument-IDs für jede Eval-Query und (b) Instrumentierung, die die angewendeten Filterprädikate protokolliert, nicht nur die finalen Ergebnisse. Legen Sie das Ziel anhand der Kosten fest, die durch den Ausschluss einer gültigen Antwort entstehen, sowie anhand des Konfidenzintervalls Ihrer Produktionsstichprobe.
Hier ist eine funktionsfähige Implementierung. Sie vergleicht den korrekten Standard-Recall mit einem ungültigen Evaluator, der die Relevanz nach dem Filtering neu definiert.
# A small worked example where hard filters remove relevant documents.
docs = [
{"id": "d1", "tenant": "acme", "locale": "en-US"},
{"id": "d2", "tenant": "acme", "locale": "en-GB"},
{"id": "d3", "tenant": "globex", "locale": "en-US"},
{"id": "d4", "tenant": "acme", "locale": "en-US"},
{"id": "d5", "tenant": "acme", "locale": "de-DE"},
]
queries = [
# the gold doc lives in en-GB but the dynamic filter forced en-US
{"qid": "q1", "gold": {"d2"}, "filter": lambda d: d["locale"] == "en-US"},
# the gold doc is correctly within the tenant filter
{"qid": "q2", "gold": {"d4"}, "filter": lambda d: d["tenant"] == "acme"},
# the gold doc is in a different tenant and gets dropped
{"qid": "q3", "gold": {"d3"}, "filter": lambda d: d["tenant"] == "acme"},
# the gold doc passes the filter (de-DE locale match)
{"qid": "q4", "gold": {"d5"}, "filter": lambda d: d["locale"] == "de-DE"},
]
def filter_false_exclusion_rate(queries, docs):
n_with_gold, n_excluded = 0, 0
for q in queries:
if not q["gold"]:
continue
n_with_gold += 1
survivors = {d["id"] for d in docs if q["filter"](d)}
if not (q["gold"] & survivors):
n_excluded += 1
return n_excluded / n_with_gold if n_with_gold else 0.0
rate = filter_false_exclusion_rate(queries, docs)
print(f"filter_false_exclusion_rate = {rate:.2%}")
# filter_false_exclusion_rate = 50.00%
# Correct Recall@k keeps the original gold set as its denominator.
def standard_recall_at_k(queries, docs, k=10):
recalls = []
for q in queries:
# demo only: the survivor set stands in for a ranked run.
# A real harness ranks the survivors first, then slices to k.
survivors = [d for d in docs if q["filter"](d)][:k]
survivor_ids = {d["id"] for d in survivors}
recalls.append(len(q["gold"] & survivor_ids) / len(q["gold"]))
return sum(recalls) / len(recalls) if recalls else 0.0
print(f"standard recall@10 = {standard_recall_at_k(queries, docs):.2%}")
# standard recall@10 = 50.00%
# INVALID: rebuilding the gold set after filtering changes the question.
# It drops queries whose relevant documents did not survive, then scores 100%.
def invalid_recall_over_filtered_gold(queries, docs, k=10):
recalls = []
all_doc_ids = {d["id"] for d in docs}
for q in queries:
all_survivors = {d["id"] for d in docs if q["filter"](d)}
filtered_gold = q["gold"] & all_doc_ids & all_survivors
if not filtered_gold:
continue
top_k_ids = set(list(all_survivors)[:k])
recalls.append(len(filtered_gold & top_k_ids) / len(filtered_gold))
return sum(recalls) / len(recalls) if recalls else 0.0
invalid = invalid_recall_over_filtered_gold(queries, docs)
print(f"INVALID recall (filtered gold) = {invalid:.2%}")
# INVALID recall (filtered gold) = 100.00%
assert rate == 0.5
assert standard_recall_at_k(queries, docs) == 0.5
assert invalid == 1.0
Bei der Hälfte der Queries geht das Gold-Dokument durch den Filter verloren, sodass der korrekte Recall@10 auf 50 % fällt. Dieser Score erfasst das Symptom, kann es aber nicht zuordnen. Die False-Exclusion-Rate zeigt, dass das Prädikat zwei Antworten entfernt hat, bevor der Retriever ausgeführt wurde. Der absichtlich ungültige Evaluator meldet nur deshalb 100 %, weil er diese Fehler aus seiner Gold-Menge entfernt. Kein Model kann ein Dokument wiederherstellen, das herausgefiltert wurde.
Die oben genannte Rate von 50 % wird im begleitenden Repository als Unit-Test reproduziert: tests/test_filter_exclusion.py::test_50_percent_exclusion_rate. Notebook 04 führt den Test auf SciFact mit synthetischen Metadaten aus, sodass Sie beobachten können, wie ein echter Filter den Recall auf null setzt; die Runtime-Metrik (mit Predicate-Precision/Recall als ergänzender Metrik) befindet sich in evaluation/filter_exclusion.py.
Ergänzende Metrik: Predicate Precision und Recall
Wenn das Filtering dynamisch erfolgt (beispielsweise wenn ein LLM Filterprädikate aus der Query extrahiert), behandeln Sie den Predicate Extractor als Classification Model und evaluieren Sie ihn entsprechend. Messen Sie Predicate Precision und Recall anhand eines gelabelten Sets von (query, correct predicate)-Paaren. Eine Predicate Error Rate lässt sich nicht direkt in denselben Punktverlust beim Retrieval-Recall übersetzen; messen Sie, wie häufig diese Fehler ein Gold-Dokument ausschließen. Sobald ein harter Filter das Gold-Dokument entfernt, hilft auch noch so viel Reranking nicht weiter.
Soft Boost vs. Hard Filter
Diese Metrik erzwingt eine Designentscheidung. Verwenden Sie Hard Filters, wenn Korrektheit binär ist: rechtliche Zuständigkeit, ACL-Grenzen, veröffentlicht versus Entwurf. Verwenden Sie Soft Boosts, wenn Relevanz abgestuft ist: Locale-Präferenz, Aktualität, Version. Ohne eine Messung der Exklusionsrate ist die falsche Wahl schwer zu erkennen.
Die Entscheidungsregel, messbar formuliert:
For each filter predicate F:
hard_recall_F = retrieval_recall@k with F as a hard filter
soft_recall_F = retrieval_recall@k with F as a +0.X rerank boost
hard_precision = relevant_in_top_k / k under hard filter
soft_precision = relevant_in_top_k / k under soft boost
exclusion_rate = % of queries where the gold doc was filtered out (hard)
Use hard filter only if exclusion_rate < ε AND hard_precision >> soft_precision.
Otherwise prefer soft boost.
Wählen Sie ε anhand des Schadens eines fälschlichen Ausschlusses, des Nutzens zusätzlicher Präzision und der Größe der Evaluationsstichprobe. Ein eigener Beitrag zu diesem Trade-off ist geplant; siehe die am Ende aufgeführten Follow-ups.
Teil 6: Generation Evaluation
Retrieval-Metriken zeigen, dass das System korrekt antworten könnte. Sie zeigen nicht, dass es das auch getan hat. Generation-Metriken schließen diese Lücke.
Faithfulness und Groundedness
RAGAS Faithfulness zerlegt die Antwort in atomare Claims (kurze, in sich geschlossene faktische Aussagen) und überprüft anschließend jeden Claim anhand des abgerufenen Kontexts über einen LLM Judge:
Der Prozentsatz der unterstützten Claims ist der Score. Die Struktur ist nützlicher als jede einzelne Zahl, weil sie zeigt, welche Claims nicht unterstützt sind. Der Production Code befindet sich im Package ragas. Das Folgende ist ein No-Run-Legacy-API-Sketch für RAGAS 0.4.3, kein Copy-paste-Programm. Um ihn auszuführen, pinnen Sie ragas==0.4.3, installieren Sie einen Provider-Client, konfigurieren Sie dessen Credentials, erstellen Sie einen Provider-basierten RAGAS LLM und übergeben Sie ihn als evaluator_llm. Das Setup befindet sich absichtlich außerhalb des Blocks und ist Provider-spezifisch; die Funktion nimmt das konfigurierte Objekt als Argument entgegen, statt einen Default zu implizieren. Verwenden Sie für neuen Code die aktuelle collections-basierte API, die RAGAS als Migrationspfad von der Legacy-Metrics-API dokumentiert:
# No-run: legacy RAGAS 0.4.3 API shape.
# Before calling this function, configure a provider-backed RAGAS LLM.
# For example, with the provider credentials already set:
# from openai import AsyncOpenAI
# from ragas.llms import llm_factory
# evaluator_llm = llm_factory("gpt-4o-mini", client=AsyncOpenAI())
from ragas import EvaluationDataset, evaluate
from ragas.metrics import (
Faithfulness,
LLMContextPrecisionWithoutReference,
ResponseRelevancy,
)
def run_legacy_ragas_043(evaluator_llm):
dataset = EvaluationDataset.from_list([
{
"user_input": "How many moons does Mars have?",
"response": "Mars has two moons, Phobos and Deimos.",
"retrieved_contexts": ["Mars has two moons named Phobos and Deimos."],
"reference": "Mars has two moons.",
}
])
return evaluate(
dataset,
metrics=[Faithfulness(), ResponseRelevancy(), LLMContextPrecisionWithoutReference()],
llm=evaluator_llm,
)
RAGAS hat diese Felder in 0.2 umbenannt (question → user_input, answer → response, contexts → retrieved_contexts, ground_truth → reference). Code, der gegen 0.1 geschrieben wurde, schlägt auf verwirrende Weise fehl: Die alten Keys werden verworfen, statt abgelehnt zu werden. Daher nennt der Fehler die neuen Spalten als fehlend.
Unten ist derselbe Loop mit einem deterministischen Stand-in Judge vollständig ausgerollt, damit Sie die Struktur von Anfang bis Ende sehen können.
def extract_claims(answer: str) -> list[str]:
# Production: an LLM call that decomposes the answer.
# Demo: split on sentence-final punctuation.
return [c.strip() for c in answer.replace("?", ".").replace("!", ".").split(".") if c.strip()]
def verify_claim(claim: str, context: str) -> bool:
# Production: an NLI (natural-language inference) model or LLM judge.
# Demo: a deterministic stand-in so the example runs offline.
entailed_pairs = {
"Mars has two moons": True,
"Phobos and Deimos orbit Mars": True,
"Mars has a thick atmosphere": False, # unsupported by context
"Curiosity landed in 2012": True,
}
for k, v in entailed_pairs.items():
if k.lower() in claim.lower() or claim.lower() in k.lower():
return v
words = [w.lower() for w in claim.split() if len(w) > 3]
return all(w in context.lower() for w in words) if words else False
context = (
"Mars has two moons, Phobos and Deimos. NASA's Curiosity rover "
"landed on Mars in 2012."
)
answer = (
"Mars has two moons. Phobos and Deimos orbit Mars. "
"Mars has a thick atmosphere. Curiosity landed in 2012."
)
claims = extract_claims(answer)
verdicts = [(c, verify_claim(c, context)) for c in claims]
faithfulness = sum(1 for _, ok in verdicts if ok) / len(verdicts)
for c, ok in verdicts:
print(f" [{'✓' if ok else '✗'}] {c}")
print(f"faithfulness = {faithfulness:.2f}")
# faithfulness = 0.75 (one unsupported claim about the atmosphere)
Die Struktur ist entscheidend. In Production wird verify_claim zu einem NLI-Modell oder einem LLM Call. Der Rest des Harness bleibt unverändert: extrahieren, verifizieren, aggregieren.
End-to-End-Extraktion und Verifizierung von Claims aus generierten SciFact-Antworten: Notebook 05; Modul: evaluation/faithfulness.py. Das Repo führt denselben Loop über zwei Judge-Familien aus — das eigene Model des Generators und einen Cross-Family Judge (RAG_EVALS_JUDGE_MODEL) — sowie über eine deterministische lexikalische Baseline. So können Sie sehen, an welchen Stellen die Familien voneinander abweichen.
Eine gezielt entwickelte Alternative zu LLM-as-judge ist HHEM-2.1-Open (Hughes Hallucination Evaluation Model, Vectara) – ein auf Hallucination Detection spezialisiertes Classifier-Modell. Die Model Card dokumentiert den Checkpoint, den ausgegebenen rohen 0–1-Score und die Ergebnisse zur Balanced Accuracy auf AggreFact und RAGTruth. Eine standardmäßige Entscheidungsgrenze wird nicht veröffentlicht; diese müssen Sie selbst festlegen. Betrachten Sie diese Angaben als Evidenz aus der Model Card, nicht als Garantie für Ihr Corpus: Kalibrieren Sie den Threshold anhand lokaler Labels und vergleichen Sie ihn vor dem Deployment mit Ihrem ausgewählten Judge.
Atomic-Fact-Evaluation
FActScore (Min et al., EMNLP 2023) zerlegt Long-Form-Generierungen in atomare Fakten, ruft für jeden Fakt Evidenz ab, versieht ihn mit einem Label supported / not-supported und gibt den Anteil der unterstützten Fakten aus:
Referenzimplementierung: shmsw25/FActScore. Sie funktioniert gut für Biografien, Zusammenfassungen und andere Long-Form-Outputs. Achtung: Wiederholte triviale Fakten können den Score künstlich erhöhen, und „MontageLie“-Angriffe (wahre Fakten in irreführender Reihenfolge) können das Verfahren täuschen. VeriScore verarbeitet Claims mit erforderlichen Modifikatoren; der Core-Filter hilft, Fact-Padding zu verhindern.
Citation Accuracy
Verfolgen Sie Citation Precision (ob zitierte Textspannen den Claim tatsächlich stützen) und Citation Recall (ob Claims, die zitiert werden sollten, tatsächlich zitiert werden):
Der TREC 2024 RAG Track definiert ein reproduzierbares Protokoll für die Support Evaluation. Thakur et al. (SIGIR 2025) berichten, dass GPT-4o bei einer manuellen Bewertung von Grund auf in 56 % der Fälle mit menschlichen Judges übereinstimmte; nach dem Post-Editing von LLM-Prognosen stieg dieser Wert auf 72 %. Unter den dortigen Bedingungen ist das als Force Multiplier nützlich, nicht jedoch als Ersatz für menschliche Bewertung in High-Stakes-Kontexten. Für eine automatisierte Näherung implementiert ALCE (Gao et al., EMNLP 2023) Citation Precision und Recall mit NLI-basierter Verifikation.
Answer Correctness, Completeness, Refusal
- Answer Correctness gegenüber Ground Truth: Wenn Ground Truth verfügbar ist, verwenden Sie für Short-Answer-Tasks Exact Match oder Token-F1 (
evaluate.load("squad")), für offene Antworten Semantic Similarity (bert-score, Embedding Cosine übersentence-transformersoder RAGASAnswerCorrectness). - Completeness über Nuggets: Ein „Nugget“ ist ein einzelnes atomares Informationselement, das jede korrekte Antwort enthalten muss (für „Wann wurde das Unternehmen gegründet?“ könnten die Nuggets beispielsweise
{year: 1994, founder: Jane Doe}sein). TREC extrahiert mit AutoNuggetizer die Gold-Nuggets einer korrekten Antwort aus einer Referenz und bewertet anschließend, welchen Anteil das System abdeckt – mit starker Korrelation zur manuellen Evaluation über 21 Themen × 45 Runs beim TREC 2024. - Refusal-Verhalten: Queries, auf die das Corpus keine Antwort enthält, sollten Abstention statt Hallucination erzeugen. Verfolgen Sie Abstention Precision (korrekte Refusals) und Abstention Recall (Out-of-Scope-Queries, die eine Refusal ausgelöst haben). NoMIRACL ist der öffentliche Benchmark; in Ihrer eigenen Domain sollten Sie einen Teil der Out-of-Scope-Queries labeln und die Abstention Accuracy verfolgen.
Post-Generation Verification
Die kostengünstigsten Reliability-Gewinne entstehen häufig durch deterministische Post-Checks und nicht durch größere Models.
- Entity Grounding Check: Jede Named Entity in der Antwort muss im abgerufenen Kontext vorkommen oder daraus ableitbar sein. Ein einfacher Regex- und Exact-Match-Check (oder
spaCy’sentsgegen einen normalisierten Kontext-String) erkennt überraschend viele Hallucinations. - Claim Verification: Claims extrahieren, NLI gegen den Kontext ausführen und alle Claims unterhalb des Schwellenwerts ablehnen oder markieren. NLI-as-Faithfulness-Modelle:
cross-encoder/nli-deberta-v3-large,MoritzLaurer/DeBERTa-v3-large-mnli-fever-anli-ling-wanli. Erhöht die Latency. Für High-Stakes-Domains lohnt sich das. - Self-Consistency (Wang et al., ICLR 2023): Mehrere Generations bei einer Temperature > 0 sampeln; die Agreement Rate ausgeben (z. B. den Anteil der Generations, die mit der Modalantwort übereinstimmen, oder den paarweisen BERTScore); die Anzahl der Samples anhand der Stability–Cost-Kurve wählen und Antworten mit geringer Übereinstimmung für die Prüfung durch Menschen markieren.
- Confidence Calibration: Verbalisierte Confidence sammeln („How confident are you, 0–1?“) und mit der tatsächlichen Korrektheit auf dem Eval-Set vergleichen. Eine Calibration Curve plotten und den Expected Calibration Error ausgeben: , wobei Confidence Bins sind. Implementierungen:
netcal,torchmetrics.CalibrationError. Ein Model mit einer gemeldeten Confidence von 0.9 sollte in ungefähr 90 % vergleichbarer Fälle korrekt sein; die Abweichung messen, statt Calibration vorauszusetzen.
Part 7: Ontology-grounded RAG Evaluation
Die Standardmetriken oben decken Open-Corpus-RAG ab. Wenn dein RAG gegen eine strukturierte Ontology, Taxonomy oder einen Knowledge Graph retrievt, sind diese Metriken notwendig, aber nicht ausreichend. Beispiele sind Produkte in einem Katalog, Conditions in SNOMED, Components in einer BOM und Security Techniques in MITRE ATT&CK. Zusätzlich musst du die Ontology-Layer messen.
Entity Linking Accuracy
Die erste Aufgabe besteht darin, eine Query-Mention einer Ontology-Entity zuzuordnen („Aspirin“ → wikidata:Q18216, „the 737“ → aircraft:Boeing_737).
- Mention-Level Precision/Recall/F1: Standardmetriken, berechnet anhand von Gold-Mention-Spans (mit
seqevaloder einem Span-Set-Comparator). - Disambiguation Accuracy: Welcher Anteil der korrekt erkannten Mentions wird der richtigen Entity ID zugeordnet? Öffentliche Referenzen sind ReFinED, REL und GENRE; Benchmarks wie AIDA-CoNLL und BELB zeigen, dass die Ergebnisse je nach System und Domain variieren.
- NIL Handling: Precision/Recall für „Entity nicht in der Ontology“. Over-Linking zu ähnlichen, aber falschen Entities getrennt von korrekter Abstention messen.
Hierarchy-aware Evaluation
Plain Accuracy behandelt „Sedan vorhergesagt, obwohl Hatchback korrekt wäre“ genauso wie „Sedan vorhergesagt, obwohl Submarine korrekt wäre“. Diese Fehler sind nicht gleichwertig.
-
Hierarchical Precision/Recall/F1 (Kosmopoulos et al., 2015): Ancestors und Descendants im Ontology-DAG anrechnen. Mit dem vorhergesagten Node und all seinen Ancestors sowie dem wahren Node und all seinen Ancestors:
Mit
networkxauf dem Ontology-Graph implementieren: Jede Prediction und jedes Label um seine Ancestors erweitern und anschließend die oben beschriebenen Set-Überschneidungen berechnen. -
Wu-Palmer-Ähnlichkeit zwischen der vorhergesagten und der Gold-Entität in der Taxonomie (Wu & Palmer, 1994):
Dabei ist LCA der niedrigste gemeinsame Vorfahr in der Taxonomie. Für WordNet ist dies in NLTK standardmäßig verfügbar (
from nltk.corpus import wordnet as wn; wn.synset("car.n.01").wup_similarity(wn.synset("truck.n.01"))); für benutzerdefinierte Taxonomien berechnen Sie die LCA mitnetworkx. -
Fehlerrate bei Geschwister-/Elternverwechslungen: Erfassen Sie Verwechslungen mit Geschwistern, Eltern und Kindern separat —
count_sibling / total_errors,count_parent / total_errors,count_descendant / total_errors. Verwenden Sie geprüfte Beispiele, um zu testen, ob Geschwsterfehler durch mehrdeutige Erwähnungen und Elternfehler durch Übergeneralisierung entstehen.
Rate des fälschlichen Ausschlusses durch Filter (erneut, jetzt kritisch)
In Ontology-Grounded-Systemen stammen harte Filter häufig direkt aus der Ontologie („Rufe nur Dokumente ab, die mit Kategorie X getaggt sind“). Die Ausschlussrate (definiert in Teil 5) wird dadurch zu einem primären Signal für die Korrektheit. Eine falsche Kategorievorhersage kann den Recall auf null setzen; die Ausschlussrate ordnet diesen Verlust dem Filter zu.
Konformität bei der Constrained Generation
Wenn Ihre Ausgabe einer Ontologie entsprechen muss (jeder Entitätsname in der Antwort muss ein gültiges Ontology-Mitglied sein; jedes Prädikat muss aus einem geschlossenen Vokabular stammen), messen Sie:
- Schema-Validitätsrate: Prozentsatz der Ausgaben, die gegen das Ontology-Schema geparst und validiert werden können. Validieren Sie mit
jsonschemaoderpydantic. JSONSchemaBench ist der öffentliche Benchmark für allgemeine Structured Outputs; für schemaspezifische Ontologien erstellen Sie einen eigenen Validator. - Vokabular-Konformität: Prozentsatz der benannten Entitäten in der Ausgabe, die gültige Ontology-IDs sind — eine einfache Prüfung der Set-Mitgliedschaft gegen das geschlossene Vokabular.
- Semantische Konformität: Eine syntaktisch gültige Ausgabe kann dennoch die falsche, aber gültige Entität auswählen. Kombinieren Sie die Konformitätsmessung mit der Korrektheit der nachgelagerten Antwort.
Constrained-Decoding-Frameworks (Outlines, XGrammar, Guidance, OpenAI Structured Outputs) sind darauf ausgelegt, die Schema-Validität zu erzwingen. JSONSchemaBench vergleicht Effizienz, Abdeckung und Qualität verschiedener Implementierungen. Führen Sie die zu Ihren Schemas und Ihrem Serving-Backend passenden Fälle erneut aus, da Abdeckung und Latenz von beiden abhängen.
Auditierbarkeit
Für Ontology-Grounded-Systeme, deren Antworten geprüft werden:
- Vollständigkeit der Zitate: Prozentsatz der faktischen Aussagen mit mindestens einem überprüfbaren Zitat.
- Tiefe der Provenance: Prozentsatz der Zitate, die bis zu einem Quelldokument mit stabiler ID aufgelöst werden können, nicht nur bis zu einem Chunk-Hash.
- Reproduzierbarkeitsrate: Bei erneuter Ausführung derselben Anfrage mit einem festen Snapshot wird dieselbe Antwort zurückgegeben. Fixieren Sie die Model-Version, den Runtime, die Decoding-Konfiguration und den Seed. Legen Sie anschließend die erforderliche Wiederholungsrate anhand der Auditierbarkeitsanforderungen des Workflows fest. Temperatur null allein garantiert keinen deterministischen Ablauf. Ein Fehlschlag kann durch die Generation, den Serving-Runtime oder jede vorgelagerte Stufe verursacht werden.
Teil 8: Evaluation auf Systemebene
Ganzheitliche Antwortqualität
- LLM-as-Judge (Zheng et al., NeurIPS 2023): ein skalierbarer Model-basierter Evaluationsansatz. G-Eval (Liu et al., EMNLP 2023) leitet aus einem natürlichsprachlichen Kriterium eine Bewertungsrichtlinie ab. Anschließend wird mithilfe einer nach Log-Probability gewichteten Ausgabe bewertet. Die Übereinstimmung hängt vom Judge, der Aufgabe, dem Prompt und dem Calibration Set ab.
- Paarweiser Präferenzvergleich: Dem Judge wird Antwort A gegenüber Antwort B präsentiert; anschließend wird die Präferenz erfasst. Dadurch entfallen Probleme bei der Kalibrierung absoluter Scores. MT-Bench berichtete unter den Bedingungen seines Benchmarks eine Übereinstimmung des GPT-4 Judge von über 80 % sowohl mit menschlichen Präferenzen als auch mit der Übereinstimmung zwischen Menschen; ohne Calibration sollte dieser Wert nicht auf eine andere Domäne übertragen werden.
LLM-as-Judge weist reale Verzerrungen auf:
- Positionsbias: Judges bevorzugen unabhängig von der Qualität die erste oder zweite Antwort. Gegenmaßnahmen: die Reihenfolge randomisieren oder beide Reihenfolgen ausführen und mitteln.
- Verbosity Bias: Judges können Länge mit Qualität verwechseln. Eine kontrollierte Studie aus dem Jahr 2026 stellte ein heterogenes Verhalten bei Expansion-Paaren fest. Drei Judges bevorzugten längere Antworten, Claude bevorzugte knappe Antworten, und GPT-4o war ungefähr neutral. Alle fünf schnitten bei Truncation Controls gut ab. Diese Ergebnisse sind an den Benchmark gebunden. Geben Sie Ihrem Judge daher vor, wie Vollständigkeit und Fülltext zu behandeln sind, und berichten Sie die längenkontrollierte Performance anhand Ihrer eigenen Bewertungsrichtlinie.
- Self-Preference Bias: GPT-4 bevorzugt GPT-4-Ausgaben; der Bias korreliert mit der Perplexity der Ausgabe (Judges bevorzugen Text, der ihnen vertraut ist). Gegenmaßnahme: Verwenden Sie eine andere Judge-Familie als für das evaluierte System. Verwenden Sie kein Model, um sich selbst zu bewerten.
Praktisches Vorgehen: Wählen Sie anhand von von Menschen gelabelten Calibration Data einen Judge aus, randomisieren Sie die Reihenfolge der Antworten, maskieren Sie Model-Identitäten und legen Sie die Längenrichtlinie in der Bewertungsrichtlinie fest. Wiederholen Sie Fälle nur, wenn die zusätzlichen Samples die Unsicherheit substanziell reduzieren. Vergleichen Sie bei High-Stakes-Evaluationen Judges aus unterschiedlichen Model-Familien und analysieren Sie Abweichungen anhand menschlicher Labels.
Schema-Guided Reasoning für Judges
Freiform-Ausgaben sind eine Quelle für Variationen in Judge-Runs. Zwei Runs mit derselben Antwort können die Bewertungsrichtlinie unterschiedlich strukturieren und verschiedene Scores erzeugen. Schema-Guided Reasoning (SGR) macht diese Bewertungsrichtlinie explizit: Definieren Sie die Evaluationsstufen als Pydantic-Schema und verwenden Sie anschließend Constrained Output mit Outlines, XGrammar, vLLM Structured Outputs oder OpenAI response_format, sodass jeder Run dieselben Felder in derselben Reihenfolge zurückgibt.
Für RAG-Evals zerlegt das Schema die Bewertung in explizite, auditierbare Felder, statt das Model direkt zu einer Zahl springen zu lassen:
from pydantic import BaseModel, Field
from typing import Literal
class FaithfulnessJudgment(BaseModel):
extracted_claims: list[str] = Field(
description="Atomic factual claims in the answer, one per item."
)
supported_claims: list[str] = Field(
description="Subset of extracted_claims that are entailed by the context."
)
unsupported_claims: list[str] = Field(
description="Subset that is NOT entailed by the context."
)
failure_mode: Literal[
"none", "fabrication", "overgeneralization", "wrong_entity", "stale_fact"
]
score: float = Field(ge=0.0, le=1.0)
rationale: str
Die strukturierten Felder machen den Score als len(supported) / len(extracted) rekonstruierbar und zeigen exakt, bei welchen Claims sich zwei Judges uneinig waren. Das Pydantic-Model macht außerdem eine Änderung der Bewertungsrichtlinie als Code-Diff sichtbar. Constrained Output garantiert die Form, nicht ein unvoreingenommenes Urteil. Positionsrandomisierung, Judges aus unterschiedlichen Model-Familien und die Kalibrierung durch Menschen bleiben daher erforderlich.
Dies funktioniert für jeden Judge auf Basis einer Bewertungsrichtlinie, nicht nur für Faithfulness. Paarweise Präferenzen, Citation Support und die Korrektheit von Refusals profitieren gleichermaßen von diesem Vorgehen.
Ein G-Eval-/Pairwise-/Position-Bias-/Cross-Family-Judge-Harness befindet sich in Notebook 07; Modul: evaluation/llm_judge.py. Der Benchmark-Sweep (make benchmark im Repository) verbindet drei Modelle (gpt-5-mini, claude-haiku-4-5, gemini-2.5-flash) mit einem rotierenden Pairwise-A/B-Judge, sodass jedes Modell die beiden anderen bewertet und sich die Selbstpräferenz als Zahl zeigt.
Latenz und Kosten
- p50, p95, p99 in jeder Pipeline-Phase. Wähle das SLO-Perzentil und den Alert-Schwellenwert anhand der User Journey, des Traffic-Volumens und des Error Budgets.
- Time-to-first-token im Vergleich zur gesamten Generierungszeit. Für eine Streaming-UX ist TTFT für User entscheidend.
- Aufschlüsselung nach Phasen: Retrieval, Reranking, Generierung, Post-Processing. Nutze den Trace, um den Tail zu lokalisieren, statt anzunehmen, welche Phase ihn verursacht hat; erfasse beim Vergleich von Runs Device und Batch-Größe des Rerankers.
- Gesamtbetrag $/Query = Embedding + Retrieval + Reranking + Generierung + anteilige Storage-Kosten. Erfasse p50 und p99; im Long Tail entsteht der größte Teil des Budgets.
- Cache-Hit-Raten auf den Ebenen Embedding-Cache, Retrieval-Cache und KV-Cache. Lege separate Ziele fest, basierend auf beobachteter Wiederholung, Invalidation Policy und den auf jeder Ebene vermiedenen Kosten.
P50/P95/P99 pro Phase einschließlich einer Aufschlüsselung nach Phasen ist in Notebook 08 sowie im Runner unter evaluation/latency.py integriert; der Benchmark-Report kombiniert Latenz und Faithfulness in einer einzigen Matrix, die du mit make benchmark erneut ausführen kannst.
A/B-Testing
- Randomisierungseinheit: Wähle die Einheit anhand des Estimands, Carryover und Interference. Verwende eine Zuordnung pro User oder pro Session, wenn wiederholte Exposition das Verhalten ändern oder eine inkonsistente UX erzeugen kann. Eine Zuordnung pro Query ist nur dann vertretbar, wenn diese Effekte vernachlässigbar sind und die Analyse wiederholte Beobachtungen modelliert.
- Primäre Metriken, Guardrails und explorative Metriken: Registriere sie vorab. Wähle die primäre Metrik anhand des Product Outcomes; Proxies für Zufriedenheit sind unter anderem Thumbs, Regenerations und Verweildauer. Behandle Latenz und Kosten als Guardrails, wenn sie die User Experience begrenzen.
- Sample Size: Führe vor dem Launch eine Power-Analyse durch – ausgehend vom kleinsten erkennbaren Effekt, der Baseline-Varianz, der Zuordnungseinheit und der Stopping Rule.
Teil 9: Erstellung des Test-Sets
!!! Byte sagt
Ich habe mein Golden Set aus den Fragen zusammengestellt, die ich selbst beantworten konnte. Recall@10 stieg einen Monat lang. Ich bewertete den Retriever auf der einfachen Hälfte des Traffics.
Eine Metrik ist nur so gut wie das Test-Set, auf dem sie ausgeführt wird. Wenn dein Golden Set drei Intents abdeckt, der Production Traffic aber zwölf umfasst, misst Recall@10 nur diese drei Intents. Schlimmer noch: Ein Test-Set, das auf einfache Fragen überfitten kann („Wie lautet die Rückerstattungsrichtlinie des Unternehmens?“), kann ein System freigeben, das bei den schwierigen Fragen versagt („Rückerstattungsberechtigung für eine teilweise Stornierung gemäß dem EU Digital Services Act von 2023, Abrechnung in EUR, ausgehend von Irland?“). Der aggregierte Score steigt, während das System weiterhin bei einem wichtigen Teil des Production Traffics versagt.
Dasselbe Problem betrifft Ground Truth. Wenn SMEs die offensichtlichen Dokumente gelabelt, aber die relevanten Dokumente im Long Tail übersehen haben, wird Recall@k einen Retriever, der sie tatsächlich gefunden hat, zu schlecht bewerten. Du optimierst auf die Labels – nicht auf die Wahrheit.
Stellen Sie den Testsatz zunächst auf Basis der tatsächlichen Query-Verteilung und des tatsächlichen Schwierigkeitsgrads zusammen. Wählen Sie anschließend Metriken, die auf die angestrebten Failure Modes reagieren, und optimieren Sie das System anhand dieser Metriken.
Synthetische Query-Generierung
Verwenden Sie ein LLM, um aus Ihrem Korpus Fragen zu generieren:
- Pro Chunk: „Generiere 3 Fragen, die ein Nutzer stellen könnte und die dieser Chunk beantwortet.“
- Multi-Hop: Samplen Sie zwei Chunks und generieren Sie eine Frage, für deren Beantwortung beide erforderlich sind.
- Adversarial: Generieren Sie Fragen mit Distractor-Entitäten, nahezu identischer Formulierung und mehrdeutigen Verweisen.
RAGAS verfügt über eine integrierte Verteilung von Fragetypen (Reasoning, Conditional, Multi-Context). DataMorgana generiert konfigurierbare synthetische Benchmarks für verschiedene Nutzer- und Fragekategorien. Synthetische Daten sind für Cold Starts und Coverage-Tests nützlich. Sie können reale User Queries jedoch nicht ersetzen.
Aufbau des Golden Dataset
Von Menschen kuratierte Daten bilden die Grundlage des Golden Sets.
- Samplen Sie reale User Queries (oder bei einem Pre-Launch simulierte Queries), stratifiziert nach Intent.
- Lassen Sie SMEs jede Frage beantworten und identifizieren, welche Dokumente die Antwort enthalten.
- Bestimmen Sie die Größe des Sets anhand der Coverage-Matrix und des für Release-Entscheidungen erforderlichen Konfidenzintervalls. Die Coverage ist wichtiger als eine übernommene Anzahl von Queries.
- Kuratieren Sie das Set neu, wenn Release-Kadenz, Drift-Signale, Domain-Risiko und Annotationskapazität dies rechtfertigen.
Adversarial-Testsets
- Kontrafaktische Abfragen: Tauschen Sie zentrale Entitäten in der Query aus. Ruft das System für die geänderte Query die richtigen Chunks ab?
- Distractors: Queries, bei denen das Korpus eine plausible, aber falsche Antwort enthält, die nicht abgerufen werden sollte. Genau das testet RGB (Chen et al., AAAI 2024) unter hoher Belastung: Robustheit gegenüber Rauschen, Zurückweisung negativer Treffer, Informationsintegration und kontrafaktische Robustheit.
- Negation und Quantoren: Queries mit „nicht“, „außer“ und „nur“. Dense Retriever haben damit häufig Schwierigkeiten.
- Out-of-Scope: Queries, auf die es im Korpus keine Antwort gibt. Das System sollte „Ich weiß es nicht“ sagen und nicht halluzinieren. NoMIRACL fällt in diese Kategorie. Evaluieren Sie Abstention für Ihre Production-Query-Typen explizit.
Coverage und kontinuierliche Evaluation
- Erstellen Sie eine Coverage-Matrix: Query-Intent × Dokumenttyp × Ontologiezweig. Streben Sie mindestens eine Query pro Zelle an. Leere Zellen sind nicht überwachte Bereiche, in denen sich Regressionen verbergen.
- Führen Sie bei jedem PR eine begrenzte, schnelle Regression-Teilmenge und nach einem langsameren Zeitplan die vollständige Suite aus.
- Planen Sie die vollständige Golden-Set-Evaluation anhand der Release-Kadenz und der Evaluationskosten. Release Candidates sind ein natürlicher Gate.
- Planen Sie die Drift-Evaluation anhand von Traffic-Volumen, erwarteten Änderungen und Risiko. Verwenden Sie ein rollierendes Production-Sample und stratifizieren Sie nach Feedback, statt die Zielverteilung unbemerkt zu verändern.
Teil 10: Production Monitoring
Die Eval-Suite, die Sie ausliefern, beschreibt das System zum Launch. Danach verändert sich der Production-Traffic.
Implizites und explizites Feedback
- Click-through- bzw. Open-Rate der zitierten Quellen (falls Ihre UI diese Metriken bereitstellt).
- Verweildauer bei der Antwort.
- Regeneration Rate: Prozentsatz der Antworten, zu denen der Benutzer erneut fragt oder das System um eine Überarbeitung bittet. Betrachten Sie dies als ein Unzufriedenheitssignal und kalibrieren Sie es anhand geprüfter Konversationen.
- Copy-, Share- bzw. Export-Raten – ein starkes positives Signal.
- Follow-up-Muster: Muster wie „Sind Sie sicher?“ oder „Aber was ist mit X?“ deuten auf Misstrauen hin.
- Daumen hoch/runter mit optionalen Begründungskategorien (falsch, unvollständig, nicht zum Thema passend, schädlich, langsam). Inline-Edits liefern, sofern Ihre UI sie ermöglicht, in der Regel die informationsreichsten Feedback-Signale.
Drift-Erkennung
- Query Drift: Verfolgen Sie die Verteilung der Query-Embeddings im Vergleich zu einem Referenzfenster mithilfe der KL-Divergenz, von MMD oder eines modellbasierten Detektors. Lösen Sie bei einer Verschiebung einen Alert aus und führen Sie anschließend eine segmentierte Fehlersuche durch.
- Embedding Drift: Halten Sie ein Probe-Set fester Dokumente vor; erzeugen Sie regelmäßig neue Embeddings und messen Sie deren Cosine Similarity zu den ursprünglichen Embeddings. Selbst geringe Abweichungen zwischen Versionen des Provider-Modells können Retrieval unbemerkt beeinträchtigen. Versionierter Embedding-Speicher (unveränderliche Snapshots pro Version) ist die kostengünstigste Gegenmaßnahme.
- Performance Drift: Verfolgen Sie im Zeitverlauf produktionsnahe Metriken (Regeneration Rate nach Intent). Plötzliche Anstiege bedeuten, dass etwas kaputtgegangen ist; langsame Veränderungen bedeuten, dass sich die Welt verändert hat.
Shadow Evaluation und Human-in-the-Loop
Führen Sie das Kandidatensystem parallel zur Produktion aus, vergleichen Sie die Outputs offline und stellen Sie sie den Benutzern nicht bereit. So erkennen Sie Regressionen vor dem Launch. Das verursacht zusätzliche Inference-Kosten, hat aber keine Auswirkungen auf Kunden.
Für das Human-in-the-Loop-(HITL)-Review:
- Übernehmen Sie Outputs mit niedriger Konfidenz in eine Review-Queue.
- Nehmen Sie für ein Blind-Review eine Zufallsstichprobe des Produktions-Traffics auf; legen Sie deren Anteil anhand von Traffic-Volumen, Risiko und Review-Kapazität fest.
- Gewichten Sie Outputs mit negativem Feedback besonders stark.
- Verwenden Sie geprüfte Outputs, um das Golden Set zu erweitern.
Die minimale Guardrail-Menge
Lösen Sie für diese Metriken in der folgenden Prioritätsreihenfolge Alerts aus:
- Faithfulness-/HHEM-Score unterhalb des Schwellenwerts in einer rollierenden Produktionsstichprobe.
- p95-Latency oberhalb des SLO.
- False-Exclusion-Rate des Filters oberhalb des Schwellenwerts (stichprobenbasiert).
- Regeneration Rate außerhalb eines lokal kalibrierten Kontrollbands, das Fenstergröße, Traffic, Saisonalität und das Budget für False Alerts berücksichtigt.
- Kosten pro Query oberhalb des Budgets.
Wenn ein Alert ohne entsprechende Code- oder Model-Änderung ausgelöst wird, handelt es sich wahrscheinlich um Drift. Wird er nach einer Änderung ausgelöst, handelt es sich wahrscheinlich um eine Regression. In beiden Fällen erhalten Sie ein Signal, bevor Support-Tickets eintreffen.
Einschränkungen
- Ziele sind lokal, nicht universell. Jede in diesem Leitfaden als illustrativ gekennzeichnete Zahl ist eine Beispielkonfiguration oder ein berechnetes Ergebnis, kein Release-Schwellenwert. Kalibrieren Sie Schwellenwerte auf Ihre Domäne, die Stakes, die Unsicherheit Ihres Evaluationssets und die Erwartungen der User.
- Der Framework-Bereich entwickelt sich schnell. HHEM-Versionen, RAGAS-Metriknamen, Model Cards und die Reihenfolge auf Leaderboards können sich nach der Veröffentlichung ändern. Prüfen Sie die verlinkte Quelle erneut und führen Sie vor einer Festlegung ein erneutes Benchmarking durch.
- Übereinstimmungswerte für LLM-as-Judge sind mit Vorbehalten zu betrachten. Der Wert von 80 % für GPT-4 im Vergleich zu Menschen stammt aus den Bedingungen von MT-Bench / Chatbot Arena. In Nischendomänen und bei adversarialen Fällen sinkt die Übereinstimmung stark. Setzen Sie Judges als Multiplikator ein, nicht als Ersatz für Stichprobenprüfungen.
- Von Anbietern angegebene Benchmark-Steigerungen sind häufig nicht unabhängig reproduzierbar. Reproduzieren Sie Ergebnisse auf Ihren eigenen Daten, bevor Sie einer Zahl Glauben schenken – insbesondere bei neueren Rerankern und OCR-Systemen.
- Keine Metrik ersetzt die Prüfung der Outputs. Planen Sie eine blinde Prüfung einer zufälligen Produktionsstichprobe ein, abgestimmt auf Traffic, Risiko und die Kapazität der Reviewer. Die Metriken skalieren diese Gewohnheit; sie ersetzen sie nicht.
Als Nächstes in dieser Serie
Dies war der Index. Folgende Fortsetzungen sind geplant:
- Soft Boosts vs. Hard Filters: eine ausführliche Analyse der False-Exclusion-Rate von Filtern – mit Code, echten Produktionsbeispielen und einem Entscheidungs-Framework.
- Chunking Is the Hidden Variable: ein kontrolliertes Experiment zu rekursivem, semantischem, spätem und strukturellem Chunking auf drei Corpora.
- Reranker Selection in 2026: BGE vs. Cohere vs. ZeRank vs. aktuelle Cross-Encoder-Modelle – ein direkter Vergleich von Kosten, Latency und Uplift.
- Ontology-Grounded RAG: An End-to-End Walkthrough: Aufbau des vollständigen Evaluations-Harness für ein Entity-Grounded-Retrieval-System.
- LLM-as-Judge Without the Self-Preference Trap: praxisnahe Rezepte für eine unverzerrte automatisierte Evaluation.
- Online Evaluation in Production: Instrumentierungsmuster, Alerting-Richtlinien und die Dashboards, die echte Regressionen erkennen.
Referenzen
Frameworks und Benchmarks
- Es et al., Ragas: Automated Evaluation of Retrieval Augmented Generation, 2023.
- RAGAS-Dokumentation und GitHub.
- Saad-Falcon et al., ARES: An Automated Evaluation Framework for Retrieval-Augmented Generation Systems, NAACL 2024.
- TruLens, DeepEval, Arize Phoenix.
- Thakur et al., BEIR: A Heterogenous Benchmark for Zero-shot Evaluation of Information Retrieval Models, NeurIPS 2021.
- MTEB Leaderboard.
- TREC 2024 RAG Track.
- Pradeep et al., Initial Nugget Evaluation Results for the TREC 2024 RAG Track with the AutoNuggetizer Framework, 2024.
Retrieval und Ranking
- Cormack, Clarke, Buettcher, Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods, SIGIR 2009.
- Gao et al., Precise Zero-Shot Dense Retrieval Without Relevance Labels (HyDE), 2022.
- Jeong et al., Adaptive-RAG: Learning to Adapt Retrieval-Augmented Large Language Models through Question Complexity, NAACL 2024.
- Anthropic, Introducing Contextual Retrieval, September 2024.
- Günther et al., Late Chunking: Contextual Chunk Embeddings Using Long-Context Embedding Models, 2024.
Generierung, Faktentreue, Judges
- Min et al., FActScore: Fine-grained Atomic Evaluation of Factual Precision in Long Form Text Generation, EMNLP 2023.
- Liu et al., Lost in the Middle: How Language Models Use Long Contexts, TACL 2023.
- Chen et al., Benchmarking Large Language Models in Retrieval-Augmented Generation (RGB), AAAI 2024.
- Vectara, HHEM-2.1-Open hallucination evaluation model.
- Zheng et al., Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena, NeurIPS 2023.
- Thakur et al., Support Evaluation for the TREC 2024 RAG Track: Comparing Human versus LLM Judges, SIGIR 2025.
- Thakur et al., NoMIRACL: Knowing When You Don’t Know for Robust Multilingual Retrieval-Augmented Generation, 2023.
- Geng et al., JSONSchemaBench: A Rigorous Benchmark of Structured Outputs for Language Models, 2025.
- Kosmopoulos et al., Evaluation Measures for Hierarchical Classification: a unified view and novel approaches, 2015.
Drift und Produktion
- Evidently, Embedding drift detection methods compared.
Begleitender Code
slavadubrov/rag-evals-demo— ausführbares Harness für jede Metrik in diesem Artikel auf dem SciFact-Korpus sowie ein Benchmark-Sweep über Chunking × Embedding × LLM. Die Notebooks 00–09, Unit-Tests, die die oben ausgearbeiteten Beispiele absichern, und ein eingebetteter Qdrant-Index ermöglichen die Ausführung ohne Docker.