mindnet/docs/mindnet_technical_architecture.md
Lars 1c42cd1f78
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 3s
Dateien nach "docs" hochladen
2025-11-09 21:16:56 +01:00

19 KiB
Raw Blame History

Mindnet Technische Architektur

Version: 2.0 • Datum: 2025-11-09 • Autor: Systemarchitektur (gemeinsam mit Owner)


0. Zweck dieses Dokuments

Dieses Dokument beschreibt die technische Architektur von mindnet so präzise, dass ein erfahrener Engineer sie 1:1 implementieren kann. Es konsolidiert die bisherigen Überlegungen, eliminiert redundante/unklare Passagen und ergänzt fehlende Details (Datenmodell, Indizes, ImportPipelines, Scoring, Erklärbarkeit, Skalierung, Betrieb). Gültige Inhalte aus früheren Fassungen bleiben erhalten (siehe Anhang A: Originalinhalt).

Kernziele:

  • Persönliches Wissensnetz mit langlebiger Semantik (Notizen, Erlebnisse, Entscheidungen).
  • Antworten, die erklärbar auf Erfahrungen, Konditionierung und Persönlichkeit beruhen.
  • Konfigurierbare Regeln (Zeitgewichtung, Relationstypen, TypProfile).
  • Lokal betreibbar, später skalierbar (onprem → Rechenzentrum/Cloud).
  • Deterministisch, idempotent, auditierbar.

1. Systemkontext (High Level)

  • Quellen: ObsidianVault (Markdown + Frontmatter), künftig MediaWiki/HTML/PDF/E-Mail/Images.
  • Ingestion: Validator → Parser → Chunker (Profile) → Embedding → Graph& PayloadIndexierung.
  • Speicher: Qdrant als Vektorstore + Payload (JSON), ergänzt um Dateimetadaten.
  • APIs: FastAPI (Read/Write), Tools (mindnet_query, mindnet_subgraph), n8nGlue.
  • Retrieval/Reasoning: Hybrid (Vektor + Keyword + GraphWalk) mit konfigurierbaren ScoringRegeln und Erklärpfad.
  • Ops: Deterministische IDs, Versions/ProvenanceFelder, Observability, Tests.

2. Zielarchitektur (Komponenten)

2.1 Ingestion Layer

  1. FrontmatterValidator

    • Erzwingt Pflichtfelder: id, title, type, created, modified
    • Optionale Felder: tags, visibility, relevance, time_weight_override, retriever_weight, chunk_profile, sources, aliases, edge_hints.
    • Validiert type gegen types.yaml (Konfiguration).
  2. Parser

    • Extrahiert: reinen Text, Überschriften, Querverweise ([[Note]], MarkdownLinks), Zitate/Quellen.
    • Normalisiert Unicode, trennt Codeblöcke, Zitate, Aufzählungen.
  3. Chunker (profilgesteuert)

    • Profile: short (~300500 Token), medium (~7001000), long (~12001600).
    • Regeln: Absatz, Überschriften, semantische Grenzen, Überschneidung ~1015% für Kontextkohärenz.
    • ChunkHeader speichert: {note_id, path, type, idx, section_hierarchy, tokens, chunk_profile}.
  4. Embedding

    • Standard: MiniLM384d (lokal über Ollama/TEI), konfigurierbar (embedding.model, dim).
    • Persistiert Vektor + Payload.
  5. EdgeBuilder

    • Declared Edges: aus expliziten Links/Referenzen in der Quelle.
    • Inferred Edges (Rules): aus types.yaml.edge_defaults und Heuristiken (z.B. Abschnittstitel „Bezug“, „siehe auch“).
    • Beide Ebenen als Edges persistiert mit source='declared' | 'rule', kein bloßer DotMarker.

2.2 Storage Layer (Qdrant)

Collections (empfohlen):

  • mindnet_notes (1 Vektor je Note, optional)
  • mindnet_chunks (primärer Suchraum)
  • mindnet_edges (Graph als PayloadDokumente)
  • mindnet_runs (ImportLäufe, Audit/Provenance)
  • mindnet_configs (aktive Konfigurationen, z.B. types.yaml Schnappschuss)

BeispielSchemas:

