CogniVault Backend erklärt, Teil 2 · Von der Datei zum durchsuchbaren Wissen
Alle Abkürzungen werden im Anhang am Ende der Seite vollständig erklärt.
Ein LLM kann dein PDF nicht “öffnen”. Dieser Satz überrascht viele Neulinge, also lass uns das kurz sacken lassen: Wenn du in CogniVault mit deinen Dokumenten chattest, fasst das Modell die Originaldateien nie an. Es muss etwas zwischen “Ich habe eine Datei in den Browser gezogen” und “Die KI hat mir gerade Seite 47 zitiert” passieren.
Dieses Etwas nennt man Ingestion (Datenaufnahme), und darum geht es in diesem Teil. In Teil 1 haben wir das große Ganze skizziert; heute zoomen wir in einen bestimmten Bereich – das Fließband, das Dateien in durchsuchbares Wissen verwandelt.
Das Fließband
Stell dir die Ingestion wie ein Fließband mit vier Stationen vor:
- Extrahieren: Den Text aus jeder Datei herausholen – auch aus gescannten.
- Chunken (Zerlegen): Den Text in Stücke zerschneiden, die klein genug sind, um in einen Prompt zu passen.
- Embedden (Einbetten): Jeden Chunk in einen Vektor (eine Liste von Zahlen, die seine Bedeutung einfängt) verwandeln, damit ähnliche Ideen im Vektorraum nah beieinander landen.
- Speichern: Vektoren und Metadaten so ablegen, dass sie später durchsucht werden können.
POST /upload
gespeichert in docs/"] --> B subgraph WF["DBOS dauerhafter Workflow"] B["Schritt 1
Welche Dateien haben sich geändert?
SHA-256 Fingerabdrücke"] --> C["Schritt 2
Text extrahieren
pro Format + OCR-Fallback"] C --> D["Chunking
1000 Zeichen, 100 Überlappung"] D --> E["Schritt 3
Embedden
embeddinggemma, 5er-Batches"] E --> F["Schritt 4
Speichern
FAISS Index + Metadaten JSON"] end F --> G["In-Memory Index neu laden
sofort durchsuchbar"]
Ziemlich simpel. Die spannende Ingenieursarbeit steckt in den Fehlerfällen – fangen wir also damit an.
Das Kassenbuch der Fabrik: Warum die Pipeline keine Arbeit verlieren darf
Das Embedden einer großen Bibliothek dauert Minuten. Was passiert, wenn dein Laptop bei Seite 800 eines 1.000-seitigen Handbuchs in den Ruhezustand geht? Bei einem einfachen Python-Skript fängt alles wieder bei Seite 1 an.
CogniVault schreibt die Pipeline stattdessen als einen dauerhaften DBOS-Workflow. Stell dir eine Fabrik vor, in der jede Station einen dauerhaften Stempel in ein Kassenbuch drückt, sobald sie eine Kiste fertiggestellt hat. Fällt der Strom aus, baut niemand fertige Kisten neu zusammen – die Arbeiter lesen das Buch und machen beim ersten ungestempelten Eintrag weiter.
DBOS ist dieses Buch, und PostgreSQL ist das Papier, auf dem es geschrieben steht. Jede Station der Pipeline ist ein mit Checkpoints versehener Schritt; nach einem Neustart liefern abgeschlossene Schritte sofort ihre aufgezeichneten Ergebnisse zurück und die Ausführung geht beim ersten unfertigen Schritt weiter. Ein fehlgeschlagener Embedding-Batch wird einfach nochmal probiert.
Das ist auch der Mechanismus hinter der Live-Fortschrittsanzeige in der UI: Der Start einer Ingestion liefert eine workflow_id zurück, und das Frontend fragt regelmäßig einen Status-Endpoint ab, der meldet, welche Schritte abgeschlossen sind, welche laufen und welche noch warten.
Ich habe einen ausführlichen Deep-Dive über diesen Mechanismus geschrieben – inklusive dessen, was passiert, wenn du den Prozess mitten in der Ingestion mit kill -9 beendest – in Crash-Resumable Ingestion: DBOS, SHA-256, and Surviving a kill -9.
Fingerabdrücke, kein Blindflug: SHA-256 Änderungserkennung
Deine komplette Bibliothek jedes Mal neu zu embedden, wenn du eine einzige Datei hinzufügst, wäre Verschwendung. Bevor also irgendwelche Arbeit passiert, berechnet die Pipeline für jede Datei einen SHA-256 Hash (einen Inhalts-Fingerabdruck – ändere ein Zeichen in der Datei, und der Fingerabdruck ändert sich komplett) und vergleicht ihn mit dem Fingerabdruck, der bei den vorhandenen Chunks der Datei gespeichert ist:
- Noch nie gesehen → einlesen (ingest).
- Fingerabdruck hat sich geändert → die alten Chunks werden soft-gelöscht und die Datei wird neu eingelesen.
- Fingerabdruck identisch → komplett überspringen.
Warum “soft”-gelöscht? Weil der FAISS-Indextyp, den CogniVault nutzt, keine einzelnen Vektoren entfernen kann. Veraltete Chunks werden in den Metadaten einfach als deleted: true markiert; ihre Vektoren bleiben im Index, aber jede Suche filtert sie heraus. Das ist eine ehrliche, langweilige Lösung – und sie korrumpiert niemals den Index.
Jedes Format kriegt eine Sonderbehandlung
Hier ist ein Detail, das eine Demo von einem Produkt unterscheidet. Eine naive Pipeline extrahiert einfach “den ganzen Text” und macht dann Feierabend. Bei CogniVault bekommt jedes Format einen Extractor, der genau die Struktur beibehält, die das Retrieval später braucht:
| Format | Strategie |
|---|---|
| Seite für Seite, wobei die Seitenzahlen behalten werden (diese werden später zu Quellenangaben). Jede Seite mit weniger als 50 Zeichen gilt als gescannt und wird an die OCR geschickt | |
| Gescannte Seite | Die Seite wird mit etwa 144 dpi als Bild gerendert, dann extrahiert Tesseract OCR (Optical Character Recognition – Text aus Bildern auslesen) die Wörter |
| Markdown | Wird an Überschriften aufgeteilt; jeder Abschnitts-Chunk bekommt einen Breadcrumb-Präfix wie [Section: Intro > Setup], damit sein Embedding die Dokumentenhierarchie in sich trägt |
| CSV | Zeilen werden in 20er-Gruppen gechunkt – und jeder Chunk bekommt die Kopfzeile vorangestellt, sodass das Modell immer die Spaltennamen kennt |
| Excel | Gleiches Zeilen-Gruppen-Prinzip pro Arbeitsblatt, mit dem Präfix [Sheet: name] |
| PowerPoint | Ein Chunk pro Folie |
| Word | Absätze plus Tabellenzellen |
| Webseiten | Werden bei Bedarf abgerufen und auf sauberen Artikeltext reduziert – geschützt durch einen SSRF-Guard (Schutz vor Server-Side Request Forgery: der Server weigert sich, private oder interne Adressen abzurufen) |
Frag dich mal, warum das CSV-Detail wichtig ist. Wenn Chunk 14 eines Spreadsheets einfach nur zwanzig nackte Zahlenreihen enthält, wird keine Suche ihn jemals mit der Frage “Wie hoch war das Q3-Budget?” in Verbindung bringen. Stellst du die Kopfzeile voran, weiß der Chunk, dass er Budget-Spalten enthält. Struktur ist der Treibstoff fürs Retrieval.
Chunking: 1.000 Zeichen mit 100 Zeichen Sicherheitsnetz (Überlappung)
Lange Texte werden in Stücke von etwa 1.000 Zeichen zerlegt, wobei sich benachbarte Stücke um 100 Zeichen überlappen. Diese Überlappung ist eine Versicherung: Ein Satz, der genau an der Chunk-Grenze zerschnitten wird, taucht in einem der beiden Nachbarn immer noch als Ganzes auf, sodass keine Idee in die Lücke zwischen den Chunks fällt.
Embedden und Speichern
Chunks werden von embeddinggemma (via Ollama) in 5er-Batches embedded – jeder Chunk wird zu einem Vektor. Die Vektoren werden normalisiert und an einen FAISS-Index angehängt; daneben hält eine JSON-Datei für jeden Chunk den Quelldateinamen, die Seitenzahl, die Kategorie, den Fingerabdruck und den eigentlichen Text fest. Der Index speichert die Zahlen; das JSON speichert die Bedeutung.
Eine Designentscheidung, die man für Anfänger hervorheben sollte: Das hier ist ein exakter Index, kein approximativer. Viele Vektor-Datenbanken nutzen ANN (Approximate Nearest Neighbour)-Abkürzungen, die bei riesiger Skalierung ein wenig Genauigkeit gegen Geschwindigkeit tauschen. Im Maßstab einer persönlichen Bibliothek brauchst du diesen Kompromiss nicht – CogniVault prüft jeden Vektor bei jeder Suche und ist trotzdem schnell.
Die gesamte Reise, von Anfang bis Ende
Fazit
Bei der Ingestion entscheidet sich meistens die eigentliche RAG-Qualität – lange bevor irgendwelches clevere Prompting ins Spiel kommt. Beibehaltene Seitenzahlen, Header, die in jeden Spreadsheet-Chunk kopiert werden, gerettete Scans durch OCR, und ein Kassenbuch, das das Ganze absturzsicher macht: Nichts davon ist glamourös, aber alles davon zeigt sich später in Form von Antworten, die die richtige Seite zitieren.
Anhang: Abkürzungen in diesem Post
| Abkürzung | Volle Form | Bedeutung |
|---|---|---|
| LLM | Large Language Model | Ein neuronales Netz, trainiert mit riesigen Textmengen, das Sprache lesen und erzeugen kann |
| DBOS | Database-Oriented Operating System | Die Bibliothek, die Workflow-Schritte in PostgreSQL sichert, damit abgestürzte Jobs fortgesetzt werden können |
| SHA-256 | Secure Hash Algorithm, 256-bit | Ein Inhalts-Fingerabdruck – ändere ein Byte einer Datei und der Hash ändert sich komplett |
| OCR | Optical Character Recognition | Text aus Bildern lesen – der Rettungsweg für gescannte PDF-Seiten |
| SSRF | Server-Side Request Forgery | Ein Angriff, bei dem ein Server ausgetrickst wird, interne URLs abzurufen; der URL-Importer blockiert dies |
| FAISS | Facebook AI Similarity Search | Der Vektor-Index, an den die Embeddings angehängt werden |
| ANN | Approximate Nearest Neighbour | Die Genauigkeit-gegen-Geschwindigkeit-Abkürzung, die CogniVault absichtlich nicht nimmt |
| dpi | Dots Per Inch | Bildauflösung – gescannte Seiten werden vor der OCR mit ca. 144 dpi gerendert |
| JSON | JavaScript Object Notation | Das Format der Chunk-Metadaten-Datei neben dem FAISS-Index |
| PDF / CSV | Portable Document Format / Comma-Separated Values | Zwei der acht+ unterstützten Dateiformate |
| API | Application Programming Interface | Die Endpoints (/upload, /ingest, /ingest/status/…), die den Ablauf steuern |
Als Nächstes: Teil 3 · Wie aus einer Frage eine belegte Antwort wird — hybrides Retrieval, der 6-Tools-Agent und der 2-Phasen-Stream, der zeigt, wie das Modell denkt, bevor es antwortet.

Ähnliches
- CogniVault Backend erklärt, Teil 1 · Das Backend kennenlernen: Drei Prozesse, vier Schichten
- CogniVault Backend erklärt, Teil 3 · Wie aus einer Frage eine belegte Antwort wird
- Teil 1 · CogniVault Architektur: Warum Standard-RAG nicht reicht (Hybride Suche)
- Teil 4 · Crash-Resumable Ingestion: DBOS, SHA-256 und wie man ein kill -9 überlebt
- CogniVault Backend erklärt, Teil 4 · Study Tools, Fortschritt und die Privacy-Belege