Warum deine RAG-Pipeline selbstbewussten Unsinn zurückgibt: Chunk-Größe, Reranking und das Eval-Framework, das du vor dem Launch brauchst

#RAG Produktionsfehler

Gründer & Lead Developer

Experte für Softwareentwicklung und Legacy-Code-Optimierung

LinkedIn

Retrieval-Augmented Generation hat ein schmutziges Geheimnis: Die Demo funktioniert immer. Du fügst ein paar Dokumente in ein Notebook ein, schickst eine Anfrage an den Vektorspeicher, und das LLM antwortet flüssig und korrekt. Du zeigst es dem Stakeholder. Alle sind beeindruckt. Du bringst es live.

Drei Wochen später halluziniert das RAG-System in der Produktion Richtliniennummern, zitiert selbstbewusst die falsche Version eines Dokuments, und dein Support-Team hat eine Warteschlange voller verwirrter Folgeanfragen. Aus der Demo ist eine Pipeline geworden, die selbstbewussten Unsinn zurückgibt.

Das ist kein Modellproblem. Das Modell tut genau das, worum du es gebeten hast: eine Antwort aus den abgerufenen Chunks synthetisieren. Das Problem ist, dass die falschen Chunks zurückgegeben wurden - oder die richtigen Chunks auf eine Art zurückkamen, die den Kontext zerstört hat, den das Modell benötigt hätte. RAG-Produktionsfehler sind fast immer Retrieval-Fehler, die als Generierungsfehler verkleidet sind.

In diesem Post möchte ich die drei Schichten durchgehen, die die meisten RAG-Systeme in der Praxis kaputt machen - Chunking, Reranking und Evaluation - anhand von Fehlermustern, die mir wiederholt bei Code-Audits und KI-Integrationsprojekten begegnen. Am Ende solltest du ein konkretes Eval-Framework haben, das du vor dem Launch brauchst und danach offline vor jeder wesentlichen Änderung an deiner Pipeline ausführen kannst.


Das Chunking-Problem, über das niemand ehrlich spricht

Wenn Entwickler zum ersten Mal eine RAG-Pipeline aufbauen, kopieren sie in der Regel die Chunk-Größe aus dem Tutorial, das sie gefunden haben. 512 Token sind häufig. Manchmal 256. Gelegentlich 1.000. Es gibt selten einen prinzipiengeleiteten Grund hinter der Wahl, und das macht einen größeren Unterschied, als die meisten erwarten.

Chunk-Größe ist kein Hyperparameter, den man einmal einstellt und vergisst. Sie ist eine Funktion von drei interagierenden Dingen: der Struktur deiner Quelldokumente, dem Kontextfenster deines Embedding-Modells und der Art der Anfragen, die Nutzer tatsächlich stellen.

Kurze Chunks (128-256 Token) bewahren die lexikalische Präzision - eine bestimmte Klausel in einem Vertrag, ein einzelner Schritt in einem Verfahren. Sie zerstören aber auch den semantischen Kontext. Wenn ein Nutzer fragt "Wie lange ist das Rückgabefenster für Enterprise-Kunden?" und die Antwort einen Absatz umfasst, der lautet "Enterprise-Konten haben Anspruch auf Erstattungen innerhalb von 90 Tagen, sofern der Antrag über das Abrechnungsportal gestellt und vom Account-Management genehmigt wird" - ein 128-Token-Chunk könnte dem LLM das 90-Tage-Fenster ohne die Bedingungen liefern, oder die Bedingungen ohne das Fenster. Das Modell synthetisiert dann eine selbstbewusste, aber unvollständige Antwort.

Lange Chunks (1.024-2.048 Token) bewahren den Kontext, verdünnen aber das Embedding. Ein 1.500-Token-Chunk über deine Preisseite, deine Erstattungsrichtlinie und dein Enterprise-SLA zusammen ergibt ein Embedding, das in einem vagen Bereich des Vektorraums liegt. Er wird für Fragen abgerufen, für die er nicht die beste Antwort ist, und bei Fragen, für die er die beste Antwort wäre, wird er übergangen.

Die ehrliche Antwort ist, dass es keine universell korrekte Chunk-Größe gibt - aber es gibt prinzipiengeleitete Wege, eine zu wählen. Beginne mit der typischen Länge der bedeutungsvollen Einheit in deinem Quellkorpus. Rechtsdokumente haben Klauseln. Support-Dokumentation hat Verfahren. Produkt-Changelogs haben Releases. Identifiziere die semantische Einheit und setze deine Ziel-Chunk-Größe so, dass sie ungefähr eine davon enthält, mit einer Überlappung von 10-20% der Chunk-Größe, um Kontexttrennung an Grenzen zu verhindern.

