11 KiB
| doc_type | audience | scope | status | version | context |
|---|---|---|---|---|---|
| technical_reference | developer, devops | backend, ingestion, smart_edges, edge_registry, modularization | active | 2.13.12 | Detaillierte technische Beschreibung der Import-Pipeline, Two-Pass-Workflow (WP-15b) und modularer Datenbank-Architektur (WP-14). Integriert Mistral-safe Parsing und Deep Fallback. |
Ingestion Pipeline & Smart Processing
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.
1. Der Import-Prozess (16-Schritte-Workflow)
Der Prozess ist asynchron, idempotent und wird nun in zwei logische Durchläufe (Passes) unterteilt, um die semantische Genauigkeit zu maximieren.
Phase 1: Pre-Scan & Context (Pass 1)
- Trigger & Async Dispatch:
- API (
/save): Nimmt Request entgegen, validiert und startet Background-Task ("Fire & Forget"). Antwortet sofort mit202/Queued. - CLI: Iteriert über Dateien und nutzt
asyncio.Semaphorezur Drosselung.
- API (
- Markdown lesen: Rekursives Scannen des Vaults zur Erstellung des Dateiinventars.
- Frontmatter Check & Hard Skip (WP-22):
- Extraktion von
statusundtype. - Hard Skip Rule: Wenn
statusin['system', 'template', 'archive', 'hidden']ist, wird die Datei für das Deep-Processing übersprungen, ihre Metadaten werden jedoch für den Kontext-Cache erfasst. - Validierung der Pflichtfelder (
id,title) für alle anderen Dateien.
- Extraktion von
- Edge Registry Initialisierung (WP-22):
- Laden der Singleton-Instanz der
EdgeRegistry. - Validierung der Vokabular-Datei unter
MINDNET_VOCAB_PATH.
- Laden der Singleton-Instanz der
- Config Resolution (WP-14 / v2.13.12):
- Bestimmung von
chunking_profileundretriever_weightvia zentralerTypeRegistry. - Priorität: 1. Frontmatter (Override) -> 2.
types.yaml(Type) -> 3. Global Default. - Registry-First Profiling: Automatische Anwendung der korrekten Profile basierend auf dem Note-Typ (z.B.
valuenutzt automatischstructured_smart_edges_strict).
- Bestimmung von
- LocalBatchCache & Summary Generation (WP-15b):
- Erstellung von Kurz-Zusammenfassungen für jede Note.
- Speicherung im
batch_cacheals Referenzrahmen für die spätere Kantenvalidierung.
Phase 2: Semantic Processing & Persistence (Pass 2)
- Note-Payload & Multi-Hash (WP-15b):
- Erstellen des JSON-Objekts inklusive
status. - Multi-Hash Calculation: Berechnet Hashtabellen für
body(nur Text) undfull(Text + Metadaten) zur präzisen Änderungskontrolle.
- Erstellen des JSON-Objekts inklusive
- Change Detection:
- Vergleich des aktuellen Hashes mit den Daten in Qdrant (Collection
{prefix}_notes). - Strategie wählbar via ENV
MINDNET_CHANGE_DETECTION_MODE(fulloderbody). Unveränderte Dateien werden hier final übersprungen.
- Vergleich des aktuellen Hashes mit den Daten in Qdrant (Collection
- Purge Old Artifacts (WP-14):
- Bei Änderungen löscht
purge_artifacts()viaapp.core.ingestion.ingestion_dballe alten Chunks und Edges der Note. - Die Namensauflösung erfolgt nun über das modularisierte
database-Paket.
- Bei Änderungen löscht
- Chunking anwenden: Zerlegung des Textes basierend auf dem ermittelten Profil (siehe Kap. 3).
- Smart Edge Allocation & Semantic Validation (WP-15b):
- Der
SemanticAnalyzerschlä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_textFunktion zur Bereinigung von Steuerzeichen (, [OUT]). - Deep Fallback (v2.11.14): Erkennt "Silent Refusals". Liefert die Cloud keine verwertbaren Kanten, wird ein lokaler Fallback via Ollama erzwungen.
- Der
- Inline-Kanten finden: Parsing von
[[rel:...]]und Callouts. - Alias-Auflösung & Kanonisierung (WP-22):
- Jede Kante wird via
EdgeRegistrynormalisiert (z.B.basiert_auf->based_on). - Unbekannte Typen werden in
unknown_edges.jsonlprotokolliert.
- Jede Kante wird via
- Default- & Strukturkanten: Anwendung der
edge_defaultsund Erzeugung von Systemkanten (belongs_to,next,prev). - Embedding (Async): Generierung der Vektoren via
nomic-embed-text(768 Dimensionen). - Database Sync (WP-14): Batch-Upsert aller Points in die Collections
{prefix}_chunksund{prefix}_edgesüber die zentrale Infrastruktur.
2. Betrieb & CLI Befehle
2.1 API-Endpunkt: /ingest/save (Background Tasks)
Seit WP-14 nutzt der /ingest/save Endpunkt Background Tasks für non-blocking Ingestion:
Workflow:
- Request: Frontend sendet Markdown an
/ingest/save - Sofortige Antwort: API antwortet mit
status: "queued"undnote_id: "pending" - Datei-Persistenz: Markdown wird sofort auf Festplatte geschrieben
- Background Task: Ingestion läuft asynchron im Hintergrund
- Chunking
- Embedding-Generierung
- Smart Edge Allocation (WP-15)
- Hybrid-Cloud-Analyse (WP-20)
- 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)
Erkennt Änderungen via Multi-Hash.
export QDRANT_URL="http://localhost:6333"
export COLLECTION_PREFIX="mindnet"
export MINDNET_CHANGE_DETECTION_MODE="full"
# 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-upsertnutzt nuningestion_db.purge_artifacts. Es ist kritisch, um "Geister-Chunks" (verwaiste Daten nach Textlöschung) konsistent aus den spezialisierten Collections zu entfernen.
2.2 Full Rebuild (Clean Slate)
Notwendig bei Änderungen an types.yaml, der Registry oder Modell-Wechsel.
# --force ignoriert alle Hashes und erzwingt den vollständigen Two-Pass Workflow
python3 -m scripts.import_markdown --vault ./vault --prefix "mindnet" --apply --force
3. Chunking & Payload
Das Chunking ist profilbasiert und bezieht seine Konfiguration dynamisch aus der TypeRegistry.
3.1 Profile und Strategien
| Profil | Strategie | Parameter | Einsatzgebiet |
|---|---|---|---|
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. |
3.2 Die by_heading Logik (v3.9.9 Atomic Section Logic)
Die Strategie by_heading implementiert seit v3.9.9 das "Pack-and-Carry-Over" Verfahren (Regel 1-3), um Sektions-Überschriften und deren Inhalte atomar in Chunks zu halten.
Kernprinzipien:
- Atomic Section Logic: Überschriften und deren Inhalte werden als atomare Einheiten behandelt und nicht über Chunk-Grenzen hinweg getrennt.
- H1-Context Preservation: Der Dokumenttitel (H1) wird zuverlässig als Breadcrumb in das Embedding-Fenster (
window) aller Chunks injiziert. - Signature Alignment: Parameter-Synchronisierung zwischen Orchestrator und Strategien (
context_prefixstattdoc_title).
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. - Merge-Check: Wenn der vorherige Chunk leer war (nur Überschriften), wird gemergt.
- Safety Net: Wird ein Abschnitt zu lang (>
maxToken), wird auch ohne Überschrift getrennt.
Modus "Soft" (strict_heading_split: false):
- Hierarchie-Check: Überschriften oberhalb des Split-Levels erzwingen immer einen Split.
- 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. - Pack-and-Carry-Over: Wenn ein Abschnitt zu groß ist, wird er intelligent zerlegt, wobei der Rest (mit Überschrift) zurück in die Queue gelegt wird.
- Safety Net: Auch hier greift das
maxToken Limit.
3.3 Registry-First Profiling (v2.13.12)
Seit v2.13.12 nutzt der IngestionService die korrekte Hierarchie zur Ermittlung des Chunking-Profils:
Priorität:
- Frontmatter (Override) - Explizite
chunking_profileAngabe types.yamlTyp-Config - Profil basierend auftype- Global Defaults - Fallback auf
sliding_standard
Wichtig: Ein Hard-Fallback auf sliding_standard erfolgt nur noch, wenn keine Konfiguration existiert. Dies stellt sicher, dass Note-Typen wie value automatisch das korrekte Profil (z.B. structured_smart_edges_strict) erhalten.
3.4 Deterministic Hashing (v2.13.12)
Der full-Hash inkludiert nun alle strategischen Parameter (z.B. split_level, strict_heading_split), sodass Konfigurationsänderungen im Frontmatter zwingend einen Re-Import auslösen.
Impact: Änderungen an Chunking-Parametern werden zuverlässig erkannt, auch wenn der Text unverändert bleibt.
4. Edge-Erzeugung & Prioritäten (Provenance)
Kanten werden nach Vertrauenswürdigkeit (provenance) priorisiert. Die höhere Prio gewinnt.
| Prio | Quelle | Rule ID / Provenance | Confidence | Erläuterung |
|---|---|---|---|---|
| 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. |
| 4 | Semantic AI | semantic_ai |
0.90 | KI-validiert gegen LocalBatchCache. |
| 5 | Type Default | edge_defaults |
0.70 | Heuristik aus der Registry. |
| 6 | Struktur | structure |
1.00 | System-interne Verkettung (belongs_to). |
5. Quality Gates & Monitoring
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.
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.
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.