Skip to content

5 Context Engineering und Grounding

Im vorherigen Kapitel haben wir unsere RAG-Pipeline um Hybrid Search, Reciprocal Rank Fusion und Reranking erweitert. Wir können jetzt unterschiedliche Suchverfahren kombinieren, die Rangfolge der Treffer verbessern und ungeeignete Dokumentversionen durch Metadatenfilter ausschließen.

Damit haben wir eine wichtige Voraussetzung für gute RAG-Antworten geschaffen: Wir finden die Informationen, die das Sprachmodell für seine Antwort benötigt.

Aber was passiert, nachdem wir diese Informationen gefunden haben?

Stellen wir uns vor, unsere Suche liefert zehn Dokumentabschnitte zur Frage nach der Gültigkeitsdauer eines Orbit-3-Access-Tokens. Einige enthalten die gesuchte Antwort von 60 Minuten. Andere wiederholen dieselbe Information, beschreiben zusätzliche API-Einstellungen oder beziehen sich auf ältere Produktversionen.

Wir könnten sämtliche Treffer an das Sprachmodell übergeben. Technisch wäre das häufig möglich. Aber wäre es auch sinnvoll?

Ein großer Kontext verursacht zusätzliche Tokenkosten und kann irrelevante, redundante oder widersprüchliche Informationen enthalten. Selbst wenn die richtige Antwort irgendwo im Kontext steht, ist nicht garantiert, dass das Modell sie korrekt verwendet.

Gutes Retrieval allein garantiert noch keine gute Antwort.

Genau hier setzt Context Engineering an. Wir entscheiden, welche der gefundenen Informationen das Sprachmodell erhält, wie wir sie strukturieren und welche Regeln für ihre Verwendung gelten.

In diesem Kapitel beschäftigen wir uns mit fünf Fragen:

  1. Wie begrenzen wir die Menge der bereitgestellten Informationen auf ein sinnvolles Tokenbudget?
  2. Wie vermeiden wir, dass identische Inhalte unnötig Platz verbrauchen?
  3. Welche Rolle spielt die Reihenfolge der Informationen im Modellkontext?
  4. Wie stellen wir einen nachvollziehbaren Bezug zwischen Aussagen und ihren Quellen her?
  5. Wie sollte ein RAG-System reagieren, wenn Informationen fehlen oder Quellen einander widersprechen?

Dafür führen wir fünf Python-Experimente durch. Wir untersuchen zunächst die Auswahl und Anordnung der Dokumentabschnitte. Anschließend beschäftigen wir uns mit Grounding, also der Frage, ob die erzeugten Aussagen tatsächlich durch die bereitgestellten Quellen gestützt werden.

Unser Ziel ist nicht, eine vollständige Produktionsarchitektur zu entwickeln. Wir wollen verstehen, wie aus gefundenen Dokumenten ein geeigneter Modellkontext entsteht und welche Grenzen bei der anschließenden Antwortgenerierung bestehen.

So arbeiten wir mit dem Python-Labor

Wir verwenden weiterhin unser Projekt rag-python-lab und den Teralune-Corpus.

Voraussetzung: Die Chroma-Collection teralune_corpus aus Kapitel 3 muss bereits vorhanden sein. Sie enthält 115 Chunks aus 36 Markdown-Dokumenten.

Falls die Collection noch nicht aufgebaut wurde, führen wir zunächst das Indexierungsskript aus:

uv run python 03_embeddings_and_vector_database/06_index_corpus.py

Die fünf Experimente dieses Kapitels liegen im Verzeichnis 05_context_engineering/. Wir starten sie wie gewohnt aus dem Projektverzeichnis, beispielsweise:

uv run python 05_context_engineering/01_context_budget.py
Skript Thema Abschnitt
01_context_budget.py Kontext anhand eines Tokenbudgets begrenzen 5.2
02_context_deduplication.py Identische Inhalte aus dem Kontext entfernen 5.3
03_context_ordering.py Die Position relevanter Informationen untersuchen 5.3
04_grounding_and_citations.py Quellenangaben und Aussagen überprüfen 5.4
05_missing_and_conflicting_evidence.py Fehlende und widersprüchliche Informationen behandeln 5.5

Die Experimente bauen auf den Werkzeugen der vorherigen Kapitel auf. Wir entwickeln keine neue Retrieval-Pipeline, sondern konzentrieren uns auf die Verarbeitung der bereits gefundenen Informationen.

Die ersten drei Experimente untersuchen die Kontextgestaltung ohne zusätzliche Antwortgenerierung. In den Experimenten 5.04 und 5.05 verwenden wir gpt-4.1-mini, um das Verhalten eines Sprachmodells anhand konkreter Quellen zu untersuchen.

Wir betrachten im Buch die entscheidenden Codeausschnitte und ihre tatsächlichen Ergebnisse.

5.1 Vom Retrieval zum Modellkontext

In Kapitel 4 haben wir unsere RAG-Pipeline so aufgebaut, dass sie relevante Dokumentabschnitte findet, ihre Rangfolge verbessert und die besten Treffer an ein Sprachmodell übergibt.

Dabei haben wir eine einfache Strategie verwendet: Wir wählen die drei höchstplatzierten Chunks aus, versehen sie mit Quellenkennungen und stellen sie dem Modell zusammen mit der Benutzerfrage bereit.

Für einen ersten RAG-Prototyp ist das ein sinnvoller Ausgangspunkt. Allerdings beantworten die drei besten Retrieval-Treffer nicht automatisch jede Frage vollständig.

Ein Chunk kann die gesuchte Information enthalten, aber eine wichtige Einschränkung auslassen. Zwei Treffer können dieselbe Aussage wiederholen, während ein weiterer Chunk zusätzliche Bedingungen beschreibt. Außerdem kann ein Dokument zwar thematisch relevant sein, aber für die konkrete Antwort keinen Mehrwert bieten.

Retrieval-Relevanz und Nutzen für die Antwortgenerierung sind nicht dasselbe.

Genau deshalb betrachten wir die Verarbeitung zwischen Retrieval und Sprachmodell als eigenständige Aufgabe.

Context Engineering als eigener Verarbeitungsschritt

Nach dem Retrieval verfügen wir über eine Rangliste potenziell relevanter Chunks. Daraus müssen wir einen Modellkontext zusammenstellen.

