Weniger ist mehr: Warum wir 949 Zeilen aus unserem RAG-System gelöscht haben

Holger von Ellerts
Mar 20, 2026By Holger von Ellerts

 Es gibt wenige Dinge, die befriedigender sind, als ein Feature zu bauen. Und es gibt wenige Dinge, die schwieriger sind, als ein Feature wieder zu löschen — besonders wenn man Wochen damit verbracht hat.

Dieser Artikel ist ein Erfahrungsbericht darüber, wie wir drei vielversprechende Features in unserem RAG-System implementiert, systematisch evaluiert und schliesslich komplett entfernt haben. Minus 949 Zeilen, plus 45. Netto: -904 LOC. Und das System wurde dadurch besser.

Das System

"RAG-Wissen" ist unser internes Retrieval-Augmented-Generation-System. Der Stack: Python 3.13, Qdrant als Vektordatenbank, Ollama mit qwen2.5:7b-instruct (4-bit quantisiert) als LLM. Für die systematische Evaluation setzen wir RAGAS ein — ein Framework, das Metriken wie Faithfulness, Answer Relevancy, Context Precision und Context Recall berechnet.

Das System funktionierte. Aber wie das so ist: Es hätte ja noch besser funktionieren können.


Was wir gebaut haben


Drei Features, alle aus der akademischen RAG-Literatur motiviert, alle plausibel:

1. MMR (Maximal Marginal Relevance): Ein Diversitäts-Reranking nach dem Cross-Encoder. Die Idee: Wenn die Top-5-Chunks alle fast identisch sind, verschwendet man Context-Window. MMR wählt stattdessen Chunks, die sowohl relevant als auch untereinander divers sind.

2. Intent Detection: Eine Query-Klassifikation, die eingehende Fragen in Typen einteilt — FACTUAL, SUMMARY, COMPARE, EXPLORE, LIST. Implementiert mit Keyword-Matching und optionalem LLM-Fallback. Je nach Intent werden andere Such-Strategien und Parameter verwendet.

3. Query Refinement: Wenn die initialen Suchergebnisse schlecht scoren, reformuliert ein LLM die Query iterativ und sucht erneut. Die Annahme: Manchmal ist die User-Query einfach nicht optimal formuliert für die Vektorsuche.


Jedes dieser Features ist in der Literatur gut dokumentiert. Jedes klingt vernünftig. Jedes hat uns Arbeit gekostet.


Was die Daten zeigten


Wir haben ein Golden Set aus 50 handkuratierten Fragen mit Referenzantworten aufgebaut. Die Evaluation lief über mehrere Runs, wobei jedes Feature einzeln aktiviert und gegen die Baseline getestet wurde.


RunKonfigurationFaithfulnessDelta vs. Baseline
#17Baseline (alle Features OFF)0.650
#14Nur MMR aktiv~0.340-48%
#15Nur Intent Detection aktiv~0.455-30%
#16Nur Query Refinement aktiv~0.403-38%


Jedes einzelne Feature verschlechterte die Faithfulness — und zwar massiv. Kein Feature zeigte eine Verbesserung.


Der versteckte Messfehler


Aber halt — die Geschichte hat eine Ebene mehr. Unsere ursprüngliche Baseline aus einem früheren Run lag bei Faithfulness 0.900. Das sieht nach einem dramatischen Unterschied zu den 0.650 von Run #17 aus.

Die Ursache: Der alte Benchmark-Runner nutzte einen anderen Code-Pfad als die Production-Pipeline. Er rief Search und Chat getrennt auf, während die Production einen einzigen chat(include_sources=True)-Call macht. Der alte Pfad war "optimistischer" — er lieferte Scores, die nicht der Realität im Produktionsbetrieb entsprachen.

Als wir den Runner auf den tatsächlichen Production-Pfad umstellten, fiel die Baseline von 0.900 auf 0.650. Das ist kein Bug im System — das ist ein Bug in der Messung. Und er ist heimtückisch, weil man monatelang glauben kann, das System performt besser als es tatsächlich tut.

Lektion Nummer eins: Wenn dein Benchmark nicht denselben Code-Pfad nutzt wie die Production, misst du Fiktion.


Optuna: Die letzte Chance



Bevor wir die Features endgültig begruben, gaben wir ihnen eine letzte Chance. Mit Optuna suchten wir systematisch nach Parameter-Kombinationen: Feature on/off in allen Kombinationen, dazu Parameter wie MMR Lambda, Intent Threshold und Refinement Retries. 20 Trials, 9.3 Stunden Rechenzeit.


