310 lines
13 KiB
Markdown
310 lines
13 KiB
Markdown
# Mindnet v2.4 – Developer Guide
|
||
**Datei:** `docs/mindnet_developer_guide_v2.6.md`
|
||
**Stand:** 2025-12-12
|
||
**Status:** **FINAL** (Inkl. Async Core, Nomic, Traffic Control & Frontend State)
|
||
**Quellen:** `mindnet_technical_architecture.md`, `Handbuch.md`, `DEV_WORKFLOW.md`.
|
||
|
||
> **Zielgruppe:** Entwickler:innen.
|
||
> **Zweck:** Anleitung zum Aufsetzen der Entwicklungsumgebung, Verständnis der Modulstruktur und Durchführung von Tests.
|
||
|
||
---
|
||
- [Mindnet v2.4 – Developer Guide](#mindnet-v24--developer-guide)
|
||
- [1. Projektstruktur (Post-WP15)](#1-projektstruktur-post-wp15)
|
||
- [2. Lokales Setup (Development)](#2-lokales-setup-development)
|
||
- [2.1 Voraussetzungen](#21-voraussetzungen)
|
||
- [2.2 Installation](#22-installation)
|
||
- [2.3 Konfiguration (Environment)](#23-konfiguration-environment)
|
||
- [2.4 Dienste starten (API \& UI)](#24-dienste-starten-api--ui)
|
||
- [3. Core-Module \& Entwicklung](#3-core-module--entwicklung)
|
||
- [3.1 Der Importer (`scripts.import_markdown`)](#31-der-importer-scriptsimport_markdown)
|
||
- [3.2 Der Hybrid Router (`app.routers.chat`)](#32-der-hybrid-router-approuterschat)
|
||
- [3.3 Der Retriever (`app.core.retriever`)](#33-der-retriever-appcoreretriever)
|
||
- [3.4 Das Frontend (`app.frontend.ui`)](#34-das-frontend-appfrontendui)
|
||
- [3.5 Embedding Service (`app.services.embeddings_client`)](#35-embedding-service-appservicesembeddings_client)
|
||
- [3.6 Traffic Control (`app.services.llm_service`)](#36-traffic-control-appservicesllm_service)
|
||
- [4. Tests \& Debugging](#4-tests--debugging)
|
||
- [4.1 Unit Tests (Pytest)](#41-unit-tests-pytest)
|
||
- [4.2 Integration / Pipeline Tests](#42-integration--pipeline-tests)
|
||
- [4.3 Smoke Tests (E2E)](#43-smoke-tests-e2e)
|
||
- [5. Das "Teach-the-AI" Paradigma (Context Intelligence)](#5-das-teach-the-ai-paradigma-context-intelligence)
|
||
- [A. Workflow: Einen neuen Typ implementieren (z. B. `type: risk`)](#a-workflow-einen-neuen-typ-implementieren-z-b-type-risk)
|
||
- [B. Workflow: Neue Beziehungen (Edges) nutzen (z. B. `beeinflusst_von`)](#b-workflow-neue-beziehungen-edges-nutzen-z-b-beeinflusst_von)
|
||
- [C. Workflow: Interview-Schema anpassen (WP07)](#c-workflow-interview-schema-anpassen-wp07)
|
||
- [Fazit](#fazit)
|
||
- [6. Nützliche Einzeiler](#6-nützliche-einzeiler)
|
||
|
||
---
|
||
|
||
## 1. Projektstruktur (Post-WP15)
|
||
|
||
Der Code ist modular in `app` (Logik), `scripts` (CLI) und `config` (Steuerung) getrennt.
|
||
|
||
mindnet/
|
||
├── app/
|
||
│ ├── core/ # Kernlogik
|
||
│ │ ├── ingestion.py # NEU: Async Ingestion Service mit Change Detection
|
||
│ │ ├── chunker.py # Smart Chunker Orchestrator
|
||
│ │ ├── derive_edges.py # Edge-Erzeugung (WP03 Logik)
|
||
│ │ ├── retriever.py # Scoring & Hybrid Search
|
||
│ │ ├── qdrant.py # DB-Verbindung
|
||
│ │ └── ...
|
||
│ ├── models/ # Pydantic DTOs
|
||
│ │ └── dto.py # Zentrale DTO-Definition
|
||
│ ├── routers/ # FastAPI Endpoints
|
||
│ │ ├── query.py # Suche
|
||
│ │ ├── ingest.py # NEU: Save/Analyze (WP11)
|
||
│ │ ├── chat.py # Hybrid Router v5 & Interview Logic
|
||
│ │ ├── feedback.py # Feedback (WP04c)
|
||
│ │ └── ...
|
||
│ ├── services/ # Interne & Externe Dienste
|
||
│ │ ├── llm_service.py # Ollama Client mit Traffic Control
|
||
│ │ ├── semantic_analyzer.py# NEU: LLM-Filter für Edges (WP15)
|
||
│ │ ├── embeddings_client.py# 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
|
||
│ ├── 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)
|
||
├── tests/ # Pytest Suite & Smoke Scripts
|
||
└── vault/ # Dein lokaler Markdown-Content (Git-ignored)
|
||
|
||
---
|
||
|
||
## 2. Lokales Setup (Development)
|
||
|
||
### 2.1 Voraussetzungen
|
||
* **Python:** 3.10 oder höher.
|
||
* **Docker:** Für Qdrant.
|
||
* **Ollama:** Für lokale LLM-Inference (erforderlich für `/chat` und Embeddings).
|
||
* **Vault:** Ein Ordner mit Markdown-Dateien (z.B. `./mindnet_v2_test_vault` für Tests).
|
||
|
||
### 2.2 Installation
|
||
|
||
# 1. Repository klonen & Verzeichnis wechseln
|
||
git clone <repo> mindnet
|
||
cd mindnet
|
||
|
||
# 2. Virtual Environment erstellen
|
||
python3 -m venv .venv
|
||
source .venv/bin/activate
|
||
|
||
# 3. Abhängigkeiten installieren (inkl. Streamlit)
|
||
pip install -r requirements.txt
|
||
|
||
# 4. Ollama Setup (Modelle laden)
|
||
# Chat-Modell (Phi-3)
|
||
ollama pull phi3:mini
|
||
# Embedding-Modell (Nomic) - PFLICHT für v2.4!
|
||
ollama pull nomic-embed-text
|
||
|
||
### 2.3 Konfiguration (Environment)
|
||
Erstelle eine `.env` Datei im Root-Verzeichnis.
|
||
|
||
# Qdrant Verbindung
|
||
QDRANT_URL="http://localhost:6333"
|
||
QDRANT_API_KEY="" # Leer lassen für lokal
|
||
|
||
# Mindnet Core Settings
|
||
COLLECTION_PREFIX="mindnet_dev"
|
||
VECTOR_DIM=768 # NEU: 768 für Nomic (vorher 384)
|
||
MINDNET_TYPES_FILE="./config/types.yaml"
|
||
MINDNET_RETRIEVER_CONFIG="./config/retriever.yaml"
|
||
MINDNET_VAULT_ROOT="./vault"
|
||
|
||
# LLM / RAG Settings (WP06/07)
|
||
MINDNET_LLM_MODEL="phi3:mini"
|
||
MINDNET_EMBEDDING_MODEL="nomic-embed-text" # NEU
|
||
MINDNET_OLLAMA_URL="http://127.0.0.1:11434"
|
||
MINDNET_LLM_TIMEOUT=300.0 # Timeout für CPU-Inference Cold-Starts
|
||
MINDNET_DECISION_CONFIG="./config/decision_engine.yaml"
|
||
MINDNET_LLM_BACKGROUND_LIMIT=2 # NEU: Limit für parallele Import-Tasks
|
||
|
||
# Frontend Settings (WP10)
|
||
MINDNET_API_URL="http://localhost:8002"
|
||
MINDNET_API_TIMEOUT=300.0 # Erhöht wegen Smart Edge Berechnung
|
||
|
||
# Import-Strategie
|
||
MINDNET_HASH_COMPARE="Body"
|
||
MINDNET_HASH_SOURCE="parsed"
|
||
|
||
### 2.4 Dienste starten (API & UI)
|
||
|
||
Wir entwickeln mit zwei Services. Du kannst sie manuell in zwei Terminals starten oder die Systemd-Services nutzen (siehe `admin_guide.md`).
|
||
|
||
**Terminal A: Backend (API)**
|
||
|
||
# Startet auf Port 8002 (Dev Standard)
|
||
uvicorn app.main:app --host 0.0.0.0 --port 8002 --env-file .env --reload
|
||
|
||
**Terminal B: Frontend (UI)**
|
||
|
||
# Startet auf Port 8502 (Dev Standard)
|
||
# --server.port 8502 verhindert Konflikte mit Prod (8501)
|
||
streamlit run app/frontend/ui.py --server.port 8502
|
||
|
||
---
|
||
|
||
## 3. Core-Module & Entwicklung
|
||
|
||
### 3.1 Der Importer (`scripts.import_markdown`)
|
||
Dies ist das komplexeste Modul.
|
||
* **Einstieg:** `scripts/import_markdown.py` -> `main_async()`.
|
||
* **Smart Edges:** Nutzt `app.core.chunker` und `app.services.semantic_analyzer` zur Kanten-Filterung.
|
||
* **Idempotenz:** Der Importer muss mehrfach laufen können, ohne Duplikate zu erzeugen. Wir nutzen deterministische IDs (UUIDv5).
|
||
* **Robustheit:** In `ingestion.py` sind Mechanismen wie Change Detection und Robust File I/O (fsync) implementiert.
|
||
|
||
### 3.2 Der Hybrid Router (`app.routers.chat`)
|
||
Hier liegt die Logik für Intent Detection (WP06) und Interview-Modus (WP07).
|
||
* **Question Detection:** Prüft zuerst, ob der Input eine Frage ist. Falls ja -> RAG.
|
||
* **Keyword Match:** Prüft Keywords in `decision_engine.yaml` und `types.yaml`.
|
||
* **Priority:** Ruft `llm_service` mit `priority="realtime"` auf.
|
||
|
||
### 3.3 Der Retriever (`app.core.retriever`)
|
||
Hier passiert das Scoring.
|
||
* **Hybrid Search:** Der Chat-Endpoint erzwingt `mode="hybrid"`.
|
||
* **Strategic Retrieval:** In `chat.py` wird der Retriever *zweimal* aufgerufen, wenn ein Intent (z.B. `DECISION`) eine Injection (`value`) erfordert.
|
||
|
||
### 3.4 Das Frontend (`app.frontend.ui`)
|
||
Eine Streamlit-App (WP10).
|
||
* **Resurrection Pattern:** Das UI nutzt ein spezielles State-Management, um Eingaben bei Tab-Wechseln (Chat <-> Editor) zu erhalten. Widgets synchronisieren sich mit `st.session_state`.
|
||
* **Healing Parser:** Die Funktion `parse_markdown_draft` repariert defekte YAML-Frontmatter (fehlendes `---`) automatisch.
|
||
* **Logik:** Ruft `/chat`, `/feedback` und `/ingest/analyze` Endpoints der API auf.
|
||
|
||
### 3.5 Embedding Service (`app.services.embeddings_client`)
|
||
**Neu in v2.4:**
|
||
* Nutzt `httpx.AsyncClient` für non-blocking Calls an Ollama (Primary Mode).
|
||
* Besitzt einen **Fallback** auf `requests` (Synchron), falls Legacy-Skripte ihn nutzen.
|
||
* Unterstützt dediziertes Embedding-Modell (`nomic-embed-text`) getrennt vom Chat-Modell.
|
||
|
||
### 3.6 Traffic Control (`app.services.llm_service`)
|
||
**Neu in v2.6 (Version 2.8.0):**
|
||
* Stellt sicher, dass Batch-Prozesse (Import) den Live-Chat nicht ausbremsen.
|
||
* **Methode:** `generate_raw_response(..., priority="background")` aktiviert eine Semaphore.
|
||
* **Limit:** Konfigurierbar über `MINDNET_LLM_BACKGROUND_LIMIT` (Default: 2) in der `.env`.
|
||
|
||
---
|
||
|
||
## 4. Tests & Debugging
|
||
|
||
Wir unterscheiden drei Test-Ebenen. Ein Pull Request sollte alle passieren.
|
||
|
||
### 4.1 Unit Tests (Pytest)
|
||
Für isolierte Logik (Parsing, Scoring).
|
||
|
||
pytest tests/test_retriever_basic.py
|
||
pytest tests/test_chunking.py
|
||
pytest tests/test_edges_all.py
|
||
|
||
### 4.2 Integration / Pipeline Tests
|
||
Prüfen den Datenfluss von Markdown bis Qdrant-JSON.
|
||
* **Payload Dryrun:** Prüft JSON-Schema Konformität.
|
||
|
||
python3 -m scripts.payload_dryrun --vault ./mindnet_v2_test_vault
|
||
|
||
* **Edge Checks:** Prüft Graph-Invarianten.
|
||
|
||
python3 -m scripts.edges_full_check
|
||
|
||
### 4.3 Smoke Tests (E2E)
|
||
Prüfen das laufende System gegen eine echte Qdrant-Instanz und Ollama.
|
||
|
||
# 1. API Test (Decision Engine)
|
||
python tests/test_wp06_decision.py -p 8002 -e DECISION -q "Soll ich X tun?"
|
||
|
||
# 2. UI Test (Manuell)
|
||
# Öffne http://localhost:8502
|
||
# Stelle eine Frage und prüfe Intent-Badge und Quellen-Anzeige.
|
||
|
||
# 3. Feedback Test
|
||
python tests/test_feedback_smoke.py --url http://localhost:8002/query
|
||
|
||
# 4. Intelligence Test (WP11)
|
||
python debug_analysis.py
|
||
|
||
---
|
||
|
||
## 5. Das "Teach-the-AI" Paradigma (Context Intelligence)
|
||
|
||
Mindnet lernt nicht durch Training (Fine-Tuning), sondern durch **Konfiguration**, **Vernetzung** und **Prompting**. Dies ist der **Core-Workflow** für Erweiterungen.
|
||
|
||
### A. Workflow: Einen neuen Typ implementieren (z. B. `type: risk`)
|
||
|
||
**1. Daten-Ebene (`config/types.yaml`)**
|
||
Definiere die "Physik" des Typs (Import-Regeln und Basis-Wichtigkeit).
|
||
|
||
risk:
|
||
chunk_profile: sliding_short # Risiken sind oft kurze Statements
|
||
retriever_weight: 0.90 # Sehr wichtig
|
||
edge_defaults: ["blocks"] # Automatische Kante zu verlinkten Projekten
|
||
detection_keywords: ["gefahr", "risiko"]
|
||
|
||
**2. Strategie-Ebene (`config/decision_engine.yaml`)**
|
||
Damit dieser Typ aktiv geladen wird, musst du ihn einer Strategie zuordnen.
|
||
|
||
DECISION:
|
||
inject_types: ["value", "principle", "goal", "risk"] # <--- "risk" hinzugefügt
|
||
|
||
*Ergebnis:* Wenn der Intent `DECISION` erkannt wird, sucht das System nun auch aktiv nach Risiken.
|
||
|
||
**3. Kognitive Ebene (`config/prompts.yaml`)**
|
||
Erkläre dem LLM im Template, was es damit tun soll.
|
||
|
||
### B. Workflow: Neue Beziehungen (Edges) nutzen (z. B. `beeinflusst_von`)
|
||
|
||
Beziehungen sind der Klebstoff für die "Why"-Erklärungen.
|
||
|
||
**1. Erfassung im Vault (Markdown)**
|
||
Nutze die Inline-Syntax im Fließtext:
|
||
> "Die Entscheidung für Qdrant wurde [[rel:beeinflusst_von Budgetkürzung 2024]]."
|
||
|
||
**2. Gewichtung (`config/retriever.yaml`)**
|
||
Konfiguriere `edge_weights`, wenn Kausalität wichtiger ist als Ähnlichkeit.
|
||
|
||
### C. Workflow: Interview-Schema anpassen (WP07)
|
||
|
||
Wenn Mindnet neue Fragen stellen soll:
|
||
|
||
**1. Schema erweitern (`config/types.yaml`)**
|
||
Füge das Feld in die Liste ein (Neu: Schemas liegen jetzt hier).
|
||
|
||
project:
|
||
schema:
|
||
- "Titel"
|
||
- "Ziel"
|
||
- "Budget (Neu)"
|
||
|
||
**2. Keine Code-Änderung nötig**
|
||
Der `One-Shot Extractor` (Prompt Template) liest diese Liste dynamisch.
|
||
|
||
### Fazit
|
||
* **Vault:** Liefert das Wissen.
|
||
* **Config:** Liefert die Strategie (Router & Weights).
|
||
* **Prompt:** Liefert die Interpretation.
|
||
|
||
---
|
||
|
||
## 6. Nützliche Einzeiler
|
||
|
||
**DB komplett zurücksetzen (Vorsicht!):**
|
||
|
||
# --yes überspringt die Bestätigung
|
||
python3 -m scripts.reset_qdrant --mode wipe --prefix "mindnet_dev" --yes
|
||
|
||
**Einen einzelnen File inspizieren (Parser-Sicht):**
|
||
|
||
python3 tests/inspect_one_note.py --file ./vault/MeinFile.md
|
||
|
||
**Live-Logs sehen (Systemd):**
|
||
|
||
# Backend
|
||
journalctl -u mindnet-dev -f
|
||
# Frontend
|
||
journalctl -u mindnet-ui-dev -f |