19 KiB
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, Import‑Pipelines, 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, Typ‑Profile).
- Lokal betreibbar, später skalierbar (on‑prem → Rechenzentrum/Cloud).
- Deterministisch, idempotent, auditierbar.
1. Systemkontext (High Level)
- Quellen: Obsidian‑Vault (Markdown + Frontmatter), künftig MediaWiki/HTML/PDF/E-Mail/Images.
- Ingestion: Validator → Parser → Chunker (Profile) → Embedding → Graph‑& Payload‑Indexierung.
- Speicher: Qdrant als Vektorstore + Payload (JSON), ergänzt um Dateimetadaten.
- APIs: FastAPI (Read/Write), Tools (mindnet_query, mindnet_subgraph), n8n‑Glue.
- Retrieval/Reasoning: Hybrid (Vektor + Keyword + Graph‑Walk) mit konfigurierbaren Scoring‑Regeln und Erklärpfad.
- Ops: Deterministische IDs, Versions/Provenance‑Felder, Observability, Tests.
2. Zielarchitektur (Komponenten)
2.1 Ingestion Layer
-
Frontmatter‑Validator
- Erzwingt Pflichtfelder:
id,title,type,created,modified - Optionale Felder:
tags,visibility,relevance,time_weight_override,retriever_weight,chunk_profile,sources,aliases,edge_hints. - Validiert
typegegen types.yaml (Konfiguration).
- Erzwingt Pflichtfelder:
-
Parser
- Extrahiert: reinen Text, Überschriften, Querverweise (
[[Note]], Markdown‑Links), Zitate/Quellen. - Normalisiert Unicode, trennt Codeblöcke, Zitate, Aufzählungen.
- Extrahiert: reinen Text, Überschriften, Querverweise (
-
Chunker (profilgesteuert)
- Profile:
short(~300–500 Token),medium(~700–1000),long(~1200–1600). - Regeln: Absatz‑, Überschriften‑, semantische Grenzen, Überschneidung ~10–15% für Kontextkohärenz.
- Chunk‑Header speichert:
{note_id, path, type, idx, section_hierarchy, tokens, chunk_profile}.
- Profile:
-
Embedding
- Standard: MiniLM‑384d (lokal über Ollama/TEI), konfigurierbar (
embedding.model,dim). - Persistiert Vektor + Payload.
- Standard: MiniLM‑384d (lokal über Ollama/TEI), konfigurierbar (
-
Edge‑Builder
- Declared Edges: aus expliziten Links/Referenzen in der Quelle.
- Inferred Edges (Rules): aus
types.yaml.edge_defaultsund Heuristiken (z. B. Abschnittstitel „Bezug“, „siehe auch“). - Beide Ebenen als Edges persistiert mit
source='declared' | 'rule', kein bloßer Dot‑Marker.
2.2 Storage Layer (Qdrant)
Collections (empfohlen):
mindnet_notes(1 Vektor je Note, optional)mindnet_chunks(primärer Suchraum)mindnet_edges(Graph als Payload‑Dokumente)mindnet_runs(Import‑Läufe, Audit/Provenance)mindnet_configs(aktive Konfigurationen, z. B.types.yamlSchnappschuss)
Beispiel‑Schemas:
# 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 # ISO‑Datum
modified: string # ISO‑Datum
chunk_idx: int
chunk_profile: string # short|medium|long
retriever_weight: float # aus types.yaml oder Note‑Override
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) - Payload‑Indizes:
type(keyword),visibility(keyword),created/modified(datetime),note_id(keyword)- optional: Full‑Text auf
text(Qdrant payload text index) für Hybrid‑Suche
2.3 Retrieval & Scoring
Hybrid‑Pipeline (empfohlen):
- Lexikalische Kandidaten (FTS auf
text,title,aliases) – k_l. - Vektor‑Kandidaten (ANN auf Embeddings) – k_v.
- Graph‑Expansion: 1–2 Hops über
mindnet_edgesmit relation‑spezifischen Boosts. - Re‑Ranking (finale Score):
S = α·sim + β·kw + γ·G + δ·time_decay + ε·type_weight + ζ·recency_boost_overridestype_weight=retriever_weightaus types.yaml oder Note‑Override.time_decay=exp(−λ·age_days); λ global/konfigurierbar; Override per Frontmatter möglich.- Erklärbarkeit: Speichere die Summanden + Top‑Edges als evidence im Query‑Log.
Relation‑Gewichte (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, Whitespace‑Policy, Überschriften‑Normalisierung).
- Import‑Lauf (
mindnet_runs):{run_id, started_at, finished_at, config_hash, files_seen, files_changed, errors}. - Idempotenz: nur
changedbeicontent_hash‑Abweichung.
2.6 Erklärbarkeit (Audit Trail)
- Jede Antwort liefert: Top‑Chunks, Summanden des Scores, angetretene Kanten inkl. Relation & Gewicht, Zeitfaktor.
- Persistiere Query‑Logs (optional):
{query, filters, topk, decision_trace, timestamp}.
2.7 Sicherheit & Datenschutz
- visibility:
public|internal|sensitive, Query‑Filter standardmäßiginternal. - Optionale ACL‑Schicht: Nutzer/Gruppen, Freigabe je Note/Chunk/Edge.
- Redaktions‑Flags:
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 + Vault‑Repo Snapshot (rsync/borg).
- Observability: Prometheus‑Exporter (API Latenz, Import‑Dauer, Chunks/Edges pro Lauf), strukturierte Logs (JSON).
- Tests: deterministische Golden‑Files für Parser/Chunker; Contract‑Tests für API; Offline‑Eval 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 Note‑Level‑Suche gewünscht)mindnet_edges(dim=0)(reiner Payload‑Store; kein Vektor)- Payload‑Indizes: siehe 2.2
3.2 Import‑Pipeline (CLI)
- Scan Vault → valide Dateien.
- Make Note Payload (inkl. Typ‑Regeln;
retriever_weight/chunk_profileaus types.yaml, Override per Frontmatter). - Chunken gemäß Profil +
chunk_idx. - Edges bauen: declared + rule‑inferred (duplizierte Kanten per ID‑Determinismus verhindern).
- Upsert: Notes → Chunks → Edges (in dieser Reihenfolge).
- Run‑Record und Config‑Schnappschuss persistieren.
3.3 Query‑API (FastAPI)
POST /query: text, filters({visibility, types, date_range}), topk, graph_hops,explain=true.GET /subgraph/{id}: Nachbarschaft, Relation‑Filter, Depth.POST /admin/reindex/POST /admin/import.
3.4 Konfigurierbarkeit
types.yamlheiß ladbar (mit Versionsstempel); bei Änderung →config_hash& reimport optional.retrieval.yamlfür Gewichte, Relation‑Boosts, Zeitdecay.
4. Migrations‑ und Qualitätsregeln
- Keine Workarounds, die Semantik zerstören (z. B. „Dot‑Edge“ ohne Relation).
- Explizite Kantenpersistenz: jede Regelkante wird als
source='rule'gespeichert. - Chunk‑Zahl: Profiltreue sicherstellen; Regressionstest (z. B. 171 ➝ 59 = Fehler oder Profiländerung dokumentieren).
- Provenance Pflicht:
import_run_idin Chunks/Edges setzen.
5. Offene Erweiterungen (vordenken)
- ML‑Edge‑Inference (NER, Coref, TEI‑Reranking).
- Reasoning‑Graph (Motivationsketten: Kindheitserlebnis → Prinzip → Entscheidung).
- Citations‑Fabric (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 | 1–5 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.mdoderslug.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 350–500 (max 600)
- Overlap: 30–40 % für semantische Kohärenz
- Overlap wird in
windowintegriert, sodasstext ≠ 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örperfrontmatter→ Nur Metadatenfull→ 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-upsertzur 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 ≠ textbei > 60 % der Chunks- Roundtrip-Vergleich liefert „OK“
- Edge-Anzahl entspricht Modell (belongs_to = #Chunks, next/prev ≈ #Chunks – 1)
10. Export & Roundtrip-Verhalten
export_markdown.pyerzeugt 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
- Suche top-k Chunks (cosine distance)
- Erweiterung um Edges (
references,backlinks) - Kontext-Assembling via
window-Text - 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:
windowvstextFeld inmindnet_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-upsertund--note-scope-refsParameter 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