Überlappung ist bei sequenziellen Dokumenten nicht optional. Wenn du ein zehnstufiges Verfahren hast und Chunks zufällig zwischen Schritt 3 und 4 abschneiden, könnte eine Anfrage zu Schritt 4 einen Chunk zurückgeben, der mitten im Satz beginnt. Das Embedding wird verwirrt sein, und das Modell auch. Eine Überlappung von 50-100 Token bei einem 512-Token-Chunk ist kostengünstig und verhindert die meisten dieser Fehler.

Ein Muster, das die Retrieval-Qualität bei Audits konsistent verbessert, ist hierarchisches Chunking: Speichere sowohl einen kleinen Chunk (für präzises Retrieval) als auch einen größeren Eltern-Chunk (für die Kontextlieferung). Du erstellst Embeddings und suchst in den kleinen Chunks, aber wenn ein kleiner Chunk ausgewählt wird, fügst du den vollständigen Eltern-Chunk in den Prompt ein. Das gibt dir sowohl Retrieval-Präzision als auch Generierungskontext gleichzeitig. Bibliotheken wie LlamaIndex nennen das "Small-to-Big Retrieval", aber das Muster ist direkt gegen pgvector implementierbar, wenn du einen Symfony-Stack betreibst - die Schema-Details findest du in unserem pgvector-Architektur-Blueprint-Post.


Warum ein Reranker das Ergebnis mehr verändert als ein besseres Embedding-Modell

Die meisten Teams, die ihre RAG-Pipeline optimieren, konzentrieren sich auf den Wechsel von Embedding-Modellen. Sie wechseln von text-embedding-ada-002 zu einem neueren Modell, führen ein paar manuelle Tests durch und sind mit der Änderung zufrieden. Die Qualität des Embedding-Modells spielt eine Rolle - aber sie ist nicht der wirkungsvollste Hebel für die meisten produktiven Pipelines.

Der wirkungsvollste Hebel ist das Hinzufügen eines Cross-Encoder-Rerankers zwischen Vektor-Retrieval und Prompt-Zusammenstellung.

Hier ist der Unterschied: Ein Bi-Encoder (die Art von Modell, die zur Erstellung von Embeddings verwendet wird) kodiert Anfrage und jedes Dokument unabhängig und berechnet dann die Ähnlichkeit im Vektorraum. Das ist schnell und skalierbar, weshalb es für das Retrieval über Millionen von Dokumenten funktioniert. Bi-Encoder verlieren jedoch die feinkörnige Token-Level-Interaktion zwischen Anfrage und Dokument - zwei Texte können semantisch nah im Embedding-Raum sein, während einer von ihnen tatsächlich eine viel bessere Antwort auf die spezifische Frage ist.

Ein Cross-Encoder nimmt die Anfrage und einen Kandidaten-Chunk zusammen als einzelne Eingabe und erzeugt einen Relevanzscore. Er beachtet jedes Token der Anfrage in Bezug auf jedes Token des Dokuments. Das ist viel genauer - und viel langsamer, weshalb du ihn nicht für den initialen Retrieval-Durchlauf verwendest.

Das Standardmuster ist: 20-50 Kandidaten aus dem Vektorspeicher abrufen (günstig), mit einem Cross-Encoder neu ordnen (mäßige Kosten, begrenzt durch die Anzahl der Kandidaten), die Top 3-5 für den Prompt nehmen. Bei den meisten RAG-Pipelines, die ich auditiert habe, hat das Hinzufügen eines Cross-Encoder-Rerankers die Faithfulness-Scores um 15-30 Prozentpunkte verbessert, ohne das Embedding-Modell oder die Prompt-Vorlage zu berühren. Das ist eine erhebliche Verbesserung für die Kosten eines zusätzlichen Modellaufrufs pro Anfrage.

Für selbst gehostete Stacks ist cross-encoder/ms-marco-MiniLM-L-6-v2 von HuggingFace ein praktischer Ausgangspunkt - klein genug, um auf einer einzelnen GPU oder sogar einem leistungsstarken CPU-Server für mäßige Query-Volumen zu laufen. Für verwaltete Optionen ist Cohere Rerank einfach zu integrieren und funktioniert gut, wenn du bereits ihr Embedding-Modell verwendest. Das Latenzbudget für ein Cross-Encoder-Reranking über 20 Kandidaten beträgt typischerweise 50-150ms, was innerhalb eines nutzerseitigen Chat-Interface akzeptabel ist.

