Automatisiert progressive RAG-Poisoning-Experimente: Lädt PDF-Dokumente in eine LightRAG-Instanz hoch, wartet auf die Indizierung und startet nach jeder Stufe eine Qualitätsmessung via RAGChecker.
Der Ablauf eines vollständigen Runs:
1. 64 saubere Dokumente hochladen
2. Warten bis LightRAG alle Dokumente indiziert hat
3. RAGChecker ausführen → "clean baseline"
4. Für jede der 13 Poisoning-Stufen:
a. Delta-Dokumente (neu für diese Stufe) hochladen
b. Warten bis LightRAG fertig ist
c. RAGChecker ausführen → Messung für diese Stufe
Die Stufenverzeichnisse sind kumulativ – jedes Verzeichnis enthält alle vergifteten Dokumente bis einschließlich dieser Stufe. Der Orchestrator berechnet selbst, welche Dateien neu sind, und lädt nur die Deltas hoch.
| Enum-Wert | Verzeichnis | Label-Suffix | Anteil an 64 clean docs |
|---|---|---|---|
| P01PCT | 01pct |
p01pct |
1 % |
| P02PCT | 02pct |
p02pct |
2 % |
| P04PCT | 04pct |
p04pct |
4 % |
| P06PCT | 06pct |
p06pct |
6 % |
| P08PCT | 08pct |
p08pct |
8 % |
| P10PCT | 10pct |
p10pct |
10 % |
| P17PCT | 17pct |
p17pct |
17,5 % |
| P25PCT | 25pct |
p25pct |
25 % |
| P50PCT | 50pct |
p50pct |
50 % |
| P75PCT | 75pct |
p75pct |
75 % |
| P100PCT | 100pct |
p100pct |
100 % |
| P150PCT | 150pct |
p150pct |
150 % |
| P200PCT | 200pct |
p200pct |
200 % |
Der RAGChecker-Label für jede Stufe lautet <RUN_GROUP>_<labelSuffix>, z. B. run_001_p10pct.
- Java 21
- Maven 3.9+
- Docker (Daemon muss erreichbar sein, Socket wird gemountet)
- Laufende LightRAG-Instanz
- Docker-Image
ragchecker:latest(oder eigener Image-Name per Env-Var) - Externes Docker-Netzwerk
aibox_network
data/
├── clean/ # 64 saubere Basis-PDFs
└── poisoned/
├── 01pct/ # kumulativ: alle vergifteten Docs bis Stufe 1 %
├── 02pct/
├── ...
└── 200pct/
testcases/ # YAML-Testfälle für RAGChecker
reports/ # Ausgabeverzeichnis (wird von RAGChecker beschrieben)
config/
├── override.env # LightRAG-Konfiguration (für RAGChecker)
└── ragchecker.env # RAGChecker-Umgebungsvariablen
Alle Einstellungen werden über Umgebungsvariablen gesetzt. Spring Boot mappt sie via Relaxed Binding auf die entsprechenden Properties.
| Env-Variable | Beschreibung |
|---|---|
LIGHTRAG_URL |
URL der LightRAG-Instanz, z. B. http://lightrag:9622 |
LIGHTRAG_API_KEY |
API-Key für LightRAG |
RAGINGESTER_RUN_GROUP |
Bezeichner des Runs, z. B. 20260306_run |
| Env-Variable | Default | Beschreibung |
|---|---|---|
RAGINGESTER_CLEAN_DOCS_PATH |
/data/clean |
Pfad zu den sauberen PDFs |
RAGINGESTER_POISONED_DOCS_PATH |
/data/poisoned |
Pfad zum Poisoning-Wurzelverzeichnis |
RAGINGESTER_TESTCASES_PATH |
/app/testcases |
Host-Pfad zum Testfall-Verzeichnis — wird direkt als Volume in den RAGChecker-Container gemountet |
RAGINGESTER_REPORTS_PATH |
/app/reports |
Host-Pfad zum Report-Verzeichnis — wird direkt als Volume in den RAGChecker-Container gemountet |
RAGINGESTER_OVERRIDE_ENV_PATH |
/config/override.env |
LightRAG override.env für RAGChecker |
RAGINGESTER_RAGCHECKER_IMAGE |
ragchecker:latest |
Docker-Image für RAGChecker |
RAGINGESTER_RAGCHECKER_ENV_FILE |
/config/ragchecker.env |
Env-File für den RAGChecker-Container |
RAGINGESTER_POLLING_TIMEOUT_MINUTES |
10 |
Timeout beim Warten auf Indizierung |
RAGINGESTER_DRY_RUN |
false |
Nur loggen, nichts wirklich ausführen |
Vorlage: .env-example
cp .env-example .env-local
# LIGHTRAG_URL, LIGHTRAG_API_KEY und RAGINGESTER_RUN_GROUP anpassen
cp config/ragchecker.env.example config/ragchecker.env
# Werte in ragchecker.env befüllen
# override.env vom LightRAG-Host holen oder selbst erstellen:
touch config/override.env# Env-Vars laden und App starten
set -a && source .env-local && set +a
./mvnw spring-boot:rundocker compose -f docker-compose-local.yml up --buildMounts für den lokalen Compose:
./data→/data(read-only)./config/override.env→/config/override.env(read-only)./config/ragchecker.env→/config/ragchecker.env(read-only)/var/run/docker.sock→/var/run/docker.sock
Hinweis:
testcases/undreports/werden nicht in den RAGIngester-Container gemountet. RAGIngester übergibt die Host-Pfade (RAGINGESTER_TESTCASES_PATH,RAGINGESTER_REPORTS_PATH) direkt als Volume-Argumente andocker run, sodass der Docker-Daemon sie unmittelbar in den RAGChecker-Container mountet. Die Pfade müssen daher auf dem Docker-Host existieren — z. B. dastestcases/- undreports/-Verzeichnis aus dem RAGChecker-Repo.
docker compose up --buildErwartet auf dem Host:
/opt/lightrag/override.env/opt/ragchecker/ragchecker.env
Das externe Netzwerk aibox_network muss existieren:
docker network create aibox_networkMit RAGINGESTER_DRY_RUN=true läuft der Orchestrator komplett durch, ohne Dokumente hochzuladen, LightRAG zu pollen oder RAGChecker zu starten. Nützlich zum Testen der Konfiguration und der Verzeichnisstruktur:
RAGINGESTER_DRY_RUN=true ./mvnw spring-boot:runTestfälle für RAGChecker werden als YAML-Dateien im Verzeichnis testcases/ abgelegt:
- id: TC-001
prompt: "Gibt es eine Abmahnung in Verbindung mit Arbeitsunfähigkeit?"
expected_documents:
- "Fall1_Abmahnung_15_05_25.pdf"
notes: "Fall 1 – Hauptfrage"Der Pfad zur zu verwendenden Testfall-Datei wird in ragchecker.env über RAGCHECKER_TESTCASES_PATH konfiguriert.
./mvnw testEnthaltene Testklassen:
| Klasse | Was wird getestet |
|---|---|
PoisoningStageCalculationTest |
expectedDocCount() für alle Stufen |
LabelGenerationTest |
label(runGroup) für alle Stufen |
PollingServiceTest |
Polling-Logik mit Mock-Clock (Erfolg, Timeout, Sofortmatch) |
RagIngesterApplication Spring Boot Entry Point (ApplicationRunner)
└── IngestionOrchestrator Orchestriert den Gesamtablauf
├── LightRagClient HTTP-Client (RestClient) für LightRAG REST API
│ ├── POST /documents/upload Einzeldokument hochladen
│ └── POST /documents/paginated Anzahl indizierter Dokumente abfragen
├── PollingService Wartet bis Indexcount >= erwartet (mit Timeout)
└── DockerService Startet RAGChecker-Container via ProcessBuilder
| Fehler | Verhalten |
|---|---|
| Upload eines einzelnen Docs | WARN + überspringen, Run läuft weiter |
| Polling-Timeout | ERROR + Exception, Run bricht ab |
| Docker nicht erreichbar | ERROR + Exception beim Start |
| RAGChecker Exit-Code != 0 | ERROR + DockerExecutionException, Run bricht ab |
| Stufenverzeichnis fehlt | WARN + Stufe wird übersprungen |
# JAR bauen
./mvnw package -DskipTests
# Docker-Image bauen
docker build -t ragingester:latest .Das Dockerfile verwendet einen Multi-Stage-Build:
maven:3.9-eclipse-temurin-21zum Baueneclipse-temurin:21-jreals schlankes Runtime-Image