# 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 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