Dabei treffen wir mehrere Entscheidungen:

  1. Auswahl: Welche Chunks enthalten die Informationen, die zur Beantwortung der Frage benötigt werden?
  2. Begrenzung: Wie viel Platz steht für die Dokumentinformationen zur Verfügung?
  3. Redundanz: Welche Inhalte wiederholen sich, ohne zusätzliche Informationen zu liefern?
  4. Anordnung: In welcher Reihenfolge stellen wir die ausgewählten Informationen bereit?
  5. Quellenbezug: Wie kennzeichnen wir die Herkunft der Informationen, damit Aussagen später überprüft werden können?

Diese Entscheidungen hängen zusammen.

Entfernen wir beispielsweise identische Chunks, steht mehr Tokenbudget für andere Informationen zur Verfügung. Ändern wir die Reihenfolge der Quellen, verändert sich zwar nicht ihr Inhalt, möglicherweise aber ihre Verarbeitung durch das Sprachmodell.

Auch die Auswahlstrategie beeinflusst das Ergebnis. Ein kurzer Chunk kann eine entscheidende Einschränkung enthalten, obwohl er im Retrieval-Ranking weiter hinten steht.

Es gibt deshalb keine universell optimale Methode zur Zusammenstellung des Kontexts. Welche Strategie geeignet ist, hängt von den Dokumenten, den Fragen und dem verwendeten Modell ab.

Retrieval, Context Engineering und Generation unterscheiden

Für die Entwicklung und Fehlersuche ist es hilfreich, die Aufgaben unserer RAG-Pipeline klar voneinander zu trennen.

Verarbeitungsschritt Leitfrage
Retrieval Welche Chunks könnten relevante Informationen enthalten?
Reranking Welche gefundenen Kandidaten passen am besten zur Frage?
Context Engineering Welche Informationen erhält das Modell, und wie werden sie aufbereitet?
Generation Welche Antwort formuliert das Modell anhand des bereitgestellten Kontexts?
Grounding-Prüfung Werden die Aussagen durch die angegebenen Quellen tatsächlich gestützt?

Diese Unterscheidung hilft uns, Fehler systematisch einzugrenzen.

Angenommen, unsere Wissensbasis enthält die Information, dass ein Orbit-3-Access-Token 60 Minuten gültig ist.

Wenn das Retrieval den entsprechenden Chunk nicht findet, liegt das Problem zunächst bei der Suche.

Findet das Retrieval den Chunk, aber unsere Kontextauswahl verwirft ihn, müssen wir die Regeln des Context Engineering untersuchen.

Ist die Information im Modellkontext vorhanden und das Sprachmodell antwortet trotzdem mit 90 Minuten, liegt der Fehler bei der Verarbeitung oder Interpretation der bereitgestellten Informationen.

Eine falsche RAG-Antwort muss also nicht durch ein schlechtes Sprachmodell entstehen. Sie kann bereits durch Entscheidungen in den vorherigen Verarbeitungsschritten verursacht werden.

Was gehört zum Modellkontext?

Der Begriff Kontext wird bei Sprachmodellen häufig für unterschiedliche Dinge verwendet.

Im weiteren Sinne umfasst der Modellkontext alle Informationen, die dem Modell bei einer Anfrage zur Verfügung stehen. Dazu können gehören:

  • Anweisungen: Wie soll das Modell antworten, und wie soll es mit Unsicherheit umgehen?
  • Benutzerfrage: Welche konkrete Aufgabe soll bearbeitet werden?
  • Dokumentauszüge: Welche externen Informationen stehen zur Beantwortung bereit?
  • Quellenkennungen und Metadaten: Woher stammen die Informationen, und für welchen Gültigkeitsbereich gelten sie?
  • Weitere Anwendungsdaten: Beispielsweise Gesprächsverlauf oder Ergebnisse anderer Werkzeuge.

Diese Bestandteile erfüllen unterschiedliche Funktionen.

Anweisungen beschreiben das gewünschte Verhalten des Modells. Die Benutzerfrage definiert die Aufgabe. Die Dokumentauszüge liefern die fachliche Informationsgrundlage.

Dabei müssen wir eine wichtige Grenze beachten: Abgerufene Dokumente sind Daten, keine vertrauenswürdigen Anweisungen. Ihr Inhalt darf nicht automatisch dieselbe Autorität erhalten wie die Anweisungen unserer Anwendung.

In den folgenden Experimenten konzentrieren wir uns hauptsächlich auf den Dokumentkontext, also die Auswahl, Begrenzung und Anordnung der gefundenen Chunks sowie deren Quellenkennungen.

Context Engineering ist mehr als Prompt Engineering

Prompt Engineering beschäftigt sich insbesondere mit der Formulierung von Aufgaben und Anweisungen.

Context Engineering betrachtet darüber hinaus, welche Informationen einem Modell zur Verfügung gestellt werden, wie sie ausgewählt und strukturiert werden und welche Teile des verfügbaren Kontexts für die jeweilige Aufgabe relevant sind.

Beide Bereiche greifen ineinander. Ein gut formulierter Prompt kann fehlende oder ungeeignete Quellen jedoch nicht ersetzen.

Damit haben wir die Aufgabenverteilung unserer RAG-Pipeline präzisiert.

Im nächsten Abschnitt untersuchen wir die erste praktische Herausforderung: Wie begrenzen wir die Menge der bereitgestellten Informationen, ohne wichtige Inhalte zu verlieren?

5.2 Context Budget: Wie viel Kontext ist sinnvoll?

Sprachmodelle können nur eine begrenzte Anzahl von Tokens innerhalb ihres Kontextfensters verarbeiten. Wie groß dieses Fenster ist, hängt vom verwendeten Modell ab.

Allerdings ist es selten sinnvoll, das gesamte verfügbare Kontextfenster mit Dokumenttexten zu füllen. Neben den gefundenen Informationen benötigen wir Platz für Anweisungen, die Benutzerfrage, gegebenenfalls weitere Anwendungsdaten und die generierte Antwort.

Deshalb unterscheiden wir zwei Größen:

Kontextfenster: Die maximale Tokenmenge, die ein Sprachmodell gemäß seinen technischen Grenzen verarbeiten kann.

Context Budget: Die Tokenmenge, die unsere Anwendung bewusst für einen bestimmten Teil des Modellkontexts reserviert. In unserem Fall sind das die gefundenen Dokumentabschnitte.

Das Context Budget ist somit eine Entscheidung unserer Anwendung und keine automatisch vom Modell vorgegebene Grenze.

Warum Top-k nicht ausreicht

Bisher haben wir die Anzahl der Retrieval-Ergebnisse mit top_k begrenzt.

Ein Wert von top_k=5 bedeutet, dass wir höchstens fünf Treffer auswählen. Er sagt jedoch nichts darüber aus, wie viele Tokens diese Treffer insgesamt benötigen.

