# Mindnet – Technische Architektur (V2, Stand: 2025-11-xx) > **Ziel dieses Dokuments:** > Vollständige, konsolidierte Beschreibung der aktuellen technischen Architektur von **Mindnet V2** – insbesondere der Verarbeitung von Markdown-Notizen, des Chunkings, der Kantenableitung (Edges) inkl. `rule_id` / `confidence` und der Speicherung in Qdrant. > Das Dokument bildet den **aktuellen Implementierungsstand** ab, nicht mehr gültige Annahmen sind bereinigt, neue Konzepte (Typ-Defaults, Inline-Relationen, Edges-Schema) sind integriert. --- ## 1. Systemüberblick ### 1.1 Zielbild Mindnet ist ein **persönliches Wissensnetz**. Technisch bedeutet das: - Markdown-Notizen in einem Vault (Obsidian-kompatibel) werden - geparst (Frontmatter + Body), - in **Notes**, **Chunks** und **Edges** überführt, - in **Qdrant** als drei Collections abgelegt: - `_notes` - `_chunks` - `_edges`. - Das System ist so konzipiert, dass es: - **deterministisch** arbeitet (IDs, Chunks, Kanten), - über `types.yaml` **konfigurierbar** ist, - später von einem LLM-basieren Agenten als **Graph-Retriever** genutzt werden kann. --- ### 1.2 Verzeichnisstruktur (Server) /home/llmadmin/mindnet/: - **/app** - `main.py` – FastAPI-App / Einstieg - **/app/core** - `qdrant.py` – QdrantConfig, Client-Factory, Collection-Management - `qdrant_points.py` – Upserts / Deletes / Queries auf Punktebene - `note_payload.py` – Bau von Note-Payloads - `chunk_payload.py` – Bau von Chunk-Payloads - `chunker.py` – Chunking-Logik - `edges.py` – Datenstruktur & Hilfsfunktionen für Edges - `derive_edges.py` – Ableitung von Edges aus Text und Typen - **/app/models** - `dto.py` – DTOs für API / Services - **/app/routers** - `qdrant_router.py` – API-Layer Richtung Qdrant - **/app/services** - `llm_ollama.py` – Anbindung an Ollama-LLM - `embeddings_client.py` – Embedding-Service (z. B. Ollama / lokaler Dienst) - **/config** - `types.yaml` – Typdefinitionen inkl. Chunk-Profilen und Edge-Defaults - **/scripts** - `import_markdown.py` – Hauptimporter für Vault - `reset_qdrant.py` – Collections löschen/neu anlegen (inkl. Indizes) - `setup_mindnet_collections.py` – Collection-Setup (historisch / Hilfsskript) - diverse Diagnose- und Testskripte, z. B. - `payload_dryrun.py` - `edges_full_check.py` - **/tests** - `test_edges_smoke.py` – einfache Edge-Smoke-Tests - `test_edges_all.py` – umfassendere Checks (Counts, Plausibilität) - `ensure_indexes_and_show.py`, `assert_payload_schema.py` – Schema/Index-Checks - **/vault** - produktives Vault (Obsidian) - **/mindnet_v2_test_vault** - Test-Vault für V2-Funktionen (Chunking, Edges, Typ-Defaults) --- ## 2. Datenmodell & Collections ### 2.1 Note, Chunk, Edge – Begriffe - **Note** Entspricht einer Markdown-Datei mit YAML-Frontmatter (`id`, `title`, `type`, …). In Qdrant als ein Punkt in `_notes`. - **Chunk** Ein Abschnitt einer Note (z. B. Absatz, Überschrifts-Block, Sliding Window). In Qdrant als Punkt in `_chunks`. - **Edge** Eine gerichtete Kante, die eine Beziehung zwischen: - zwei Chunks, - Chunk ↔ Note, - oder (konzeptionell) Note ↔ Note beschreibt. Gespeichert in `_edges`. --- ### 2.2 Qdrant Collections (Stand V2) **Namenskonvention:** Prefix aus ENV (`COLLECTION_PREFIX`, z. B. `mindnet`): - `mindnet_notes` - `mindnet_chunks` - `mindnet_edges` Die Collections werden über: ```bash python3 -m scripts.reset_qdrant --mode wipe --prefix "$COLLECTION_PREFIX" ``` **vollständig neu angelegt**, inkl. Payload-Indizes (Details in 6.1). --- ### 2.3 Notes – Payload & Felder Minimale, indexierte Felder (Auszug, Schema laut `diag_payload_indexes`): - `note_id` (keyword) – stabile Note-ID (Frontmatter `id`) - `title` (text) – Notiz-Titel - `type` (keyword) – logischer Typ (z. B. `concept`, `project`, `profile`, `journal`, `source`) - `tags` (keyword[]) – Tags aus Frontmatter - `updated` (integer) – Zeitstempel (z. B. `YYYYMMDDHHMMSS` oder epoch; Implementierungsdetail) Weitere Felder (nicht alle indexiert, aber im Payload vorhanden): - `retriever_weight` (float) – wie stark diese Note/Chunks im Retrieval gewichtet werden - `chunk_profile` (string) – Name des verwendeten Chunk-Profils - `edge_defaults` (string[]) – Liste von Default-Relationen pro Typ (z. B. `["references","related_to"]`) - `confidentiality`, `visibility`, weitere Metadaten aus Frontmatter Diese Felder werden in `app/core/note_payload.py` aus Frontmatter + `types.yaml` konstruiert. --- ### 2.4 Chunks – Payload & Felder Indexierte Kernfelder: - `note_id` (keyword) – Referenz auf die übergeordnete Note - `chunk_id` (keyword) – deterministische Chunk-ID: `"{note_id}#c{index:02d}"` (z. B. `20251110-ollama-llm-9f0a12#c02`) - `index` (integer) – 0-basiert; Position in der Note - `type` (keyword) – Note-Typ (vom Note geerbt) - `tags` (keyword[]) – Tags (vom Note geerbt) Weitere wichtige Payload-Felder: - `ord` (integer) – 1-basiertes Pendant zu `index` (für menschliche Lesbarkeit) - `text` (string) – eigentlicher Chunk-Text (ggf. gereinigt/normalisiert) - `window` (string) – Kontext-Fenster (z. B. Chunk ± Nachbarn) - `retriever_weight` (float) – gültiger Wert aus `types.yaml` (oder Default) - `chunk_profile` (string) – verwendetes Profil, z. B. `short`, `medium`, `long`, `by_heading` - `neighbors_prev` (string[]) – Liste von `chunk_id`s direkter Vorgänger (i. d. R. 0 oder 1 ID) - `neighbors_next` (string[]) – Liste von `chunk_id`s direkter Nachfolger Die Konstruktion erfolgt in `app/core/chunk_payload.py` auf Basis der Chunks aus `chunker.py` und der aufgelösten Typ-Defaults. --- ### 2.5 Edges – Payload & Felder Indexierte Felder: - `note_id` (keyword) – Note, zu der der **Quell-Chunk** gehört - `source_id` (keyword) – i. d. R. `chunk_id` des Quell-Chunks (z. B. `2025…#c00`) - `target_id` (keyword) – Zielobjekt (z. B.: - `chunk_id` eines anderen Chunks - Note-Titel (`"Embeddings 101"`) bei **konzeptionellen Referenzen** - `kind` (keyword) – Kantenart: - Struktur: `belongs_to`, `next`, `prev` - Explizit: `references` - Inline: z. B. `similar_to`, `depends_on`, `related_to` - Typ-Defaults: ebenfalls z. B. `depends_on`, `related_to` (aus `edge_defaults`) - `scope` (keyword) – aktuell immer `"chunk"` (Kante wird auf Chunk-Ebene geführt) - `chunk_id` (keyword) – `chunk_id` des Quell-Chunks Weitere Payload-Felder: - `rule_id` (string) – Herkunftsregel: - Struktur: - `structure:belongs_to` - `structure:next` - `structure:prev` - Explizite Wiki-Links: - `explicit:wikilink` - Inline-Relationen: - `inline:rel` - Typ-Defaults aus `types.yaml`: - `edge_defaults::` z. B. `edge_defaults:concept:related_to` - `confidence` (float) – Stärke / Vertrauensgrad: - Struktur-Kanten: `1.0` - Explizite Wiki-Links: `1.0` - Inline-Relationen (`[[rel:… …]]`): z. B. `0.95` - Typ-Defaults: z. B. `0.7` Edges werden in `app/core/derive_edges.py` erzeugt und in `mindnet_edges` gespeichert. --- ## 3. Typ-Konfiguration (`config/types.yaml`) ### 3.1 Struktur des Files `types.yaml` (vereinfachtes Beispiel): ```yaml version: 1.0 default: retriever_weight: 1.0 chunk_profile: default types: concept: chunk_profile: medium edge_defaults: ["references", "related_to"] retriever_weight: 0.35 task: chunk_profile: short edge_defaults: ["depends_on", "belongs_to"] retriever_weight: 0.8 experience: chunk_profile: medium edge_defaults: ["derived_from", "inspired_by"] retriever_weight: 0.9 project: chunk_profile: long edge_defaults: ["references", "depends_on"] retriever_weight: 0.97 profile: chunk_profile: long edge_defaults: ["references", "depends_on"] retriever_weight: 0.66 ``` ### 3.2 Typauflösung – Reihenfolge der Prioritäten Für eine Note mit `type` und optionalen Frontmatter Feldern `retriever_weight`, `chunk_profile` gilt aktuell: 1. **Typ-spezifische Defaults** aus `types.yaml`: - `retriever_weight` ← `types..retriever_weight` (falls vorhanden) - `chunk_profile` ← `types..chunk_profile` (falls vorhanden) 2. **Globaler Default** `default` in `types.yaml`, falls Typ-Eintrag fehlt. 3. **Frontmatter `retriever_weight` / `chunk_profile`** werden aktuell *nicht* mehr als Konfigurationsebene verwendet, sondern eher als historische Relikte. (Dies kann zukünftig wieder aktiviert werden, ist aber im aktuellen Stand bewusst abgeschaltet zugunsten klarer, zentraler Konfiguration über `types.yaml`.) Das Ergebnis dieser Auflösung wird im Payload als: - `note_payload["retriever_weight"]` - `note_payload["chunk_profile"]` gesetzt und **1:1 an alle Chunks vererbt**. --- ## 4. Import-Pipeline (Markdown → Qdrant) ### 4.1 Runbook Standard-Import (mit Purge-Before-Upsert): ```bash export COLLECTION_PREFIX=mindnet export MINDNET_TYPES_FILE="$(pwd)/config/types.yaml" python3 -m scripts.import_markdown \ --vault ./mindnet_v2_test_vault \ --apply \ --purge-before-upsert \ --prefix "$COLLECTION_PREFIX" ``` Nur Sync-Deletes (entfernte Dateien in Qdrant aufräumen): ```bash python3 -m scripts.import_markdown \ --vault ./mindnet_v2_test_vault \ --sync-deletes \ --apply \ --prefix "$COLLECTION_PREFIX" ``` --- ### 4.2 Verarbeitungsschritte **1. Discovery & Parsing** - `import_markdown.py` traversiert das Vault‐Verzeichnis. - Für jede `.md`: - YAML-Frontmatter extrahieren (id, title, type, created, updated, tags, …). - Body (Markdown) als String. **2. Typauflösung & Payload-Bau (Note)** - Laden & Auflösen von `types.yaml` (über ENV `MINDNET_TYPES_FILE` oder Default `./config/types.yaml`). - Bestimmung des effektiven Typs (`type` aus Frontmatter; ggf. Fallback). - Anwendung der Typdefaults: - `retriever_weight` und `chunk_profile` werden aus `types.yaml` gelesen. - Konstruktion des Note-Payloads via `make_note_payload` (in `note_payload.py`): - Felder wie `note_id`, `title`, `type`, `tags`, `updated`, `retriever_weight`, `chunk_profile`, `edge_defaults`, … **3. Chunking** - Übergabe des Note-Bodies + `chunk_profile` an `chunker.py`. - `chunker.py` nutzt `chunk_config.py`, das definierte Profile bereitstellt, z. B.: ```python CHUNK_PROFILES = { "short": {"max_tokens": 128, "overlap": 32}, "medium": {"max_tokens": 256, "overlap": 64}, "long": {"max_tokens": 512, "overlap": 128}, "by_heading": {"strategy": "by_heading", "max_chars": 2000}, "default": {"max_tokens": 256, "overlap": 64}, } ``` - Ergebnis: Liste geordneter Chunks mit: - `chunk_id` (`note_id#cXX`), - `index` (0..N-1), - `ord` (1..N), - `text`, - `window` (inkl. Nachbartexte), - `neighbors_prev` / `neighbors_next`. **4. Chunk-Payloads** - In `chunk_payload.py` werden für jeden Chunk die Payloads gebaut: - Vererbung von `note_id`, `type`, `tags`, `retriever_weight`, `chunk_profile`. - Setzen von `index`, `ord`, `neighbors_prev`, `neighbors_next`. - Persistieren von `text` und `window`. **5. Kantenableitung (Edges)** - `derive_edges.py` wird mit Note + Chunks + Typinformationen aufgerufen. - Es entstehen mehrere Gruppen von Kanten: 1. **Struktur-Kanten**: - `belongs_to`: Chunk → Note - `next`: Chunk[i] → Chunk[i+1] - `prev`: Chunk[i] → Chunk[i-1] 2. **Explizite Kanten aus Text**: - Wiki-Links: `[[Target Title]]` → `kind="references"`, `rule_id="explicit:wikilink"`, `confidence=1.0`. - Inline-Relationen: `[[rel:depends_on Embeddings 101]]`: - `kind="depends_on"` - `rule_id="inline:rel"` - `confidence≈0.95` - `target_id="Embeddings 101"` (Titel, nicht ID – Auflösung erfolgt später im Agenten). 3. **Typ-basierte Defaults (`edge_defaults`)**: - Aus `types.yaml` je `type`: Liste von Relations-Kinds, z. B.: - `concept.edge_defaults = ["references","related_to"]` - `project.edge_defaults = ["references","depends_on"]` - Für jede explizite Referenz Quelle→Ziel (z. B. `references`, `similar_to`) werden **zusätzliche Kanten** erzeugt, z. B.: - `edge_defaults:project:depends_on` - `edge_defaults:concept:related_to` - `confidence≈0.7`. 4. **Deduplication**: - Alle Kanten werden in einem Set anhand eines Keys wie - `(kind, scope, source_id, target_id, rule_id)` dedupliziert (idempotent). **6. Upsert nach Qdrant** - Punkte (Notes, Chunks, Edges) werden via `qdrant_points.py` in die entsprechenden Collections upserted. - Option `--purge-before-upsert` sorgt dafür, dass alte Punkte mit denselben IDs entfernt werden, bevor neue geschrieben werden (stabiler Reimport). - `--sync-deletes` entfernt Punkte, deren zugehörige Dateien im Vault nicht mehr existieren. --- ## 5. Edges im Detail – Semantik & Regeln ### 5.1 Struktur-Kanten Erzeugt für **jede Note** mit >0 Chunks: - **belongs_to** - pro Chunk genau eine Kante: - `source_id = chunk_id` - `target_id = note_id` *oder* (konzeptionell) ein Note-Identifikator - `kind = "belongs_to"` - `scope = "chunk"` - `rule_id = "structure:belongs_to"` - `confidence = 1.0` - **next / prev** - für Index i (`0..N-2`): - `next`: `chunk_i → chunk_{i+1}` - `prev`: `chunk_{i+1} → chunk_i` - `kind = "next"` bzw. `"prev"` - `scope = "chunk"` - `rule_id = "structure:next"` / `"structure:prev"` - `confidence = 1.0` Tests (`tests.test_edges_smoke` / `tests.test_edges_all`) stellen sicher: - `belongs_to` == `#chunks` - `next` == `prev` == `#chunks - 1` - keine Duplikate der Strukturkanten. --- ### 5.2 Explizite Wiki-Links (`[[Target Title]]`) - Parser in `derive_edges.py` sucht im Chunk-Text nach Mustern: - `[[Some Page]]` (kein `rel:` Präfix) - Erzeugt Kanten: - `kind = "references"` - `scope = "chunk"` - `source_id = chunk_id` - `target_id = ""` (z. B. `"Vector DB Basics"`) - `rule_id = "explicit:wikilink"` - `confidence = 1.0` Diese Kanten bilden das **explizite Referenznetz** des Nutzers ab (Obsidian-typische Wikilinks). --- ### 5.3 Inline-Relationen (`[[rel:… …]]`) Aktuell **implementiert und funktional** ist folgende Form: - **Format (aktuell unterstützt):** ```md [[rel:depends_on Embeddings 101]] [[rel:similar_to Vector DB Basics]] [[rel:related_to Qdrant Vektordatenbank]] ``` - Parsing-Strategie: - Link-Inhalt wird gesplittet: - Erster Token: `rel:depends_on` - Rest: Zielbezeichnung (`Embeddings 101`) - `kind` wird aus dem Teil `depends_on` extrahiert (z. B. `similar_to`, `related_to`). - `target_id` wird aus dem Rest (meist ein Titel) abgeleitet. - Ergebnis-Kante: - `kind = ""` - `scope = "chunk"` - `source_id = chunk_id` - `target_id = ""` - `rule_id = "inline:rel"` - `confidence ≈ 0.95` - **Nicht unterstützt (Stand jetzt):** ```md rel: depends_on [[Embeddings 101]] [[Vector DB Basics]] ``` Diese Syntax wird derzeit **nicht** erkannt. Multi-Target-Inline-Relationen (`rel: similar_to [[A]] [[B]]`) sind ein **offener Task**. --- ### 5.4 Typ-basierte Default-Edges (`edge_defaults`) Zweck: - Für bestimmte Typen (vor allem `concept`, `project`, `profile`) sollen zusätzliche Kanten automatisch ergänzt werden, um das **Semantiknetz zu verdichten**, ohne dass der Nutzer jede Relation explizit pflegen muss. Konfiguration: - In `types.yaml` definiert, z. B.: ```yaml types: concept: edge_defaults: ["references", "related_to"] project: edge_defaults: ["references", "depends_on"] ``` Aktuelle Implementierung: - Für jede **explizite** Referenz (Wiki-Link oder Inline-Relation) von Chunk → Ziel: - `kind="references"` (Wiki) oder die Inline-Relation (`depends_on`, `similar_to`, …) - Auf Basis des Note-Typs (`type`) wird pro Default-Relation eine zusätzliche Kante erzeugt: Beispiel: - Note-Typ: `project` - `edge_defaults: ["references","depends_on"]` - Explizit: `references` von `Edge Index` → `Embeddings 101` - Abgeleitete Kanten: - `kind="references"`, `rule_id="edge_defaults:project:references"`, `confidence=0.7` - `kind="depends_on"`, `rule_id="edge_defaults:project:depends_on"`, `confidence=0.7` - Symmetrische Kanten: - Für einige Relations-Typen (z. B. `related_to`) wird zusätzlich eine **spiegelbildliche** Kante Ziel → Quelle erzeugt. - Dies erklärt in Tests z. B. Paare wie: - `related_to (Source=Ollama LLM, Target=Qdrant Vektordatenbank)` - `related_to (Source=Qdrant Vektordatenbank, Target=Ollama LLM)` - Deduplication: - Es wird verhindert, dass mehrfach identische Kanten geschrieben werden. - Schlüssel: `(kind, scope, source_id, target_id, rule_id)`. --- ### 5.5 `rule_id` & `confidence` – Bedeutung **`rule_id`** kodiert **Herkunft** und **Regel**, z. B.: - `structure:belongs_to`, `structure:next`, `structure:prev` - `explicit:wikilink` - `inline:rel` - `edge_defaults::` **`confidence`** dient als späterer Gewichtungsfaktor im Retrieval / Ranking: - `1.0` → harte Struktur- oder explizite Kante (vom Nutzer direkt gesetzt) - `0.95` → Inline-Relation (stark, aber nicht so „hart“ wie die reine Referenz) - `0.7` → Typ-Default-Edges (abgeleitete Hypothesen aus Typwissen) Ein künftiger LLM-Agent kann daraus z. B.: - Kanten mit hoher `confidence` priorisieren, - Default-Edges als schwächere Hinweise betrachten, - Inline-Relationen gezielt als semantische Aussagen über die Beziehung interpretieren. --- ## 6. Qdrant-Schema & Indizes ### 6.1 Erstellung & Indizes Die Erstellung erfolgt über: ```bash python3 -m scripts.reset_qdrant --mode wipe --prefix "$COLLECTION_PREFIX" ``` Intern: - `qdrant.py` / `setup_mindnet_collections.py`: - Collections anlegen, ggf. mit Vektor-Konfiguration (Single-Vector; Named-Vectors sind vorbereitet aber optional). - `ensure_payload_indexes()`: - Legt für jede Collection die relevanten Payload-Indizes an. Verifizierbar durch: ```bash python3 -m tests.ensure_indexes_and_show ``` Beispielauszug (bereits real so gesehen): - **mindnet_notes** ```json { "tags": { "data_type": "keyword", "points": 8 }, "note_id":{ "data_type": "keyword", "points": 8 }, "title": { "data_type": "text", "points": 8 }, "updated":{ "data_type": "integer", "points": 0 }, "type": { "data_type": "keyword", "points": 8 } } ``` - **mindnet_chunks** ```json { "note_id": { "data_type": "keyword", "points": 44 }, "chunk_id":{ "data_type": "keyword", "points": 44 }, "index": { "data_type": "integer", "points": 44 }, "type": { "data_type": "keyword", "points": 44 }, "tags": { "data_type": "keyword", "points": 44 } } ``` - **mindnet_edges** ```json { "scope": { "data_type": "keyword", "points": 135 }, "kind": { "data_type": "keyword", "points": 135 }, "chunk_id":{ "data_type": "keyword", "points": 135 }, "target_id":{ "data_type": "keyword", "points": 135 }, "note_id": { "data_type": "keyword", "points": 135 }, "source_id":{ "data_type": "keyword", "points": 135 } } ``` ### 6.2 Schema-Validierung `tests/assert_payload_schema.py` prüft: - ob die Minimalfelder (`note_id`, `type`, `title`, `updated`, `tags` etc.) vorhanden sind, - berichtet fehlende Felder. Nach Korrektur der Indexanlage sollte: - `ok = true` sein, bzw. zumindest alle Kernfelder unter `present` geführt werden. (Im aktuellen Stand werden sie als Indizes geführt; Qdrant speichert zusätzliche Felder ohne explizite Schema-Zeile, was technisch unproblematisch ist.) --- ## 7. Nutzung im Retrieval (Ausblick) ### 7.1 Typbewusstes Chunk-Retrieval Ein typischer Query-Pfad eines LLM-Agents: 1. Query → Embedding 2. Suche in `mindnet_chunks` mit Filter, z. B.: ```python f = rest.Filter( must=[ rest.FieldCondition(key="type", match=rest.MatchValue(value="concept")), rest.FieldCondition(key="tags", match=rest.MatchAny(any=["ki","ollama"])) ] ) ``` 3. Treffer werden nach: - Vektor-Score, - `retriever_weight`, - ggf. Edges (z. B. Projekte mit `depends_on` → Konzepte) gewichtet. ### 7.2 Graph-orientierte Navigation Basierend auf `mindnet_edges` kann der Agent: - ausgehend von einem relevanten Chunk: - Struktur-Kanten (`next`, `prev`) zur Kontextvergrößerung nutzen, - `references` / `depends_on` / `related_to` interpretieren, - `edge_defaults` als semantische Ausdehnung (z. B. von `project` zu seinen `concept`-Bausteinen) nutzen. Die Bedeutung der Kanten ist dabei durch `rule_id` und `confidence` klar nachvollziehbar. --- ## 8. Offene Punkte / Known Limitations 1. **Multi-Target Inline-Relationen** Syntax wie: ```md [[rel:similar_to Vector DB Basics]] [[rel:similar_to Embeddings 101]] ``` funktioniert (zwei separate Inline-Links). **Nicht** unterstützt (Stand jetzt): ```md [[rel:similar_to Vector DB Basics]] [[Embeddings 101]] rel: similar_to [[Vector DB Basics]] [[Embeddings 101]] ``` → Offener Task: Parser erweitern, um mehrere Ziele in einer Inline-Relation zu unterstützen. 2. **Callout-Edges (`[!edge]`)** - Konzeptionell vorgesehen, z. B.: ```md > [!edge] related_to: [[Vector DB Basics]] ``` - Im aktuellen Implementierungsstand werden Callouts entweder: - gar nicht, oder - nur teilweise verarbeitet (in den aktuellen Test-Runs war `callout_total = 0`). → Offener Task: Callout-Parser robust implementieren und mit Tests absichern. 3. **Frontmatter-Overrides für `retriever_weight` / `chunk_profile`** - Aktuell **nicht** wirksam. - Typdefaults aus `types.yaml` sind der **Single Source of Truth**. - Später können kontrollierte Overrides (z. B. für Sonderfälle) eingeführt werden. 4. **Vektor-Konfiguration für Edges** - `mindnet_edges` wird derzeit ohne Vektoren betrieben (`vectors = null`). - Später könnte z. B. eine semantische Repräsentation von Kanten eingeführt werden (z. B. Embedding von `(source_chunk_text + relation + target_title)`). --- ## 9. Zusammenfassung - Die Mindnet-V2-Architektur implementiert einen **dreistufigen Speicher**: - Notes (`mindnet_notes`), - Chunks (`mindnet_chunks`), - Edges (`mindnet_edges`). - **`types.yaml`** steuert: - `retriever_weight` und `chunk_profile` je Typ (inkl. Default), - `edge_defaults` je Typ (automatische Relations-Ableitung). - Das **Chunking** ist profilbasiert (short/medium/long/by_heading) und deterministisch. - Die **Kantenableitung** in `derive_edges.py` erzeugt: - strukturelle Kanten (belongs_to / next / prev), - explizite Kanten aus Wiki-Links (`[[Target]]`), - semantische Inline-Relationen (`[[rel:depends_on Target]]`), - typbasierte Default-Kanten (z. B. `edge_defaults:project:depends_on`). - `rule_id` und `confidence` machen die Herkunft jeder Kante transparent und ermöglichen später eine **gewichtete Auswertung** durch LLM-basierte Agenten. - Qdrant-Collections und Payload-Indizes sind konsistent eingerichtet und durch Tests verifiziert. Dieses Dokument bildet damit das aktuelle technische Gesamtbild von Mindnet V2 ab, inkl. aller relevanten Mechanismen rund um Typen, Chunking, Edges und Qdrant-Schema.