Die Ergebnisse waren eindeutig — und ernüchternd:

Fünf der 20 Trials waren reine Baseline-Runs (alle Features OFF). Ihre Faithfulness-Werte schwankten zwischen 0.533 und 0.767. Das ist eine natürliche Varianz von ±0.12, die durch das nicht-deterministische Verhalten des quantisierten LLM entsteht.

Kein einziger Trial mit aktivierten Features lag ausserhalb dieser Baseline-Varianz. Der beste Trial insgesamt? Baseline. Faithfulness 0.767. Alle Features aus.

Die Features brachten bestenfalls nichts und schlimmstenfalls erheblichen Schaden.


Die Entscheidung: Code löschen

An diesem Punkt gibt es zwei Wege. Der eine: Die Features "für später" im Code lassen, hinter Feature-Flags versteckt. Der andere: Löschen.

Wir haben gelöscht.

3 Dateien entfernt
5 Dateien geändert
-949 Zeilen, +45 Zeilen
81 von 81 Tests grün nach dem Cleanup


Der Code wurde einfacher, die Pipeline kürzer, die Fehlerquellen weniger. Kein Feature-Flag, das jemand in sechs Monaten versehentlich aktiviert. Kein toter Code, durch den sich neue Teammitglieder lesen müssen.


Lessons Learned


1. YAGNI gilt auch für "intelligente" Features.
Maximal Marginal Relevance, Intent Detection, Query Refinement — das sind keine schlechten Ideen. Sie sind gut dokumentiert und in manchen Systemen sicher nützlich. Aber in unserem System, mit unserem Datenbestand, mit unserem LLM, brachten sie nichts. Die Literatur ist kein Ersatz für Messung.

2. Miss auf dem Production-Pfad oder miss gar nicht.
Unser grösster Fehler war nicht die Feature-Entwicklung. Es war, dass wir wochenlang mit einem Benchmark gearbeitet haben, der einen anderen Code-Pfad nutzte als das produktive System. Die 0.900 Faithfulness war eine Illusion. Die echte Baseline lag bei 0.650. Jede Optimierungsentscheidung, die auf den alten Zahlen basierte, war auf Sand gebaut.

3. Varianz-Bewusstsein ist Pflicht.
Ein quantisiertes 7B-Modell ist nicht deterministisch. Faithfulness schwankte in unseren Baseline-Runs zwischen 0.533 und 0.767. Wer ein einzelnes Run-Ergebnis als Wahrheit nimmt, optimiert auf Rauschen. Mindestens 3-5 Baseline-Runs sind nötig, bevor man sagen kann, ob ein Feature wirklich hilft.

4. Code löschen ist ein Feature.
949 Zeilen weniger bedeuten: weniger Bugs, weniger Wartung, weniger Cognitive Load, schnellere Pipeline. Die Versuchung, Code "für später" zu behalten, ist gross. Aber Code, der nachweislich nichts bringt, ist kein Asset — er ist Ballast.

5. Vier Wochen sind nicht verschwendet.
Wir haben eine robuste Evaluationsinfrastruktur aufgebaut: Golden Set, RAGAS-Integration, Optuna-Tuning, reproduzierbare Runs. Diese Infrastruktur bleibt. Wenn wir das nächste Feature evaluieren, dauert es Stunden statt Wochen. Und wir wissen jetzt, dass unsere Baseline bei ~0.650 liegt — ehrlich gemessen.


Fazit

Die verlockendste Falle im Machine Learning Engineering ist die Annahme, dass mehr Komponenten zu besseren Ergebnissen führen. Mehr Reranking, mehr Query-Verarbeitung, mehr Intelligenz in der Pipeline. Manchmal stimmt das. In unserem Fall stimmte es dreimal nicht.

YAGNI — You Ain't Gonna Need It — ist kein Aufruf zur Faulheit. Es ist ein Aufruf zur Disziplin: Bau nur, was nachweislich hilft. Miss ehrlich. Und wenn die Daten gegen dich sprechen, lösch den Code.

Minus 904 Zeilen. Null Reue.


___ 
Holger von Ellerts ist KI-Dozent an Schweizer Hochschulen und Gründer der digital opua GmbH. RAG-Wissen ist ein internes System der digital opua GmbH.