Ein Chunk kann nur wenige Sätze enthalten, während ein anderer mehrere Hundert Wörter umfasst. Hinzu kommen Quellenkennungen, Dokumenttitel und weitere Metadaten, die wir zusammen mit den eigentlichen Inhalten an das Sprachmodell übergeben.

Die Anzahl der Chunks ist deshalb kein zuverlässiges Maß für die Größe des Modellkontexts.

Eine einfache Lösung besteht darin, ein festes Tokenbudget vorzugeben und die gefundenen Chunks in ihrer Rangfolge zu durchlaufen.

Wir übernehmen einen Chunk vollständig, wenn er noch in das verfügbare Budget passt. Ist er zu groß, überspringen wir ihn und prüfen den nächsten Kandidaten.

Dieses Verfahren ist leicht umzusetzen und berücksichtigt die Reihenfolge des Retrieval-Rankings. Es garantiert allerdings keine optimale Auswahl: Ein kurzer, weniger relevanter Chunk kann aufgenommen werden, während ein längerer, möglicherweise wichtigerer Chunk keinen Platz mehr findet.

Tokens sind modellabhängig

Die Tokenisierung haben wir bereits in den ersten Kapiteln kennengelernt. Für unser Context Budget wird nun ein wichtiger Unterschied relevant: Nicht jedes Modell zerlegt denselben Text in dieselben Tokens.

Ein Embedding-Modell kann einen anderen Tokenizer verwenden als das Sprachmodell, das später die Antwort generiert.

Für die Vektorsuche verwenden wir weiterhin unsere bestehenden Embeddings. Für das Context Budget orientieren wir uns dagegen am Tokenizer des Generierungsmodells.

Mit tiktoken können wir die passende Kodierung auswählen:

import tiktoken

encoding = tiktoken.encoding_for_model("gpt-4.1-mini")
token_count = len(encoding.encode(context))

Damit bestimmen wir die Tokenzahl des übergebenen Textes nach der Tokenisierung des gewählten Modells.

Allerdings entspricht diese Zahl nicht zwangsläufig dem vollständigen Tokenverbrauch einer API-Anfrage. Anweisungen, Benutzerfrage, Nachrichtenstruktur und weitere Bestandteile können zusätzliche Tokens benötigen.

Für unser Experiment messen wir deshalb bewusst nur den formatierten Dokumentkontext. Sein Budget betrachten wir getrennt vom gesamten Kontextfenster.

Weitere Informationen finden sich im tiktoken-Repository.

Experiment 5.01: Context Budget

Wir untersuchen jetzt, wie sich ein begrenztes Tokenbudget auf die Auswahl unserer Retrieval-Ergebnisse auswirkt.

Experiment ausführen:

uv run python 05_context_engineering/01_context_budget.py

Das Skript verwendet die Retrieval-Verfahren aus Kapitel 4:

  1. Dense Retrieval und BM25 finden relevante Dokumentabschnitte.
  2. Reciprocal Rank Fusion kombiniert die beiden Ranglisten.
  3. Ein Cross-Encoder bewertet die Kandidaten erneut.
  4. Die gefundenen Chunks werden anhand eines Tokenbudgets ausgewählt.

Wie in Abschnitt 4.8 beschränken wir die Suche auf aktuelle Dokumente der Produktversion 3.0.

Neu ist die Kontextauswahl nach dem Reranking.

Wir betrachten die zehn höchstplatzierten Kandidaten und reservieren 650 Tokens für den Dokumentkontext.

Dabei berücksichtigen wir nicht nur den eigentlichen Chunk-Text, sondern auch die formatierten Quellenkennungen und Metadaten.

Die zentrale Logik lässt sich vereinfacht so darstellen:

selected = []
used_tokens = 0

for chunk in ranked_chunks:
    formatted = format_chunk(chunk)
    tokens = len(encoding.encode(formatted))

    if used_tokens + tokens <= context_budget:
        selected.append(formatted)
        used_tokens += tokens

Wir durchlaufen die Kandidaten in ihrer Rangfolge. Für jeden Chunk berechnen wir die benötigte Tokenmenge und prüfen, ob er vollständig in das verbleibende Budget passt.

Ist das der Fall, übernehmen wir ihn. Andernfalls überspringen wir ihn.

Das tatsächliche Skript berücksichtigt bei der Tokenzählung zusätzlich den Zeilenumbruch zwischen den formatierten Quellenblöcken.

Die Summe der einzeln berechneten Tokenzahlen dient dabei als Budgetschätzung. Da Tokenizer Text über Blockgrenzen hinweg unterschiedlich zerlegen können, muss sie nicht exakt der Tokenzahl des später zusammengesetzten Gesamtkontexts entsprechen.

Für unser Experiment genügt diese einfache Strategie. Eine produktive Anwendung sollte die tatsächliche Größe des vollständigen API-Inputs zusätzlich kontrollieren.

Unser tatsächliches Ergebnis

Wir stellen erneut unsere bekannte Frage:

How long is an Orbit 3 access token valid?

Das Experiment lieferte folgende Rangliste:

Rang Chunk Tokens Entscheidung
1 D002-chunk-1 161 Aufgenommen
2 D033-chunk-1 145 Aufgenommen
3 D005-chunk-1 159 Aufgenommen
4 D033-chunk-2 112 Aufgenommen
5 D001-chunk-3 137 Übersprungen
6 D002-chunk-2 178 Übersprungen
7 D005-chunk-2 142 Übersprungen
8 D018-chunk-3 121 Übersprungen
9 D021-chunk-1 138 Übersprungen
10 D038-chunk-2 178 Übersprungen

Die Zusammenfassung des Skripts lautete:

Selected: 4 / 10 sources
Used: 577 / 650 tokens

Von zehn Kandidaten wurden vier in den Modellkontext aufgenommen.

Die ersten beiden Chunks stammen aus der OAuth-Dokumentation und den Orbit-3-Release-Notes. Beide nennen die gesuchte Tokenlaufzeit von 60 Minuten.

Der dritte Chunk beschreibt die Migration von Orbit 2.4 auf Orbit 3.0 und bestätigt, dass sich die Tokenlaufzeit von 120 auf 60 Minuten geändert hat.

Diese drei Quellen liefern somit relevante Informationen zur Beantwortung unserer Frage.

Der vierte Chunk, D033-chunk-2, behandelt dagegen unter anderem Request-Limits, Aufbewahrungsfristen und Webhook-Retries. Er passt zwar in das verbleibende Budget, trägt aber nicht unmittelbar zur Antwort auf unsere Frage bei.

