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

475 lines
19 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:**
```yaml
# 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
}
```
```yaml
# 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):**
```yaml
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)
```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_hash`Abweichung.
### 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 **ACL**Schicht: 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
---
## 4. Link- und Edge-Design
**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
---