2025-12-13 18:38:37 +01:00
---
doc_type: technical_reference
audience: developer, devops
scope: backend, ingestion, smart_edges
status: active
2025-12-16 18:46:11 +01:00
version: 2.7.0
2025-12-16 14:48:04 +01:00
context: "Detaillierte technische Beschreibung der Import-Pipeline, Chunking-Strategien und CLI-Befehle."
2025-12-13 18:38:37 +01:00
---
# Ingestion Pipeline & Smart Processing
**Quellen:** `pipeline_playbook.md` , `Handbuch.md`
2025-12-16 18:46:11 +01:00
Die Ingestion transformiert Markdown in den Graphen. Entrypoint: `scripts/import_markdown.py` (CLI) oder `routers/ingest.py` (API).
2025-12-13 18:38:37 +01:00
2025-12-16 18:46:11 +01:00
## 1. Der Import-Prozess (14-Schritte-Workflow)
2025-12-13 18:38:37 +01:00
Der Prozess ist **asynchron** und **idempotent** .
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.
2. **Markdown lesen:** Rekursives Scannen des Vaults.
3. **Frontmatter extrahieren:** Validierung von Pflichtfeldern (`id`, `type` , `title` ).
4. **Config Resolution:**
* Bestimmung von `chunking_profile` und `retriever_weight` .
* **Priorität:** 1. Frontmatter (Override) -> 2. `types.yaml` (Type) -> 3. Default.
5. **Note-Payload generieren:**
* Erstellen des JSON-Objekts für `mindnet_notes` .
* **Multi-Hash Calculation:** Berechnet Hashtabellen für `body` (nur Text) und `full` (Text + Metadaten).
6. **Change Detection:**
* Vergleich des Hashes mit Qdrant.
* Strategie wählbar via ENV `MINDNET_CHANGE_DETECTION_MODE` (`full` oder `body` ).
7. **Chunking anwenden:** Zerlegung des Textes basierend auf dem ermittelten Profil (siehe Kap. 3).
8. **Smart Edge Allocation (WP15):**
2025-12-13 18:38:37 +01:00
* Wenn `enable_smart_edge_allocation: true` : Der `SemanticAnalyzer` sendet Chunks an das LLM.
2025-12-16 14:48:04 +01:00
* **Traffic Control:** Request nutzt `priority="background"` . Semaphore (Limit via `.env` ) drosselt die Last.
2025-12-13 18:38:37 +01:00
* **Resilienz:** Bei Timeout (Ollama) greift ein Fallback (Broadcasting an alle Chunks).
2025-12-16 18:46:11 +01:00
9. **Inline-Kanten finden:** Parsing von `[[rel:...]]` .
10. **Callout-Kanten finden:** Parsing von `> [!edge]` .
11. **Default-Edges erzeugen:** Anwendung der `edge_defaults` aus Registry.
12. **Strukturkanten erzeugen:** `belongs_to` , `next` , `prev` .
13. **Embedding (Async):** Generierung via `nomic-embed-text` (768 Dim).
14. **Diagnose:** Integritäts-Check nach dem Lauf.
2025-12-13 18:38:37 +01:00
---
## 2. Betrieb & CLI Befehle
### 2.1 Standard-Betrieb (Inkrementell)
Für regelmäßige Updates (Cronjob). Erkennt Änderungen via Hash.
```bash
export QDRANT_URL="http://localhost:6333"
export COLLECTION_PREFIX="mindnet"
2025-12-16 18:46:11 +01:00
# Steuert, wann eine Datei als "geändert" gilt
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**
> Das Flag `--purge-before-upsert` ist kritisch. Es löscht vor dem Schreiben einer Note ihre alten Chunks/Edges. Ohne dieses Flag entstehen **"Geister-Chunks"** (alte Textabschnitte, die im Markdown gelöscht wurden, aber im Index verbleiben).
### 2.2 Full Rebuild (Clean Slate)
2025-12-16 14:48:04 +01:00
Notwendig bei Änderungen an `types.yaml` (z.B. neue Chunking-Profile) oder Modell-Wechsel.
2025-12-13 18:38:37 +01:00
```bash
# 0. Modell sicherstellen
ollama pull nomic-embed-text
# 1. Qdrant Collections löschen (Wipe)
python3 -m scripts.reset_qdrant --mode wipe --prefix "mindnet" --yes
# 2. Vollständiger Import (Force)
2025-12-16 18:46:11 +01:00
# --force ignoriert alle Hashes und schreibt alles neu
2025-12-13 18:38:37 +01:00
python3 -m scripts.import_markdown --vault ./vault --prefix "mindnet" --apply --force
```
---
## 3. Chunking & Payload
2025-12-16 18:46:11 +01:00
Das Chunking ist profilbasiert und in `types.yaml` konfiguriert.
2025-12-13 18:38:37 +01:00
2025-12-16 14:48:04 +01:00
### 3.1 Profile und Strategien
| Profil | Strategie | Parameter | Einsatzgebiet |
2025-12-13 18:38:37 +01:00
| :--- | :--- | :--- | :--- |
2025-12-16 14:48:04 +01:00
| `sliding_short` | `sliding_window` | Max: 350, Target: 200 | Kurze Logs, Chats, Risiken. |
| `sliding_standard` | `sliding_window` | Max: 650, Target: 450 | Massendaten (Journal, Quellen). |
| `sliding_smart_edges` | `sliding_window` | Max: 600, Target: 400 | Fließtexte mit hohem Wert (Projekte, Erfahrungen). |
| `structured_smart_edges` | `by_heading` | `strict: false` (Soft) | Strukturierte Texte, wo kleine Abschnitte gemergt werden dürfen. |
| `structured_smart_edges_strict` | `by_heading` | `strict: true` (Hard) | **Atomare Einheiten** : Entscheidungen, Werte, Profile. |
2025-12-16 18:46:11 +01:00
| `structured_smart_edges_strict_L3` | `by_heading` | `strict: true` , `level: 3` | Tief geschachtelte Prinzipien (Tier 2/MP1 Logik). |
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-16 18:46:11 +01:00
Die Strategie `by_heading` zerlegt Texte anhand ihrer Struktur (Überschriften). Sie unterstützt seit v2.9 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-16 18:46:11 +01:00
* *Merge-Check:* Wenn der vorherige Chunk leer war (nur Überschriften), wird gemergt (verhindert verwaiste Überschriften).
* *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-16 18:46:11 +01:00
* **Hierarchie-Check:** Überschriften *oberhalb* des Split-Levels (z.B. H1 bei Level 2) erzwingen **immer** einen Split.
* **Füll-Logik:** Überschriften *auf* dem Split-Level (z.B. H2) lösen nur dann einen neuen Chunk aus, wenn der aktuelle Chunk die `target` -Größe erreicht hat.
* *Safety Net:* Auch hier greift das `max` Token Limit.
2025-12-16 14:48:04 +01:00
### 3.3 Payload-Felder (Qdrant)
2025-12-16 18:46:11 +01:00
* `text` : Der reine Inhalt (Anzeige im UI). Überschriften bleiben erhalten.
* `window` : Inhalt plus Overlap (für Embedding). Bei `by_heading` wird der Kontext (Eltern-Überschrift) oft vorangestellt.
* `chunk_profile` : Das effektiv genutzte Profil (zur Nachverfolgung).
2025-12-13 18:38:37 +01:00
---
## 4. Edge-Erzeugung & Prioritäten
Kanten werden nach Vertrauenswürdigkeit (`provenance`) priorisiert. Die höhere Prio gewinnt.
| Prio | Quelle | Rule ID | Confidence |
| :--- | :--- | :--- | :--- |
| **1** | Inline | `inline:rel` | 0.95 |
| **2** | Callout | `callout:edge` | 0.90 |
| **3** | Wikilink | `explicit:wikilink` | 1.00 |
| **4** | Smart Edge | `smart:llm_filter` | 0.90 |
| **5** | Type Default | `edge_defaults` | 0.70 |
| **6** | Struktur | `structure` | 1.00 |
---
## 5. Quality Gates & Tests
Diese Tests garantieren die Stabilität der Pipeline.
**1. Payload Dryrun (Schema-Check):**
Simuliert Import, prüft JSON-Schema Konformität.
```bash
python3 -m scripts.payload_dryrun --vault ./test_vault
```
**2. Full Edge Check (Graph-Integrität):**
Prüft Invarianten (z.B. `next` muss reziprok zu `prev` sein).
```bash
python3 -m scripts.edges_full_check
```