Damit zeigt das Experiment zwei Dinge.

Erstens begrenzen wir die Menge der bereitgestellten Informationen. Statt alle zehn Kandidaten zu übergeben, verwenden wir nur vier Quellen.

Zweitens führt diese Begrenzung nicht automatisch dazu, dass ausschließlich die nützlichsten Informationen ausgewählt werden.

Ein Tokenbudget kontrolliert die Kontextgröße, nicht die Kontextqualität.

Wie wählen wir ein sinnvolles Budget?

Es gibt keinen universell richtigen Wert für ein Context Budget.

Ein kleineres Budget reduziert die Menge der übergebenen Dokumenttexte und damit häufig auch die Tokenkosten. Gleichzeitig steigt das Risiko, dass wichtige Informationen ausgeschlossen werden.

Ein größeres Budget ermöglicht es, zusätzliche Belege und Einschränkungen bereitzustellen. Es kann aber auch redundante oder irrelevante Informationen aufnehmen.

Die geeignete Größe hängt unter anderem von den Chunk-Größen, der Komplexität der Fragen, dem verwendeten Modell und der gewünschten Antwortlänge ab.

Unser Wert von 650 Tokens dient ausschließlich dazu, die Auswirkungen der Kontextbegrenzung im Experiment sichtbar zu machen. Er ist keine allgemeine Empfehlung für RAG-Anwendungen.

Praxis: Context Budgets müssen evaluiert werden

Ein größeres Kontextfenster bedeutet nicht automatisch, dass wir mehr Dokumenttext übergeben sollten.

Sinnvoll ist es, unterschiedliche Budgets anhand repräsentativer Fragen zu vergleichen. Dabei sollten wir nicht nur Tokenverbrauch und Kosten betrachten, sondern vor allem, ob die benötigten Informationen im Kontext enthalten sind und ob das Modell daraus korrekte Antworten erzeugt.

Wie wir solche Entscheidungen systematisch bewerten, untersuchen wir in Kapitel 6.

Unsere bisherige Auswahlstrategie ist bewusst einfach. Weiterführende Ansätze könnten Chunks gezielt kürzen, anhand ihres zusätzlichen Informationsgehalts auswählen oder zusammengehörige Abschnitte verdichten.

Bevor wir solche Verfahren betrachten, untersuchen wir eine grundlegende Verbesserung: Was passiert, wenn mehrere gefundene Chunks exakt denselben Inhalt enthalten?

Damit beschäftigen wir uns im nächsten Abschnitt.

5.3 Context Deduplication und Ordering

Ein begrenztes Tokenbudget zwingt uns, Informationen auszuwählen. Dabei entstehen zwei weitere Fragen: Enthält unser Kontext unnötige Wiederholungen? Und spielt es eine Rolle, an welcher Position wir wichtige Informationen platzieren?

Beide Fragen betreffen die Zusammenstellung des Kontexts nach dem Retrieval. Wir müssen dafür weder neue Embeddings erzeugen noch unsere Suchverfahren verändern.

Context Deduplication: Identische Inhalte entfernen

Doppelte Inhalte können auf unterschiedlichen Wegen in eine Wissensbasis gelangen. Beispielsweise wird ein Dokument versehentlich mehrfach importiert, eine Datei liegt in zwei Verzeichnissen oder ein Verarbeitungsschritt erzeugt identische Chunks mit unterschiedlichen Kennungen.

Ein Retriever kann solche Chunks als eigenständige Treffer behandeln. Werden beide in den Modellkontext übernommen, verbrauchen sie Platz, ohne zusätzliche Informationen bereitzustellen.

Das Problem lässt sich mit einem einfachen Beispiel verdeutlichen:

D002-chunk-1   Orbit 3.0 access token lasts 60 minutes.
D002-copy      Orbit 3.0 access token lasts 60 minutes.
D033-chunk-1   The token lifetime is 60 minutes.

Die ersten beiden Einträge sind inhaltlich identisch. Der dritte stammt dagegen aus einer anderen Quelle und formuliert die Information anders.

Diesen Unterschied müssen wir berücksichtigen.

Deduplication bedeutet nicht, alle Quellen mit derselben Aussage zu entfernen. Unterschiedliche Dokumente können sich gegenseitig bestätigen. Gerade bei technischen Informationen kann es hilfreich sein, wenn beispielsweise eine API-Dokumentation und die Release Notes dieselbe Änderung beschreiben.

Für unser Experiment beschränken wir uns auf die Erkennung textuell identischer Inhalte. Unterschiede bei Leerzeichen und Groß- oder Kleinschreibung ignorieren wir dabei.

Experiment 5.02: Context Deduplication

Experiment ausführen:

uv run python 05_context_engineering/02_context_deduplication.py

Wir laden drei vorhandene Chunks aus Chroma und erzeugen im Arbeitsspeicher eine zusätzliche Kopie von D002-chunk-1.

Das Duplikat erhält die Kennung D002-copy. Sein Text bleibt unverändert.

Anschließend vergleichen wir die Kontextauswahl mit und ohne Deduplication. Beide Varianten verwenden dasselbe Tokenbudget.

Die eigentliche Erkennung benötigt für diesen einfachen Fall nur einen Vergleich der Inhalte. Vereinfacht:

seen = set()
unique_chunks = []

for chunk in chunks:
    if chunk["text"] in seen:
        continue

    seen.add(chunk["text"])
    unique_chunks.append(chunk)

Wir speichern die bereits gesehenen Texte in einer Menge. Taucht derselbe Text erneut auf, übernehmen wir den Chunk nicht noch einmal.

Für größere Datenmengen könnte man statt vollständiger Texte beispielsweise normalisierte Inhalte oder kryptografische Hashwerte verwenden. Dabei müsste allerdings klar definiert sein, wann zwei Inhalte als identisch gelten sollen.

Unser tatsächliches Ergebnis

Unser Skript lieferte:

Context budget: 423 tokens
Without deduplication: D002-chunk-1, D002-copy, D033-chunk-1
With deduplication:    D002-chunk-1, D033-chunk-1, D005-chunk-1
Duplicates removed:   1

Ohne Deduplication verbraucht die Kopie von D002-chunk-1 einen Teil des verfügbaren Budgets. Dadurch findet D005-chunk-1 keinen Platz mehr.

Nach der Entfernung des Duplikats kann dieser zusätzliche Chunk aufgenommen werden.