# mindnet_chunks.payload
id: string                 # deterministic (UUIDv5 über prefix+path+idx)
note_id: string            # FK mindnet_notes.id
type: string               # z. B. concept|task|experience|project|event …
title: string
path: string               # Pfad im Vault
collection: string         # Präfix/Namespace
created: string            # ISODatum
modified: string           # ISODatum
chunk_idx: int
chunk_profile: string      # short|medium|long
retriever_weight: float    # aus types.yaml oder NoteOverride
time_weight: float         # berechnet (Decay) oder Override
section: string            # Überschrift/Gliederung
text: string               # Rohtext des Chunks
tokens: int
hash: string               # content_hash (idempotent)
visibility: string         # public|internal|sensitive
source: {                  # Provenance
  repo: string|null,
  path: string,
  commit: string|null,
  import_run_id: string
}
# mindnet_edges.payload
id: string                 # deterministic (UUIDv5 über src_id + dst_id + relation + source)
src_id: string             # id (Note ODER Chunk)
dst_id: string             # id (Note ODER Chunk)
src_kind: string           # note|chunk
dst_kind: string           # note|chunk
relation: string           # references|related_to|depends_on|belongs_to|derived_from|inspired_by|mentions|contradicts|supports …
weight: float              # Standard 1.0; typenspezifische Offsets möglich
source: string             # declared|rule|ml
evidence: string|null      # Textausschnitt/Link der Ableitung
created: string
import_run_id: string
visibility: string

Indizes (Qdrant):

  • Vektorindex auf mindnet_chunks (HNSW)
  • PayloadIndizes:
    • type (keyword), visibility (keyword), created/modified (datetime), note_id (keyword)
    • optional: FullText auf text (Qdrant payload text index) für HybridSuche

2.3 Retrieval & Scoring

HybridPipeline (empfohlen):

  1. Lexikalische Kandidaten (FTS auf text, title, aliases) k_l.
  2. VektorKandidaten (ANN auf Embeddings) k_v.
  3. GraphExpansion: 12 Hops über mindnet_edges mit relationspezifischen Boosts.
  4. ReRanking (finale Score):
    • S = α·sim + β·kw + γ·G + δ·time_decay + ε·type_weight + ζ·recency_boost_overrides
    • type_weight = retriever_weight aus types.yaml oder NoteOverride.
    • time_decay = exp(λ·age_days); λ global/konfigurierbar; Override per Frontmatter möglich.
    • Erklärbarkeit: Speichere die Summanden + TopEdges als evidence im QueryLog.

RelationGewichte (Defaultvorschlag):

relation_weights:
  references: 1.0
  related_to: 0.6
  depends_on: 1.2
  belongs_to: 0.8
  derived_from: 1.1
  inspired_by: 0.8
  supports: 1.0
  contradicts: -0.9

2.4 Konfiguration (types.yaml + config.yaml)

version: 1.0
types:
  concept:    { chunk_profile: medium, edge_defaults: [references, related_to],    retriever_weight: 0.33 }
  task:       { chunk_profile: short,  edge_defaults: [depends_on, belongs_to],   retriever_weight: 0.80 }
  experience: { chunk_profile: medium, edge_defaults: [derived_from, inspired_by],retriever_weight: 0.90 }
  project:    { chunk_profile: long,   edge_defaults: [references, depends_on],   retriever_weight: 0.95 }
retrieval:
  alpha: 0.45   # sim
  beta:  0.25   # keyword
  gamma: 0.20   # graph
  delta: 0.07   # time decay
  epsilon: 0.03 # type weight
time_decay:
  lambda: 0.0025   # ~ Halbwertzeit ≈ 277 Tage
visibility_defaults: public

2.5 Determinismus, Versionierung, Idempotenz

  • IDs: UUIDv5 über {collection_prefix}:{path}:{chunk_idx} (Chunks) bzw. {collection_prefix}:{path} (Notes).
  • content_hash: SHA256 über normalisierte Inhalte (Unicode NFC, WhitespacePolicy, ÜberschriftenNormalisierung).
  • ImportLauf (mindnet_runs): {run_id, started_at, finished_at, config_hash, files_seen, files_changed, errors}.
  • Idempotenz: nur changed bei content_hashAbweichung.

