mindnet/docs/mindnet_technical_architecture.md
2025-12-13 06:37:24 +01:00

450 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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 v2.6 Technische Architektur
**Datei:** `docs/mindnet_technical_architecture_v2.6.md`
**Stand:** 2025-12-12
**Status:** **FINAL** (Integrierter Stand WP01WP15: Smart Edges & Traffic Control)
**Quellen:** `Programmplan_V2.6.md`, `Handbuch.md`, `chunking_strategy.md`, `wp04_retriever_scoring.md`.
> **Ziel dieses Dokuments:**
> Vollständige Beschreibung der technischen Architektur inkl. Graph-Datenbank, Retrieval-Logik, der **RAG-Komponenten (Decision Engine & Hybrid Router)**, des **Traffic Control Systems** und dem **Frontend (Streamlit)**.
---
<details>
<summary>📖 <b>Inhaltsverzeichnis (Klicken zum Öffnen)</b></summary>
- [Mindnet v2.6 Technische Architektur](#mindnet-v26--technische-architektur)
- [](#)
- [1. Systemüberblick](#1-systemüberblick)
- [1.1 Architektur-Zielbild](#11-architektur-zielbild)
- [1.2 Verzeichnisstruktur \& Komponenten (Post-WP15)](#12-verzeichnisstruktur--komponenten-post-wp15)
- [2. Datenmodell \& Collections (Qdrant)](#2-datenmodell--collections-qdrant)
- [2.1 Notes Collection (`<prefix>_notes`)](#21-notes-collection-prefix_notes)
- [2.2 Chunks Collection (`<prefix>_chunks`)](#22-chunks-collection-prefix_chunks)
- [2.3 Edges Collection (`<prefix>_edges`)](#23-edges-collection-prefix_edges)
- [3. Konfiguration](#3-konfiguration)
- [3.1 Typ-Registry (`config/types.yaml`)](#31-typ-registry-configtypesyaml)
- [3.2 Retriever-Config (`config/retriever.yaml`)](#32-retriever-config-configretrieveryaml)
- [3.3 Decision Engine (`config/decision_engine.yaml`)](#33-decision-engine-configdecision_engineyaml)
- [3.4 Prompts (`config/prompts.yaml`)](#34-prompts-configpromptsyaml)
- [3.5 Environment (`.env`)](#35-environment-env)
- [4. Import-Pipeline (Markdown → Qdrant)](#4-import-pipeline-markdown--qdrant)
- [4.1 Verarbeitungsschritte (Async + Smart)](#41-verarbeitungsschritte-async--smart)
- [5. Retriever-Architektur \& Scoring](#5-retriever-architektur--scoring)
- [5.1 Betriebsmodi](#51-betriebsmodi)
- [5.2 Scoring-Formel (WP04a)](#52-scoring-formel-wp04a)
- [5.3 Explanation Layer (WP04b)](#53-explanation-layer-wp04b)
- [5.4 Graph-Expansion](#54-graph-expansion)
- [6. RAG \& Chat Architektur (WP06 Hybrid Router + WP07 Interview)](#6-rag--chat-architektur-wp06-hybrid-router--wp07-interview)
- [6.1 Architektur-Pattern: Intent Router v5](#61-architektur-pattern-intent-router-v5)
- [6.2 Traffic Control (Priorisierung)](#62-traffic-control-priorisierung)
- [6.3 Schritt 1: Intent Detection (Question vs. Action)](#63-schritt-1-intent-detection-question-vs-action)
- [6.4 Schritt 2: Strategy Resolution](#64-schritt-2-strategy-resolution)
- [6.5 Schritt 3: Retrieval vs. Extraction](#65-schritt-3-retrieval-vs-extraction)
- [6.6 Schritt 4: Generation \& Response](#66-schritt-4-generation--response)
- [7. Frontend Architektur (WP10)](#7-frontend-architektur-wp10)
- [7.1 Kommunikation](#71-kommunikation)
- [7.2 Features \& UI-Logik](#72-features--ui-logik)
- [7.3 Draft-Editor \& Healing Parser (Neu in WP10a/v2.5)](#73-draft-editor--healing-parser-neu-in-wp10av25)
- [7.4 State Management (Resurrection Pattern)](#74-state-management-resurrection-pattern)
- [7.5 Deployment Ports](#75-deployment-ports)
- [8. Feedback \& Logging Architektur (WP04c)](#8-feedback--logging-architektur-wp04c)
- [8.1 Komponenten](#81-komponenten)
- [8.2 Log-Dateien](#82-log-dateien)
- [8.3 Traceability](#83-traceability)
- [9. Indizes \& Performance](#9-indizes--performance)
- [10. Offene Punkte / Known Limitations](#10-offene-punkte--known-limitations)
</details>
---
## 1. Systemüberblick
### 1.1 Architektur-Zielbild
Mindnet ist ein **lokales RAG-System (Retrieval Augmented Generation)** mit Web-Interface.
1. **Source:** Markdown-Notizen in einem Vault (Obsidian-kompatibel).
2. **Pipeline:** Ein Python-Importer transformiert diese in **Notes**, **Chunks** und **Edges**.
* **Neu in v2.6:** Intelligente Kanten-Zuweisung durch lokale LLMs (**Smart Edge Allocation**).
3. **Storage:**
* **Qdrant:** Vektor-Datenbank für Graph und Semantik (Collections: notes, chunks, edges).
* **Local Files (JSONL):** Append-Only Logs für Feedback und Search-History (Data Flywheel).
4. **Backend:** Eine FastAPI-Anwendung stellt Endpunkte für **Semantische** und **Hybride Suche** sowie **Feedback** bereit.
* **Update v2.6:** Der Core arbeitet nun vollständig **asynchron (AsyncIO)** mit **Traffic Control** (Semaphore zur Lastverteilung).
5. **Frontend:** Streamlit-App (`ui.py`) für Interaktion und Visualisierung inkl. **Draft Editor**, **Active Intelligence** und **Healing Parser**.
6. **Inference:** Lokales LLM (Ollama: Phi-3 Mini) für RAG-Chat und Antwortgenerierung. Embedding via `nomic-embed-text`.
Das System arbeitet **deterministisch** (stabile IDs) und ist **konfigurationsgetrieben** (`types.yaml`, `retriever.yaml`, `decision_engine.yaml`, `prompts.yaml`).
### 1.2 Verzeichnisstruktur & Komponenten (Post-WP15)
/mindnet/
├── app/
│ ├── main.py # FastAPI Einstiegspunkt
│ ├── core/
│ │ ├── ingestion.py # NEU: Async Ingestion mit Change Detection
│ │ ├── qdrant.py # Client-Factory & Connection
│ │ ├── qdrant_points.py # Low-Level Point Operations (Upsert/Delete)
│ │ ├── note_payload.py # Bau der Note-Objekte
│ │ ├── chunk_payload.py # Bau der Chunk-Objekte
│ │ ├── chunker.py # Smart Chunker Orchestrator (WP15)
│ │ ├── edges.py # Edge-Datenstrukturen
│ │ ├── derive_edges.py # Logik der Kantenableitung (WP03)
│ │ ├── graph_adapter.py # Subgraph & Reverse-Lookup (WP04b)
│ │ └── retriever.py # Scoring, Expansion & Explanation (WP04a/b)
│ ├── models/ # Pydantic DTOs
│ │ └── dto.py # Zentrale DTO-Definition
│ ├── routers/
│ │ ├── query.py # Such-Endpunkt
│ │ ├── ingest.py # NEU: API für Save & Analyze (WP11)
│ │ ├── chat.py # Hybrid Router v5 & Interview Logic (WP06/07)
│ │ ├── feedback.py # Feedback-Endpunkt (WP04c)
│ │ └── ...
│ ├── services/
│ │ ├── llm_service.py # Ollama Chat Client mit Traffic Control (v2.8.0)
│ │ ├── semantic_analyzer.py# NEU: LLM-Filter für Edges (WP15)
│ │ ├── embeddings_client.py# NEU: Async Embeddings (HTTPX)
│ │ ├── feedback_service.py # Logging (JSONL Writer)
│ │ └── discovery.py # NEU: Intelligence Logic (WP11)
│ ├── frontend/ # NEU (WP10)
│ │ └── ui.py # Streamlit Application inkl. Healing Parser
│ └── main.py # Entrypoint der API
├── config/ # YAML-Konfigurationen (Single Source of Truth)
│ ├── types.yaml # Import-Regeln & Smart-Edge Config
│ ├── prompts.yaml # LLM Prompts & Interview Templates (WP06/07)
│ ├── decision_engine.yaml # Router-Strategien (Actions only)
│ └── retriever.yaml # Scoring-Regeln & Kantengewichte
├── data/
│ └── logs/ # Lokale Logs (search_history.jsonl, feedback.jsonl)
├── scripts/ # CLI-Tools (Import, Diagnose, Reset)
│ ├── import_markdown.py # Haupt-Importer CLI (Async)
│ ├── payload_dryrun.py # Diagnose: JSON-Generierung ohne DB
│ └── edges_full_check.py # Diagnose: Graph-Integrität
├── tests/ # Pytest Suite & Smoke Scripts
└── vault/ # Dein lokaler Markdown-Content (Git-ignored)
---
## 2. Datenmodell & Collections (Qdrant)
Das Datenmodell verteilt sich auf drei Collections, definiert durch `COLLECTION_PREFIX` (Standard: `mindnet`).
### 2.1 Notes Collection (`<prefix>_notes`)
Repräsentiert die Metadaten einer Datei.
* **Zweck:** Filterung, Metadaten-Haltung, Vererbung von Eigenschaften an Chunks.
* **Schema (Payload):**
| Feld | Datentyp | Beschreibung | Herkunft |
| :--- | :--- | :--- | :--- |
| `note_id` | Keyword | Stabile ID (UUIDv5 oder Slug). | Frontmatter |
| `title` | Text | Titel der Notiz. | Frontmatter |
| `type` | Keyword | Logischer Typ (z.B. `concept`). | `types.yaml` Resolver |
| `retriever_weight` | Float | Wichtigkeit im Retrieval. | `types.yaml` |
| `chunk_profile` | Keyword | Genutztes Chunking-Profil. | `types.yaml` |
| `edge_defaults` | List[Str] | Aktive Default-Relationen. | `types.yaml` |
| `tags` | List[Kw] | Tags zur Filterung. | Frontmatter |
| `updated` | Integer | Zeitstempel (z.B. YYYYMMDD...). | File Stats |
| `fulltext` | Text | Gesamter Inhalt (für Export/Rekonstruktion). | Body |
### 2.2 Chunks Collection (`<prefix>_chunks`)
Die atomaren Sucheinheiten.
* **Zweck:** Vektorsuche (Embeddings), Granulares Ergebnis.
* **Update v2.4:** Vektor-Dimension ist jetzt **768** (für `nomic-embed-text`).
* **Schema (Payload):**
| Feld | Datentyp | Beschreibung |
| :--- | :--- | :--- |
| `chunk_id` | Keyword | Deterministisch: `{note_id}#c{index:02d}`. |
| `note_id` | Keyword | Referenz zur Note. |
| `type` | Keyword | **Kopie des Note-Typs** (Denormalisiert für Filter). |
| `text` | Text | **Reiner Inhalt** (ohne Overlap). Anzeige-Text. |
| `window` | Text | **Kontext-Fenster** (mit Overlap). Embedding-Basis. |
| `ord` | Integer | Sortierreihenfolge (1..N). |
| `retriever_weight` | Float | Vererbt von Note. |
| `chunk_profile` | Keyword | Vererbt von Note. |
| `neighbors_prev` | List[Str] | ID des Vorgänger-Chunks. |
| `neighbors_next` | List[Str] | ID des Nachfolger-Chunks. |
### 2.3 Edges Collection (`<prefix>_edges`)
Gerichtete Kanten. Massiv erweitert in WP03 für Provenienz-Tracking.
* **Zweck:** Graph-Traversal, Kontext-Anreicherung.
* **Schema (Payload):**
| Feld | Datentyp | Beschreibung | Wertebereich (Bsp.) |
| :--- | :--- | :--- | :--- |
| `edge_id` | Keyword | Hash aus (src, dst, kind). | |
| `source_id` | Keyword | ID des Start-Chunks. | |
| `target_id` | Keyword | ID des Ziel-Chunks (oder Note-Titel). | |
| `note_id` | Keyword | Note, die diese Kante definiert. | |
| `kind` | Keyword | Art der Beziehung. | `references`, `depends_on`, `next` |
| `scope` | Keyword | Geltungsbereich. | Immer `"chunk"` (v2.2). |
| `rule_id` | Keyword | Herkunftsregel. | `explicit:wikilink`, `inline:rel` |
| `confidence` | Float | Vertrauenswürdigkeit (0.0-1.0). | 1.0, 0.95, 0.7 |
| `provenance` | Keyword | Quelle der Kante (Neu in v2.6). | `explicit`, `rule`, `smart` |
---
## 3. Konfiguration
Die Logik ist ausgelagert in YAML-Dateien.
### 3.1 Typ-Registry (`config/types.yaml`)
Steuert den Import-Prozess.
* **Priorität:** Frontmatter > Pfad > Default.
* **Neu in v2.6:**
* `enable_smart_edge_allocation`: (Bool) Aktiviert den LLM-Filter für diesen Typ.
* `detection_keywords`: (List) Keywords für den Hybrid Router ("Objekterkennung").
* **Inhalt (Beispiel):**
types:
concept:
chunk_profile: sliding_standard
edge_defaults: ["references", "related_to"]
retriever_weight: 0.60
experience:
chunk_profile: sliding_smart_edges
enable_smart_edge_allocation: true
detection_keywords: ["erfahrung", "erlebt"]
### 3.2 Retriever-Config (`config/retriever.yaml`)
Steuert das Scoring zur Laufzeit (WP04a).
* **Inhalt (Beispiel):**
scoring:
semantic_weight: 1.0
edge_weight: 0.7
centrality_weight: 0.5
### 3.3 Decision Engine (`config/decision_engine.yaml`)
**Neu in WP06/07:** Steuert den Intent-Router.
* Definiert Strategien (`DECISION`, `INTERVIEW`, etc.).
* **Update v2.6:** Enthält nur noch **Handlungs-Keywords** (Verben wie "neu", "erstellen"). Objektnamen ("Projekt") werden nun über `types.yaml` aufgelöst.
* Definiert LLM-Router-Settings (`llm_fallback_enabled`).
### 3.4 Prompts (`config/prompts.yaml`)
Steuert die LLM-Persönlichkeit und Templates.
* Enthält Templates für alle Strategien inkl. `interview_template` und neu `router_prompt`.
### 3.5 Environment (`.env`)
Erweiterung für LLM-Steuerung und Embedding-Modell:
MINDNET_LLM_MODEL=phi3:mini
MINDNET_EMBEDDING_MODEL=nomic-embed-text # NEU in v2.3.10
MINDNET_OLLAMA_URL=http://127.0.0.1:11434
MINDNET_LLM_TIMEOUT=300.0 # Neu: Erhöht für CPU-Inference Cold-Starts
MINDNET_API_TIMEOUT=300.0 # Neu: Timeout für Frontend-API (Smart Edges brauchen Zeit)
MINDNET_DECISION_CONFIG="config/decision_engine.yaml"
MINDNET_VAULT_ROOT="./vault" # Neu: Pfad für Write-Back
MINDNET_LLM_BACKGROUND_LIMIT=2 # Neu: Limit für parallele Hintergrund-Jobs (Traffic Control)
---
## 4. Import-Pipeline (Markdown → Qdrant)
Das Skript `scripts/import_markdown.py` orchestriert den Prozess.
**Neu in v2.6:** Der Import nutzt `asyncio` und **Traffic Control**, um Ollama nicht zu überlasten.
### 4.1 Verarbeitungsschritte (Async + Smart)
1. **Discovery & Parsing:** Hash-Vergleich zur Erkennung von Änderungen.
2. **Typauflösung:** Bestimmung des `type` via `types.yaml`.
3. **Config Check:** Laden des `chunk_profile` und `enable_smart_edge_allocation`.
4. **Chunking & Smart Edges (WP15):**
* Zerlegung des Textes via `chunker.py`.
* Wenn Smart Edges aktiv: Der `SemanticAnalyzer` sendet Chunks an das LLM.
* **Traffic Control:** Der Request nutzt `priority="background"`. Die Semaphore (Limit: 2) drosselt die Parallelität.
5. **Kantenableitung (Edge Derivation):**
* `derive_edges.py` erzeugt Inline-, Callout- und Default-Edges.
6. **Embedding (Async):**
* Der `EmbeddingsClient` (`app/services/embeddings_client.py`) sendet Text-Chunks asynchron an Ollama.
* Modell: `nomic-embed-text` (768d).
7. **Upsert:**
* Schreiben in Qdrant. Nutzung von `--purge-before-upsert`.
* **Strict Mode:** Der Prozess bricht ab, wenn Embeddings leer sind oder Dimension `0` haben.
---
## 5. Retriever-Architektur & Scoring
Der Retriever (`app/core/retriever.py`) unterstützt zwei Modi. Für den Chat wird **zwingend** der Hybrid-Modus genutzt.
### 5.1 Betriebsmodi
* **Semantic:** Reine Vektorsuche (768d).
* **Hybrid:** Vektorsuche + Graph-Expansion (Tiefe N) + Re-Ranking.
### 5.2 Scoring-Formel (WP04a)
Die Relevanzberechnung ist nun eine gewichtete Summe:
$$
TotalScore = (W_{sem} \cdot S_{sem} \cdot \max(W_{type}, 0)) + (W_{edge} \cdot B_{edge}) + (W_{cent} \cdot B_{cent})
$$
* **Komponenten:**
* $S_{sem}$: Semantic Score (Cosine Similarity).
* $W_{type}$: `retriever_weight` (aus Note/Chunk Payload).
* $B_{edge}$: Edge-Bonus (Summe der Konfidenzen eingehender relevanter Kanten).
* $B_{cent}$: Centrality-Bonus (im lokalen Subgraphen).
* **Gewichte ($W$):** Stammen aus `retriever.yaml`.
### 5.3 Explanation Layer (WP04b)
Der Retriever ist keine Blackbox mehr. Er liefert auf Wunsch (`explain=True`) eine strukturierte Begründung (`Explanation`-Objekt).
**Die "Warum"-Logik:**
1. **Semantik:** Prüfung der Cosine-Similarity ("Sehr hohe textuelle Übereinstimmung").
2. **Typ:** Prüfung des `retriever_weight` ("Bevorzugt, da Entscheidung").
3. **Graph (Kontext):**
* **Hub (Outgoing):** Worauf verweist dieser Treffer? ("Verweist auf Qdrant").
* **Authority (Incoming):** Wer verweist auf diesen Treffer? ("Wird referenziert von Projekt Alpha").
Die API gibt diese Analysen als menschenlesbare Sätze (`reasons`) und als Datenstruktur (`score_breakdown`) zurück.
### 5.4 Graph-Expansion
Der Hybrid-Modus lädt dynamisch die Nachbarschaft der Top-K Vektor-Treffer ("Seeds") über `graph_adapter.expand`. Dies baut einen temporären `NetworkX`-artigen Graphen im Speicher (Klasse `Subgraph`), auf dem Boni berechnet werden.
---
## 6. RAG & Chat Architektur (WP06 Hybrid Router + WP07 Interview)
Der Flow für eine Chat-Anfrage (`/chat`) wurde in WP06 auf eine **Configuration-Driven Architecture** umgestellt und in WP15 (v2.6) verfeinert.
### 6.1 Architektur-Pattern: Intent Router v5
Die Behandlung einer Anfrage ist nicht mehr hartkodiert, sondern wird dynamisch zur Laufzeit entschieden.
* **Input:** User Message.
* **Config:** `decision_engine.yaml` (Strategien) + `types.yaml` (Objekte).
* **Komponenten:**
* **Traffic Control:** `LLMService` priorisiert Chat-Anfragen.
* **Question Detection:** Unterscheidung Frage vs. Befehl.
### 6.2 Traffic Control (Priorisierung)
Der `LLMService` implementiert zwei Spuren basierend auf `app/services/llm_service.py` (v2.8.0):
* **Realtime (Chat):** `priority="realtime"`. Umgeht die Semaphore. Antwortet sofort.
* **Background (Import/Analyse):** `priority="background"`. Wartet in der Semaphore (`asyncio.Semaphore`), die lazy mit `MINDNET_LLM_BACKGROUND_LIMIT` initialisiert wird.
### 6.3 Schritt 1: Intent Detection (Question vs. Action)
Der Router ermittelt die Absicht (`Intent`) des Nutzers.
1. **Frage-Check:** Wenn der Input ein `?` enthält oder mit W-Wörtern beginnt, wird der **RAG-Modus** erzwungen (oder LLM-Entscheidung). Interviews werden hier unterdrückt.
2. **Keyword Scan (Fast Path):**
* Prüfung auf `trigger_keywords` (Handlung) in `decision_engine.yaml`.
* Prüfung auf `detection_keywords` (Objekt) in `types.yaml`.
* Treffer -> **INTERVIEW Modus** (Erfassen).
3. **LLM Fallback (Slow Path):**
* Greift, wenn keine Keywords passen. Sendet Query an LLM Router.
### 6.4 Schritt 2: Strategy Resolution
Basierend auf dem Intent lädt der Router die Parameter:
* **Bei RAG (FACT/DECISION):** `inject_types` für Strategic Retrieval.
* **Bei INTERVIEW (WP07):** `schemas` (Pflichtfelder) basierend auf der erkannten Ziel-Entität (`_detect_target_type`).
### 6.5 Schritt 3: Retrieval vs. Extraction
Der Router verzweigt hier:
**A) RAG Modus (FACT, DECISION, EMPATHY):**
1. **Primary Retrieval:** Hybride Suche nach der User-Query.
2. **Strategic Retrieval (Conditional):** Wenn `inject_types` definiert sind, erfolgt eine zweite Suche, die explizit auf diese Typen filtert.
3. **Merge:** Ergebnisse werden dedupliziert zusammengeführt.
**B) Interview Modus (INTERVIEW):**
1. **Kein Retrieval:** Der Kontext ist der Chat-Verlauf (oder initial die Query).
2. **Schema Injection:** Das Schema für den erkannten Typ (z.B. "Project") wird geladen.
3. **Prompt Assembly:** Der `interview_template` Prompt wird mit der Schema-Definition ("Ziel", "Status") gefüllt.
### 6.6 Schritt 4: Generation & Response
* **Templating:** Das LLM erhält den Prompt basierend auf dem gewählten Template.
* **Execution:** Der `LLMService` führt den Call mit `priority="realtime"` aus.
* **Response:** Rückgabe enthält Antworttext (im Interview-Modus: Markdown Codeblock), Quellenliste und den erkannten `intent`.
---
## 7. Frontend Architektur (WP10)
Das Frontend ist eine **Streamlit-Anwendung** (`app/frontend/ui.py`), die als separater Prozess läuft und via HTTP mit dem Backend kommuniziert.
### 7.1 Kommunikation
* **Backend-URL:** Konfiguriert via `MINDNET_API_URL` (Default: `http://localhost:8002`).
* **Endpoints:**
* `/chat` (Interaktion)
* `/feedback` (Bewertungen)
* `/ingest/analyze` (Active Intelligence / Link-Vorschläge)
* `/ingest/save` (Persistence / Speichern im Vault)
* **Resilienz:** Das Frontend nutzt `MINDNET_API_TIMEOUT` (300s), um auf langsame Backend-Prozesse (Smart Edges) zu warten.
### 7.2 Features & UI-Logik
* **State Management:** Session-State speichert Chat-Verlauf und `query_id`.
* **Visualisierung:**
* **Intent Badges:** Zeigt Router-Entscheidung (`DECISION`, `INTERVIEW`, etc.).
* **Source Expanders:** Zeigt verwendete Chunks inkl. Score und "Why"-Explanation.
* **Sidebar:** Zeigt Suchhistorie (Log-basiert) und Konfiguration.
### 7.3 Draft-Editor & Healing Parser (Neu in WP10a/v2.5)
Wenn der Intent `INTERVIEW` ist, rendert die UI statt einer Textblase den **Draft-Editor**.
1. **Parsing:** Die Funktion `parse_markdown_draft` extrahiert den Codeblock aus der LLM-Antwort.
* **Healing:** Erkennt und repariert defekte YAML-Frontmatter (z.B. fehlendes schließendes `---`), falls das LLM unter Last Fehler macht.
2. **Sanitization (`normalize_meta_and_body`):**
* Prüft den YAML-Frontmatter auf unerlaubte Felder (Halluzinationen des LLMs).
* Verschiebt ungültige Felder (z.B. "Situation") in den Body der Notiz.
3. **Editor Widget:** `st.text_area` erlaubt das Bearbeiten des Inhalts vor dem Speichern.
4. **Save Action:** Speichert über `/ingest/save` atomar in Vault und DB. Erzeugt intelligente Dateinamen via `slugify`.
### 7.4 State Management (Resurrection Pattern)
Um Datenverlust bei Tab-Wechseln (Chat <-> Editor) zu verhindern, nutzt `ui.py` ein Persistenz-Muster:
* Daten liegen in `st.session_state[data_key]`.
* Widgets liegen in `st.session_state[widget_key]`.
* Callbacks (`on_change`) synchronisieren Widget -> Data.
* Beim Neu-Rendern wird Widget-State aus Data-State wiederhergestellt.
### 7.5 Deployment Ports
Zur sauberen Trennung von Prod und Dev laufen Frontend und Backend auf dedizierten Ports:
| Umgebung | Backend (FastAPI) | Frontend (Streamlit) |
| :--- | :--- | :--- |
| **Production** | 8001 | 8501 |
| **Development** | 8002 | 8502 |
---
## 8. Feedback & Logging Architektur (WP04c)
Mindnet implementiert ein "Data Flywheel" zur späteren Optimierung (Self-Tuning).
### 8.1 Komponenten
* **Feedback Service (`app/services/feedback_service.py`):** Kapselt die Schreibzugriffe.
* **Storage:** Lokales Dateisystem (`data/logs/`), Format JSONL (Line-delimited JSON).
### 8.2 Log-Dateien
1. **`search_history.jsonl`**:
* Speichert jede Anfrage an `/query` und `/chat`.
* Enthält: `query_id`, `query_text`, `timestamp`, `hits` (inkl. `score_breakdown` Snapshots).
* Zweck: Trainingsdaten ("Was hat das System gesehen?").
2. **`feedback.jsonl`**:
* Speichert User-Reaktionen an `/feedback`.
* Enthält: `query_id`, `node_id`, `score` (1-5), `comment`.
* **Granularität:** Kann sich auf `generated_answer` (Global) oder eine spezifische `node_id` (Quelle) beziehen.
* Zweck: Labels ("War es gut?").
### 8.3 Traceability
Die `query_id` (UUIDv4) wird im `/query` Response generiert und muss vom Client beim `/feedback` Aufruf mitgesendet werden. Dies ermöglicht den Join zwischen Snapshot und Bewertung.
---
## 9. Indizes & Performance
Damit Qdrant performant bleibt, sind Payload-Indizes essenziell.
**Erforderliche Indizes:**
* **Notes:** `note_id`, `type`, `tags`.
* **Chunks:** `note_id`, `chunk_id`, `type`.
* **Edges:** `source_id`, `target_id`, `kind`, `scope`, `note_id`.
Validierung erfolgt über `tests/ensure_indexes_and_show.py`.
---
## 10. Offene Punkte / Known Limitations
1. **Multi-Target Inline-Relations:**
* `rel: similar_to [[A]] [[B]]` wird aktuell parser-seitig nicht unterstützt.
* Workaround: Zwei separate Inline-Links `[[rel:similar_to A]] [[rel:similar_to B]]`.
2. **Unresolved Targets:**
* Kanten zu Notizen, die noch nicht existieren, werden mit `target_id="Titel"` angelegt.
* Heilung durch `scripts/resolve_unresolved_references.py` möglich.
3. **Hardware-Last bei Smart Import:**
* Der "Smart Edge" Import ist rechenintensiv. Trotz Traffic Control kann die Antwortzeit im Chat leicht steigen, wenn die GPU am VRAM-Limit arbeitet.