mindnet/docs/developer_guide.md
Lars 5d8e96372f
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 3s
docs/developer_guide.md aktualisiert
2025-12-08 17:39:01 +01:00

246 lines
9.3 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.2 Developer Guide
**Datei:** `docs/mindnet_developer_guide_v2.2.md`
**Stand:** 2025-12-08
**Status:** **FINAL** (Inkl. RAG, Edge-Config & AI-Teaching)
**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.
---
## 1. Projektstruktur (Aktualisiert)
Der Code ist modular in `app` (Logik), `scripts` (CLI) und `config` (Steuerung) getrennt.
mindnet/
├── app/
│ ├── core/ # Kernlogik
│ │ ├── chunker.py # Text-Zerlegung
│ │ ├── 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
│ │ ├── chat.py # RAG-Chat (WP05)
│ │ ├── feedback.py # Feedback (WP04c)
│ │ └── ...
│ ├── services/ # Interne & Externe Dienste
│ │ ├── llm_service.py # Ollama Client (WP05)
│ │ ├── feedback_service.py # Logging (JSONL Writer)
│ │ └── embeddings_client.py
│ └── main.py # Entrypoint der API
├── config/ # YAML-Konfigurationen (Single Source of Truth)
│ ├── types.yaml # Import-Regeln
│ ├── prompts.yaml # LLM Prompts & RAG Templates (WP05)
│ └── 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`).
* **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
pip install -r requirements.txt
# 4. Ollama Setup (Modell laden)
# Wir nutzen Phi-3 Mini für schnelle CPU-Inference
ollama pull phi3:mini
### 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"
MINDNET_TYPES_FILE="./config/types.yaml"
MINDNET_RETRIEVER_CONFIG="./config/retriever.yaml"
# LLM / RAG Settings (WP05)
MINDNET_LLM_MODEL="phi3:mini"
MINDNET_OLLAMA_URL="http://127.0.0.1:11434"
MINDNET_PROMPTS_PATH="./config/prompts.yaml"
# Import-Strategie
MINDNET_HASH_COMPARE="Body"
MINDNET_HASH_SOURCE="parsed"
### 2.4 Dienste starten (Systemd bevorzugt)
Auf dem Entwicklungsserver (Beelink) nutzen wir Systemd.
# Starten / Neustarten
sudo systemctl restart mindnet-dev
# Logs prüfen
journalctl -u mindnet-dev -f
Falls du lokal auf Windows entwickelst:
# 1. Qdrant starten
docker run -p 6333:6333 qdrant/qdrant
# 2. Ollama starten
ollama serve
# 3. API starten
uvicorn app.main:app --host 0.0.0.0 --port 8002 --env-file .env --reload
---
## 3. Core-Module & Entwicklung
### 3.1 Der Importer (`scripts.import_markdown`)
Dies ist das komplexeste Modul.
* **Einstieg:** `scripts/import_markdown.py` -> `main()`.
* **Idempotenz:** Der Importer muss mehrfach laufen können, ohne Duplikate zu erzeugen. Wir nutzen deterministische IDs (UUIDv5).
* **Debugging:** Nutze `--dry-run` oder `scripts/payload_dryrun.py`.
### 3.2 Edge-Logik (`app.core.derive_edges`)
Hier wird entschieden, welche Kanten entstehen.
* **Rule-ID:** Vergib zwingend eine eindeutige `rule_id` (z.B. `custom:my_rule`), damit die Herkunft für die Explanation nachvollziehbar bleibt.
### 3.3 Der Retriever & Chat (`app.core.retriever` / `app.routers.chat`)
Hier passiert das Scoring und die Generation.
* **Hybrid Search:** Der Chat-Endpoint erzwingt `mode="hybrid"`.
* **Context Enrichment:** In `_build_enriched_context` (chat.py) werden Metadaten (Typ, Score) in den Prompt injiziert. Achte darauf, dass neue Typen hier ggf. berücksichtigt werden, falls sie spezielle Behandlung brauchen (aktuell generisch gelöst).
---
## 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 (API) gegen eine echte Qdrant-Instanz und Ollama.
# 1. Retriever Test (Hybrid + Explanation)
python scripts/test_retriever_smoke.py --query "Test" --mode hybrid --top-k 5 --explain
# 2. Chat / RAG Test (WP05)
# Prüft die gesamte Kette: Suche -> Kontext -> LLM -> Antwort
python tests/test_chat_wp05.py
# 3. Feedback Test (WP04c)
python tests/test_feedback_smoke.py --url http://localhost:8002/query
---
## 5. Das "Teach-the-AI" Paradigma (Context Intelligence)
Mindnet lernt nicht durch Training (Fine-Tuning), sondern durch **Konfiguration**, **Vernetzung** und **Prompting**. Wenn du dem System ein neues Konzept beibringen willst, musst du in der Regel an drei Stellen eingreifen. 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: short # Risiken sind oft kurze Statements
retriever_weight: 0.90 # Sehr wichtig, fast so hoch wie Decisions
edge_defaults: ["blocks"] # Automatische Kante zu verlinkten Projekten
*Ergebnis:* Notizen werden importiert und landen bei Suchen weit oben.
**2. Labeling-Ebene (`app/routers/chat.py`)**
Der Router liest das Feld `type` automatisch aus und injiziert es als `TYP: [RISK]` in den Prompt.
* *Prüfung:* Keine Code-Änderung nötig, da der Router generisch ist.
**3. Kognitive Ebene (`config/prompts.yaml`)**
Erkläre dem LLM, was `[RISK]` bedeutet. Ergänze den `system_prompt`:
system_prompt: |
...
REGELN FÜR TYPEN:
- [RISK]: Warnung! Wenn ein [RISK] im Kontext ist, weise den User darauf hin.
### 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)**
Du musst dem System keinen neuen Edge-Typ "beibringen" (Schema-less). Du nutzt ihn einfach.
Nutze die Inline-Syntax im Fließtext:
Die Entscheidung für Qdrant wurde [[rel:beeinflusst_von Budgetkürzung 2024]].
Diese Strategie ist eine [[rel:reaktion_auf Marktveränderung]].
*Ergebnis:* Der Importer erzeugt Kanten mit `kind="beeinflusst_von"`.
**2. Gewichtung (`config/retriever.yaml`)**
Standardmäßig werden alle expliziten Kanten gleich behandelt (hoher Bonus). Wenn du willst, dass `beeinflusst_von` *wichtiger* ist als `related_to`, konfigurierst du dies hier.
scoring:
edge_weight: 0.7
# Optional: Spezifische Boosts für Kanten-Typen (Advanced)
edge_type_weights:
beeinflusst_von: 1.5 # Sehr starker Einfluss auf das Ranking
reaktion_auf: 1.2
related_to: 0.5 # Schwächerer Einfluss
*Hinweis:* Wenn `edge_type_weights` nicht definiert ist, gilt der Standard-Algorithmus (Confidence ~0.95 für Inline-Relations).
**3. Verständnis beim LLM (`config/prompts.yaml`)**
Damit der Chatbot versteht, dass "beeinflusst_von" eine Kausalität ist (und nicht nur Ähnlichkeit), kannst du dies im Prompt erklären, falls die Explanation-Daten in den Kontext geladen werden (Roadmap WP-06).
### Fazit
Nur wenn **Daten** (Vault), **Physik** (Config) und **Semantik** (Prompt) zusammenspielen, entsteht ein intelligenter Zwilling.
* **Vault:** Liefert das Wissen.
* **Config:** Liefert die Priorität (Weights).
* **Prompt:** Liefert die Interpretation.
---
## 6. Nützliche Einzeiler
**DB komplett zurücksetzen (Vorsicht!):**
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 (Beelink):**
journalctl -u mindnet-dev -f