2.6 Erklärbarkeit (Audit Trail)

  • Jede Antwort liefert: TopChunks, Summanden des Scores, angetretene Kanten inkl. Relation & Gewicht, Zeitfaktor.
  • Persistiere QueryLogs (optional): {query, filters, topk, decision_trace, timestamp}.

2.7 Sicherheit & Datenschutz

  • visibility: public|internal|sensitive, QueryFilter standardmäßig internal.
  • Optionale ACLSchicht: Nutzer/Gruppen, Freigabe je Note/Chunk/Edge.
  • RedaktionsFlags: needs_review, draft, private_journal (werden standardmäßig ausgeschlossen).

2.8 Skalierung & Betrieb

  • Shards/Replicas (Qdrant): 1/1 lokal; 2/2 in DC/Cloud.
  • Snapshots/Backups: Qdrant Snapshot + VaultRepo Snapshot (rsync/borg).
  • Observability: PrometheusExporter (API Latenz, ImportDauer, Chunks/Edges pro Lauf), strukturierte Logs (JSON).
  • Tests: deterministische GoldenFiles für Parser/Chunker; ContractTests für API; OfflineEval für Retrieval.

3. Implementierungsleitfaden (konkret)

3.1 Collections anlegen (Qdrant)

  • mindnet_chunks(dim=384, distance=cosine)
  • mindnet_notes(dim=384, distance=cosine) (optional, falls NoteLevelSuche gewünscht)
  • mindnet_edges(dim=0) (reiner PayloadStore; kein Vektor)
  • PayloadIndizes: siehe 2.2

3.2 ImportPipeline (CLI)

  1. Scan Vault → valide Dateien.
  2. Make Note Payload (inkl. TypRegeln; retriever_weight/chunk_profile aus types.yaml, Override per Frontmatter).
  3. Chunken gemäß Profil + chunk_idx.
  4. Edges bauen: declared + ruleinferred (duplizierte Kanten per IDDeterminismus verhindern).
  5. Upsert: Notes → Chunks → Edges (in dieser Reihenfolge).
  6. RunRecord und ConfigSchnappschuss persistieren.

3.3 QueryAPI (FastAPI)

  • POST /query: text, filters({visibility, types, date_range}), topk, graph_hops, explain=true.
  • GET /subgraph/{id}: Nachbarschaft, RelationFilter, Depth.
  • POST /admin/reindex / POST /admin/import.

3.4 Konfigurierbarkeit

  • types.yaml heiß ladbar (mit Versionsstempel); bei Änderung → config_hash & reimport optional.
  • retrieval.yaml für Gewichte, RelationBoosts, Zeitdecay.

4. Migrations und Qualitätsregeln

  • Keine Workarounds, die Semantik zerstören (z.B. „DotEdge“ ohne Relation).
  • Explizite Kantenpersistenz: jede Regelkante wird als source='rule' gespeichert.
  • ChunkZahl: Profiltreue sicherstellen; Regressionstest (z.B. 171 ➝ 59 = Fehler oder Profiländerung dokumentieren).
  • Provenance Pflicht: import_run_id in Chunks/Edges setzen.

5. Offene Erweiterungen (vordenken)

  • MLEdgeInference (NER, Coref, TEIReranking).
  • ReasoningGraph (Motivationsketten: Kindheitserlebnis → Prinzip → Entscheidung).
  • CitationsFabric (autom. Quellenkonsolidierung).
  • Temporale Graphabfragen (Edges mit Zeitintervallen).

Anhang A: Originalinhalt (unverändert, falls vorhanden)

Der vollständige Originaltext aus knowledge_design.md bleibt hier als Referenz erhalten, damit keine implizite Aussage verloren geht.


mindnet Knowledge Design

Version: 1.4.0 (aktualisiert 2025-10-06)

1. Gesamtziel und Systemverständnis

mindnet ist ein lokales Wissensnetzwerk, das alle meine Notizen, Projekte, Gedanken, Erfahrungen und Pläne als Markdown-Dateien speichert, automatisch importiert, semantisch in Chunks zerlegt und als Graph-Struktur in Qdrant ablegt.
Es ist die Grundlage für ein agentenfähiges, lokal betriebenes LLM-System, das meine Daten verknüpft, abfragt und erweitert.

