Taha @ MJTHD
/
GitHub
Blog
·2 Min. Lesezeit

Warum ein schlechter Ingest Dokki nicht kaputt machen kann

Immutable Versionen, Snapshots als Manifest und Rollback als reiner Pointer-Flip — wie Dokki den produktiven Korpus schützt.

airagversioningdokki

Die naheliegende Art, einen RAG-Korpus zu pflegen: Dokument neu importieren, alte Chunks überschreiben, fertig. Das Problem — wenn der neue Import kaputt ist (verkorkstes PDF-Layout, halber Text fehlt), hast du die Produktion gerade live beschädigt, und der alte gute Stand ist weg.

Dokki macht es andersherum. Der produktive Stand ist unantastbar, bis du aktiv etwas anderes aktivierst.

Versionen sind immutable

Jeder Re-Ingest eines Dokuments erzeugt eine neue document_version mit eigenem version_no und eigenen Chunks — nie ein Update der alten.

arabische-grammatik.pdf
├── version_no = 1   (ready)   → 500 chunks   [im aktiven Snapshot]
└── version_no = 2   (ready)   → 512 chunks   [in KEINEM aktiven Snapshot]

Die Chunks von version_no = 2 liegen schon in der Datenbank — aber für Queries unsichtbar, bis sie bewusst in einen Snapshot aufgenommen und der aktiviert wird. Eine Version durchläuft dabei eine simple State-Machine:

pending → ingesting → ready → failed

Ein Snapshot ist nur ein Manifest

Ein Snapshot speichert keine Daten. Er ist eine Liste: „welche Version jedes Dokuments gehört zu diesem Stand?"

snapshot "lughaty-2026-06-20"  (active)
└── snapshot_members
    ├── grammatik.pdf     → version_no 1
    ├── wortschatz.epub   → version_no 3
    └── dialekte.pdf      → version_no 2

Pro Collection zeigt genau eine active_pointer-Zeile auf den produktiven Snapshot. Queries laufen ausschließlich gegen dessen Members — alles andere ist zwar in der DB, aber außerhalb der Sicht.

Promotion: bauen, prüfen, umschalten

Aus den gewünschten Versionen wird ein Draft-Snapshot gebaut. Das Quality Gate prüft den Kandidaten. Erst bei Bestehen springt der Pointer um und snapshot.activated informiert den RAG-Service. Der alte Stand bleibt während der gesamten Prüfung unangetastet live.

Rollback ist ein Pointer-Flip

Weil alle alten Vektoren noch in der DB liegen, ist ein Rollback sofort — keine Neuberechnung, kein Re-Embedding:

UPDATE knowledge.active_pointer
SET active_snapshot_id = $previousSnapshot
WHERE collection_id = $c;
-- danach: NATS-Event snapshot.activated → RAG-Service invalidiert Cache

Ein Garbage-Collector-Job räumt später Versionen weg, die in keinem der letzten N Snapshots mehr referenziert sind — der einzige Ort, an dem überhaupt etwas gelöscht wird.

Was das praktisch bedeutet

Rollback ist das Sicherheitsnetz, nicht der Normalfall.

Ein schlechter Ingest wird durch das Quality Gate gar nicht erst aktiv — der Rollback greift nur, falls eine Verschlechterung erst im Betrieb auffällt. Die Kombination aus immutable Versionen und „live erst nach Promotion" macht die Produktion strukturell robust: Du kannst jederzeit importieren, experimentieren und Snapshots bauen, ohne je den laufenden Stand zu riskieren.

Wie genau das Gate entscheidet, ob ein Kandidat besser oder schlechter ist als der aktive Snapshot, steht im nächsten Post.