Die Entscheidungsmatrix für "Lohnt sich ein Reranker?" ist ungefähr folgende: Wenn dein Retrieval-Recall (erscheint das richtige Dokument irgendwo in den Top-20-Ergebnissen?) bereits über 80% liegt, deine Präzision (ist das richtige Dokument unter den Top-3, die in den Prompt eingehen?) aber unter 60% liegt, füge einen Reranker hinzu. Wenn dein Recall unter 80% liegt, behebe zuerst dein Chunking und dein Embedding - ein Reranker kann keine Dokumente wiederherstellen, die nie abgerufen wurden.


Das Vier-Fragen-Eval-Framework

Das mit Abstand häufigste Versagen, das ich in der KI-Produktentwicklung sehe, ist das Ausliefern ohne ein Offline-Evaluierungs-Framework. Teams testen nach Gefühl - sie führen ein paar Anfragen aus, die Antworten sehen vernünftig aus, und sie deployen. Das funktioniert, bis es katastrophal nicht mehr funktioniert.

Ein gutes RAG-Eval-Framework beantwortet vier Fragen zu jeder Anfrage in einem repräsentativen Testset:

1. Faithfulness - ist jede Behauptung in der generierten Antwort im abgerufenen Kontext enthalten? Ein Faithfulness-Score von 1,0 bedeutet, dass das Modell keine Behauptungen aufgestellt hat, die nicht in den abgerufenen Chunks begründet waren. Halluzinationen zeigen sich als Faithfulness unter 1,0. Du misst das, indem du die atomaren Behauptungen in der Antwort extrahierst und jede gegen den abgerufenen Kontext prüfst - das kann mit einem kleinen LLM-Judge-Prompt automatisiert werden. RAGAS ist die am weitesten verbreitete Open-Source-Bibliothek dafür.

2. Antwortrelevanz - beantwortet die Antwort tatsächlich das, was der Nutzer gefragt hat? Ein Modell kann perfekt treu (jede Behauptung ist begründet) sein und trotzdem die Frage umgehen oder eine leicht andere Frage als die gestellte beantworten. Messe das mit einem semantischen Ähnlichkeitsscore zwischen Frage und Antwort, oder mit einem Judge-Prompt, der bewertet, ob die Antwort die Nutzerabsicht auflöst.

3. Kontext-Relevanz - sind die abgerufenen Chunks tatsächlich relevant für die Frage? Das ist eine Retrieval-Qualitätsmetrik, keine Generierungsqualitätsmetrik. Wenn deine Kontext-Relevanz niedrig ist, ist deine Retrieval-Schicht unabhängig davon, was das Modell mit dem schlechten Kontext macht, defekt. Verfolge das getrennt von der Antwortqualität, damit du weißt, ob du Retrieval oder Generierung optimieren musst.

4. End-to-End-Latenz - P50, P95, P99. RAG-Pipelines unter produktiver Last verhalten sich anders als beim Testen, weil Vektorspeicher kalte Caches haben, Reranker Aufwärmkosten haben und LLM-Anbieter Rate-Limits haben. Nimm die Latenz in dein Eval auf, damit du eine Regressions-Basislinie hast, nicht nur Qualitäts-Basislinien.

Das Aufbauen eines Testsets erfordert Disziplin. Du benötigst mindestens 50-100 Frage-Antwort-Paare, die aus realistischen Nutzeranfragen stammen, nicht aus Anfragen, die du dir beim Aufbau des Features ausgedacht hast. Der schnellste Weg, ein realistisches Testset aufzubauen, ist, die ersten zwei Wochen der Produktionsanfragen zu sammeln, eine repräsentative Auswahl zu treffen und die korrekten Antworten manuell zu annotieren. Ja, manuell. Synthetische Testsets, die von demselben LLM generiert wurden, das du evaluierst, sind zirkulär und unzuverlässig - das Modell wird bei seinen eigenen Fehlermustern gut abschneiden.