Das Ergebnis zeigt den Nutzen sehr deutlich: Bei gleichem Kontextbudget erhalten wir mehr unterschiedliche Informationen.

Allerdings löst die einfache Methode nicht alle Formen von Redundanz. Zwei Abschnitte können nahezu denselben Inhalt besitzen, obwohl sich ihre Texte unterscheiden. Um solche Fälle zu erkennen, wären weiterführende Verfahren erforderlich, etwa Ähnlichkeitsvergleiche oder eine semantische Gruppierung.

Dabei entsteht jedoch ein neues Risiko: Eine zu aggressive Deduplication könnte unterschiedliche Aussagen, wichtige Einschränkungen oder unabhängige Belege entfernen.

Deduplication darf keine Informationen zerstören

Identische Texte lassen sich vergleichsweise einfach erkennen. Semantisch ähnliche Texte sind dagegen nicht automatisch austauschbar.

Besonders bei technischen Dokumentationen können kleine Unterschiede entscheidend sein: eine andere Produktversion, eine zusätzliche Bedingung oder ein geänderter Grenzwert. Solche Informationen dürfen nicht allein wegen hoher Textähnlichkeit entfernt werden.

Context Ordering: Wo stehen wichtige Informationen?

Nachdem wir entschieden haben, welche Chunks in den Kontext gelangen, müssen wir sie anordnen.

Die naheliegende Lösung besteht darin, die Reihenfolge des Retrieval-Rankings beizubehalten. Der relevanteste Chunk steht dann am Anfang, gefolgt von den weiteren Treffern.

Es gibt jedoch Gründe, die Anordnung bewusst zu gestalten.

Ein Dokument kann beispielsweise eine grundlegende Definition enthalten, während ein anderes die konkrete Antwort liefert. Bei manchen Aufgaben kann es sinnvoll sein, zuerst die Definition und anschließend die Details bereitzustellen.

Bei anderen Fragen möchten wir den unmittelbar beantwortenden Beleg möglichst weit vorne platzieren.

Die Reihenfolge beeinflusst zunächst nur, wo Informationen im Modellkontext erscheinen. Ob dadurch die Antwortqualität steigt oder sinkt, ist eine empirische Frage.

Das Lost-in-the-Middle-Phänomen

Eine bekannte Untersuchung von Nelson F. Liu und weiteren Autoren beschäftigt sich mit der Frage, wie Sprachmodelle Informationen innerhalb langer Kontexte verwenden.

Die Arbeit Lost in the Middle: How Language Models Use Long Contexts zeigt für die untersuchten Modelle und Aufgaben, dass relevante Informationen häufig besser genutzt wurden, wenn sie am Anfang oder Ende des Kontexts standen. Informationen in der Mitte wurden teilweise schlechter berücksichtigt.

Das bedeutet nicht, dass jedes aktuelle Sprachmodell grundsätzlich Schwierigkeiten mit mittig platzierten Informationen hat. Der Effekt hängt von Modell, Aufgabe, Kontextlänge und weiteren Bedingungen ab.

Für unsere RAG-Anwendung ergibt sich daraus dennoch eine wichtige Überlegung: Die Reihenfolge der Quellen sollte nicht als bedeutungsloses Formatierungsdetail betrachtet werden.

Experiment 5.03: Context Ordering

Experiment ausführen:

uv run python 05_context_engineering/03_context_ordering.py

Wir verwenden fünf vorhandene Teralune-Chunks. Einer davon enthält die für unsere Frage entscheidende Information zur Tokenlaufzeit.

Anschließend erstellen wir zwei Kontexte:

  • Middle: Der relevante Beleg steht zwischen anderen Chunks.
  • First: Derselbe Beleg steht am Anfang.

Die enthaltenen Quellen und Texte bleiben identisch. Nur ihre Reihenfolge verändert sich.

Mit tiktoken messen wir anschließend, an welcher Tokenposition der relevante Beleg beginnt.

Unser tatsächliches Ergebnis

Middle | evidence starts at token  243 / 644 (38% of context)
First  | evidence starts at token    0 / 644 (0% of context)
Same sources: True
Note: Token position is not a measure of answer accuracy.

Beide Kontexte enthalten dieselben fünf Quellen und umfassen jeweils 644 Tokens.

Im ersten Fall beginnt der relevante Beleg bei Token 243, also bei ungefähr 38 Prozent des Kontexts. Im zweiten Fall steht er unmittelbar am Anfang.

Damit haben wir gezeigt, dass wir die Position wichtiger Informationen gezielt verändern können, ohne Quellen hinzuzufügen oder zu entfernen.

Wir haben aber nicht gezeigt, dass eine der beiden Anordnungen zu besseren Antworten führt.

Dafür müssten wir das Sprachmodell mit beiden Kontextvarianten befragen und die Ergebnisse über mehrere Fragen und Wiederholungen vergleichen. Ein einzelner Test wäre auch dann noch kein allgemeiner Qualitätsnachweis.

Context Ordering ist eine Hypothese, keine Erfolgsgarantie

Die Position relevanter Informationen kann die Modellleistung beeinflussen. Eine bestimmte Reihenfolge ist jedoch nicht für jede Aufgabe und jedes Modell optimal.

Unser Experiment misst ausschließlich die Position eines Belegs. Ob das Modell ihn tatsächlich berücksichtigt, untersuchen wir hier nicht.

Welche Reihenfolge sollten wir verwenden?

Für einen einfachen RAG-Prototyp ist die Reihenfolge des Retrieval-Rankings ein vernünftiger Ausgangspunkt.

Weiterführende Strategien könnten beispielsweise unmittelbar beantwortende Quellen bevorzugen, zusammengehörige Abschnitte nebeneinander platzieren oder grundlegende Definitionen vor detaillierte Erläuterungen stellen.

Solche Strategien sollten wir allerdings nicht allein aufgrund ihrer Plausibilität übernehmen. Entscheidend ist, ob sie für unsere tatsächlichen Fragen und Dokumente bessere Ergebnisse liefern.

Damit sind wir bei der nächsten Herausforderung: Selbst ein sorgfältig zusammengestellter Kontext garantiert noch keine sachlich richtige Antwort.

5.4 Grounding und Quellenangaben

Ein RAG-System soll Antworten erzeugen, die sich auf die bereitgestellten Informationen stützen.

Diese Verbindung zwischen einer Aussage und ihrer Informationsgrundlage bezeichnen wir als Grounding.

Für unsere Orbit-Frage bedeutet das: Die Antwort „60 Minuten“ soll nicht aus einer allgemeinen Vermutung über OAuth entstehen. Sie soll durch die tatsächlich bereitgestellte Orbit-3-Dokumentation gestützt werden.

