All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s
235 lines
10 KiB
Markdown
235 lines
10 KiB
Markdown
# Mindnet v2.2 – Fachliche Architektur
|
||
**Datei:** `docs/mindnet_functional_architecture_v2.2.md`
|
||
**Stand:** 2025-12-07
|
||
**Status:** **FINAL** (Integrierter Stand WP01–WP04a)
|
||
|
||
> Dieses Dokument beschreibt **was** Mindnet fachlich tut und **warum** – mit Fokus auf die Erzeugung und Nutzung von **Edges** (Kanten) zwischen Notizen/Chunks sowie die Logik des Retrievers. Die technische Umsetzung (Module, Flags, Schemas) wird im technischen Dokument detailliert.
|
||
|
||
---
|
||
|
||
## 0) Zielbild & Grundprinzip
|
||
|
||
Mindnet wandelt Obsidian-Markdown-Notizen in einen **dynamischen Graphen aus Punkten und Kanten** um.
|
||
Die drei zentralen Artefakt-Sammlungen lauten:
|
||
|
||
- `mindnet_notes` – genau **eine** Note pro Markdown-Datei (Metadaten & Hashes)
|
||
- `mindnet_chunks` – semantische Teilstücke einer Note (Fenster/„Chunks“)
|
||
- `mindnet_edges` – gerichtete Beziehungen zwischen Knoten (Chunks/Notes)
|
||
|
||
Die Import-Pipeline erzeugt diese Artefakte **deterministisch** und **idempotent** (erneute Läufe überschreiben konsistent statt zu duplizieren). Die Import-Schritte sind: *parse → chunk → edge → upsert*.
|
||
|
||
---
|
||
|
||
## 1) Notizen & Chunks (fachliche Perspektive)
|
||
|
||
### 1.1 Notiz (Note)
|
||
- Repräsentiert eine fachliche Einheit (z. B. *„Vector DB Basics“*, *„KI-Projekt“*).
|
||
- Trägt Eigenschaften (Titel, Typ, Zeitstempel, optionale Policies).
|
||
- **Typ** (*type*) steuert u. a. Chunk-Profil und Default-Relationen (siehe §4).
|
||
- **retriever_weight** und **chunk_profile** werden systematisch an Note **und** Chunks gespiegelt, damit der Retriever beides nutzen kann.
|
||
|
||
### 1.2 Chunk
|
||
- Ausschnitt/Textfenster aus der Note, als eigenständiger Such-Anker.
|
||
- Jeder Chunk gehört **genau einer** Note.
|
||
- Chunks bilden eine Sequenz (1…N) – das ermöglicht *next/prev*.
|
||
- **Neu in v2.2:** Alle Kanten entstehen ausschließlich zwischen Chunks (Scope="chunk"), nie zwischen Notes direkt. Notes dienen nur noch als Metadatencontainer.
|
||
|
||
> **Wichtig:** Chunking-Profile (short/medium/long) kommen aus `types.yaml` (per Note-Typ), können aber lokal überschrieben werden. Die effektiven Werte werden bei der Payload-Erzeugung bestimmt.
|
||
|
||
---
|
||
|
||
## 2) Edges – fachliche Typen & Bedeutung
|
||
|
||
Edges kodieren Beziehungen. Sie sind **gerichtet** und werden in `mindnet_edges` gespeichert. Die Erzeugung folgt einer strengen Priorität: **Inline > Callout > Defaults > Struktur**.
|
||
|
||
### 2.1 Struktur-Kanten (Das Skelett)
|
||
- **belongs_to**: *Chunk → Note* (Zuordnung)
|
||
- **next / prev**: Kettenbeziehungen zwischen aufeinanderfolgenden Chunks derselben Note.
|
||
→ ermöglichen „lineares Weiterlesen“ oder Kontextpfade in Antworten.
|
||
Diese Kanten entstehen immer, unabhängig von Inhalten.
|
||
|
||
### 2.2 Inhalts-Kanten (explizit)
|
||
Hier unterscheidet v2.2 präzise zwischen verschiedenen Quellen der Evidenz:
|
||
|
||
1. **Explizite Inline-Relationen (Höchste Priorität):**
|
||
Im Fließtext notierte, semantisch qualifizierte Relationen.
|
||
* Syntax: `[[rel:depends_on Embeddings 101]]`
|
||
* Fachliche Aussage: "Hängt ab von", "Ähnlich zu".
|
||
* *rule_id*: `inline:rel`
|
||
* *confidence*: ~0.95
|
||
|
||
2. **Callout-Edges (Kuratierte Listen):**
|
||
Redaktionell gepflegte Listen am Ende einer Notiz (z.B. "Siehe auch").
|
||
* Syntax: `> [!edge] related_to: [[Vector DB Basics]]`
|
||
* *rule_id*: `callout:edge`
|
||
* *confidence*: ~0.90
|
||
|
||
3. **Wikilinks (Standard-Referenzen):**
|
||
Der klassische Obsidian-Link.
|
||
* Syntax: `[[Vector DB Basics]]`
|
||
* Typ: `references`
|
||
* *rule_id*: `explicit:wikilink`
|
||
* *confidence*: 1.0
|
||
|
||
> Alle expliziten Quellen (Wikilink, Inline-Rel, Callout) sind **Primärbelege**.
|
||
|
||
### 2.3 Typ-basierte Default-Kanten (Regelbasiert)
|
||
Jede Note hat einen *Typ* (z. B. `concept`, `project`, `profile`). In `config/types.yaml` definieren wir pro Typ **edge_defaults**, z. B.:
|
||
|
||
- `concept`: `["references","related_to"]`
|
||
- `project`: `["references","depends_on"]`
|
||
|
||
Regel: **Für jede gefundene explizite Referenz** (s. o.) werden **zusätzliche** Edges nach diesen Defaults erzeugt.
|
||
Beispiel: Ein *project* mit `edge_defaults=["depends_on"]` erzeugt zu *jedem* explizit referenzierten Ziel **zusätzlich** eine `depends_on`-Kante.
|
||
Diese Kanten tragen *provenance=rule* und eine **rule_id** der Form `edge_defaults:{note_type}:{relation}` sowie eine geringere Confidence (~0.7).
|
||
|
||
---
|
||
|
||
## 3) Edge-Payload – Felder & Semantik
|
||
|
||
Jede Kante hat mindestens:
|
||
|
||
- `kind` – Beziehungsart *(belongs_to, next, prev, references, related_to, depends_on, similar_to, …)*
|
||
- `scope` – `"chunk"` (Standard in v2.2)
|
||
- `source_id`, `target_id` – Quell-/Ziel-Knoten (Chunk-IDs oder Note-Titel bei unresolved Targets)
|
||
- `note_id` – **Owner-Note** (die Note, aus der die Kante stammt)
|
||
|
||
Erweiterte/abgeleitete Felder (WP03 Superset):
|
||
|
||
- `provenance` – `"explicit"` (Wikilink/Inline/Callout) oder `"rule"` (Typ-Defaults)
|
||
- `rule_id` – maschinenlesbare Regelquelle (z.B. `inline:rel`, `edge_defaults:project:depends_on`)
|
||
- `confidence` – 0.0–1.0; Heuristik zur Gewichtung im Scoring.
|
||
|
||
**Dedup-Schlüssel** (fachlich): Gleichlautende `(source_id, target_id, kind, scope, rule_id)` werden nicht mehrfach geschrieben.
|
||
|
||
---
|
||
|
||
## 4) Typ-Registry (`config/types.yaml`)
|
||
|
||
### 4.1 Zweck
|
||
- Steuert **Chunking-Profile** (`short|medium|long`) **pro Typ**
|
||
- Liefert **retriever_weight** (Note-/Chunk-Gewichtung im Ranking) **pro Typ**
|
||
- Definiert **edge_defaults** je Typ (s. o.)
|
||
|
||
Der Importer lädt die Registry aus `MINDNET_TYPES_FILE` oder nutzt Fallbacks. **Frontmatter-Overrides** für Profile werden in v2.2 weitgehend ignoriert zugunsten einer zentralen Governance in der YAML-Datei.
|
||
|
||
### 4.2 Beispiel (auslieferungsnah)
|
||
version: 1.0
|
||
types:
|
||
concept:
|
||
chunk_profile: medium
|
||
edge_defaults: ["references", "related_to"]
|
||
retriever_weight: 0.60
|
||
project:
|
||
chunk_profile: long
|
||
edge_defaults: ["references", "depends_on"]
|
||
retriever_weight: 0.97
|
||
|
||
**Auflösung im Importer**
|
||
- `effective_chunk_profile(note_type, registry)` → `"short|medium|long"|None`
|
||
- `effective_retriever_weight(note_type, registry)` → `float|None`
|
||
- Ergebnis wird in `note_payload` **und** `chunk_payloads` gespiegelt.
|
||
|
||
---
|
||
|
||
## 5) Der Retriever (Funktionaler Layer)
|
||
|
||
Der Retriever ist in v2.2 der zentrale Zugangspunkt zum Wissen. Er realisiert die **Hybride Suche**.
|
||
|
||
### 5.1 Scoring-Modell
|
||
Die Relevanz eines Treffers ergibt sich nicht mehr nur aus Textähnlichkeit, sondern aus einer gewichteten Formel:
|
||
|
||
total_score =
|
||
semantic_weight * semantic_score
|
||
+ edge_weight * edge_bonus
|
||
+ centrality_weight * centrality_bonus
|
||
+ type_weight * retriever_weight
|
||
|
||
* **semantic_score:** Vektorähnlichkeit (Qdrant).
|
||
* **retriever_weight:** Wichtigkeit des Typs (z.B. Projekte > Quellen).
|
||
* **edge_bonus:** Belohnung für Chunks, die im Kontext der Anfrage stark vernetzt sind (unter Berücksichtigung der *confidence*).
|
||
* **centrality_bonus:** Belohnung für Knoten, die zentrale Hubs im lokalen Graphen darstellen.
|
||
|
||
### 5.2 Erklärbarkeit (Explainability)
|
||
Der Retriever liefert **Begründungspfade**. Er gibt nicht nur Text zurück, sondern:
|
||
* `score_breakdown`: Warum ist dieser Chunk oben? (War es der Text oder der Graph?)
|
||
* `paths`: Über welche Kanten wurde dieser Chunk gefunden? (z.B. "Gefunden via `depends_on` von deiner aktuellen Projekt-Notiz").
|
||
|
||
---
|
||
|
||
## 6) Confidence & Provenance – wozu?
|
||
|
||
Der Retriever kann Edges gewichten:
|
||
- **provenance**: *explicit* > *rule*
|
||
- **confidence**: numerische Feinsteuerung
|
||
- **retriever_weight (Note/Chunk)**: skaliert die Relevanz des gesamten Knotens
|
||
|
||
Eine typische Gewichtung (konfigurierbar in `retriever.yaml`) ist:
|
||
`explicit: 1.0`, `rule: 0.8`. Damit bevorzugt der Graph **kuratiertes Wissen** (explizit notierte Links) vor „erweiterten“ Default-Ableitungen.
|
||
|
||
---
|
||
|
||
## 7) Semantik ausgewählter `kind`-Werte
|
||
|
||
- `references` – „Nutzt/erwähnt“; neutral, aber stützend für Kontext.
|
||
- `related_to` – Ähnlichkeit/Verwandtschaft (symmetrisch interpretierbar).
|
||
- `similar_to` – noch engere Ähnlichkeit; oft aus Inline-Rel (bewusst gesetzt).
|
||
- `depends_on` – fachliche Abhängigkeit (z. B. „Projekt X hängt von Y ab“).
|
||
- `belongs_to`, `next`, `prev` – Struktur.
|
||
|
||
> Symmetrische Relationen (z. B. `related_to`, `similar_to`) können **explizit** nur einseitig notiert sein, aber im Retriever beidseitig interpretiert werden.
|
||
|
||
---
|
||
|
||
## 8) Frontmatter-Eigenschaften – Rolle & Empfehlung
|
||
|
||
Frontmatter-Eigenschaften (Properties) bleiben **minimiert**:
|
||
- **type** – steuert Typ-Defaults via Registry (Pflicht für differenziertes Verhalten).
|
||
- **tags** – für klassische Filterung.
|
||
- **retriever_weight / chunk_profile** – Sollten **nicht** manuell gesetzt werden (Best Practice: `types.yaml` nutzen).
|
||
- **links** – Veraltet. Bitte Links primär über Text (Wikilink/Inline/Callout) pflegen.
|
||
|
||
---
|
||
|
||
## 9) Lösch-/Update-Garantien (Idempotenz)
|
||
|
||
- Jede Note hat einen stabilen **note_id** (Frontmatter/Hash).
|
||
- Vor einem Upsert können *alte Chunks/Edges einer Note* gefiltert gelöscht werden (`note_id`-Filter) – das hält Collections sauber bei Re-Imports.
|
||
- Die Import-Skripte unterstützen Modi wie `--purge-before-upsert` und `--sync-deletes`, um den Graph sauber zu halten.
|
||
|
||
---
|
||
|
||
## 10) Beispiel – Von Markdown zu Kanten (v2.2)
|
||
|
||
**Markdown (Auszug)**
|
||
# Relations Showcase
|
||
…
|
||
Wir nutzen [[rel:depends_on Qdrant Vektordatenbank]] für die Suche.
|
||
…
|
||
Siehe auch: [[Embeddings 101]]
|
||
|
||
> [!edge] related_to: [[Vector DB Basics]]
|
||
|
||
**Ergebnis (fachlich)**
|
||
1. `depends_on(Chunk→Qdrant)` mit `rule_id=inline:rel`, `confidence≈0.95`.
|
||
2. `references(Chunk→Embeddings 101)` mit `rule_id=explicit:wikilink`, `confidence=1.0`.
|
||
3. `related_to(Chunk→Vector DB Basics)` via Callout; `rule_id=callout:edge`, `confidence≈0.90`.
|
||
4. **Typ-Defaults:** Falls die Note vom Typ `project` ist, entstehen zusätzlich `depends_on`-Kanten zu den Zielen aus (2) und (3).
|
||
|
||
---
|
||
|
||
## 11) Qualitäts- und Testkriterien (fachlich)
|
||
|
||
- **Keine Duplikate** gleicher `(src, relation, dst)` in der Collectionsicht (Dedup).
|
||
- **Explizite Links** werden vollständig materialisiert (*explicit_total*).
|
||
- **Typ-Defaults** ergänzen, aber überdecken nicht.
|
||
- **Retriever Smoke-Test:** Ein Query muss plausible Scores liefern, die den Einfluss von `edge_bonus` zeigen.
|
||
|
||
---
|
||
|
||
## 12) Referenzen (Projektdateien & Leitlinien)
|
||
|
||
- Import-Pipeline & Registry-Auflösung: `scripts/import_markdown.py`.
|
||
- Kantenbildung (V2-Logic): `app/core/derive_edges.py`.
|
||
- Typ-Registry: `config/types.yaml` & `TYPE_REGISTRY_MANUAL.md`.
|
||
- Retriever-Scoring: `app/core/retriever.py` & `wp04_retriever_scoring.md`. |