Zentrale Ziele

  • Vollständige Repräsentation persönlichen Wissens in strukturierter, maschinenlesbarer Form
  • Reproduzierbare Verarbeitung: Import → Chunking → Embedding → Edges → Graph
  • Verlustfreie Roundtrip-Fähigkeit (Import ⇄ Export)
  • Erweiterbarkeit für Agenten, RAG-Retriever und semantische Suche

Prinzipien

  • Deterministisch: IDs, Hashes und Edges wiederholbar
  • Portabel: Markdown + YAML
  • Robust: fehlertoleranter Parser
  • Idempotent: keine Duplikate bei Re-Import
  • Erweiterbar: neue Typen und Edge-Arten ohne Migration

2. YAML-Frontmatter-Schema

Feld Typ Beschreibung
title string Menschlich lesbarer Titel
id string Eindeutige Note-ID (Slug)
type enum concept, thought, experience, task, project, journal, person, meeting, milestone
status enum draft, active, done, archived
created date ISO-Datum
updated date Letzte Änderung
area string Themen- oder Lebensbereich
project string Zugehöriges Projekt
tags list Strukturierte Tags (area/…, topic/…)
depends_on list IDs anderer Notizen
assigned_to list Beteiligte Personen
embedding_exclude bool Falls true, keine Embeddings
hash_mode enum Hash-Modus beim Import (body, frontmatter, full)
priority enum/int 15 oder low / med / high
effort_min, due int/date Aufwand / Termin
aliases list Alternative IDs
lang string ISO-Sprachcode
source string Herkunft / Referenzquelle

Pflichtfelder: title, id, type, status, created
Optionale Felder: alle übrigen


3. Dateinamen und Ordner

  • Format: YYYY-MM-DD_title.md oder slug.md
  • Strukturierte Ordner:
    • 10_thoughts/, 20_concepts/, 30_projects/, 40_experiences/, …
  • Alle Pfade relativ; Unterstriche statt Leerzeichen

Verlinkungen

  • Wikilinks: [[note-id]] oder [[Titel|note-id]]
  • Automatische Edges aus Text und Frontmatter

Edge-Typen in Qdrant

Typ Bedeutung Quelle Scope
belongs_to Chunk → Note intern chunk
prev / next Reihenfolge intern chunk
references explizite Wikilinks Text chunk
backlink Gegenkante zu references abgeleitet note
depends_on YAML-Abhängigkeiten YAML note
assigned_to YAML-Zuweisung YAML note
unresolved Ziel fehlt (Stub) abgeleitet chunk

Edge-Schlüssel

  • source_id, target_id, kind, scope, note_id
  • Dedup-Schlüssel: Kombination aus (kind, source_id, target_id, scope)

5. Chunking-Modell

Chunk-Datenstruktur

Feld Beschreibung
note_id Zugehörige Note
chunk_index Laufende Nummer
text Originalabschnitt
window Text + Overlap links/rechts
overlap_left Länge des linken Overlaps
overlap_right Länge des rechten Overlaps
embedding 384-dimensionaler Vektor
tokens Tokenanzahl (optional)

Chunking-Regeln (aus chunking_strategy.md)

  • Trennung nach Absätzen, Überschriften, Listen, Tabellen
  • Token-Zielgröße 350500 (max 600)
  • Overlap: 3040 % für semantische Kohärenz
  • Overlap wird in window integriert, sodass text ≠ window

6. Hash-Strategie und Änderungsverfolgung

Zweck: Nur bei realer Inhaltsänderung re-indexieren

Umgebungsvariable Beschreibung
MINDNET_HASH_COMPARE Vergleichsquelle (Body, Full, Frontmatter)
MINDNET_HASH_SOURCE Rohtext vs. geparst (raw / parsed)
MINDNET_HASH_NORMALIZE Normalisierung (canonical / none)

Basismodi

  • body → Nur Textkörper
  • frontmatter → Nur Metadaten
  • full → Kombination
  • Hash = SHA-256(canonicalized_input)

Bei Änderung: Re-Import, neue Embeddings, Edges werden aktualisiert.


7. Qdrant-Speicherstruktur