In unserem Corpus finden wir beispielsweise:

An Orbit 3.0 access token lasts 60 minutes.

Die Aussage stammt aus D002-chunk-1, der Dokumentation zu OAuth und API-Schlüsseln.

Eine darauf gestützte Antwort könnte lauten:

An Orbit 3.0 access token lasts 60 minutes [D002-chunk-1].

Die Quellenangabe stellt eine Verbindung zum Dokument her. Sie ist jedoch zunächst nur eine vom Modell erzeugte Zeichenfolge.

Citation und Grounding sind nicht dasselbe

Wir müssen zwei Fragen unterscheiden:

Citation Validation: Existiert die angegebene Quelle tatsächlich im bereitgestellten Kontext?

Factual Grounding: Stützt diese Quelle die konkrete Aussage?

Die erste Frage ist vergleichsweise einfach zu prüfen. Wir können die ausgegebenen Chunk-IDs mit den IDs der bereitgestellten Quellen vergleichen.

Die zweite Frage ist wesentlich anspruchsvoller.

Ein Modell könnte beispielsweise antworten:

An Orbit 3.0 access token lasts 90 minutes [D002-chunk-1].

Die Chunk-ID existiert. Die Quellenangabe ist formal gültig.

Die Aussage ist trotzdem falsch, weil die betreffende Dokumentation 60 Minuten nennt.

Eine gültige Citation beweist daher noch keine sachliche Unterstützung.

Strukturierte Quellenangaben

In unserer ersten RAG-Pipeline aus Kapitel 4 haben wir bereits Chunk-IDs in den Kontext aufgenommen.

Diese Kennungen ermöglichen es, eine Antwort auf konkrete Dokumentabschnitte zurückzuführen.

Eine einfache Darstellung sieht so aus:

[Source: D002-chunk-1]
Orbit 3.0 access tokens last 60 minutes.

[Source: D033-chunk-1]
The token lifetime is 60 minutes.

Das Modell erhält anschließend die Anweisung, seine Antwort ausschließlich aus diesen Informationen abzuleiten und passende Chunk-IDs anzugeben.

Die Anweisung ist hilfreich, aber nicht hinreichend.

Ein Sprachmodell kann eine falsche ID erzeugen, eine vorhandene ID falsch verwenden oder Aussagen formulieren, die über die Quellen hinausgehen.

Deshalb sollten wir die Quellenangaben nach der Generierung zumindest auf formale Gültigkeit prüfen.

Experiment 5.04: Grounding and Citations

Experiment ausführen:

uv run python 05_context_engineering/04_grounding_and_citations.py

Wir verwenden drei Teralune-Chunks, die die Tokenlaufzeit von Orbit 3 dokumentieren.

Das Sprachmodell erhält diese Quellen zusammen mit unserer bekannten Frage:

How long is an Orbit 3 access token valid?

Wir fordern es auf, die Frage anhand des bereitgestellten Kontexts zu beantworten und die verwendeten Chunk-IDs anzugeben.

Anschließend führen wir zwei Prüfungen durch.

Zuerst kontrollieren wir, ob die zitierten IDs im Kontext vorkommen.

Das Grundprinzip lässt sich vereinfacht so darstellen:

valid_citations = cited_ids.issubset(available_ids)

Danach überprüfen wir für unsere konkrete Testfrage, ob die Antwort die erwartete Information „60 Minuten“ enthält.

Das ist bewusst keine allgemeine Faktenprüfung. Wir verwenden eine bekannte Antwort, um den Unterschied zwischen gültigen Quellenkennungen und sachlich richtigen Aussagen sichtbar zu machen.

Unser tatsächliches Ergebnis

Das Modell antwortete:

An Orbit 3 access token is valid for 60 minutes
[D002-chunk-1][D033-chunk-1][D005-chunk-1].

Unsere Prüfungen ergaben:

Citations reference supplied chunks: True
Expected fact (60 minutes) present: True

Die Antwort nennt die korrekte Tokenlaufzeit. Außerdem existieren alle drei angegebenen Chunk-IDs im bereitgestellten Kontext.

Für diese konkrete Frage ist das ein gutes Ergebnis.

Anschließend prüften wir eine bewusst falsche Aussage mit einer vorhandenen Quellen-ID:

False claim: valid citation=True, expected fact=False

Damit demonstrieren wir die Grenze der formalen Quellenprüfung.

Die falsche Aussage verweist auf eine gültige Quelle, wird durch deren Inhalt aber nicht gestützt.

Wie lässt sich Grounding zuverlässiger prüfen?

Eine weiterentwickelte RAG-Anwendung sollte Quellenangaben nicht nur auf ihre Existenz überprüfen, sondern möglichst auch den Zusammenhang zwischen einzelnen Aussagen und den zugehörigen Belegen untersuchen.

Dafür kommen unterschiedliche Ansätze infrage:

Ansatz Was wird geprüft? Grenze
ID-Validierung Existiert die zitierte Quelle? Keine Aussage über sachliche Unterstützung
Regelbasierte Prüfung Stimmen bekannte Werte oder Bedingungen? Nur für vorher definierte Regeln geeignet
Aussage-Beleg-Vergleich Unterstützt ein Textabschnitt eine konkrete Behauptung? Sprachliche Mehrdeutigkeit und Interpretationsspielraum
Modellgestützte Bewertung Beurteilt ein weiteres Modell die Unterstützung? Auch das prüfende Modell kann Fehler machen
Menschliche Prüfung Bewertet ein fachkundiger Mensch die Aussage? Zeitaufwendig und nicht beliebig skalierbar

Bei einem Aussage-Beleg-Vergleich wird eine Antwort beispielsweise in einzelne überprüfbare Behauptungen zerlegt. Anschließend untersucht das System, ob die jeweils angegebenen Quellen diese Behauptungen tatsächlich stützen.

Eine verwandte Aufgabe ist die Natural Language Inference: Dabei wird beurteilt, ob eine Aussage aus einem gegebenen Text folgt, ihm widerspricht oder durch ihn nicht entschieden werden kann.

Solche Verfahren können für Grounding-Prüfungen nützlich sein. Sie liefern jedoch keine automatische Garantie für sachliche Korrektheit.

Die systematische Messung von Antwortqualität und Quellenunterstützung behandeln wir in Kapitel 6.

Grounding und Prompt Injection

Ein weiterer Unterschied ist wichtig: Dokumenttexte sind Daten, keine vertrauenswürdigen Anweisungen.

