mindnet/docs/03_Technical_References/03_tech_ingestion_pipeline.md

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)

  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 zur Erstellung des Dateiinventars.
  3. Frontmatter Check & Hard Skip (WP-22):
    • Extraktion von status und type.
    • 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.
    • 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.
  5. Config Resolution (WP-14 / v2.13.12):
    • Bestimmung von chunking_profile und retriever_weight via zentraler TypeRegistry.
    • 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. value nutzt automatisch structured_smart_edges_strict).
  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)

  1. 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.
  2. 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.
  3. 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.
  4. Chunking anwenden: Zerlegung des Textes basierend auf dem ermittelten Profil (siehe Kap. 3).
  5. 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 (, [OUT]).
    • Deep Fallback (v2.11.14): Erkennt "Silent Refusals". Liefert die Cloud keine verwertbaren Kanten, wird ein lokaler Fallback via Ollama erzwungen.
  6. Inline-Kanten finden: Parsing von [[rel:...]] und Callouts.
  7. Alias-Auflösung & Kanonisierung (WP-22):
    • Jede Kante wird via EdgeRegistry normalisiert (z.B. basiert_auf -> based_on).
    • Unbekannte Typen werden in unknown_edges.jsonl protokolliert.
  8. Default- & Strukturkanten: Anwendung der edge_defaults und Erzeugung von Systemkanten (belongs_to, next, prev).
  9. Embedding (Async): Generierung der Vektoren via nomic-embed-text (768 Dimensionen).
  10. Database Sync (WP-14): Batch-Upsert aller Points in die Collections {prefix}_chunks und {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:

  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)

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-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.

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_prefix statt doc_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 (> max Token), 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 max Token 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:

  1. Frontmatter (Override) - Explizite chunking_profile Angabe
  2. types.yaml Typ-Config - Profil basierend auf type
  3. 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.