2025-12-13 18:38:37 +01:00
---
doc_type: technical_reference
audience: developer, devops
2025-12-27 22:13:11 +01:00
scope: backend, ingestion, smart_edges, edge_registry, modularization
2025-12-13 18:38:37 +01:00
status: active
2025-12-27 22:13:11 +01:00
version: 2.9.0
context: "Detaillierte technische Beschreibung der Import-Pipeline, Two-Pass-Workflow (WP-15b) und modularer Datenbank-Architektur (WP-14). Integriert Mistral-safe Parsing und Deep Fallback."
2025-12-13 18:38:37 +01:00
---
# Ingestion Pipeline & Smart Processing
2025-12-27 22:13:11 +01:00
**Quellen:** `pipeline_playbook.md` , `ingestion_processor.py` , `ingestion_db.py` , `ingestion_validation.py` , `registry.py` , `edge_registry.py`
Die Ingestion transformiert Markdown in den Graphen. Entrypoint: `scripts/import_markdown.py` (CLI) oder `routers/ingest.py` (API). Seit v2.9 nutzt dieser Prozess ein hocheffizientes **Two-Pass-Verfahren** , um globale Kontext-Informationen für die semantische Validierung bereitzustellen, ohne die Idempotenz oder die Change-Detection zu verletzen.
2025-12-13 18:38:37 +01:00
2025-12-25 22:21:41 +01:00
## 1. Der Import-Prozess (16-Schritte-Workflow)
2025-12-13 18:38:37 +01:00
2025-12-27 22:13:11 +01:00
Der Prozess ist **asynchron** , **idempotent** und wird nun in zwei logische Durchläufe (Passes) unterteilt, um die semantische Genauigkeit zu maximieren.
2025-12-13 18:38:37 +01:00
2025-12-27 22:13:11 +01:00
### Phase 1: Pre-Scan & Context (Pass 1)
2025-12-16 18:46:11 +01:00
1. **Trigger & Async Dispatch:**
* **API (`/save`):** Nimmt Request entgegen, validiert und startet Background-Task ("Fire & Forget"). Antwortet sofort mit `202/Queued` .
* **CLI:** Iteriert über Dateien und nutzt `asyncio.Semaphore` zur Drosselung.
2025-12-27 22:13:11 +01:00
2. **Markdown lesen:** Rekursives Scannen des Vaults zur Erstellung des Dateiinventars.
2025-12-19 09:02:49 +01:00
3. **Frontmatter Check & Hard Skip (WP-22):**
* Extraktion von `status` und `type` .
2025-12-27 22:13:11 +01:00
* **Hard Skip Rule:** Wenn `status` in `['system', 'template', 'archive', 'hidden']` ist, wird die Datei für das Deep-Processing übersprungen, ihre Metadaten werden jedoch für den Kontext-Cache erfasst.
2025-12-19 09:02:49 +01:00
* Validierung der Pflichtfelder (`id`, `title` ) für alle anderen Dateien.
4. **Edge Registry Initialisierung (WP-22):**
* Laden der Singleton-Instanz der `EdgeRegistry` .
* Validierung der Vokabular-Datei unter `MINDNET_VOCAB_PATH` .
2025-12-27 22:13:11 +01:00
5. **Config Resolution (WP-14):**
* Bestimmung von `chunking_profile` und `retriever_weight` via zentraler `TypeRegistry` .
2025-12-19 09:02:49 +01:00
* **Priorität:** 1. Frontmatter (Override) -> 2. `types.yaml` (Type) -> 3. Global Default.
2025-12-27 22:13:11 +01:00
6. **LocalBatchCache & Summary Generation (WP-15b):**
* Erstellung von Kurz-Zusammenfassungen für jede Note.
* Speicherung im `batch_cache` als Referenzrahmen für die spätere Kantenvalidierung.
### Phase 2: Semantic Processing & Persistence (Pass 2)
7. **Note-Payload & Multi-Hash (WP-15b):**
* Erstellen des JSON-Objekts inklusive `status` .
* **Multi-Hash Calculation:** Berechnet Hashtabellen für `body` (nur Text) und `full` (Text + Metadaten) zur präzisen Änderungskontrolle.
8. **Change Detection:**
* Vergleich des aktuellen Hashes mit den Daten in Qdrant (Collection `{prefix}_notes` ).
* Strategie wählbar via ENV `MINDNET_CHANGE_DETECTION_MODE` (`full` oder `body` ). Unveränderte Dateien werden hier final übersprungen.
9. **Purge Old Artifacts (WP-14):**
* Bei Änderungen löscht `purge_artifacts()` via `app.core.ingestion.ingestion_db` alle alten Chunks und Edges der Note.
* Die Namensauflösung erfolgt nun über das modularisierte `database` -Paket.
10. **Chunking anwenden:** Zerlegung des Textes basierend auf dem ermittelten Profil (siehe Kap. 3).
11. **Smart Edge Allocation & Semantic Validation (WP-15b):**
* Der `SemanticAnalyzer` schlägt Kanten-Kandidaten vor.
* **Validierung:** Jeder Kandidat wird durch das LLM semantisch gegen das Ziel im **LocalBatchCache** geprüft.
* **Traffic Control:** Nutzung der neutralen `clean_llm_text` Funktion zur Bereinigung von Steuerzeichen (< s > , [OUT]).
* **Deep Fallback (v2.11.14):** Erkennt "Silent Refusals". Liefert die Cloud keine verwertbaren Kanten, wird ein lokaler Fallback via Ollama erzwungen.
12. **Inline-Kanten finden:** Parsing von `[[rel:...]]` und Callouts.
13. **Alias-Auflösung & Kanonisierung (WP-22):**
* Jede Kante wird via `EdgeRegistry` normalisiert (z.B. `basiert_auf` -> `based_on` ).
2025-12-19 09:02:49 +01:00
* Unbekannte Typen werden in `unknown_edges.jsonl` protokolliert.
2025-12-27 22:13:11 +01:00
14. **Default- & Strukturkanten:** Anwendung der `edge_defaults` und Erzeugung von Systemkanten (`belongs_to`, `next` , `prev` ).
15. **Embedding (Async):** Generierung der Vektoren via `nomic-embed-text` (768 Dimensionen).
16. **Database Sync (WP-14):** Batch-Upsert aller Points in die Collections `{prefix}_chunks` und `{prefix}_edges` über die zentrale Infrastruktur.
2025-12-19 09:02:49 +01:00
2025-12-13 18:38:37 +01:00
---
## 2. Betrieb & CLI Befehle
2025-12-28 10:56:34 +01:00
### 2.1 API-Endpunkt: `/ingest/save` (Background Tasks)
Seit WP-14 nutzt der `/ingest/save` Endpunkt **Background Tasks** für non-blocking Ingestion:
**Workflow:**
1. **Request:** Frontend sendet Markdown an `/ingest/save`
2. **Sofortige Antwort:** API antwortet mit `status: "queued"` und `note_id: "pending"`
3. **Datei-Persistenz:** Markdown wird sofort auf Festplatte geschrieben
4. **Background Task:** Ingestion läuft asynchron im Hintergrund
- Chunking
- Embedding-Generierung
- Smart Edge Allocation (WP-15)
- Hybrid-Cloud-Analyse (WP-20)
5. **Vorteil:** Keine Timeouts bei großen Dateien oder langsamen LLM-Calls
**Hinweis:** Die tatsächliche `note_id` steht erst nach dem Parsing fest. Das Frontend sollte den `file_path` für Tracking nutzen.
### 2.2 CLI-Betrieb (Inkrementell)
2025-12-27 22:13:11 +01:00
Erkennt Änderungen via Multi-Hash.
2025-12-13 18:38:37 +01:00
```bash
export QDRANT_URL="http://localhost:6333"
export COLLECTION_PREFIX="mindnet"
2025-12-16 18:46:11 +01:00
export MINDNET_CHANGE_DETECTION_MODE="full"
2025-12-13 18:38:37 +01:00
# Nutzt das Venv der Produktionsumgebung
/home/llmadmin/mindnet/.venv/bin/python3 -m scripts.import_markdown \
--vault ./vault \
--prefix "$COLLECTION_PREFIX" \
--apply \
--purge-before-upsert \
--sync-deletes
```
> **[!WARNING] Purge-Before-Upsert**
2025-12-27 22:13:11 +01:00
> Das Flag `--purge-before-upsert` nutzt nun `ingestion_db.purge_artifacts`. Es ist kritisch, um "Geister-Chunks" (verwaiste Daten nach Textlöschung) konsistent aus den spezialisierten Collections zu entfernen.
2025-12-13 18:38:37 +01:00
### 2.2 Full Rebuild (Clean Slate)
2025-12-27 22:13:11 +01:00
Notwendig bei Änderungen an `types.yaml` , der Registry oder Modell-Wechsel.
2025-12-13 18:38:37 +01:00
```bash
2025-12-27 22:13:11 +01:00
# --force ignoriert alle Hashes und erzwingt den vollständigen Two-Pass Workflow
2025-12-13 18:38:37 +01:00
python3 -m scripts.import_markdown --vault ./vault --prefix "mindnet" --apply --force
```
---
## 3. Chunking & Payload
2025-12-27 22:13:11 +01:00
Das Chunking ist profilbasiert und bezieht seine Konfiguration dynamisch aus der `TypeRegistry` .
2025-12-13 18:38:37 +01:00
2025-12-27 22:13:11 +01:00
### 3.1 Profile und Strategien
2025-12-16 14:48:04 +01:00
| Profil | Strategie | Parameter | Einsatzgebiet |
2025-12-13 18:38:37 +01:00
| :--- | :--- | :--- | :--- |
2025-12-27 22:13:11 +01:00
| `sliding_short` | `sliding_window` | Max: 350, Target: 200 | Kurze Logs, Chats. |
| `sliding_standard` | `sliding_window` | Max: 650, Target: 450 | Standard-Wissen. |
| `sliding_smart_edges` | `sliding_window` | Max: 600, Target: 400 | Fließtexte (Projekte). |
| `structured_smart_edges` | `by_heading` | `strict: false` | Strukturierte Texte. |
2025-12-16 14:48:04 +01:00
2025-12-16 18:46:11 +01:00
### 3.2 Die `by_heading` Logik (v2.9 Hybrid)
2025-12-16 14:48:04 +01:00
2025-12-27 22:13:11 +01:00
Die Strategie `by_heading` zerlegt Texte anhand ihrer Struktur (Überschriften). Sie unterstützt ein "Safety Net" gegen zu große Chunks.
2025-12-16 14:48:04 +01:00
* **Split Level:** Definiert die Tiefe (z.B. `2` = H1 & H2 triggern Split).
* **Modus "Strict" (`strict_heading_split: true`):**
* Jede Überschrift (`< = split_level`) erzwingt einen neuen Chunk.
2025-12-25 22:21:41 +01:00
* *Merge-Check:* Wenn der vorherige Chunk leer war (nur Überschriften), wird gemergt.
2025-12-16 18:46:11 +01:00
* *Safety Net:* Wird ein Abschnitt zu lang (> `max` Token), wird auch ohne Überschrift getrennt.
2025-12-16 14:48:04 +01:00
* **Modus "Soft" (`strict_heading_split: false`):**
2025-12-19 09:02:49 +01:00
* **Hierarchie-Check:** Überschriften *oberhalb* des Split-Levels erzwingen **immer** einen Split.
2025-12-25 22:21:41 +01:00
* **Füll-Logik:** Überschriften *auf* dem Split-Level lösen nur dann einen neuen Chunk aus, wenn der aktuelle Chunk die `target` -Größe erreicht hat.
2025-12-16 18:46:11 +01:00
* *Safety Net:* Auch hier greift das `max` Token Limit.
2025-12-16 14:48:04 +01:00
2025-12-13 18:38:37 +01:00
---
2025-12-19 09:02:49 +01:00
## 4. Edge-Erzeugung & Prioritäten (Provenance)
2025-12-13 18:38:37 +01:00
Kanten werden nach Vertrauenswürdigkeit (`provenance`) priorisiert. Die höhere Prio gewinnt.
2025-12-25 19:39:16 +01:00
| Prio | Quelle | Rule ID / Provenance | Confidence | Erläuterung |
2025-12-19 09:02:49 +01:00
| :--- | :--- | :--- | :--- | :--- |
| **1** | Wikilink | `explicit:wikilink` | **1.00** | Harte menschliche Setzung. |
| **2** | Inline | `inline:rel` | **0.95** | Typisierte menschliche Kante. |
| **3** | Callout | `callout:edge` | **0.90** | Explizite Meta-Information. |
2025-12-27 22:13:11 +01:00
| **4** | Semantic AI | `semantic_ai` | **0.90** | KI-validiert gegen LocalBatchCache. |
2025-12-19 09:02:49 +01:00
| **5** | Type Default | `edge_defaults` | **0.70** | Heuristik aus der Registry. |
2025-12-25 19:39:16 +01:00
| **6** | Struktur | `structure` | **1.00** | System-interne Verkettung (`belongs_to`). |
2025-12-13 18:38:37 +01:00
---
2025-12-19 09:02:49 +01:00
## 5. Quality Gates & Monitoring
2025-12-27 22:13:11 +01:00
**1. Registry Review (WP-14):** Prüfung der `data/logs/unknown_edges.jsonl` . Die zentrale Auflösung via `registry.py` verhindert Inkonsistenzen zwischen Import und Retrieval.
2025-12-13 18:38:37 +01:00
2025-12-27 22:13:11 +01:00
**2. Mistral-safe Parsing:** Automatisierte Bereinigung von LLM-Antworten in `ingestion_validation.py` . Stellt sicher, dass semantische Entscheidungen ("YES"/"NO") nicht durch technische Header verfälscht werden.
2025-12-13 18:38:37 +01:00
2025-12-27 22:13:11 +01:00
**3. Purge Integrity:** Validierung, dass vor jedem Upsert alle assoziierten Artefakte in den Collections `{prefix}_chunks` und `{prefix}_edges` gelöscht wurden, um Daten-Duplikate zu vermeiden.