Ein abgerufener Chunk könnte beispielsweise eine Aufforderung enthalten, die bisherigen Regeln zu ignorieren oder zusätzliche Informationen preiszugeben.

Das Modell sollte solche Texte als Quellenmaterial behandeln, nicht als Anweisungen mit höherer Priorität.

Wir können dieses Verhalten durch geeignete Instruktionen unterstützen. Eine Prompt-Regel allein stellt jedoch keine Sicherheitsgrenze dar.

Insbesondere Zugriffskontrolle, Mandantentrennung und die Auswahl erlaubter Dokumente müssen außerhalb des Sprachmodells durchgesetzt werden. Die technischen Sicherheitsmechanismen behandeln wir ausführlicher in Kapitel 7.

Quellenangaben ersetzen keine Sicherheits- und Faktenprüfung

Eine zitierte Chunk-ID ist zunächst eine Referenz im Antworttext. Sie beweist weder, dass die Quelle die Aussage unterstützt, noch, dass der Nutzer auf diese Quelle zugreifen darf.

Grounding-Prüfung und Zugriffskontrolle sind unterschiedliche Aufgaben. Beide müssen unabhängig von der Formulierung des Prompts berücksichtigt werden.

Quellenbezug als Teil der Anwendungsarchitektur

Für einen ersten RAG-Prototyp genügt es, Quellenkennungen im Kontext bereitzustellen und die generierten Referenzen zu kontrollieren.

In einer produktiven Anwendung benötigen wir darüber hinaus eine verlässliche Zuordnung zwischen Chunk-ID, Ursprungsdokument, Dokumentversion und gegebenenfalls dem konkreten Textabschnitt.

Das ermöglicht beispielsweise, Quellen in einer Benutzeroberfläche anzuzeigen, Aussagen nachzuvollziehen oder bei einer späteren Prüfung den verwendeten Dokumentstand zu rekonstruieren.

Unser Teralune-Corpus besitzt dafür bereits stabile Dokument- und Chunk-Kennungen. Wir verwenden diese Grundlage, ohne in diesem Kapitel eine vollständige Provenienz-Infrastruktur zu entwickeln.

5.5 Fehlende und widersprüchliche Evidenz

Bisher haben wir überwiegend mit Fragen gearbeitet, für die unser Corpus eindeutige Antworten enthält.

In realen Anwendungen ist das nicht immer der Fall.

Manchmal findet das Retrieval keine passende Information. Manchmal enthalten die gefundenen Dokumente zwar relevante Begriffe, beantworten die Frage aber nicht. Und manchmal widersprechen sich zwei Quellen.

Ein RAG-System muss deshalb nicht nur Antworten formulieren können. Es sollte auch erkennen, wann die bereitgestellten Informationen keine belastbare Antwort erlauben.

Fehlende Evidenz: Wenn der Kontext keine Antwort enthält

Nehmen wir erneut unsere bekannte Frage:

How long is an Orbit 3 access token valid?

Wir stellen dem Sprachmodell diesmal absichtlich einen Dokumentabschnitt bereit, der andere Orbit-Einstellungen beschreibt, aber keine Tokenlaufzeit nennt.

Der Kontext enthält beispielsweise Informationen über Request-Limits, Aufbewahrungsfristen und Webhook-Retries.

Ein Sprachmodell könnte versuchen, die Frage trotzdem zu beantworten. Schließlich besitzt es allgemeines Wissen über OAuth und möglicherweise ähnliche Systeme.

Für unsere RAG-Anwendung wäre das jedoch problematisch.

Wir möchten eine Antwort aus der bereitgestellten Dokumentation, keine plausible Vermutung.

Die angemessene Reaktion lautet daher sinngemäß:

The provided context does not contain information about the validity duration of an Orbit 3 access token.

Das Modell benennt die Wissenslücke, statt eine unbelegte Zahl zu nennen.

Dieses Verhalten wird häufig als Abstention bezeichnet: Das System verzichtet auf eine konkrete Antwort, wenn die Informationsgrundlage nicht ausreicht.

Warum eine Antwortverweigerung sinnvoll sein kann

Bei technischen Fragen kann eine unbelegte Antwort erhebliche Folgen haben.

Eine falsche Tokenlaufzeit könnte beispielsweise dazu führen, dass eine Anwendung ihre Zugangsdaten zu spät erneuert. Eine erfundene API-Eigenschaft könnte Entwickler zu einer fehlerhaften Implementierung verleiten.

Ein System, das Unsicherheit offenlegt, ist in solchen Situationen häufig hilfreicher als eines, das jede Frage unbedingt beantworten möchte.

Allerdings dürfen wir daraus keine einfache Regel ableiten, nach der möglichst viele Antworten verweigert werden sollten.

Eine RAG-Anwendung soll weiterhin nützlich sein. Wenn ausreichende Informationen vorhanden sind, sollte sie diese auch verwenden.

Die Herausforderung besteht darin, zwischen beantwortbaren und nicht ausreichend belegten Fragen zu unterscheiden.

Widersprüchliche Evidenz: Wenn Quellen unterschiedliche Werte nennen

Noch schwieriger wird die Situation, wenn zwei Quellen dieselbe Frage unterschiedlich beantworten.

Stellen wir uns folgende Dokumentauszüge vor:

[Source: D002-chunk-1]
An Orbit 3.0 access token lasts 60 minutes.

[Source: SIMULATED-CONFLICT]
Orbit 3.0 access tokens are valid for 90 minutes.

Beide Aussagen beziehen sich ausdrücklich auf Orbit 3.0. Sie können daher nicht ohne Weiteres als unterschiedliche Produktversionen interpretiert werden.

Das Modell sollte den Widerspruch erkennen und offenlegen.

Es sollte nicht allein deshalb 60 Minuten wählen, weil diese Angabe zuerst erscheint. Ebenso wenig sollte es 90 Minuten übernehmen, weil die zweite Quelle möglicherweise ausführlicher formuliert ist.

Eine belastbare Entscheidung würde zusätzliche Informationen benötigen: beispielsweise den Dokumentstatus, eine verlässliche Priorisierung der Quellen oder eine fachliche Klärung.

In unserem Experiment fehlen solche Informationen bewusst.

Experiment 5.05: Missing and Conflicting Evidence

Experiment ausführen:

uv run python 05_context_engineering/05_missing_and_conflicting_evidence.py

Das Experiment verwendet zwei Szenarien.

Szenario A: Fehlende Evidenz

