Anhang A: Der Teralune-Corpus¶
In den praktischen Beispielen dieses Buchs verwenden wir den Teralune-Corpus, einen eigens entwickelten, vollständig synthetischen Dokumentbestand. Er bildet die technische Dokumentation des fiktiven Unternehmens Teralune Systems und seiner Cloud-Plattform Orbit ab.
Der Corpus enthält 48 Dokumente in fünf Dateiformaten. Neben regulären Produktinformationen umfasst er historische Versionen, widersprüchliche Aussagen und Dokumente mit unterschiedlichen Zugriffsberechtigungen. Damit können wir typische Herausforderungen von RAG-Systemen unter kontrollierten Bedingungen untersuchen.
Der Corpus steht im GitHub-Repository zur Verfügung.
Dieser Anhang beschreibt den Aufbau des Corpus, die wichtigsten Dateien und ihre Aufgaben. Außerdem erläutern wir, wie Fakten, Versionen und Zugriffsrechte organisiert sind und wie sich die bereitgestellten Evaluationsdaten für eigene Experimente verwenden lassen.
Grundlage ist Teralune RAG Training Corpus 1.0.0.
10.1 Der Teralune-Corpus¶
Der Teralune RAG Training Corpus ist ein kontrollierter Dokumentbestand für die Entwicklung und Untersuchung von Retrieval-Augmented-Generation-Anwendungen.
Er wurde speziell für praktische Übungen mit Python erstellt. Anders als ein gewöhnlicher Beispieldatensatz enthält er eine zusammenhängende Produktdokumentation mit unterschiedlichen Dateiformaten, Dokumentversionen, Zugriffsklassen und bewusst eingebauten Schwierigkeiten.
Der Corpus ist vollständig synthetisch. Unternehmen, Produkte, Organisationen, Supportfälle und technische Kennungen wurden für dieses Projekt entwickelt. Die Dokumente enthalten keine echten Kundendaten oder Zugangsdaten.
Das fiktive Unternehmen Teralune Systems¶
Teralune Systems ist ein fiktiver Anbieter einer B2B-Cloud-Plattform namens Teralune Orbit.
Orbit dient der Verwaltung von Geräteidentitäten, der Verarbeitung von Telemetriedaten und der Integration externer Anwendungen.
Die Plattform besitzt typische Funktionen eines industriellen Cloud-Dienstes:
| Bereich | Funktion |
|---|---|
| Geräteverwaltung | Geräte registrieren und Workspaces zuordnen |
| Telemetrie | Messwerte erfassen, abfragen und aufbewahren |
| Authentifizierung | API-Keys, OAuth und Berechtigungen |
| Webhooks | Ereignisse an externe Anwendungen zustellen |
| Alerts | Messwerte überwachen und Benachrichtigungen auslösen |
| Exporte | Daten für externe Verarbeitung bereitstellen |
| Administration | Organisationen, Teams und Rollen verwalten |
| Betrieb | Fehlerdiagnose, Incident-Berichte und Runbooks |
| Abrechnung | Tarife, Kontingente und Abrechnungszeiträume |
Die Dokumentation beschreibt mehrere Produktgenerationen.
Orbit 1.8 und 2.4 repräsentieren ältere Versionen. Orbit 3.0 ist die aktuelle Version innerhalb des Corpus.
Diese Produktgeschichte ist für unsere RAG-Experimente wichtig. Eine Frage nach dem Retry-Verhalten von Webhooks kann beispielsweise unterschiedliche Antworten liefern, abhängig davon, welche Produktversion gemeint ist.
Die Dokumente bilden damit eine kleine, aber zusammenhängende technische Wissensbasis.
Umfang und Zusammensetzung¶
Version 1.0.0 enthält insgesamt 48 Dokumente in fünf Dateiformaten.
| Dateiformat | Dokumente | Typische Inhalte |
|---|---|---|
| Markdown | 36 | Produktdokumentation, technische Referenzen, Runbooks |
| HTML | 3 | Strukturierte technische Dokumente |
| CSV | 3 | Tabellarische Referenzdaten |
| 3 | Dokumente mit Seitenstruktur | |
| DOCX | 3 | Bearbeitbare Office-Dokumente |
| Gesamt | 48 |
Die Dokumente liegen in zwei Sprachen vor: 36 auf Englisch und zwölf auf Deutsch.
Die unterschiedlichen Dateiformate sind bewusst Bestandteil des Datensatzes.
Ein RAG-System muss Informationen zunächst aus ihren jeweiligen Dateiformaten extrahieren. Dabei entstehen unterschiedliche Herausforderungen.
Markdown enthält beispielsweise eine gut erkennbare Überschriftenstruktur. Bei HTML müssen wir relevante Inhalte aus dem Dokumentbaum extrahieren. CSV-Dateien besitzen eine tabellarische Struktur, die beim Chunking nicht verloren gehen sollte.
PDF-Dokumente enthalten Seitenumbrüche, wiederkehrende Kopfzeilen und Seitenzahlen. DOCX-Dateien besitzen wiederum eigene Absatz-, Überschriften- und Tabellenstrukturen.
Die fünf Formate enthalten eigenständige Dokumente. Es handelt sich nicht einfach um fünf unterschiedliche Exporte desselben Handbuchs.
Dadurch eignet sich der Corpus auch für Experimente zum Document Loading, Parsing und Chunking.
Verzeichnisstruktur¶
Das Projekt besteht aus mehreren Verzeichnissen, die unterschiedliche Aufgaben erfüllen.
Die folgende Darstellung zeigt die wichtigsten Bestandteile:
teralune-rag-corpus/
│
├── corpus/
│ ├── public/
│ ├── customer/
│ ├── internal/
│ └── restricted/
│
├── source/
│ ├── WORLD.md
│ ├── facts.yaml
│ ├── documents.json
│ ├── document_manifest.json
│ ├── taxonomy.json
│ ├── question_plan.json
│ └── ...
│
├── source_documents/
│ ├── D001.json
│ ├── D002.json
│ └── ...
│
├── evaluation/
│ ├── questions.jsonl
│ ├── evidence.jsonl
│ ├── smoke_questions.jsonl
│ ├── test_questions.jsonl
│ └── ...
│
├── scripts/
│ ├── build_corpus.py
│ ├── validate_corpus.py
│ └── common.py
│
├── tests/
│
├── README.md
├── AUTHOR_GUIDE.md
├── EVALUATION.md
├── CORPUS_REPORT_1.0.md
└── requirements.txt
Die Verzeichnisse erfüllen unterschiedliche Funktionen.
corpus/ enthält die eigentlichen Produktdokumente.
Diese Dateien bilden die Wissensbasis für unsere RAG-Anwendungen. Sie werden vom Build-Prozess in den fünf unterstützten Dateiformaten erzeugt.
source/ enthält die maßgeblichen Quelldaten.
Dort befinden sich die kanonischen Produktfakten, die zentralen Dokumentdefinitionen und die Metadaten.
source_documents/ enthält generierte Einzelkopien der Dokumentdefinitionen.
Für jedes Dokument wird beim Build eine eigene JSON-Datei erzeugt. Diese Dateien sind keine unabhängigen Datenquellen. Ihre Inhalte stammen aus source/documents.json und werden beim nächsten Build überschrieben.
evaluation/ enthält die Testdaten.
Dazu gehören Fragen, erwartete Evidenzstellen und weitere Informationen zur Bewertung von RAG-Systemen.
scripts/ und tests/ dienen der Erstellung und Überprüfung des Corpus.
Sie gehören nicht zur eigentlichen Produktdokumentation.
Wie der Corpus erzeugt wird¶
Der Corpus wird durch das Skript scripts/build_corpus.py erstellt.
Dabei werden drei zentrale Datenquellen eingelesen:
| Datei | Aufgabe |
|---|---|
source/facts.yaml |
Definiert die kanonischen Produktfakten |
source/documents.json |
Enthält die maßgeblichen Dokumentdefinitionen |
source/document_manifest.json |
Definiert Metadaten und Ausgabepfade |
Die Dokumentdefinitionen enthalten strukturierte Abschnitte mit Überschriften, Texten und gegebenenfalls Tabellen.
Einige Texte enthalten Referenzen auf Werte aus facts.yaml. Beim Build werden diese Referenzen aufgelöst und durch die entsprechenden Produktfakten ersetzt.
Anschließend erzeugt das Skript die eigentlichen Produktdokumente.
Der Datenfluss lässt sich vereinfacht so darstellen:
flowchart TD
F["source/facts.yaml"] --> B["build_corpus.py"]
D["source/documents.json"] --> B
M["source/document_manifest.json"] --> B
B --> C["corpus/<br/>48 Produktdokumente"]
B --> S["source_documents/<br/>48 JSON-Einzelkopien"]
B --> E["evaluation/<br/>Evidenzstellen und Fragen"]
classDef source fill:#dbeafe,stroke:#2563eb,color:#1e40af
classDef process fill:#fef3c7,stroke:#d97706,color:#92400e
classDef output fill:#dcfce7,stroke:#16a34a,color:#166534
class F,D,M source
class B process
class C,S,E output
Der Build-Prozess arbeitet ohne Netzwerkzugriff und ohne Sprachmodell.
Neben den Produktdokumenten erzeugt er auch die Evidenzdatei, die Evaluationsfragen und Prüfsummen für die veröffentlichten Dokumente.
Damit lässt sich der Corpus reproduzierbar aus seinen Quelldaten erstellen.
Warum gibt es documents.json und source_documents/?¶
Auf den ersten Blick wirken diese beiden Bestandteile redundant.
Tatsächlich enthalten sie dieselben ursprünglichen Dokumentdefinitionen, allerdings in unterschiedlicher Organisation.
source/documents.json enthält sämtliche Dokumentdefinitionen in einer zentralen Datei.
source_documents/ enthält dagegen für jedes Dokument eine eigene JSON-Datei, beispielsweise D001.json.
Die zentrale Datei ist die maßgebliche Quelle. Die Einzeldateien sind generierte Kopien.
Der Build-Prozess liest ausschließlich source/documents.json als Quelle für die Dokumentinhalte.
Für jedes Dokument schreibt er zusätzlich dessen ursprüngliche Definition in die entsprechende Datei unter source_documents/.
Dabei werden die ursprünglichen Daten übernommen, nicht die bereits aufgelösten Fakten aus facts.yaml.
Die Einzeldateien erfüllen vor allem zwei Aufgaben.
Erstens lassen sich einzelne Dokumentdefinitionen separat betrachten, ohne die gesamte zentrale JSON-Datei durchsuchen zu müssen.
Zweitens werden sie für die Konsistenzprüfung und die Reproduzierbarkeitstests verwendet.
Der Validator überprüft beispielsweise, ob die generierten Einzeldateien mit den zentralen Dokumentdefinitionen übereinstimmen.
Der entsprechende Vergleich lautet:
Damit erkennt die Validierung Abweichungen zwischen der zentralen Quelle und den generierten Einzeldateien.
Wer Dokumentinhalte dauerhaft verändern möchte, muss deshalb source/documents.json bearbeiten.
Änderungen an Dateien unter source_documents/ gehen beim nächsten Build verloren.
Für unsere RAG-Experimente benötigen wir diese Einzeldateien normalerweise nicht.
Welche Dateien gehören in den RAG-Index?¶
Für die Übungen in diesem Buch verwenden wir die Produktdokumente aus corpus/.
Die übrigen Verzeichnisse enthalten Informationen über den Datensatz selbst.
Würden wir beispielsweise source/facts.yaml, source_documents/ oder die Evaluationsfragen ebenfalls indexieren, könnte unser RAG-System Antworten aus den redaktionellen Quelldaten oder den Testdaten übernehmen.
Das würde die Ergebnisse unserer Experimente verfälschen.
Deshalb gilt für den Aufbau des Dokumentindex:
Nur die Produktdokumente aus corpus/ werden als Retrieval-Inhalte eingelesen.
Die Metadaten aus dem Dokumentmanifest dürfen wir zusätzlich verwenden, um Dokumente und Chunks korrekt zu kennzeichnen.
Die Unterverzeichnisse von corpus/ unterscheiden vier Zugriffsklassen:
| Verzeichnis | Zugriffsklasse |
|---|---|
public/ |
Öffentlich zugängliche Produktdokumentation |
customer/ |
Kundenspezifische Dokumente |
internal/ |
Interne Unternehmensdokumente |
restricted/ |
Besonders eingeschränkte Dokumente |
Für unsere einfachen Retrieval-Experimente verwenden wir überwiegend öffentliche Dokumente.
Bei Experimenten mit Zugriffskontrollen müssen wir dagegen berücksichtigen, welche Dokumente ein Benutzer tatsächlich sehen darf.
Die genaue Bedeutung dieser Zugriffsklassen behandeln wir in Abschnitt 10.2.
Das Dokumentmanifest¶
Eine der wichtigsten Projektdateien ist:
source/document_manifest.json
Das Manifest beschreibt sämtliche 48 Dokumente.
Für jedes Dokument enthält es unter anderem Angaben zu:
- Dokument-ID und Titel
- Produkt und Produktversion
- Sprache und Dateiformat
- Zugriffsklasse
- Dokumenttyp und Veröffentlichungsdatum
- Dokumentstatus und Quellenautorität
- Dateipfad und Pfad zur generierten JSON-Einzelquelle
Das Manifest verbindet damit die Dokumentdefinitionen mit den erzeugten Dateien.
Es legt beispielsweise fest, unter welchem Pfad ein Dokument im Verzeichnis corpus/ gespeichert wird und wo seine JSON-Einzelkopie unter source_documents/ liegt.
Für RAG-Anwendungen sind besonders die fachlichen Metadaten wertvoll.
Wir können sie beim Einlesen an Dokumente und Chunks binden.
Später ermöglichen sie beispielsweise eine Suche, die ausschließlich Dokumente einer bestimmten Produktversion berücksichtigt.
Dabei ist wichtig, dass die Metadaten nicht zwingend im eigentlichen Dokumenttext stehen.
Die Markdown-Dateien enthalten bewusst kein YAML-Front-Matter. Die strukturierte Beschreibung erfolgt über das separate Manifest.
Die wichtigsten Projektdateien¶
Neben den eigentlichen Produktdokumenten enthält das Repository mehrere Dateien, die für die Arbeit mit dem Corpus relevant sind.
| Datei | Aufgabe |
|---|---|
README.md |
Einstieg, Projektstruktur und Verwendung |
source/WORLD.md |
Beschreibung der Produktwelt und ihrer grundlegenden Regeln |
source/facts.yaml |
Maßgebliche Faktenbasis |
source/documents.json |
Zentrale, editierbare Dokumentdefinitionen |
source/document_manifest.json |
Metadaten und Ausgabepfade aller 48 Dokumente |
source/taxonomy.json |
Strukturierte Themenklassifikation |
source_documents/ |
Generierte Einzelkopien der Dokumentdefinitionen |
AUTHOR_GUIDE.md |
Hinweise zur Dokumentauswahl und zu didaktischen Herausforderungen |
EVALUATION.md |
Beschreibung der Evaluationsdaten und ihrer Verwendung |
CORPUS_REPORT_1.0.md |
Bericht über Umfang, Prüfungen und Grenzen der Version 1.0.0 |
Für Leser, die den Corpus ausschließlich als Wissensbasis verwenden möchten, sind vor allem corpus/, das Dokumentmanifest und die README relevant.
Die übrigen Dateien werden interessant, wenn wir die Entstehung des Corpus nachvollziehen, seine Inhalte verändern oder systematische Evaluationen durchführen möchten.
Warum wir einen kontrollierten Corpus verwenden¶
Ein öffentlich verfügbarer Dokumentbestand wäre für viele RAG-Experimente ebenfalls geeignet.
Allerdings kennen wir bei solchen Daten häufig nicht sämtliche Zusammenhänge.
Wir wissen möglicherweise nicht, welche Aussage aktuell ist, ob eine Dokumentversion veraltet ist oder ob eine scheinbar widersprüchliche Information tatsächlich einen Fehler darstellt.
Beim Teralune-Corpus sind diese Eigenschaften bewusst definiert.
Wir kennen die maßgeblichen Produktfakten und können nachvollziehen, welche Dokumente sie enthalten.
Gleichzeitig existieren historische Informationen, widersprüchliche Aussagen und unterschiedliche Zugriffsklassen.
Dadurch können wir gezielt untersuchen, wie sich ein RAG-System unter bestimmten Bedingungen verhält.
Der Corpus ist allerdings kein wissenschaftlich validierter Benchmark.
Er ist ein kontrollierter Lehr-, Experimentier- und Evaluationsdatensatz. Seine Ergebnisse lassen sich nicht ohne Weiteres auf beliebige reale Unternehmensdokumentationen übertragen.
Für die praktischen Beispiele dieses Buchs bietet er dennoch einen entscheidenden Vorteil: Wir können Retrieval-Verfahren anhand einer konsistenten Dokumentwelt vergleichen, deren fachliche Grundlagen bekannt sind.
Im nächsten Abschnitt betrachten wir genauer, wie diese Grundlagen organisiert sind und welche Rolle Versionierung, Quellenautorität und Zugriffskontrollen spielen.
10.2 Fakten, Versionen und Sicherheit¶
Eine der wichtigsten Eigenschaften des Teralune-Corpus ist seine kontrollierte Faktenbasis.
Wir wissen nicht nur, welche Dokumente existieren, sondern auch, welche technischen Aussagen innerhalb der fiktiven Produktwelt gültig sind. Gleichzeitig enthält der Corpus ältere Produktversionen, fehlerhafte Behauptungen und Dokumente mit unterschiedlichen Zugriffsberechtigungen.
Dadurch können wir typische Probleme realer RAG-Anwendungen gezielt untersuchen.
Die kanonische Faktenbasis¶
Die zentrale Datei für die technischen Produktfakten lautet:
source/facts.yaml
Sie bildet die Single Source of Truth des Corpus.
Darin sind unter anderem API-Eigenschaften, Authentifizierungsregeln, Webhook-Verhalten, Aufbewahrungsfristen und Produktlimits definiert.
Ein Auszug zeigt die Unterschiede zwischen den drei Orbit-Versionen:
{
"versions": {
"1.8": {
"api_prefix": "/api/v1",
"webhook_retry_hours": 6,
"access_token_minutes": 180,
"status": "legacy"
},
"2.4": {
"api_prefix": "/api/v2",
"webhook_retry_hours": 24,
"access_token_minutes": 120,
"status": "previous"
},
"3.0": {
"api_prefix": "/api/v3",
"webhook_retry_hours": 72,
"access_token_minutes": 60,
"status": "current"
}
}
}
Die tatsächliche Datei enthält weitere Eigenschaften. Der Ausschnitt beschränkt sich auf einige für unsere Experimente relevante Werte.
Wir erkennen, dass sich die technischen Eigenschaften zwischen den Versionen erheblich unterscheiden.
| Eigenschaft | Orbit 1.8 | Orbit 2.4 | Orbit 3.0 |
|---|---|---|---|
| API-Präfix | /api/v1 |
/api/v2 |
/api/v3 |
| Webhook-Retry-Dauer | 6 Stunden | 24 Stunden | 72 Stunden |
| Access-Token-Laufzeit | 180 Minuten | 120 Minuten | 60 Minuten |
| Standard-Retention | 14 Tage | 30 Tage | 90 Tage |
| Request-Limit pro Minute | 200 | 500 | 1000 |
Die Werte sind nicht zufällig gewählt. Sie ermöglichen Fragen, bei denen die korrekte Antwort vom Versionsbezug abhängt.
Beispielsweise ist die Aussage, dass Webhooks 24 Stunden lang erneut zugestellt werden, für Orbit 2.4 korrekt.
Für Orbit 3.0 ist dieselbe Aussage falsch.
Der Corpus verwendet den 15. Oktober 2026 als eingefrorenen fachlichen Stichtag. Innerhalb dieser Dokumentwelt gilt Orbit 3.0 als aktuelle Version.
Dokumente und Fakten voneinander trennen¶
Die Faktenbasis ist nicht identisch mit den Dokumenten, die unsere RAG-Anwendung durchsucht.
Die eigentlichen Produktdokumente liegen unter corpus/. Ihre editierbaren Inhalte und Strukturen werden separat in source/documents.json und den Dateien unter source_documents/ verwaltet.
Bei der Erstellung des Corpus werden definierte Fakten in die Dokumente übernommen.
Dadurch können beispielsweise mehrere Dokumente dieselbe technische Eigenschaft beschreiben, ohne dass die Werte unabhängig voneinander gepflegt werden müssen.
Für die Evaluation ist diese Trennung besonders hilfreich:
Die Faktenbasis definiert die fachliche Grundlage. Die Produktdokumente bilden den Informationsbestand, den unser RAG-System tatsächlich durchsuchen soll.
Deshalb nehmen wir source/facts.yaml nicht in den Vektorindex auf.
Andernfalls könnte das System die maßgeblichen Werte unmittelbar aus der redaktionellen Faktenbasis abrufen, statt sie aus der Produktdokumentation zu ermitteln.
Das würde die vorgesehenen Retrieval-Experimente verfälschen.
Dokumentversionen und Quellenautorität¶
Nicht jedes Dokument besitzt dieselbe fachliche Bedeutung.
Im Teralune-Corpus unterscheiden wir unter anderem aktuelle Produktdokumente, historische Verträge, Supportfälle und importierte Notizen.
Die zugehörigen Informationen stehen im Dokumentmanifest:
source/document_manifest.json
Für jedes Dokument enthält das Manifest unter anderem die Felder version, status und authority.
Diese Eigenschaften erfüllen unterschiedliche Aufgaben.
| Metadatum | Bedeutung |
|---|---|
version |
Produktversion, auf die sich das Dokument bezieht |
status |
Aktueller Bearbeitungs- oder Gültigkeitsstatus |
authority |
Fachliche Autorität der Quelle |
published_at |
Veröffentlichungsdatum |
document_type |
Art des Dokuments |
Besonders wichtig ist die Unterscheidung zwischen Relevanz und Autorität.
Ein historischer Vertrag kann für eine Suchanfrage semantisch hochrelevant sein. Trotzdem darf er nicht als maßgebliche Quelle für eine neuere Produktversion verwendet werden.
Ein Beispiel haben wir bereits mehrfach untersucht.
Der aktuelle Webhook Delivery Contract D003 beschreibt für Orbit 3.0 eine Retry-Dauer von 72 Stunden.
Der historische Vertrag D004 dokumentiert dagegen das Retry-Verhalten von Orbit 2.4 mit 24 Stunden.
Beide Dokumente sind für eine Suche nach Webhook-Retry-Dauern relevant.
Welches Dokument die richtige Antwort liefert, hängt jedoch von der Benutzerfrage ab.
Fragt ein Benutzer ausdrücklich nach Orbit 2.4, ist der historische Vertrag die passende Quelle.
Fragt er nach Orbit 3.0, müssen wir den aktuellen Vertrag berücksichtigen.
Eine sinnvolle RAG-Anwendung sollte deshalb Versionsinformationen bereits beim Retrieval verwenden und nicht erst bei der Antwortgenerierung.
Absichtlich widersprüchliche Dokumente¶
Der Corpus enthält auch Dokumente mit fachlich unzutreffenden Aussagen.
Ein wichtiges Beispiel ist:
corpus/public/D011.md
Die Datei enthält eine importierte Receiver Note.
Darin wird behauptet, dass Orbit 3.0 fehlgeschlagene Webhook-Zustellungen nur 24 Stunden lang wiederholt.
Außerdem beschreibt die Note eine Receiver-Konfiguration, die verarbeitete Zustellungsdatensätze nach diesem Zeitraum entfernt.
Beide Angaben stehen im Widerspruch zur maßgeblichen Orbit-3.0-Dokumentation.
Der aktuelle Webhook-Vertrag definiert:
| Eigenschaft | Maßgeblicher Wert |
|---|---|
| Senderseitiges Retry-Fenster | 72 Stunden ab dem ersten Zustellversuch |
| Receiverseitige Deduplication Retention | 96 Stunden nach der ersten Annahme |
Die unterschiedlichen Zeitangaben haben verschiedene Bedeutungen.
Das Retry-Fenster beschreibt, wie lange Orbit als Sender fehlgeschlagene Zustellungen erneut versucht.
Die Deduplication Retention beschreibt, wie lange die empfangende Anwendung bereits verarbeitete Zustellungen wiedererkennen soll.
Die Receiver Note verwechselt beziehungsweise verkürzt diese Anforderungen.
Im Manifest ist D011 deshalb als unreviewed und untrusted gekennzeichnet.
Das Dokument eignet sich für Experimente zur Konflikterkennung und Quellenbewertung.
Ein RAG-System sollte die abweichende Behauptung erkennen können, ohne sie als verbindliche Produktregel zu übernehmen.
Der Corpus enthält weitere vergleichbare Herausforderungen. Beispielsweise beschreibt D037 einen Kundenfall mit einer veralteten Aussage zur Tokenlaufzeit.
Solche Dokumente machen sichtbar, weshalb eine reine Ähnlichkeitssuche für anspruchsvolle Unternehmensanwendungen nicht ausreicht.
Zugriffskontrolle und Berechtigungen¶
Neben der fachlichen Gültigkeit müssen RAG-Anwendungen berücksichtigen, welche Dokumente ein Benutzer überhaupt lesen darf.
Der Teralune-Corpus verwendet dafür vier Zugriffsklassen.
| Zugriffsklasse | Dokumente | Zugriffsregel |
|---|---|---|
PUBLIC |
35 | Öffentlich zugänglich |
CUSTOMER |
6 | Nur für Benutzer der zugeordneten Organisation |
INTERNAL |
5 | Nur für Mitarbeiter des zugeordneten Teams |
RESTRICTED |
2 | Mitarbeiter des zugeordneten Teams mit zusätzlichen Rollen |
| Gesamt | 48 |
Die Zugriffsklasse wird im Dokumentmanifest festgelegt.
Zusätzlich können Dokumente Angaben zur Organisation, zum zuständigen Team und zu erforderlichen Rollen besitzen.
Das Berechtigungsmodell verwendet keine einfache Hierarchie, bei der eine höhere Rolle automatisch Zugriff auf sämtliche niedrigeren Klassen erhält.
Ein Kundenadministrator erhält beispielsweise nicht automatisch Zugriff auf interne Dokumente.
Ebenso besitzt ein Mitarbeiter des Operations-Teams nicht grundsätzlich Zugriff auf Dokumente des Security-Teams.
Für die Übungen enthält der Corpus vordefinierte Benutzerprofile in:
evaluation/users.json
Die zugehörige Berechtigungslogik ist in scripts/common.py implementiert.
Berechtigungen technisch prüfen¶
Die Funktion allowed() entscheidet anhand der Dokumentmetadaten und des Benutzerprofils, ob ein Dokument zugänglich ist.
Der zentrale Teil lautet:
def allowed(document: dict, user: dict) -> bool:
"""Deny by default. Roles are not a hierarchy and staff has no tenant bypass."""
access = document["access"]
if access == "PUBLIC":
return True
if access == "CUSTOMER":
return (
user["kind"] == "customer"
and user["organization"] == document["organization"]
)
if access == "INTERNAL":
return (
user["kind"] == "staff"
and document["team"] in user["teams"]
)
if access == "RESTRICTED":
return (
user["kind"] == "staff"
and document["team"] in user["teams"]
and set(document["required_roles"]).issubset(user["roles"])
)
return False
Die Funktion verwendet das Prinzip Deny by Default.
Wenn keine der ausdrücklich definierten Zugriffsregeln erfüllt ist, wird der Zugriff verweigert.
Für ein RAG-System ist entscheidend, an welcher Stelle diese Prüfung stattfindet.
Die Zugriffskontrolle muss sicherstellen, dass unzulässige Dokumente weder in den Kontext des Sprachmodells gelangen noch durch nachgelagerte Verarbeitungsschritte offengelegt werden.
Ein geeigneter Ablauf sieht beispielsweise so aus:
flowchart TD
Q[Benutzerfrage und Benutzeridentität] --> A[Zugriffsberechtigung bestimmen]
A --> R[Retrieval mit Berechtigungsfilter]
R --> C[Zulässige Dokumentkandidaten]
C --> K[Reranking und Kontextaufbau]
K --> L[Sprachmodell]
L --> O[Antwort]
classDef input fill:#dbeafe,stroke:#2563eb,color:#1e40af
classDef security fill:#f3e8ff,stroke:#9333ea,color:#6b21a8
classDef retrieval fill:#fef3c7,stroke:#d97706,color:#92400e
classDef output fill:#dcfce7,stroke:#16a34a,color:#166534
class Q input
class A,R security
class C,K retrieval
class L,O output
Wichtig ist, dass der Berechtigungsfilter nicht nur im Prompt beschrieben wird.
Die Anwendung muss den Zugriff technisch durchsetzen.
Außerdem darf ein Benutzer aus einer verweigerten Antwort nicht ableiten können, ob ein bestimmtes geschütztes Dokument existiert.
Der Teralune-Corpus simuliert solche Berechtigungen anhand seiner Metadaten und Benutzerprofile.
Da sämtliche Dokumente Bestandteil eines synthetischen Übungsdatensatzes sind, bietet die Verzeichnisstruktur selbst keine echte Geheimhaltung.
Sicherheitsbezogene Testdokumente¶
Der Corpus enthält außerdem bewusst präparierte Dokumente, mit denen sich das Verhalten eines RAG-Systems gegenüber nicht vertrauenswürdigen Inhalten untersuchen lässt.
Dazu gehören insbesondere:
| Dokument | Besonderheit |
|---|---|
D010 |
Funktionsloser Sicherheitsmarker für Zugriffstests |
D011 |
Falsche Retry-Behauptung und indirekte Prompt Injection |
D037 |
Veraltete Tokenbehauptung und Prompt Injection in einem Kundendokument |
Diese Dokumente sind im Manifest als Security-Fixtures erkennbar.
Die eigentlichen Produkttexte enthalten dagegen keine ausdrücklichen Hinweise darauf, dass sie als Testfälle dienen.
Dadurch begegnet das RAG-System den problematischen Aussagen wie gewöhnlichen Dokumentinhalten.
Besonders relevant ist die Prompt Injection.
Dabei versucht ein Dokument, dem Sprachmodell Anweisungen zu geben, obwohl es lediglich als Informationsquelle dienen soll.
Ein Dokument könnte beispielsweise verlangen, bisherige Anweisungen zu ignorieren oder eine bestimmte Antwort auszugeben.
Ein robustes System muss zwischen vertrauenswürdigen Anweisungen der Anwendung und nicht vertrauenswürdigen Dokumentinhalten unterscheiden.
Das ist besonders bei agentischen RAG-Anwendungen wichtig, deren Werkzeuge möglicherweise weitere Aktionen ausführen können.
Was wir daraus lernen¶
Der Teralune-Corpus trennt drei Eigenschaften, die bei einer einfachen semantischen Suche leicht miteinander vermischt werden:
Relevanz: Passt ein Dokument inhaltlich zur Benutzerfrage?
Autorität: Ist das Dokument für die gesuchte Aussage und Produktversion maßgeblich?
Berechtigung: Darf der Benutzer auf dieses Dokument zugreifen?
Diese Eigenschaften sind voneinander unabhängig.
Ein Dokument kann hochrelevant, aber veraltet sein. Es kann fachlich korrekt, aber für den Benutzer gesperrt sein. Oder es kann zugänglich sein und trotzdem eine falsche Behauptung enthalten.
Ein zuverlässiges RAG-System muss deshalb mehr leisten, als lediglich die semantisch ähnlichsten Textabschnitte zu finden.
Die kontrollierte Faktenbasis, das Dokumentmanifest und das Berechtigungsmodell des Teralune-Corpus ermöglichen es uns, genau diese Unterschiede in praktischen Experimenten zu untersuchen.
Im nächsten Abschnitt betrachten wir, wie der Corpus dafür Evaluationsfragen und überprüfbare Evidenzstellen bereitstellt.
10.3 Evaluation und Verwendung¶
Der Teralune-Corpus enthält nicht nur Produktdokumente, sondern auch einen eigenen Evaluationsdatensatz. Damit können wir überprüfen, ob ein RAG-System relevante Informationen findet, fachlich korrekte Antworten erzeugt und die definierten Zugriffsregeln einhält.
Version 1.0.0 stellt dafür 120 Evaluationsfragen und 146 annotierte Evidenzstellen bereit.
Die Evaluationsdaten liegen im Verzeichnis evaluation/. Sie sind von den eigentlichen Produktdokumenten getrennt und dürfen nicht in den Retrieval-Index aufgenommen werden.
Die Evaluationsfragen¶
Die zentrale Datei lautet:
evaluation/questions.jsonl
Sie enthält die Fragen, mit denen wir das Verhalten eines RAG-Systems untersuchen können.
Die Fragen decken unterschiedliche Herausforderungen ab:
| Kategorie | Was wird untersucht? |
|---|---|
| Faktenfragen | Findet das System eine konkrete technische Information? |
| Versionsfragen | Unterscheidet es aktuelle und historische Produktversionen? |
| Konfliktfragen | Erkennt es widersprüchliche Dokumentaussagen? |
| Mehrstufige Fragen | Kann es Informationen aus mehreren Quellen kombinieren? |
| Berechtigungsfragen | Werden unzulässige Dokumente ausgeschlossen? |
| Sicherheitsfragen | Ignoriert das System Anweisungen aus nicht vertrauenswürdigen Dokumenten? |
Ein einfaches Beispiel ist die Frage:
Wie lange versucht Orbit 3.0, einen fehlgeschlagenen Webhook erneut zuzustellen?
Die erwartete fachliche Antwort lautet 72 Stunden.
Interessanter wird die Evaluation, wenn das System gleichzeitig den historischen Vertrag für Orbit 2.4 oder die fehlerhafte Receiver Note findet.
Dann genügt es nicht, irgendeinen Textabschnitt mit einer Zeitangabe abzurufen. Das System muss die richtige Produktversion und die Autorität der Quelle berücksichtigen.
Evidenzstellen als Referenz¶
Neben den Fragen enthält der Corpus annotierte Evidenzstellen in:
evaluation/evidence.jsonl
Jede Evidenzstelle besitzt eine eindeutige Kennung.
Beispielsweise verweist D003-chunk-1 auf den Abschnitt des aktuellen Webhook-Vertrags, der die Retry-Dauer von Orbit 3.0 beschreibt.
Die Kennungen verbinden Evaluationsfragen mit den Dokumentstellen, die für ihre Beantwortung relevant sind.
Damit können wir zwei unterschiedliche Aspekte untersuchen:
Retrieval: Hat das System die benötigten Informationen gefunden?
Generation: Hat das Sprachmodell aus diesen Informationen eine korrekte und ausreichend belegte Antwort erzeugt?
Diese Trennung ist wichtig.
Eine falsche Antwort kann entstehen, weil das Retrieval die entscheidende Quelle nicht gefunden hat. Sie kann aber auch entstehen, obwohl die richtige Quelle im Kontext vorhanden war.
Die Evaluationsdaten helfen uns, solche Fehler systematischer einzuordnen.
Die annotierten Evidenzstellen sind dabei Referenzen auf den bereitgestellten Dokumentbestand. Sie entsprechen nicht automatisch den Chunks, die unser eigener Text-Splitter erzeugt.
Wenn wir andere Chunking-Verfahren verwenden, müssen wir die Referenzen gegebenenfalls auf die tatsächlich indexierten Textabschnitte abbilden.
Erwartetes Antwortverhalten¶
Nicht jede Frage soll zu einer direkten Sachantwort führen.
Der Evaluationsdatensatz unterscheidet vier grundlegende Verhaltensweisen:
| Verhalten | Erwartung |
|---|---|
answer |
Eine fachlich belegte Antwort geben |
abstain |
Keine unbelegte Antwort erfinden |
deny |
Den Zugriff auf geschützte Informationen verweigern |
clarify |
Eine notwendige Rückfrage stellen |
Diese Unterscheidung ist für die Evaluation von RAG-Anwendungen besonders wichtig.
Ein System, das jede Frage beantwortet, ist nicht automatisch ein gutes System.
Wenn die Dokumente keine ausreichende Grundlage liefern, kann eine begründete Enthaltung die richtige Reaktion sein.
Wenn eine Frage mehrere Produktversionen betrifft, ohne eine davon zu nennen, kann eine Rückfrage sinnvoller sein als eine willkürliche Entscheidung.
Und wenn der Benutzer keine Berechtigung besitzt, darf das System die gesuchten Informationen nicht offenlegen.
Wir bewerten deshalb nicht nur, was ein System antwortet, sondern auch, ob es überhaupt antworten sollte.
Den Corpus validieren¶
Der Corpus besitzt einen eigenen Build- und Validierungsprozess.
Die wichtigsten Skripte befinden sich im Verzeichnis scripts/:
| Skript | Aufgabe |
|---|---|
build_corpus.py |
Produktdokumente aus den Quelldaten erzeugen |
validate_corpus.py |
Konsistenz und Struktur des Corpus prüfen |
common.py |
Gemeinsam verwendete Funktionen, unter anderem für Berechtigungen |
Die Validierung prüft unter anderem, ob Dokumente und Metadaten konsistent sind und ob die definierten Referenzen auf gültige Inhalte verweisen.
Sie dient dazu, Fehler im Datensatz selbst zu erkennen.
Das ist nicht mit der Evaluation eines RAG-Systems zu verwechseln.
Der Validator überprüft den Corpus. Die Evaluationsfragen überprüfen dagegen, wie unsere RAG-Anwendung mit diesem Corpus arbeitet.
Verwendung in eigenen RAG-Projekten¶
Für eigene Experimente empfiehlt sich ein einfacher Ablauf:
- Die Produktdokumente aus
corpus/einlesen. - Die Dokumentmetadaten aus dem Manifest übernehmen.
- Die Dokumente in Chunks zerlegen und indexieren.
- Ein Retrieval-Verfahren implementieren.
- Ausgewählte Fragen aus
evaluation/questions.jsonlausführen. - Die gefundenen Quellen mit den annotierten Evidenzstellen vergleichen.
- Die generierten Antworten anhand der erwarteten Fakten und Verhaltensweisen bewerten.
Für erste Experimente genügt eine kleine Auswahl von Fragen.
Beispielsweise können wir zunächst untersuchen, ob ein einfacher Vektorindex den aktuellen Webhook-Vertrag findet.
Anschließend können wir dieselbe Frage mit einem Metadatenfilter, Hybrid Search oder Reranking wiederholen.
So lässt sich beobachten, welche Auswirkungen die verschiedenen Retrieval-Strategien auf die gefundenen Quellen haben.
Für anspruchsvollere Experimente kommen Versionskonflikte, mehrstufige Fragen und Berechtigungstests hinzu.
Dabei sollten wir die Evaluationsdaten nicht verwenden, um die Antworten direkt in den Prompt einzubauen. Sie dienen als unabhängige Referenz für die Bewertung.
Grenzen des Datensatzes¶
Der Teralune-Corpus ist ein synthetischer Lehr- und Evaluationsdatensatz.
Seine kontrollierte Struktur erleichtert reproduzierbare Experimente. Gleichzeitig bildet er die Komplexität realer Unternehmensdokumentationen nur teilweise ab.
In produktiven Umgebungen treffen wir häufig auf deutlich größere Dokumentbestände, uneinheitliche Metadaten, unvollständige Berechtigungsinformationen und widersprüchliche Inhalte, deren fachliche Richtigkeit nicht bereits bekannt ist.
Auch die 120 Evaluationsfragen stellen keinen allgemein anerkannten Benchmark dar.
Sie ermöglichen Vergleiche innerhalb der Teralune-Dokumentwelt, erlauben aber keine pauschalen Aussagen über die Leistungsfähigkeit eines RAG-Systems in anderen Anwendungsgebieten.
Für die Übungen dieses Buchs ist genau diese kontrollierte Umgebung jedoch hilfreich.
Wir können Retrieval, Chunking, Metadatenfilter, Quellenbewertung und Antwortgenerierung verändern und anschließend anhand derselben Dokumente und Fragen untersuchen, welche Auswirkungen unsere Entscheidungen haben.
Damit bildet der Teralune-Corpus eine gemeinsame Grundlage für die praktischen Beispiele des Buchs und für weiterführende eigene RAG-Experimente.