Collection Inhalt Primärfelder Embedding
mindnet_notes Notes mit Fulltext & Hash note_id optional
mindnet_chunks Chunks mit Text, Window, Embedding chunk_id, note_id 384 d
mindnet_edges Graphkanten edge_id, source_id, target_id

Upsert-Strategie

  • Idempotente UUIDv5-IDs
  • Keine Duplikate durch deterministische Signaturen
  • purge-before-upsert zur Bereinigung

Indizes

  • notes: note_id, hash_signature
  • chunks: note_id, chunk_index
  • edges: (kind, source_id, target_id, scope)

8. Fehler-Toleranz und Parser-Robustheit

  • UTF-8 mit Fallback: ersetzt ungültige Bytes (errors="replace")
  • Ignoriert Nullbytes, BOM, exotische Zeilenenden
  • Erkennt defekte oder leere YAML-Header und überspringt sie
  • Logt Problemfälle (read_markdown failed, make_note_payload returned non-dict)
  • Bei Fehlern: Import → warn → continue

9. Tests & Validierung

Integrationstests

  • Roundtrip: Import → Export → Compare (compare_vaults.py)
  • Chunk-Integrität: verify_chunks_integrity.py
  • Hash-Audit: hash_reporter.py
  • Window-Vergleich: check_chunks_window_vs_text.py

Erwartete Ergebnisse

  • Alle Notes werden erkannt
  • window ≠ text bei > 60 % der Chunks
  • Roundtrip-Vergleich liefert „OK“
  • Edge-Anzahl entspricht Modell (belongs_to = #Chunks, next/prev ≈ #Chunks 1)

10. Export & Roundtrip-Verhalten

  • export_markdown.py erzeugt identische Markdown-Dateien
  • Schreibt YAML + Body in korrekter Reihenfolge
  • Roundtrip-Prüfung (compare_vaults.py) validiert:
    • vollständigen Body
    • unveränderte Hash-Signatur
    • gleiche Chunkzahl

11. Graph-Schicht und WP-04-Integration

  • Qdrant fungiert als Graph-Backend
  • graph/service.py (WP-04): stellt API für Mehrhop-Abfragen bereit
  • Unterstützt:
    • expand(note_id, hops=2)
    • resolve_unresolved()
    • neighbors(kind=…)
  • Grundlage für spätere Retriever-Funktionen (LLM / Agenten)

12. Agenten- und LLM-Integration

Retriever-Pipeline

  1. Suche top-k Chunks (cosine distance)
  2. Erweiterung um Edges (references, backlinks)
  3. Kontext-Assembling via window-Text
  4. Prompt-Generierung

Agent-Use-Cases

  • Automatisches Tagging (type, status)
  • Vorschläge für neue Edges
  • Auflösen von unresolved-Referenzen
  • Auto-Import externer Quellen (MediaWiki, PDFs, Webseiten)

13. Erweiterbarkeit

  • Neue Edge-Typen: inspired_by, relates_to, contradicts
  • Neue Note-Typen: decision, resource, recommendation
  • Embedding-Engines austauschbar (MiniLM → LaBSE → E5)
  • Versionierte Chunking-Strategien (chunk_config.py)

14. Qualitätssicherung und Best Practices

  • Validierung vor Upsert
  • Keine Leer-Chunks
  • Vollständige Metadaten in Notes
  • Tests in tests/ automatisch ausführbar (run_e2e_roundtrip.sh)
  • Ergebnis: „Roundtrip OK“ und verify_chunks_integrity = OK

15. Änderungsverlauf

v1.4.0 (2025-10-06)

  • Neu: window vs text Feld in mindnet_chunks
  • Neu: Hash-Modi (body, frontmatter, full) mit Env-Steuerung
  • Neu: Baseline-Modus für Vergleich
  • Parser → fehlertolerant (UTF-8 replace)
  • Roundtrip-Test vollständig integriert
  • Graph-Service und Mehrhop-Abfragen (WP-04-Vorbereitung)
  • purge-before-upsert und --note-scope-refs Parameter ergänzt

v1.3.0 (2025-09-09)

  • Hash-Normalisierung und Edge-Scope
  • Roundtrip-Tests, Agenten-Integration

v1.2.0 (2025-09-02)

  • Grundstruktur des Knowledge-Designs