Wir laden D033-chunk-2 aus Chroma. Dieser Chunk enthält Informationen zu Orbit-Einstellungen, aber keine Antwort auf die Frage nach der Tokenlaufzeit.

Das Modell soll ausschließlich auf Grundlage dieses Kontexts antworten.

Szenario B: Widersprüchliche Evidenz

Wir laden D002-chunk-1, der die korrekte Tokenlaufzeit von 60 Minuten dokumentiert.

Anschließend ergänzen wir im Arbeitsspeicher eine simulierte Quelle mit der Behauptung, die Laufzeit betrage 90 Minuten.

Der Chroma-Index bleibt dabei unverändert.

Beide Szenarien verwenden dieselbe Anweisung an das Sprachmodell. Der entscheidende Teil lautet:

instructions = (
    "Answer using only the supplied context. "
    "If the information is missing, say so. "
    "If sources contradict each other, explicitly describe "
    "the conflict. Do not guess or resolve conflicts without "
    "supporting evidence. Cite source IDs."
)

Wir verlangen also ausdrücklich, fehlende Informationen und Widersprüche offenzulegen.

Diese Instruktion beschreibt das gewünschte Verhalten. Sie garantiert jedoch nicht, dass das Modell in jeder Situation entsprechend reagiert.

Unser tatsächliches Ergebnis

Szenario A – Fehlende Evidenz

Das Modell antwortete:

The provided context does not contain information about the validity duration of an Orbit 3 access token.

Es nennt keine Tokenlaufzeit und erkennt korrekt, dass der bereitgestellte Kontext die Frage nicht beantwortet.

Szenario B – Widersprüchliche Evidenz

Das Modell antwortete:

There is a conflict in the sources regarding the validity of an Orbit 3.0 access token:

Anschließend führte es beide Angaben auf:

  • D002-chunk-1: 60 Minuten
  • SIMULATED-CONFLICT: 90 Minuten

Die Antwort endete mit dem Hinweis, dass keine zusätzlichen Informationen zur Auflösung des Widerspruchs vorliegen.

Damit verhielt sich das Modell in beiden Tests wie gewünscht.

Es erfand keine Antwort auf eine unbelegte Frage und entschied einen Widerspruch nicht willkürlich.

Das ist ein erfolgreiches Experiment, aber noch kein Nachweis für allgemeine Zuverlässigkeit.

Wir haben zwei bewusst konstruierte Situationen mit einer einzigen Frage untersucht. Bei anderen Dokumenten, Formulierungen oder Modellen können die Ergebnisse anders ausfallen.

Nicht jeder scheinbare Widerspruch ist ein echter Konflikt

In technischen Dokumentationen können unterschiedliche Angaben durchaus gleichzeitig korrekt sein.

Ein Beispiel aus unserem Teralune-Corpus:

Quelle Produktversion Tokenlaufzeit
Historische Dokumentation Orbit 2.4 120 Minuten
Aktuelle Dokumentation Orbit 3.0 60 Minuten

Diese Angaben widersprechen sich nicht, wenn wir ihren jeweiligen Gültigkeitsbereich berücksichtigen.

Ein Problem entsteht erst, wenn die Anwendung die Versionsinformationen ignoriert und beide Werte als Aussagen über denselben Produktstand behandelt.

Deshalb müssen wir zwischen zwei Situationen unterscheiden:

Kontextabhängige Unterschiede: Die Quellen gelten für unterschiedliche Versionen, Zeiträume oder Bedingungen. Der scheinbare Widerspruch lässt sich durch Metadaten auflösen.

Tatsächliche Konflikte: Die Quellen machen unterschiedliche Aussagen über denselben Sachverhalt unter denselben Bedingungen.

Diese Unterscheidung zeigt erneut, warum Metadaten wichtig sind. In Kapitel 4 haben wir Versions- und Statusfilter bereits beim Retrieval eingesetzt.

Context Engineering ersetzt solche Filter nicht. Es baut auf ihnen auf.

Wie sollte eine Anwendung mit Konflikten umgehen?

Eine produktive RAG-Anwendung benötigt Regeln für den Umgang mit widersprüchlichen Informationen.

Denkbar sind beispielsweise eine Priorisierung freigegebener Dokumentversionen, die Berücksichtigung von Veröffentlichungsdaten oder die Eskalation an eine fachlich zuständige Person.

Solche Regeln sollten jedoch nicht ausschließlich in einem Prompt stehen.

Wenn eine Anwendung verbindlich festlegt, dass eine freigegebene API-Spezifikation Vorrang vor einem älteren Entwurfsdokument besitzt, sollte diese Priorität in der Dokumentverwaltung oder Anwendungslogik nachvollziehbar hinterlegt sein.

Das Modell kann anschließend erklären, welche Quelle verwendet wurde und warum.

Praxis: Unsicherheit sichtbar machen

Ein hilfreiches RAG-System muss nicht jede Frage mit einer konkreten Zahl oder Handlungsempfehlung beantworten.

Wenn Informationen fehlen, sollte es die Lücke benennen. Wenn Quellen widersprüchlich sind, sollte es die unterschiedlichen Angaben kenntlich machen.

Ob das zuverlässig gelingt, muss anhand geeigneter Testfälle überprüft werden. Ein guter Prompt ist dafür ein Ausgangspunkt, aber kein Ersatz für Evaluation.

Was wir gelernt haben

In diesem Kapitel haben wir die Perspektive gewechselt.

In Kapitel 4 ging es darum, die richtigen Informationen zu finden. Jetzt haben wir untersucht, wie wir diese Informationen für die Antwortgenerierung aufbereiten und verwenden.

In diesem Kapitel haben wir untersucht, wie aus gefundenen Dokumentabschnitten ein geeigneter Modellkontext entsteht. Dabei haben wir die Kontextgröße begrenzt, redundante Informationen entfernt und die Anordnung relevanter Quellen betrachtet.

Anschließend haben wir uns mit Grounding beschäftigt. Unsere Experimente haben gezeigt, warum gültige Quellenangaben allein keine sachliche Korrektheit garantieren und weshalb ein RAG-System fehlende oder widersprüchliche Informationen offenlegen sollte.

Damit kennen wir die wichtigsten Verarbeitungsschritte vom Retrieval bis zur quellenbezogenen Antwort. Ob unsere Entscheidungen tatsächlich zu besseren Ergebnissen führen, können wir bislang jedoch nur anhand einzelner Beispiele beurteilen. Wie wir RAG-Systeme systematisch evaluieren und Fehlerursachen untersuchen, behandeln wir in Kapitel 6.

Genau darum geht es in Kapitel 6: Evaluation und Debugging.