Führe dieses Framework bei jeder Änderung an deiner Pipeline aus: bei jeder Prompt-Bearbeitung, jedem Chunk-Größen-Experiment, jedem Embedding-Modellwechsel, jeder Reranker-Schwellwertanpassung. Eine Änderung, die die Faithfulness verbessert, aber die Kontext-Relevanz verschlechtert, hat das Problem verlagert, nicht gelöst.


Die Fehlermuster, die wir bei Audits tatsächlich sehen

Wenn wir KI-Integrations-Audits an RAG-gestützten Produkten durchführen, häufen sich die Probleme in einigen wiederkehrenden Mustern, die es wert sind, sie im Voraus zu kennen.

Versions-Verwirrung ist eines der schädlichsten. Wenn dein Dokument-Korpus mehrere Versionen derselben Richtlinie, desselben Verfahrens oder derselben Spezifikation enthält, ruft deine RAG-Pipeline die Version ab, die die höchste Embedding-Ähnlichkeit zur Anfrage aufweist - was möglicherweise nicht die aktuelle Version ist. Das LLM antwortet selbstbewusst aus einer veralteten Quelle. Die Lösung besteht darin, Versions- oder Wirksamkeitsdatum-Metadaten in deinen Chunks zu platzieren und beim Retrieval zu filtern: Nur Chunks abrufen, bei denen effective_date = latest. Metadaten-Filterung in pgvector ist kostengünstig, und diese einzelne Änderung eliminiert eine große Klasse von selbstbewussten-aber-falschen Antworten.

Das verlorene Nadelproblem tritt auf, wenn eine kleine kritische Information - eine bestimmte Zahl, ein Schwellenwert, ein Name - in einem langen Chunk voll von umgebendem Kontext eingebettet ist. Das Embedding für den vollständigen Chunk signalisiert das spezifische Faktum nicht stark, sodass Anfragen, die auf dieses Faktum abzielen, ihn verfehlen werden. Hierarchisches Chunking löst das, aber auch das explizite Extrahieren hochwertiger strukturierter Daten (Zahlen, Daten, benannte Entitäten) in einen separaten Retrieval-Pfad - manchmal ist die richtige Antwort eine SQL-Abfrage, keine Vektorsuche.

Prompt-Bleeding tritt auf, wenn du mehrere Chunks abrufst und diese widersprüchliche Informationen enthalten. Das Modell synthetisiert typischerweise über sie hinweg und erzeugt eine Antwort, die beide Quellen vermischt. Ohne Faithfulness-Evaluation wirst du das nie erkennen. Die Retrieval-Schicht sollte nahezu-doppelte Chunks deduplizieren, und deine Prompt-Vorlage sollte das Modell anweisen, Widersprüche zu melden, anstatt sie stillschweigend aufzulösen.

Token-Budget-Kollaps ist ein stiller Killer im großen Maßstab. Deine Retrieval-Logik ruft 5 Chunks ab. Jeder Chunk ist 512 Token. Du hast einen System-Prompt, eine Nutzernachricht und Konversationsverlauf. Plötzlich näherst du dich deinem Modell-Kontextlimit, und das Framework kürzt stillschweigend die letzten beiden abgerufenen Chunks ab, bevor der Prompt gesendet wird. Das Modell sieht nie den relevantesten Kontext, und dein Eval-Framework (das mit kurzen Konversationen getestet hat) hat das nie bemerkt. Instrumentiere immer deine tatsächliche Token-Nutzung in der Produktion und setze harte Limits für die abgerufene Kontextlänge, bevor der Konversationsverlauf ihn wegkomprimiert.


Bevor du das nächste RAG-Feature auslieferst

Keines dieser Probleme ist exotisch. Chunking-Strategie, Reranking und Eval-Frameworks sind alle gut verstanden - die Lücke liegt meist darin, dass Teams nicht wissen, dass sie sie benötigen, bis sie bereits ohne sie ausgeliefert haben.

Wenn du ein RAG-gestütztes Produkt aufbaust oder wartest und eine unabhängige Bewertung deiner Retrieval-Qualität vor dem nächsten Release möchtest, melde dich bei hello@wolf-tech.io oder starte eine Konversation unter wolf-tech.io. Wir können in der Regel die wirkungsvollsten Korrekturen innerhalb einer einzelnen Audit-Sitzung identifizieren und dir eine konkrete Vorher-Nachher-Basislinie aus dem Eval-Framework liefern.

Ein produktives KI-Feature, das halluziniert, ist kein KI-Problem - es ist ein Engineering-Problem. Und Engineering-Probleme haben Engineering-Lösungen.