diff --git a/Programmmanagement/Programmplan_V2.2.md b/Programmmanagement/Programmplan_V2.2.md index 009da04..c10d375 100644 --- a/Programmmanagement/Programmplan_V2.2.md +++ b/Programmmanagement/Programmplan_V2.2.md @@ -1,8 +1,45 @@ # mindnet v2.2 — Programmplan -**Version:** 2.3.0 (Post-WP05 RAG Integration) -**Stand:** 2025-12-08 +**Version:** 2.3.1 (Post-WP06 Decision Engine) +**Stand:** 2025-12-09 **Status:** Aktiv +--- +- [mindnet v2.2 — Programmplan](#mindnet-v22--programmplan) + - [1. Programmauftrag](#1-programmauftrag) + - [2. Vision](#2-vision) + - [3. Programmziele](#3-programmziele) + - [3.1 Kurzfristig (Abgeschlossen / Laufend)](#31-kurzfristig-abgeschlossen--laufend) + - [3.2 Mittelfristig (Nächste Schritte)](#32-mittelfristig-nächste-schritte) + - [3.3 Langfristig](#33-langfristig) + - [4. Architekturprinzipien](#4-architekturprinzipien) + - [5. Programmstruktur (Phasenmodell)](#5-programmstruktur-phasenmodell) + - [6. Workpackages – detaillierte Übersicht](#6-workpackages--detaillierte-übersicht) + - [Legende Aufwand / Komplexität](#legende-aufwand--komplexität) + - [WP-01 – Wissensdesign (abgeschlossen)](#wp-01--wissensdesign-abgeschlossen) + - [WP-02 – Chunking \& Hash-Strategie (abgeschlossen)](#wp-02--chunking--hash-strategie-abgeschlossen) + - [WP-03 – Import-Pipeline \& Edge-System v2 (abgeschlossen)](#wp-03--import-pipeline--edge-system-v2-abgeschlossen) + - [WP-04a – Retriever \& Graph-Scoring (abgeschlossen)](#wp-04a--retriever--graph-scoring-abgeschlossen) + - [WP-04b – Explanation Layer ("Why-Layer") (abgeschlossen)](#wp-04b--explanation-layer-why-layer-abgeschlossen) + - [WP-04c – Feedback Logging \& Bewertungsdaten (abgeschlossen)](#wp-04c--feedback-logging--bewertungsdaten-abgeschlossen) + - [WP-05 – Persönlichkeitsmodell \& RAG-Chat (abgeschlossen)](#wp-05--persönlichkeitsmodell--rag-chat-abgeschlossen) + - [WP-05b – Advanced Chat (Optional)](#wp-05b--advanced-chat-optional) + - [WP-06 – Decision Engine \& Hybrid Router (abgeschlossen)](#wp-06--decision-engine--hybrid-router-abgeschlossen) + - [WP-07 – Interview-Assistent (geplant)](#wp-07--interview-assistent-geplant) + - [WP-08 – Self-Tuning v1/v2 (geplant)](#wp-08--self-tuning-v1v2-geplant) + - [WP-09 – Vault-Onboarding \& Migration (geplant)](#wp-09--vault-onboarding--migration-geplant) + - [WP-10 – Chat-Interface \& Writeback (geplant)](#wp-10--chat-interface--writeback-geplant) + - [WP-11 – Knowledge-Builder \& Vernetzungs-Assistent (geplant)](#wp-11--knowledge-builder--vernetzungs-assistent-geplant) + - [WP-12 – Knowledge Rewriter (Soft Mode, geplant)](#wp-12--knowledge-rewriter-soft-mode-geplant) + - [WP-13 – MCP-Integration \& Agenten-Layer (geplant)](#wp-13--mcp-integration--agenten-layer-geplant) + - [WP-14 – Review / Refactoring / Dokumentation (geplant)](#wp-14--review--refactoring--dokumentation-geplant) + - [7. Abhängigkeiten (vereinfacht, aktualisiert)](#7-abhängigkeiten-vereinfacht-aktualisiert) + - [8. Laufzeit- \& Komplexitätsindikatoren (aktualisiert)](#8-laufzeit---komplexitätsindikatoren-aktualisiert) + - [9. Programmfortschritt (Ampel, aktualisiert)](#9-programmfortschritt-ampel-aktualisiert) + - [10. Governance \& Versionierung](#10-governance--versionierung) + - [11. Executive Summary](#11-executive-summary) + + + --- ## 1. Programmauftrag @@ -14,7 +51,7 @@ mindnet v2.2 entwickelt ein persönliches, wachsendes KI-Gedächtnis, das: - einen KI-Zwilling aufbaut, der ähnlich argumentiert, entscheidet und reflektiert wie du, - über mehrere Kanäle gefüttert wird: - Obsidian-Markdown (primäre Quelle), - - Chat-basierter Agent (RAG-Chat aktiv), + - Chat-basierter Agent (Decision Engine & RAG-Chat aktiv), - später: Interview-Assistent (strukturierte Dialogerfassung), - automatisch neue Zusammenhänge erkennt und vernetzt (Edges, Typen, Hinweise), - sich durch Rückmeldungen (Feedback) selbst verbessert (Self-Tuning). @@ -50,7 +87,7 @@ Kernprinzipien der Vision: Das System arbeitet von Anfang an mit unvollständigen Daten, kann aber schrittweise dichter werden, ohne dass alte Notizen massenhaft manuell angepasst werden müssen. - **Flexibilität (Late Binding):** - Semantik wird überwiegend in Konfiguration (z. B. `types.yaml`, `prompts.yaml`, Policies) festgelegt. Die Persönlichkeit entsteht durch das Prompt-Design, nicht durch Hardcoding. + Semantik wird überwiegend in Konfiguration (z. B. `types.yaml`, `prompts.yaml`, `decision_engine.yaml`, Policies) festgelegt. Die Persönlichkeit entsteht durch das Config-Design, nicht durch Hardcoding. - **Autonomie & Self-Healing:** mindnet schlägt fehlende Typen, Relationen und Edges vor (z. B. aus Inline-Relationen, Edge-Defaults, Ähnlichkeitsbeziehungen) und baut damit einen „self-healing graph“ auf. @@ -59,7 +96,7 @@ Kernprinzipien der Vision: Feedback zu Antworten (gut/schlecht, relevant/nicht relevant) fließt in Score-Gewichte, Policies und ggf. Edge-Struktur ein. - **Persönlichkeit:** - Entscheidungen werden wert- und erfahrungsbasiert begründet; das System agiert als KI-Zwilling durch Nutzung lokaler LLMs (z.B. Phi-3/Mistral). + Entscheidungen werden wert- und erfahrungsbasiert begründet; das System agiert als KI-Zwilling durch Nutzung lokaler LLMs (z.B. Phi-3/Mistral) und eines Intent-Routers. - **Incremental Growth:** Das System muss mit wenigen, heterogenen Notizen starten und sich fortlaufend verdichten können – ohne Retro-Massenmigrationen im Vault. @@ -76,17 +113,17 @@ Kernprinzipien der Vision: - **Erklärbarkeit:** Why-Layer liefert Begründungen zu Treffern (WP-04b abgeschlossen). - **Feedback-Loop:** Systematisches Logging von Suche und Bewertung (WP-04c abgeschlossen). - **RAG-Chat:** KI antwortet in natürlicher Sprache auf Basis von Wissen und Persönlichkeit (WP-05 abgeschlossen). +- **Decision Engine:** System erkennt Intent (Fakt vs. Entscheidung) und wägt Werte ab (WP-06 abgeschlossen). +- **Multi-Persona:** System wechselt den Tonfall (Empathisch vs. Analytisch) situativ (WP-06 abgeschlossen). - Technische Basis: FastAPI, Qdrant, Ollama (Local LLM). - Automatisierte Erkennung von Beziehungen: - Wikilinks, Inline-Relationen, Callout-Edges, Typ-Defaults. -- Schrittweises Lernen über Feedback (Score-Tuning, noch „manuell“ konfiguriert). - „Mitwachsendes“ Schema ohne Obsidian-Umstrukturierungen: - Neues Wissen kann sofort erfasst werden, - bestehende Notizen bleiben gültig (Virtual Schema Layer). ### 3.2 Mittelfristig (Nächste Schritte) -- **Decision Engine (WP-06):** Das System berät aktiv bei Entscheidungen, indem es `type: value` und `type: principle` Notizen gegen eine Fragestellung abwägt. - **Chat Interface (WP-10):** Ablösung der Terminal-Interaktion durch ein Web-Frontend (Streamlit/React) für bessere UX und einfacheres Feedback-Geben. - Interview-Assistent erstellt neue Notes automatisch (strukturierte Dialoge → Markdown). - mindnet erzeugt Vorschläge für neue Notes & Edges und bietet einen „Vernetzungs-Assistenten“ für manuell angelegte Notizen. @@ -109,7 +146,7 @@ Kernprinzipien der Vision: Die folgenden Prinzipien steuern alle Workpackages und Entscheidungen: 1. **Late Binding (späte Semantik)** - - Struktur und Interpretation werden in Konfigurationen (z. B. `types.yaml`, `prompts.yaml`, Policies) definiert, nicht direkt in den Vault-Dateien. + - Struktur und Interpretation werden in Konfigurationen (z. B. `types.yaml`, `prompts.yaml`, `decision_engine.yaml`) definiert, nicht direkt in den Vault-Dateien. - Die "Persönlichkeit" des Chats ist ein Prompt-Template, kein Code. 2. **Virtual Schema Layer** @@ -151,11 +188,11 @@ Die folgenden Prinzipien steuern alle Workpackages und Entscheidungen: Phase A – Fundament & Import (Fertig) Phase B – Semantik, Graph & Lernen (Fertig) - Phase C – Persönlichkeitsmodell & KI-Zwilling (Laufend) + Phase C – Persönlichkeitsmodell & KI-Zwilling (Fertig) Phase D – Agenten, MCP & Interaktion (Startend) Phase E – Review, Refactoring, Dokumentation -Alle Workpackages sind einer Phase zugeordnet. WP-01 bis WP-05 sind bereits erfolgreich abgeschlossen. +Alle Workpackages sind einer Phase zugeordnet. WP-01 bis WP-06 sind bereits erfolgreich abgeschlossen. --- @@ -294,18 +331,20 @@ Erweiterung des Chats um Gedächtnis (History) und einfache Tools. --- -### WP-06 – Decision Engine (geplant) +### WP-06 – Decision Engine & Hybrid Router (abgeschlossen) **Phase:** C -**Status:** 🟡 geplant (Priorität A) +**Status:** 🟢 abgeschlossen **Ziel:** -Entscheidungsunterstützung auf Basis von Wissen, Persönlichkeit und Zielen – inklusive nachvollziehbarer Begründung. +Transformation vom reinen Wissens-Abrufer zum strategischen Entscheidungspartner durch Intent-Erkennung. -**Umfang:** -- Erweiterung des RAG-Kontexts um gezieltes Nachladen von `type: value` und `type: principle`. -- Prompt-Engineering für "Trade-off Analyse" (Pro/Contra basierend auf Werten). -- Output-Formatierung als Entscheidungsvorlage. +**Erreichte Ergebnisse:** +- **Hybrid Intent Router:** Kombination aus schnellem Keyword-Matching und intelligentem LLM-Fallback zur Erkennung der Absicht (`DECISION`, `EMPATHY`, `FACT`, `CODING`). +- **Strategic Retrieval:** Gezieltes Nachladen von Werten (`value`), Zielen (`goal`) oder Erfahrungen (`experience`) basierend auf dem Intent. +- **Multi-Persona:** Dynamische Anpassung des Tonfalls (Berater vs. Spiegel vs. Techniker) durch `prompts.yaml`. +- **Late Binding:** Vollständige Konfiguration via `decision_engine.yaml`. +- **Robustheit:** Konfigurierbare Timeouts für CPU-Inference. **Aufwand / Komplexität:** - Aufwand: Mittel @@ -488,7 +527,7 @@ Aufräumen, dokumentieren, stabilisieren – insbesondere für Onboarding Dritte | WP04c | 🟢 | | WP05 | 🟢 | | WP05b | ⚪ | -| WP06 | 🟡 | +| WP06 | 🟢 | | WP07 | 🟡 | | WP08 | 🟡 | | WP09 | 🟡 | @@ -519,8 +558,8 @@ mindnet v2.2 ist so aufgesetzt, dass: - die Struktur **mitwächst**, ohne Retro-Massenarbeit im Vault, - ein **hybrider Retriever** qualitativ hochwertige, erklärbare Antworten liefert, - ein **Self-Healing- und Self-Tuning-Mechanismus** vorbereitet ist (durch WP-04c Feedback-Daten), -- ein **Persönlichkeitsmodell** und eine **Decision Engine** entstehen, +- ein **Persönlichkeitsmodell** (Decision Engine, Empathie) existiert und den Tonfall situativ anpasst, - langfristig ein **KI-Zwilling** aufgebaut wird, der deine Werte, Erfahrungen und Denkweise spiegelt, - die technische Architektur (FastAPI, Qdrant, YAML-Policies, MCP-Integration) lokal, nachvollziehbar und erweiterbar bleibt. -Dieser Programmplan bildet die konsolidierte Grundlage (v2.3.0) für alle weiteren Arbeiten. \ No newline at end of file +Dieser Programmplan bildet die konsolidierte Grundlage (v2.3.1) für alle weiteren Arbeiten. \ No newline at end of file diff --git a/app/config.py b/app/config.py index a1ea619..862e4f9 100644 --- a/app/config.py +++ b/app/config.py @@ -1,12 +1,7 @@ """ -app/config.py — zentrale Konfiguration (ENV → Settings) - -Version: - 0.3.1 (WP-05: Switch default to Mistral for CPU inference) -Stand: - 2025-12-08 +app/config.py — zentrale Konfiguration +Version: 0.4.0 (WP-06 Complete) """ - from __future__ import annotations import os from functools import lru_cache @@ -25,9 +20,12 @@ class Settings: # WP-05 LLM / Ollama OLLAMA_URL: str = os.getenv("MINDNET_OLLAMA_URL", "http://127.0.0.1:11434") - # ÄNDERUNG: Standard auf 'mistral' gesetzt, da bereits lokal vorhanden LLM_MODEL: str = os.getenv("MINDNET_LLM_MODEL", "phi3:mini") PROMPTS_PATH: str = os.getenv("MINDNET_PROMPTS_PATH", "config/prompts.yaml") + + # NEU für WP-06 + LLM_TIMEOUT: float = float(os.getenv("MINDNET_LLM_TIMEOUT", "120.0")) + DECISION_CONFIG_PATH: str = os.getenv("MINDNET_DECISION_CONFIG", "config/decision_engine.yaml") # API DEBUG: bool = os.getenv("DEBUG", "false").lower() == "true" diff --git a/app/models/dto.py b/app/models/dto.py index 1cfd737..c0e928c 100644 --- a/app/models/dto.py +++ b/app/models/dto.py @@ -1,12 +1,12 @@ """ -app/models/dto.py — Pydantic-Modelle (DTOs) für WP-04/WP-05 Endpunkte +app/models/dto.py — Pydantic-Modelle (DTOs) für WP-04/WP-05/WP-06 Zweck: Laufzeit-Modelle für FastAPI (Requests/Responses). - WP-05 Update: Chat-Modelle. + WP-06 Update: Intent in ChatResponse. Version: - 0.4.0 (Update für WP-05 Chat) + 0.6.0 (WP-06: Decision Engine) Stand: 2025-12-08 """ @@ -144,9 +144,10 @@ class GraphResponse(BaseModel): class ChatResponse(BaseModel): """ - WP-05: Antwortstruktur für /chat. + WP-05/06: Antwortstruktur für /chat. """ query_id: str = Field(..., description="Traceability ID (dieselbe wie für Search)") answer: str = Field(..., description="Generierte Antwort vom LLM") sources: List[QueryHit] = Field(..., description="Die für die Antwort genutzten Quellen") - latency_ms: int \ No newline at end of file + latency_ms: int + intent: Optional[str] = Field("FACT", description="WP-06: Erkannter Intent (FACT/DECISION)") \ No newline at end of file diff --git a/app/routers/chat.py b/app/routers/chat.py index 2f1a9d3..0e01dc6 100644 --- a/app/routers/chat.py +++ b/app/routers/chat.py @@ -1,18 +1,17 @@ """ -app/routers/chat.py — RAG Endpunkt (WP-05 Final Audit Version) - -Zweck: - Verbindet Retrieval mit LLM-Generation. - Enriched Context: Fügt Typen und Metadaten in den Prompt ein, - damit das LLM komplexe Zusammenhänge (z.B. Decisions) versteht. +app/routers/chat.py — RAG Endpunkt (WP-06 Hybrid Router v2) +Update: Robusteres LLM-Parsing für Small Language Models (SLMs). """ from fastapi import APIRouter, HTTPException, Depends -from typing import List +from typing import List, Dict, Any import time import uuid import logging +import yaml +from pathlib import Path +from app.config import get_settings from app.models.dto import ChatRequest, ChatResponse, QueryRequest, QueryHit from app.services.llm_service import LLMService from app.core.retriever import Retriever @@ -20,38 +19,65 @@ from app.core.retriever import Retriever router = APIRouter() logger = logging.getLogger(__name__) +# --- Helper: Config Loader --- + +_DECISION_CONFIG_CACHE = None + +def _load_decision_config() -> Dict[str, Any]: + settings = get_settings() + path = Path(settings.DECISION_CONFIG_PATH) + default_config = { + "strategies": { + "FACT": {"trigger_keywords": []} + } + } + + if not path.exists(): + logger.warning(f"Decision config not found at {path}, using defaults.") + return default_config + + try: + with open(path, "r", encoding="utf-8") as f: + return yaml.safe_load(f) + except Exception as e: + logger.error(f"Failed to load decision config: {e}") + return default_config + +def get_full_config() -> Dict[str, Any]: + global _DECISION_CONFIG_CACHE + if _DECISION_CONFIG_CACHE is None: + _DECISION_CONFIG_CACHE = _load_decision_config() + return _DECISION_CONFIG_CACHE + +def get_decision_strategy(intent: str) -> Dict[str, Any]: + config = get_full_config() + strategies = config.get("strategies", {}) + return strategies.get(intent, strategies.get("FACT", {})) + + +# --- Dependencies --- + def get_llm_service(): return LLMService() def get_retriever(): return Retriever() + +# --- Logic --- + def _build_enriched_context(hits: List[QueryHit]) -> str: - """ - Baut einen 'Rich Context' String. - Statt nur Text, injizieren wir Metadaten (Typ, Tags), damit das LLM - die semantische Rolle des Schnipsels versteht. - """ context_parts = [] - for i, hit in enumerate(hits, 1): source = hit.source or {} - - # 1. Content extrahieren (Robust: prüft alle üblichen Felder) content = ( - source.get("text") or - source.get("content") or - source.get("page_content") or - source.get("chunk_text") or - "[Kein Textinhalt verfügbar]" + source.get("text") or source.get("content") or + source.get("page_content") or source.get("chunk_text") or + "[Kein Text]" ) - - # 2. Metadaten für "Context Intelligence" - title = hit.note_id or "Unbekannte Notiz" - # Typ in Großbuchstaben (z.B. "DECISION"), damit das LLM es als Signal erkennt + title = hit.note_id or "Unbekannt" note_type = source.get("type", "unknown").upper() - # 3. Formatierung als strukturiertes Dokument für das LLM entry = ( f"### QUELLE {i}: {title}\n" f"TYP: [{note_type}] (Score: {hit.total_score:.2f})\n" @@ -61,6 +87,71 @@ def _build_enriched_context(hits: List[QueryHit]) -> str: return "\n\n".join(context_parts) +async def _classify_intent(query: str, llm: LLMService) -> str: + """ + Hybrid Router v2: + 1. Keyword Check (Best/Longest Match) -> FAST + 2. LLM Fallback (Robust Parsing) -> SMART + """ + config = get_full_config() + strategies = config.get("strategies", {}) + settings = config.get("settings", {}) + + query_lower = query.lower() + best_intent = None + max_match_length = 0 + + # 1. FAST PATH: Keywords + for intent_name, strategy in strategies.items(): + if intent_name == "FACT": continue + keywords = strategy.get("trigger_keywords", []) + for k in keywords: + if k.lower() in query_lower: + if len(k) > max_match_length: + max_match_length = len(k) + best_intent = intent_name + + if best_intent: + logger.info(f"Intent detected via KEYWORD: {best_intent}") + return best_intent + + # 2. SLOW PATH: LLM Router + if settings.get("llm_fallback_enabled", False): + router_prompt_template = settings.get("llm_router_prompt", "") + if router_prompt_template: + prompt = router_prompt_template.replace("{query}", query) + logger.info("Keywords failed. Asking LLM for Intent...") + + # Kurzer Raw Call + raw_response = await llm.generate_raw_response(prompt) + + # --- Robust Parsing für SLMs --- + # Wir suchen nach den bekannten Strategie-Namen im Output + llm_output_upper = raw_response.upper() + logger.info(f"LLM Router Raw Output: '{raw_response}'") # Debugging + + found_intents = [] + for strat_key in strategies.keys(): + # Wir prüfen, ob der Strategie-Name (z.B. "EMPATHY") im Text vorkommt + if strat_key in llm_output_upper: + found_intents.append(strat_key) + + # Entscheidung + final_intent = "FACT" + if len(found_intents) == 1: + # Eindeutiger Treffer + final_intent = found_intents[0] + logger.info(f"Intent detected via LLM (Parsed): {final_intent}") + return final_intent + elif len(found_intents) > 1: + # Mehrere Treffer (z.B. "Es ist FACT oder DECISION") -> Nimm den ersten oder Fallback + logger.warning(f"LLM returned multiple intents {found_intents}. Using first match: {found_intents[0]}") + return found_intents[0] + else: + logger.warning(f"LLM did not return a valid strategy name. Falling back to FACT.") + + return "FACT" + @router.post("/", response_model=ChatResponse) async def chat_endpoint( request: ChatRequest, @@ -69,44 +160,74 @@ async def chat_endpoint( ): start_time = time.time() query_id = str(uuid.uuid4()) - logger.info(f"Chat request [{query_id}]: {request.message[:50]}...") try: - # 1. Retrieval (Hybrid erzwingen für Graph-Nutzung) + # 1. Intent Detection + intent = await _classify_intent(request.message, llm) + logger.info(f"[{query_id}] Final Intent: {intent}") + + # Strategy Load + strategy = get_decision_strategy(intent) + inject_types = strategy.get("inject_types", []) + prompt_key = strategy.get("prompt_template", "rag_template") + prepend_instr = strategy.get("prepend_instruction", "") + + # 2. Primary Retrieval query_req = QueryRequest( query=request.message, - mode="hybrid", # WICHTIG: Hybrid Mode für Graph-Nachbarn + mode="hybrid", top_k=request.top_k, explain=request.explain ) - retrieve_result = await retriever.search(query_req) hits = retrieve_result.results + + # 3. Strategic Retrieval + if inject_types: + logger.info(f"[{query_id}] Executing Strategic Retrieval for types: {inject_types}...") + strategy_req = QueryRequest( + query=request.message, + mode="hybrid", + top_k=3, + filters={"type": inject_types}, + explain=False + ) + strategy_result = await retriever.search(strategy_req) + + existing_ids = {h.node_id for h in hits} + for strat_hit in strategy_result.results: + if strat_hit.node_id not in existing_ids: + hits.append(strat_hit) - # 2. Context Building (Enriched) + # 4. Context Building if not hits: - logger.info(f"[{query_id}] No hits found.") context_str = "Keine relevanten Notizen gefunden." else: context_str = _build_enriched_context(hits) - # 3. Generation - logger.info(f"[{query_id}] Context built with {len(hits)} chunks. Sending to LLM...") - answer_text = await llm.generate_rag_response( - query=request.message, - context_str=context_str - ) + # 5. Generation + template = llm.prompts.get(prompt_key, "{context_str}\n\n{query}") + system_prompt = llm.prompts.get("system_prompt", "") + + if prepend_instr: + context_str = f"{prepend_instr}\n\n{context_str}" + + final_prompt = template.replace("{context_str}", context_str).replace("{query}", request.message) + + logger.info(f"[{query_id}] Sending to LLM (Intent: {intent}, Template: {prompt_key})...") + + # System-Prompt separat übergeben + answer_text = await llm.generate_raw_response(prompt=final_prompt, system=system_prompt) - # 4. Response duration_ms = int((time.time() - start_time) * 1000) - logger.info(f"[{query_id}] Completed in {duration_ms}ms") return ChatResponse( - query_id=retrieve_result.query_id, + query_id=query_id, answer=answer_text, sources=hits, - latency_ms=duration_ms + latency_ms=duration_ms, + intent=intent ) except Exception as e: diff --git a/app/services/llm_service.py b/app/services/llm_service.py index 3d99064..90dd5d8 100644 --- a/app/services/llm_service.py +++ b/app/services/llm_service.py @@ -1,8 +1,6 @@ """ app/services/llm_service.py — LLM Client (Ollama) - -Version: - 0.1.2 (WP-05 Fix: Increased Timeout for CPU Inference) +Version: 0.2.1 (Fix: System Prompt Handling for Phi-3) """ import httpx @@ -18,19 +16,16 @@ class LLMService: def __init__(self): self.settings = get_settings() self.prompts = self._load_prompts() - # FIX: Timeout auf 120 Sekunden erhöht für CPU-Only Server - self.client = httpx.AsyncClient(base_url=self.settings.OLLAMA_URL, timeout=120.0) + + self.client = httpx.AsyncClient( + base_url=self.settings.OLLAMA_URL, + timeout=self.settings.LLM_TIMEOUT + ) def _load_prompts(self) -> dict: - """Lädt Prompts aus der konfigurierten YAML-Datei.""" path = Path(self.settings.PROMPTS_PATH) if not path.exists(): - logger.warning(f"Prompt config not found at {path}, using defaults.") - return { - "system_prompt": "You are a helpful AI assistant.", - "rag_template": "Context: {context_str}\nQuestion: {query}" - } - + return {} try: with open(path, "r", encoding="utf-8") as f: return yaml.safe_load(f) @@ -38,46 +33,48 @@ class LLMService: logger.error(f"Failed to load prompts: {e}") return {} - async def generate_rag_response(self, query: str, context_str: str) -> str: + async def generate_raw_response(self, prompt: str, system: str = None) -> str: """ - Generiert eine Antwort basierend auf Query und Kontext. + Führt einen LLM Call aus. + Unterstützt nun explizite System-Prompts für sauberes Templating. """ - system_prompt = self.prompts.get("system_prompt", "") - template = self.prompts.get("rag_template", "{context_str}\n\n{query}") - - # Template füllen - final_prompt = template.format(context_str=context_str, query=query) - payload = { "model": self.settings.LLM_MODEL, - "system": system_prompt, - "prompt": final_prompt, + "prompt": prompt, "stream": False, "options": { - "temperature": 0.7, - # Kleinerer Context spart Rechenzeit, falls 4096 zu viel ist - "num_ctx": 2048 + # Temperature etwas höher für Empathie, niedriger für Code? + # Wir lassen es auf Standard, oder steuern es später via Config. + "temperature": 0.7, + "num_ctx": 2048 } } + # WICHTIG: System-Prompt separat übergeben, damit Ollama formatiert + if system: + payload["system"] = system + try: response = await self.client.post("/api/generate", json=payload) - if response.status_code != 200: - error_msg = response.text - logger.error(f"Ollama API Error ({response.status_code}): {error_msg}") - return f"Fehler vom LLM (Modell '{self.settings.LLM_MODEL}' vorhanden?): {error_msg}" - - data = response.json() - return data.get("response", "") + logger.error(f"Ollama Error ({response.status_code}): {response.text}") + return "Fehler bei der Generierung." + + data = response.json() + return data.get("response", "").strip() - except httpx.ReadTimeout: - return "Timeout: Das Modell braucht zu lange zum Antworten (>120s). Hardware-Limit erreicht?" - except httpx.ConnectError: - return "Verbindungsfehler: Ist Ollama gestartet (Port 11434)?" except Exception as e: - logger.error(f"LLM Service Exception: {e}") - return f"Interner Fehler: {str(e)}" + logger.error(f"LLM Raw Gen Error: {e}") + return "Interner LLM Fehler." + + async def generate_rag_response(self, query: str, context_str: str) -> str: + """Legacy Support""" + system_prompt = self.prompts.get("system_prompt", "") + rag_template = self.prompts.get("rag_template", "{context_str}\n\n{query}") + final_prompt = rag_template.format(context_str=context_str, query=query) + + # Leite an die neue Methode weiter + return await self.generate_raw_response(final_prompt, system=system_prompt) async def close(self): await self.client.aclose() \ No newline at end of file diff --git a/config/decision_engine.yaml b/config/decision_engine.yaml new file mode 100644 index 0000000..f0f9e2d --- /dev/null +++ b/config/decision_engine.yaml @@ -0,0 +1,89 @@ +# config/decision_engine.yaml +# Steuerung der Decision Engine (WP-06) +# Hybrid-Modus: Keywords (Fast) + LLM Router (Smart Fallback) +version: 1.2 + +settings: + llm_fallback_enabled: true + + # Few-Shot Prompting für bessere SLM-Performance + llm_router_prompt: | + Du bist ein Klassifikator. Analysiere die Nachricht und wähle die passende Strategie. + Antworte NUR mit dem Namen der Strategie. + + STRATEGIEN: + - DECISION: Rat, Strategie, Vor/Nachteile, "Soll ich". + - EMPATHY: Gefühle, Frust, Freude, Probleme, "Alles ist sinnlos", "Ich bin traurig". + - CODING: Code, Syntax, Programmierung, Python. + - FACT: Wissen, Fakten, Definitionen. + + BEISPIELE: + User: "Wie funktioniert Qdrant?" -> FACT + User: "Soll ich Qdrant nutzen?" -> DECISION + User: "Schreibe ein Python Script" -> CODING + User: "Alles ist grau und sinnlos" -> EMPATHY + User: "Mir geht es heute gut" -> EMPATHY + + NACHRICHT: "{query}" + + STRATEGIE: + +strategies: + # 1. Fakten-Abfrage (Fallback & Default) + FACT: + description: "Reine Wissensabfrage." + trigger_keywords: [] + inject_types: [] + prompt_template: "rag_template" + prepend_instruction: null + + # 2. Entscheidungs-Frage + DECISION: + description: "Der User sucht Rat, Strategie oder Abwägung." + trigger_keywords: + - "soll ich" + - "meinung" + - "besser" + - "empfehlung" + - "strategie" + - "entscheidung" + - "wert" + - "prinzip" + - "vor- und nachteile" + - "abwägung" + inject_types: ["value", "principle", "goal"] + prompt_template: "decision_template" + prepend_instruction: | + !!! ENTSCHEIDUNGS-MODUS !!! + BITTE WÄGE FAKTEN GEGEN FOLGENDE WERTE, PRINZIPIEN UND ZIELE AB: + + # 3. Empathie / "Ich"-Modus + EMPATHY: + description: "Reaktion auf emotionale Zustände." + trigger_keywords: + - "ich fühle" + - "traurig" + - "glücklich" + - "gestresst" + - "angst" + - "nervt" + - "überfordert" + inject_types: ["experience", "belief", "profile"] + prompt_template: "empathy_template" + prepend_instruction: null + + # 4. Coding / Technical + CODING: + description: "Technische Anfragen und Programmierung." + trigger_keywords: + - "code" + - "python" + - "script" + - "funktion" + - "bug" + - "syntax" + - "json" + - "yaml" + inject_types: ["snippet", "reference", "source"] + prompt_template: "technical_template" + prepend_instruction: null \ No newline at end of file diff --git a/config/prompts.yaml b/config/prompts.yaml index 749ae9a..b36b12c 100644 --- a/config/prompts.yaml +++ b/config/prompts.yaml @@ -1,15 +1,20 @@ -# config/prompts.yaml — Final V2.1 -# Optimiert für Phi-3 Mini (Small Language Model) +# config/prompts.yaml — Final V2.3.1 (Multi-Personality Support) system_prompt: | - Du bist 'mindnet', das KI-Gedächtnis. + Du bist 'mindnet', mein digitaler Zwilling und strategischer Partner. - DEINE REGELN: - 1. Deine Antwort muss zu 100% auf dem KONTEXT basieren. Erfinde nichts. - 2. Wenn eine Quelle den Typ [DECISION] hat, ist sie die wichtigste Quelle für das "Warum". - 3. Nenne konkrete technische Details aus dem Text (z.B. genannte Features, Gründe), statt nur allgemein zu antworten. - 4. Antworte auf Deutsch. + DEINE IDENTITÄT: + - Du bist nicht nur eine Datenbank, sondern handelst nach MEINEN Werten und Zielen. + - Du passt deinen Stil dynamisch an die Situation an (Analytisch, Empathisch oder Technisch). + DEINE REGELN: + 1. Deine Antwort muss zu 100% auf dem bereitgestellten KONTEXT basieren. + 2. Halluziniere keine Fakten, die nicht in den Quellen stehen. + 3. Antworte auf Deutsch (außer bei Code/Fachbegriffen). + +# --------------------------------------------------------- +# 1. STANDARD: Fakten & Wissen (Intent: FACT) +# --------------------------------------------------------- rag_template: | QUELLEN (WISSEN): ========================================= @@ -20,5 +25,72 @@ rag_template: | {query} ANWEISUNG: - Beantworte die Frage basierend auf den Quellen. - Nenne die spezifischen Gründe, die im Text stehen (besonders aus [DECISION] Quellen). \ No newline at end of file + Beantworte die Frage präzise basierend auf den Quellen. + Fasse die Informationen zusammen. Sei objektiv und neutral. + +# --------------------------------------------------------- +# 2. DECISION: Strategie & Abwägung (Intent: DECISION) +# --------------------------------------------------------- +decision_template: | + KONTEXT (FAKTEN & STRATEGIE): + ========================================= + {context_str} + ========================================= + + ENTSCHEIDUNGSFRAGE: + {query} + + ANWEISUNG: + Du agierst als mein Entscheidungs-Partner. + 1. Analysiere die Faktenlage aus den Quellen. + 2. Prüfe dies hart gegen meine strategischen Notizen (Typ [VALUE], [PRINCIPLE], [GOAL]). + 3. Wäge ab: Passt die technische/faktische Lösung zu meinen Werten? + + FORMAT: + - **Analyse:** (Kurze Zusammenfassung der Fakten) + - **Abgleich:** (Gibt es Konflikte mit Werten/Zielen? Nenne die Quelle!) + - **Empfehlung:** (Klare Meinung: Ja/Nein/Vielleicht mit Begründung) + +# --------------------------------------------------------- +# 3. EMPATHY: Der Spiegel / "Ich"-Modus (Intent: EMPATHY) +# --------------------------------------------------------- +empathy_template: | + KONTEXT (ERFAHRUNGEN & GLAUBENSSÄTZE): + ========================================= + {context_str} + ========================================= + + SITUATION: + {query} + + ANWEISUNG: + Du agierst jetzt als mein empathischer Spiegel. + 1. Versuche nicht sofort, das Problem technisch zu lösen. + 2. Zeige Verständnis für die Situation basierend auf meinen eigenen Erfahrungen ([EXPERIENCE]) oder Glaubenssätzen ([BELIEF]), falls im Kontext vorhanden. + 3. Antworte in der "Ich"-Form oder "Wir"-Form. Sei unterstützend. + + TONFALL: + Ruhig, verständnisvoll, reflektiert. Keine Aufzählungszeichen, sondern fließender Text. + +# --------------------------------------------------------- +# 4. TECHNICAL: Der Coder (Intent: CODING) +# --------------------------------------------------------- +technical_template: | + KONTEXT (DOCS & SNIPPETS): + ========================================= + {context_str} + ========================================= + + TASK: + {query} + + ANWEISUNG: + Du bist Senior Developer. + 1. Ignoriere Smalltalk. Komm sofort zum Punkt. + 2. Generiere validen, performanten Code basierend auf den Quellen. + 3. Wenn Quellen fehlen, nutze dein allgemeines Programmierwissen, aber weise darauf hin. + + FORMAT: + - Kurze Erklärung des Ansatzes. + - Markdown Code-Block (Copy-Paste fertig). + - Wichtige Edge-Cases. \ No newline at end of file diff --git a/docs/Knowledge_Design_Manual.md b/docs/Knowledge_Design_Manual.md index f738615..b3f39c0 100644 --- a/docs/Knowledge_Design_Manual.md +++ b/docs/Knowledge_Design_Manual.md @@ -1,20 +1,32 @@ # mindnet v2.2 – Knowledge Design Manual **Datei:** `docs/mindnet_knowledge_design_manual_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Integrierter Stand WP01–WP05) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Integrierter Stand WP01–WP06) **Quellen:** `knowledge_design.md`, `TYPE_REGISTRY_MANUAL.md`, `chunking_strategy.md`, `mindnet_functional_architecture.md`. --- +## ⚡ Die 5 Goldenen Regeln (TL;DR) + +Damit Mindnet als dein Digitaler Zwilling funktioniert, beachte beim Schreiben diese Grundsätze: + +1. **Atomare Gedanken:** Eine Notiz = Ein Thema. Wenn du über zwei Projekte schreibst, mach zwei Notizen draus. +2. **Explizite Typen:** Setze immer den `type` im Frontmatter. Mindnet behandelt eine `decision` ("Wir machen X") völlig anders als ein `concept` ("Was ist X"). +3. **Semantische Links:** Schreibe nicht nur `[[Link]]`, sondern `[[rel:depends_on Link]]`. Sag dem System *wie* Dinge zusammenhängen. +4. **Werte & Ziele definieren:** Damit die **Decision Engine** dich beraten kann, musst du deine Kriterien (`type: value`, `type: goal`) explizit als Notizen anlegen. +5. **Emotionales Bridging:** Damit die **Empathie** funktioniert, nutze in Erfahrungsberichten (`type: experience`) emotionale Schlüsselwörter ("Krise", "Freude", "Angst"), damit der Vektor-Retriever sie bei Gefühls-Anfragen findet. + +--- + ## 1. Zweck & Scope Dieses Handbuch ist die **primäre Arbeitsanweisung** für dich als Mindmaster (Owner) und alle Autoren, die Inhalte im mindnet-Vault erstellen. ### 1.1 Zielsetzung Mindnet ist mehr als eine Dokumentablage. Es ist ein vernetztes System, das deine Persönlichkeit, Entscheidungen und Erfahrungen abbildet. -Seit Version 2.2 verfügt Mindnet über: -* **Explanation Engine:** Das System erklärt, warum es Notizen findet (über Edges). -* **RAG-Chat (KI-Zwilling):** Das System antwortet in natürlicher Sprache. **Wie** du schreibst, bestimmt, **wie schlau** die KI antwortet. +Seit Version 2.3.1 verfügt Mindnet über: +* **Hybrid Router:** Das System erkennt, ob du Fakten, Entscheidungen oder Empathie brauchst. +* **Context Intelligence:** Das System lädt je nach Situation unterschiedliche Notiz-Typen (z.B. Werte bei Entscheidungen). ### 1.2 Der Vault als „Source of Truth“ Die Markdown-Dateien in deinem Vault sind die **einzige Quelle der Wahrheit**. @@ -32,7 +44,7 @@ Jede Notiz benötigt einen YAML-Header (Frontmatter) am Dateianfang. Dieser Bloc Jede Datei muss mindestens folgende Felder enthalten, um korrekt verarbeitet zu werden: --- - id: 20251110-projekt-alpha-8a9b2c # Eindeutige Kennung + id: 20251110-projekt-alpha-8a9b2c # Eindeutige Kennung (YYYYMMDD-slug) title: Projekt Alpha # Sprechender Titel (wird in Suchergebnissen angezeigt) type: project # Steuert Verarbeitung & Vernetzung (siehe Kap. 3) status: active # Status (z.B. draft, active, archived) @@ -66,22 +78,23 @@ Diese Felder sind technisch nicht zwingend, aber für bestimmte Typen sinnvoll: ## 3. Note-Typen & Typ-Registry -Der `type` ist der wichtigste Hebel im Knowledge Design. Er verknüpft die Notiz mit der Konfiguration in `config/types.yaml`. +Der `type` ist der wichtigste Hebel im Knowledge Design. Er steuert nicht nur das Gewicht bei der Suche, sondern seit WP-06 auch, **wann** eine Notiz aktiv in den Chat geholt wird ("Strategic Retrieval"). ### 3.1 Übersicht der Kern-Typen Mindnet unterscheidet verschiedene Wissensarten. Wähle den Typ, der die **Rolle** der Notiz am besten beschreibt: -| Typ | Beschreibung & Einsatzzweck | Wichtigkeit für Chat | +| Typ | Beschreibung & Einsatzzweck | Rolle im Chat (Intent) | | :--- | :--- | :--- | -| **`concept`** | Fachbegriffe, Theorien. Zeitloses Wissen. | Mittel (Basiswissen) | -| **`project`** | Ein Vorhaben mit Ziel, Dauer und Aufgaben. | Hoch (Kontext) | -| **`experience`** | Persönliche Erfahrung, Lektion oder Erkenntnis. | Sehr Hoch (Persönlichkeit) | -| **`decision`** | Eine bewusst getroffene Entscheidung (ADR). | **Kritisch** (Begründung "Warum") | -| **`value`** | Ein persönlicher Wert oder ein Prinzip. | **Kritisch** (Moralischer Kompass) | -| **`person`** | Eine reale Person (Netzwerk, Autor). | Niedrig | -| **`journal`** | Zeitbezogener Log-Eintrag, Daily Note. | Mittel (Historie) | -| **`source`** | Externe Quelle (Buch, PDF, Artikel). | Niedrig (Faktenbasis) | +| **`concept`** | Fachbegriffe, Theorien. Zeitloses Wissen. | **FACT** (Basiswissen) | +| **`project`** | Ein Vorhaben mit Ziel, Dauer und Aufgaben. | **FACT / DECISION** (Kontext) | +| **`experience`** | Persönliche Erfahrung, Lektion oder Erkenntnis. | **EMPATHY** (Spiegelung) | +| **`decision`** | Eine bewusst getroffene Entscheidung (ADR). | **DECISION** (Begründung "Warum") | +| **`value`** | Ein persönlicher Wert oder ein Prinzip. | **DECISION** (Moralischer Kompass) | +| **`goal`** | Ein strategisches Ziel (kurz- oder langfristig). | **DECISION** (Abgleich) | +| **`person`** | Eine reale Person (Netzwerk, Autor). | **FACT** | +| **`journal`** | Zeitbezogener Log-Eintrag, Daily Note. | **FACT** (Historie) | +| **`source`** | Externe Quelle (Buch, PDF, Artikel). | **FACT** (Faktenbasis) | ### 3.2 Zusammenspiel mit `types.yaml` @@ -134,9 +147,58 @@ Für Zusammenfassungen oder "Siehe auch"-Blöcke am Ende einer Notiz. --- -## 5. Best Practices & Beispiele +## 5. Schreiben für den KI-Zwilling (New in v2.3) -### 5.1 Beispiel: Projekt-Notiz +Damit der **RAG-Chat (WP05/06)** nicht nur dumm Fakten wiedergibt, sondern dich berät, musst du "Futter" für die Decision Engine und das Empathie-Modul liefern. + +### 5.1 Futter für die Decision Engine (`DECISION`) +Das System soll abwägen: "Passt Tool X zu mir?". Dazu muss es wissen, was "Du" bist. + +**Best Practice: Werte definieren** +Erstelle Notizen mit `type: value`. + + --- + type: value + title: Prinzip: Datensparsamkeit + --- + # Prinzip: Datensparsamkeit + Wir speichern nur das Minimum an Daten. Cloud-Uploads persönlicher Daten sind verboten, es sei denn, sie sind E2E-verschlüsselt. + +**Best Practice: Ziele definieren** +Erstelle Notizen mit `type: goal`. + + --- + type: goal + title: Ziel: Unabhängigkeit 2026 + --- + # Ziel: Unabhängigkeit 2026 + Bis Ende 2026 wollen wir alle SaaS-Abos durch Self-Hosted Lösungen ersetzt haben. + +*Effekt:* Wenn du fragst "Soll ich Notion nutzen?", lädt die Engine diese beiden Notizen und antwortet: *"Nein, Notion ist SaaS und nicht E2E-verschlüsselt. Das verletzt dein Prinzip der Datensparsamkeit und dein Ziel der Unabhängigkeit."* + +### 5.2 Futter für den Empathie-Modus (`EMPATHY`) +Das System soll dich verstehen, wenn du sagst: "Alles ist grau." Dazu braucht es deine Resonanzerfahrungen. + +**Best Practice: Erfahrungen & Bridging** +Erstelle Notizen mit `type: experience`. Nutze im Text **emotionale Brückenwörter**, damit der Retriever auch bei abstrakten Gefühlen ("grau") einen Treffer landet. + + --- + type: experience + title: Erfahrung: Der Durchbruch nach der Krise + tags: [krise, hoffnung, grau, angst] + --- + # Erfahrung: Der Durchbruch nach der Krise + Es gibt Projektphasen, da wirkt alles **sinnlos** und **grau**. + Ich habe gelernt: Das ist oft das Zeichen kurz vor dem Durchbruch. + Mein Mantra in solchen Zeiten: "Einfach weitermachen, der Nebel lichtet sich." + +*Effekt:* Wenn du im Chat jammerst ("Alles ist sinnlos"), findet das System diese Notiz und spiegelt dir deine eigene Erfahrung zurück. + +--- + +## 6. Best Practices & Beispiele (Klassik) + +### 6.1 Beispiel: Projekt-Notiz Projekte profitieren von `depends_on`, um Abhängigkeiten zu klären. --- @@ -156,7 +218,7 @@ Projekte profitieren von `depends_on`, um Abhängigkeiten zu klären. ## Architektur Das Konzept basiert auf [[RAG Architecture]]. (Automatisch 'depends_on' durch Typ-Default). -### 5.2 Beispiel: Entscheidung (Decision Record) +### 6.2 Beispiel: Entscheidung (Decision Record) Entscheidungen sind hoch gewichtet (`retriever_weight: 1.0`). --- @@ -179,35 +241,15 @@ Entscheidungen sind hoch gewichtet (`retriever_weight: 1.0`). --- -## 6. Langfristige Stabilität & Virtual Schema Layer +## 7. Langfristige Stabilität & Virtual Schema Layer Mindnet ist auf Langlebigkeit ausgelegt. -### 6.1 Das "Virtual Schema" Prinzip +### 7.1 Das "Virtual Schema" Prinzip Wir vermeiden es, Logik in den Markdown-Dateien hart zu kodieren. * Statt in jeder Notiz zu schreiben `chunk_size: 500`, schreiben wir nur `type: essay`. * Wie groß ein Chunk für ein Essay ist, definieren wir in der Konfiguration (`types.yaml`). -### 6.2 Was bedeutet das für dich? +### 7.2 Was bedeutet das für dich? * Du kannst dich auf den Inhalt konzentrieren. -* Wenn wir in Zukunft (WP08) basierend auf Feedback lernen, dass "Projekte" noch wichtiger sind, ändern wir **eine Zeile** in der Konfiguration, und das gesamte System passt sich beim nächsten Import an. - ---- - -## 7. Schreiben für den KI-Zwilling (New in v2.2) - -Damit der **RAG-Chat (WP05)** gute Antworten liefert, beachte diese Regeln: - -1. **Atomare Konzepte:** - * Der Chatbot baut seine Antwort aus mehreren kleinen Text-Stücken ("Chunks") zusammen. - * Schreibe so, dass ein Absatz auch für sich allein verständlich ist. -2. **Explizite Entscheidungen:** - * Wenn du eine Meinung hast ("Tool X ist schlecht"), schreibe sie nicht in einen Nebensatz. - * Erstelle eine Notiz `type: experience` oder `decision` ("Warum Tool X nicht geeignet ist"). - * Die KI sucht gezielt nach `[DECISION]`-Typen, um "Warum"-Fragen zu beantworten. -3. **Werte definieren:** - * Erstelle Notizen mit `type: value` (z.B. "Datenschutz First"). - * Die KI nutzt diese, um bei Konflikten ("Soll ich Cloud oder Lokal nutzen?") in deinem Sinne zu argumentieren. -4. **Verlinken ist Pflicht:** - * Der Chatbot nutzt **Hybrid Search**. Er findet Notizen nur, wenn sie über Kanten verbunden sind. - * Eine isolierte Notiz (ohne Links) ist für die KI fast unsichtbar. \ No newline at end of file +* Wenn wir in Zukunft (WP08) basierend auf Feedback lernen, dass "Projekte" noch wichtiger sind, ändern wir **eine Zeile** in der Konfiguration, und das gesamte System passt sich beim nächsten Import an. \ No newline at end of file diff --git a/docs/Overview.md b/docs/Overview.md index 492761e..7a760a4 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -1,8 +1,8 @@ # Mindnet v2.2 – Overview & Einstieg **Datei:** `docs/mindnet_overview_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Post-WP05 Release) -**Version:** 2.3.0 +**Stand:** 2025-12-09 +**Status:** **FINAL** (Post-WP06 Release) +**Version:** 2.3.1 --- @@ -13,10 +13,10 @@ Anders als herkömmliche Notiz-Apps (wie Obsidian oder Evernote), die Texte nur passiv speichern, ist Mindnet ein **aktives System**: * Es **versteht** Zusammenhänge über einen Wissensgraphen. * Es **begründet** Antworten ("Warum ist das so?"). -* Es **antwortet** im Dialog als Persona (RAG-Chat), basierend auf deinen Werten. +* Es **antwortet** situativ angepasst: Mal als harter Strategieberater, mal als empathischer Spiegel. ### Die Vision -> „Ein System, das nicht nur speichert, was ich weiß, sondern auch wie ich denke.“ +> „Ein System, das nicht nur speichert, was ich weiß, sondern auch wie ich denke und fühle.“ --- @@ -39,8 +39,10 @@ Mindnet arbeitet auf drei Schichten, die aufeinander aufbauen: ### Ebene 3: Identität (Die Persönlichkeit) * **Funktion:** Interaktion und Bewertung. Das System nimmt eine Haltung ein. * **Logik:** "Ich empfehle Lösung X, weil sie unserem Wert 'Datensparsamkeit' entspricht." -* **Technik:** RAG-Chat, LLM (Phi-3), Prompt Engineering, Feedback Loop. -* **Status:** 🟢 Live (WP05). +* **Technik:** * **Intent Router:** Erkennt Absichten (Fakt vs. Gefühl vs. Entscheidung). + * **Strategic Retrieval:** Lädt gezielt Werte oder Erfahrungen nach. + * **Multi-Persona:** Passt den Tonfall an. +* **Status:** 🟢 Live (WP05–WP06). --- @@ -50,9 +52,10 @@ Der Datenfluss in Mindnet ist zyklisch ("Data Flywheel"): 1. **Input:** Du schreibst Notizen in Obsidian. 2. **Ingest:** Ein Python-Skript importiert, zerlegt (Chunking) und vernetzt (Edges) die Daten in Qdrant. -3. **Retrieval:** Bei einer Frage sucht das System semantisch (Text) und graph-basiert (Nachbarn). -4. **Generation:** Ein lokales LLM (Ollama) formuliert die Antwort, angereichert mit Kontext-Metadaten. -5. **Feedback:** Du bewertest die Antwort. Das System lernt (langfristig) daraus. +3. **Intent Recognition:** Der Router analysiert deine Frage: Willst du Fakten, Code oder Empathie? +4. **Retrieval:** Das System sucht Inhalte passend zum Intent (z.B. "Lade Erfahrungen bei Empathie"). +5. **Generation:** Ein lokales LLM (Ollama) formuliert die Antwort. +6. **Feedback:** Du bewertest die Antwort. Das System lernt (langfristig) daraus. **Tech-Stack:** * **Backend:** Python 3.12, FastAPI. @@ -88,5 +91,5 @@ Wo findest du was? ## 6. Aktueller Fokus -Wir befinden uns im Übergang von **Phase C (Persönlichkeit)** zu **Phase D (Interaktion)**. -Das "Gehirn" (WP05) ist fertig. Als Nächstes folgen die **Decision Engine (WP06)** für komplexe Entscheidungen und das **Frontend (WP10)** für bessere Usability. \ No newline at end of file +Wir haben **Phase C (Persönlichkeit)** mit WP06 (Decision Engine) abgeschlossen. +Das System kann nun strategisch denken und fühlen. Als Nächstes folgt **Phase D (Interaktion)** mit dem **Chat Interface (WP10)** für bessere Usability. \ No newline at end of file diff --git a/docs/admin_guide.md b/docs/admin_guide.md index 2c3e60a..8936df7 100644 --- a/docs/admin_guide.md +++ b/docs/admin_guide.md @@ -1,39 +1,11 @@ # Mindnet v2.2 – Admin Guide **Datei:** `docs/mindnet_admin_guide_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Inkl. RAG & LLM Ops) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Inkl. RAG, Decision Engine & LLM Ops) **Quellen:** `Handbuch.md`, `mindnet_developer_guide_v2.2.md`. > Dieses Handbuch richtet sich an **Administratoren**. Es beschreibt Installation, Konfiguration, Backup-Strategien, Monitoring und den sicheren Betrieb der Mindnet-Instanz (API + DB + LLM). ---- -
-📖 Inhaltsverzeichnis (Klicken zum Öffnen) - -- [Mindnet v2.2 – Admin Guide](#mindnet-v22--admin-guide) - - [1. Zielgruppe \& Scope](#1-zielgruppe--scope) - - [2. Initial Setup \& Installation](#2-initial-setup--installation) - - [2.1 Systemvoraussetzungen](#21-systemvoraussetzungen) - - [2.2 Installation (Code)](#22-installation-code) - - [2.3 Qdrant Setup (Docker)](#23-qdrant-setup-docker) - - [2.4 Ollama Setup (LLM Service)](#24-ollama-setup-llm-service) - - [2.5 Konfiguration (ENV)](#25-konfiguration-env) - - [2.6 Deployment via Systemd](#26-deployment-via-systemd) - - [3. Betrieb im Alltag](#3-betrieb-im-alltag) - - [3.1 Regelmäßige Importe](#31-regelmäßige-importe) - - [3.2 Health-Checks](#32-health-checks) - - [3.3 Logs \& Monitoring](#33-logs--monitoring) - - [4. Update-Prozess](#4-update-prozess) - - [5. Backup \& Restore](#5-backup--restore) - - [5.1 Vault-Backup (Priorität 1)](#51-vault-backup-priorität-1) - - [5.2 Qdrant-Snapshots (Priorität 2)](#52-qdrant-snapshots-priorität-2) - - [5.3 Log-Daten (Priorität 3)](#53-log-daten-priorität-3) - - [5.4 Notfall-Wiederherstellung (Rebuild)](#54-notfall-wiederherstellung-rebuild) - - [6. Governance \& Sicherheit](#6-governance--sicherheit) - - [6.1 Zugriffsschutz](#61-zugriffsschutz) - - [6.2 Typen-Governance](#62-typen-governance) - - --- ## 1. Zielgruppe & Scope @@ -56,6 +28,7 @@ Wir unterscheiden strikt zwischen: * Disk: SSD empfohlen für Qdrant-Performance. ### 2.2 Installation (Code) + # 1. Repository klonen git clone /home/llmadmin/mindnet cd /home/llmadmin/mindnet @@ -70,6 +43,7 @@ Wir unterscheiden strikt zwischen: ### 2.3 Qdrant Setup (Docker) Wir nutzen Qdrant als Vektor-Datenbank. Persistenz ist wichtig. + docker run -d \ --name mindnet_qdrant \ --restart always \ @@ -79,6 +53,7 @@ Wir nutzen Qdrant als Vektor-Datenbank. Persistenz ist wichtig. ### 2.4 Ollama Setup (LLM Service) Mindnet benötigt einen lokalen LLM-Server für den Chat. + # 1. Installieren (Linux Script) curl -fsSL https://ollama.com/install.sh | sh @@ -89,7 +64,7 @@ Mindnet benötigt einen lokalen LLM-Server für den Chat. curl http://localhost:11434/api/generate -d '{"model": "phi3:mini", "prompt":"Hi"}' ### 2.5 Konfiguration (ENV) -Erstelle eine `.env` Datei im Root-Verzeichnis. +Erstelle eine `.env` Datei im Root-Verzeichnis. Die neuen Settings für WP-06 (Timeout, Decision Config) sind essenziell für stabilen Betrieb auf CPUs. # Qdrant Verbindung QDRANT_URL="http://localhost:6333" @@ -97,11 +72,18 @@ Erstelle eine `.env` Datei im Root-Verzeichnis. # Mindnet Core Settings COLLECTION_PREFIX="mindnet" MINDNET_TYPES_FILE="./config/types.yaml" - MINDNET_PROMPTS_PATH="./config/prompts.yaml" - # LLM Settings + # LLM / RAG Settings MINDNET_LLM_MODEL="phi3:mini" MINDNET_OLLAMA_URL="http://127.0.0.1:11434" + + # NEU in v2.3: Config & Timeouts + # Pfad zu Prompts + MINDNET_PROMPTS_PATH="./config/prompts.yaml" + # Pfad zur Decision Engine Config + MINDNET_DECISION_CONFIG="./config/decision_engine.yaml" + # Timeout in Sekunden (300s = 5min fuer Cold Starts) + MINDNET_LLM_TIMEOUT=300.0 ### 2.6 Deployment via Systemd Mindnet wird als Systemdienst gestartet. Ollama läuft meist als eigener Dienst (`ollama.service`). @@ -120,25 +102,29 @@ Mindnet wird als Systemdienst gestartet. Ollama läuft meist als eigener Dienst Der Vault-Zustand sollte regelmäßig (z.B. stündlich per Cronjob) nach Qdrant synchronisiert werden. **Cronjob-Beispiel (stündlich):** + 0 * * * * cd /home/llmadmin/mindnet && .venv/bin/python3 -m scripts.import_markdown --vault /path/to/vault --prefix "mindnet" --apply --purge-before-upsert --sync-deletes >> ./logs/import.log 2>&1 ### 3.2 Health-Checks Prüfe regelmäßig, ob alle drei Komponenten (API, DB, LLM) laufen. **Status prüfen:** + sudo systemctl status mindnet-prod sudo systemctl status ollama **Logischer Smoke-Test:** + python3 scripts/test_retriever_smoke.py --mode hybrid --url http://localhost:8001/query ### 3.3 Logs & Monitoring * **Technische Fehler (API):** `journalctl -u mindnet-prod -f` + * Achte auf: `LLM Router Raw Output`. Hier siehst du, wie die Decision Engine entscheidet. * **LLM Fehler (Ollama):** `journalctl -u ollama -f` * **Fachliche Logs:** `data/logs/search_history.jsonl` **Troubleshooting Chat:** -* Wenn `/chat` in den Timeout läuft (>300s): Prüfe, ob `phi3:mini` geladen ist und ob der Server überlastet ist. +* Wenn `/chat` in den Timeout läuft (>300s): Prüfe `MINDNET_LLM_TIMEOUT` in `.env` und ob das Modell im RAM liegt. * Wenn `/chat` halluziniert: Prüfe `config/prompts.yaml` und ob der Import aktuell ist. --- @@ -148,14 +134,21 @@ Prüfe regelmäßig, ob alle drei Komponenten (API, DB, LLM) laufen. Wenn neue Versionen ausgerollt werden (Deployment): 1. **Code aktualisieren:** + cd /home/llmadmin/mindnet git pull origin main + 2. **Dependencies prüfen:** + source .venv/bin/activate pip install -r requirements.txt + 3. **Dienst neustarten (Zwingend!):** + sudo systemctl restart mindnet-prod + 4. **Schema-Migration (falls nötig):** + python3 -m scripts.import_markdown ... --apply --- @@ -169,6 +162,7 @@ Der Markdown-Vault ist die **Single Source of Truth**. Er muss klassisch gesiche ### 5.2 Qdrant-Snapshots (Priorität 2) Für schnelle Wiederherstellung des Suchindex. + docker stop mindnet_qdrant tar -czf qdrant_backup_$(date +%F).tar.gz ./qdrant_storage docker start mindnet_qdrant @@ -178,6 +172,7 @@ Sichere den Ordner `data/logs/`. Verlust dieser Daten bedeutet, dass das System ### 5.4 Notfall-Wiederherstellung (Rebuild) Wenn die Datenbank korrupt ist: + # 1. DB komplett leeren (Wipe) python3 -m scripts.reset_qdrant --mode wipe --prefix "mindnet" --yes # 2. Alles neu importieren diff --git a/docs/appendix.md b/docs/appendix.md index e570f93..079740c 100644 --- a/docs/appendix.md +++ b/docs/appendix.md @@ -1,7 +1,7 @@ # Mindnet v2.2 – Appendices & Referenzen **Datei:** `docs/mindnet_appendices_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Integrierter Stand WP01–WP05) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Integrierter Stand WP01–WP06) **Quellen:** `TYPE_REGISTRY_MANUAL.md`, `chunking_strategy.md`, `mindnet_technical_architecture.md`, `Handbuch.md`. > Dieses Dokument bündelt Tabellen, Schemata und technische Referenzen, die in den Prozess-Dokumenten (Playbook, Guides) den Lesefluss stören würden. @@ -10,7 +10,7 @@ ## Anhang A: Typ-Registry Referenz (Default-Werte) -Diese Tabelle zeigt die Standard-Konfiguration der `types.yaml` (Stand v2.2). +Diese Tabelle zeigt die Standard-Konfiguration der `types.yaml` (Stand v2.3.1). | Typ (`type`) | Chunk Profile | Retriever Weight | Edge Defaults (Auto-Kanten) | Beschreibung | | :--- | :--- | :--- | :--- | :--- | @@ -23,6 +23,8 @@ Diese Tabelle zeigt die Standard-Konfiguration der `types.yaml` (Stand v2.2). | **source** | `long` | 0.50 | *(keine)* | Externe Quellen (Bücher, PDFs). | | **event** | `short` | 0.60 | `related_to` | Meetings, Konferenzen. | | **value** | `medium` | 1.00 | `related_to` | Persönliche Werte/Prinzipien. | +| **goal** | `medium` | 0.95 | `depends_on` | Strategische Ziele (Neu in WP06). | +| **belief** | `medium` | 0.90 | `related_to` | Glaubenssätze (Neu in WP06). | | **default** | `medium` | 1.00 | `references` | Fallback, wenn Typ unbekannt. | --- @@ -47,9 +49,10 @@ Referenz aller implementierten Kantenarten (`kind`). ## Anhang C: Datenmodelle (JSON Payloads) -Dies sind die Felder, die effektiv in Qdrant gespeichert werden. +Diese sind die Felder, die effektiv in Qdrant gespeichert werden. ### C.1 Note Payload (`mindnet_notes`) + { "note_id": "string (keyword)", // UUIDv5 oder Slug "title": "string (text)", // Titel aus Frontmatter @@ -64,6 +67,7 @@ Dies sind die Felder, die effektiv in Qdrant gespeichert werden. } ### C.2 Chunk Payload (`mindnet_chunks`) + { "chunk_id": "string (keyword)", // Format: {note_id}#c{index} "note_id": "string (keyword)", // FK zur Note @@ -76,6 +80,7 @@ Dies sind die Felder, die effektiv in Qdrant gespeichert werden. } ### C.3 Edge Payload (`mindnet_edges`) + { "edge_id": "string (keyword)", // Deterministischer Hash "source_id": "string (keyword)", // Chunk-ID (Start) @@ -101,8 +106,10 @@ Diese Variablen steuern das Verhalten der Skripte und Container. | `MINDNET_TYPES_FILE` | `config/types.yaml` | Pfad zur Typ-Registry. | | `MINDNET_RETRIEVER_CONFIG`| `config/retriever.yaml`| Pfad zur Scoring-Konfiguration. | | `MINDNET_PROMPTS_PATH` | `config/prompts.yaml` | Pfad zu LLM-Prompts (Neu in v2.2). | +| `MINDNET_DECISION_CONFIG` | `config/decision_engine.yaml` | Pfad zur Router-Config (Neu in v2.3). | | `MINDNET_LLM_MODEL` | `phi3:mini` | Name des Ollama-Modells (Neu in v2.2). | | `MINDNET_OLLAMA_URL` | `http://127.0.0.1:11434`| URL zum LLM-Server (Neu in v2.2). | +| `MINDNET_LLM_TIMEOUT` | `120.0` | Timeout für Ollama (Erhöhen auf 300.0 für CPU). | | `MINDNET_HASH_COMPARE` | `Body` | Vergleichsmodus für Import (`Body`, `Frontmatter`, `Full`). | | `MINDNET_HASH_SOURCE` | `parsed` | Quelle für Hash (`parsed`, `raw`, `file`). | | `VECTOR_DIM` | `384` | Dimension der Embeddings (Modellabhängig). | @@ -112,19 +119,15 @@ Diese Variablen steuern das Verhalten der Skripte und Container. ## Anhang E: Glossar * **Callout-Edge:** Kante via `> [!edge]`. -* **Chunking:** Zerlegung von Notizen in kleinere Einheiten. -* **Confidence:** Vertrauenswürdigkeit einer Kante (0.0-1.0). +* **Decision Engine:** Komponente, die den Intent prüft und Strategien wählt (WP06). * **Explanation Layer:** Komponente, die Scores und Graphen als Begründung liefert. -* **Feedback Loop:** Prozess des Loggens und Auswertens von User-Reaktionen. -* **Idempotenz:** Mehrfache Ausführung liefert gleiches Ergebnis. -* **Inline-Edge:** Kante via `[[rel:type Ziel]]`. +* **Hybrid Router:** Kombination aus Keyword-Matching und LLM-Klassifizierung für Intents. * **RAG (Retrieval Augmented Generation):** Kombination aus Suche und Text-Generierung. -* **Retriever:** Suchmaschine (FastAPI). -* **Vault:** Ordner mit Markdown-Dateien. +* **Strategic Retrieval:** Gezieltes Nachladen von Werten (`value`) bei Entscheidungfragen. --- -## Anhang F: Workpackage Status (v2.3.0) +## Anhang F: Workpackage Status (v2.3.1) Aktueller Implementierungsstand der Module. @@ -137,6 +140,6 @@ Aktueller Implementierungsstand der Module. | **WP04b**| Explanation Layer | 🟢 Live | API liefert Reasons & Breakdown. | | **WP04c**| Feedback Loop | 🟢 Live | Logging (JSONL) & Traceability aktiv. | | **WP05** | Persönlichkeit / Chat | 🟢 Live | RAG-Chat mit Context Enrichment. | -| **WP06** | Decision Engine | 🟡 Geplant | Nächster Schritt (Logik). | +| **WP06** | Decision Engine | 🟢 Live | Hybrid Router, Strategic Retrieval, Multi-Persona. | | **WP08** | Self-Tuning | 🔴 Geplant | Auto-Adjustment der Gewichte. | | **WP10** | Chat Interface | 🟡 Geplant | Nächster Schritt (Frontend). | \ No newline at end of file diff --git a/docs/CHANGELOG_TYPE_REGISTRY.md b/docs/archiv/CHANGELOG_TYPE_REGISTRY.md similarity index 100% rename from docs/CHANGELOG_TYPE_REGISTRY.md rename to docs/archiv/CHANGELOG_TYPE_REGISTRY.md diff --git a/docs/Handbuch.md b/docs/archiv/Handbuch.md similarity index 100% rename from docs/Handbuch.md rename to docs/archiv/Handbuch.md diff --git a/docs/TYPE_REGISTRY_MANUAL.md b/docs/archiv/TYPE_REGISTRY_MANUAL.md similarity index 100% rename from docs/TYPE_REGISTRY_MANUAL.md rename to docs/archiv/TYPE_REGISTRY_MANUAL.md diff --git a/docs/chunking_strategy.md b/docs/archiv/chunking_strategy.md similarity index 100% rename from docs/chunking_strategy.md rename to docs/archiv/chunking_strategy.md diff --git a/docs/docs_mindnet_retriever.md b/docs/archiv/docs_mindnet_retriever.md similarity index 100% rename from docs/docs_mindnet_retriever.md rename to docs/archiv/docs_mindnet_retriever.md diff --git a/docs/archiv/knowledge_design.md b/docs/archiv/knowledge_design.md new file mode 100644 index 0000000..b3f39c0 --- /dev/null +++ b/docs/archiv/knowledge_design.md @@ -0,0 +1,255 @@ +# mindnet v2.2 – Knowledge Design Manual +**Datei:** `docs/mindnet_knowledge_design_manual_v2.2.md` +**Stand:** 2025-12-09 +**Status:** **FINAL** (Integrierter Stand WP01–WP06) +**Quellen:** `knowledge_design.md`, `TYPE_REGISTRY_MANUAL.md`, `chunking_strategy.md`, `mindnet_functional_architecture.md`. + +--- + +## ⚡ Die 5 Goldenen Regeln (TL;DR) + +Damit Mindnet als dein Digitaler Zwilling funktioniert, beachte beim Schreiben diese Grundsätze: + +1. **Atomare Gedanken:** Eine Notiz = Ein Thema. Wenn du über zwei Projekte schreibst, mach zwei Notizen draus. +2. **Explizite Typen:** Setze immer den `type` im Frontmatter. Mindnet behandelt eine `decision` ("Wir machen X") völlig anders als ein `concept` ("Was ist X"). +3. **Semantische Links:** Schreibe nicht nur `[[Link]]`, sondern `[[rel:depends_on Link]]`. Sag dem System *wie* Dinge zusammenhängen. +4. **Werte & Ziele definieren:** Damit die **Decision Engine** dich beraten kann, musst du deine Kriterien (`type: value`, `type: goal`) explizit als Notizen anlegen. +5. **Emotionales Bridging:** Damit die **Empathie** funktioniert, nutze in Erfahrungsberichten (`type: experience`) emotionale Schlüsselwörter ("Krise", "Freude", "Angst"), damit der Vektor-Retriever sie bei Gefühls-Anfragen findet. + +--- + +## 1. Zweck & Scope + +Dieses Handbuch ist die **primäre Arbeitsanweisung** für dich als Mindmaster (Owner) und alle Autoren, die Inhalte im mindnet-Vault erstellen. + +### 1.1 Zielsetzung +Mindnet ist mehr als eine Dokumentablage. Es ist ein vernetztes System, das deine Persönlichkeit, Entscheidungen und Erfahrungen abbildet. +Seit Version 2.3.1 verfügt Mindnet über: +* **Hybrid Router:** Das System erkennt, ob du Fakten, Entscheidungen oder Empathie brauchst. +* **Context Intelligence:** Das System lädt je nach Situation unterschiedliche Notiz-Typen (z.B. Werte bei Entscheidungen). + +### 1.2 Der Vault als „Source of Truth“ +Die Markdown-Dateien in deinem Vault sind die **einzige Quelle der Wahrheit**. +* Mindnet importiert diesen Zustand deterministisch in die Datenbank (Qdrant). +* Änderungen an IDs, Typen oder Inhalten müssen **immer** im Markdown erfolgen, niemals direkt in der Datenbank. +* Was nicht im Markdown steht (z. B. implizites Wissen im Kopf), existiert für das System nicht. + +--- + +## 2. Note-Struktur & Frontmatter + +Jede Notiz benötigt einen YAML-Header (Frontmatter) am Dateianfang. Dieser Block macht die Notiz maschinenlesbar. + +### 2.1 Pflichtfelder +Jede Datei muss mindestens folgende Felder enthalten, um korrekt verarbeitet zu werden: + + --- + id: 20251110-projekt-alpha-8a9b2c # Eindeutige Kennung (YYYYMMDD-slug) + title: Projekt Alpha # Sprechender Titel (wird in Suchergebnissen angezeigt) + type: project # Steuert Verarbeitung & Vernetzung (siehe Kap. 3) + status: active # Status (z.B. draft, active, archived) + created: 2025-11-10 # Erstellungsdatum (ISO 8601 oder YYYY-MM-DD) + updated: 2025-12-07 # Letzte Änderung + tags: [ki, entwicklung] # Taxonomie für Filterung + --- + +### 2.2 Optionale Felder +Diese Felder sind technisch nicht zwingend, aber für bestimmte Typen sinnvoll: + + lang: de # Sprache (Default: de) + aliases: [Alpha Projekt, Project A] # Synonyme für die Suche + visibility: internal # internal (default), public, private + +> **Hinweis:** Felder wie `retriever_weight` oder `chunk_profile` sollten **nicht** mehr manuell im Frontmatter gesetzt werden. Diese werden zentral über den `type` gesteuert (siehe Kap. 3), um die Wartbarkeit zu sichern. + +### 2.3 Empfehlungen für IDs und Pfade + +**Die ID (Identifikator):** +* Muss global eindeutig und **stabil** sein. +* Darf sich nicht ändern, wenn die Datei umbenannt oder verschoben wird. +* **Empfehlung:** `YYYYMMDD-slug-hash` (z. B. `20231027-vektor-db-a1b2`). Dies garantiert Eindeutigkeit und Chronologie. + +**Dateinamen & Pfade:** +* Pfade dienen der menschlichen Ordnung (Ordnerstruktur), sind für Mindnet aber sekundär. +* Dateinamen sollten dem Titel entsprechen (`Projekt Alpha.md`) oder dem Slug (`projekt-alpha.md`). +* Sonderzeichen vermeiden (außer Bindestrich und Unterstrich). + +--- + +## 3. Note-Typen & Typ-Registry + +Der `type` ist der wichtigste Hebel im Knowledge Design. Er steuert nicht nur das Gewicht bei der Suche, sondern seit WP-06 auch, **wann** eine Notiz aktiv in den Chat geholt wird ("Strategic Retrieval"). + +### 3.1 Übersicht der Kern-Typen + +Mindnet unterscheidet verschiedene Wissensarten. Wähle den Typ, der die **Rolle** der Notiz am besten beschreibt: + +| Typ | Beschreibung & Einsatzzweck | Rolle im Chat (Intent) | +| :--- | :--- | :--- | +| **`concept`** | Fachbegriffe, Theorien. Zeitloses Wissen. | **FACT** (Basiswissen) | +| **`project`** | Ein Vorhaben mit Ziel, Dauer und Aufgaben. | **FACT / DECISION** (Kontext) | +| **`experience`** | Persönliche Erfahrung, Lektion oder Erkenntnis. | **EMPATHY** (Spiegelung) | +| **`decision`** | Eine bewusst getroffene Entscheidung (ADR). | **DECISION** (Begründung "Warum") | +| **`value`** | Ein persönlicher Wert oder ein Prinzip. | **DECISION** (Moralischer Kompass) | +| **`goal`** | Ein strategisches Ziel (kurz- oder langfristig). | **DECISION** (Abgleich) | +| **`person`** | Eine reale Person (Netzwerk, Autor). | **FACT** | +| **`journal`** | Zeitbezogener Log-Eintrag, Daily Note. | **FACT** (Historie) | +| **`source`** | Externe Quelle (Buch, PDF, Artikel). | **FACT** (Faktenbasis) | + +### 3.2 Zusammenspiel mit `types.yaml` + +Der `type` steuert im Hintergrund drei technische Mechanismen: + +1. **`retriever_weight` (Wichtigkeit):** + * Ein `concept` (0.6) wiegt weniger als ein `project` (0.97) oder eine `decision` (1.0). + * **Warum?** Bei einer Suche nach "Datenbank" soll Mindnet bevorzugt deine *Entscheidung* ("Warum wir X nutzen") anzeigen. +2. **`chunk_profile` (Textzerlegung):** + * `journal` (short): Wird fein zerlegt. + * `project` (long): Längere Kontext-Fenster. +3. **`edge_defaults` (Automatische Vernetzung):** + * Mindnet ergänzt automatisch Kanten. + * Beispiel: Ein Link in einem `project` wird automatisch als `depends_on` (Abhängigkeit) interpretiert. + +--- + +## 4. Edges & Referenzen in Notes + +Um aus isolierten Dateien ein **Netzwerk** zu machen, nutzen wir Verlinkungen. In Version 2.2 sind diese Verlinkungen die Basis für den **Hybrid Retriever** (Suche über Nachbarn). + +### 4.1 Wikilinks (Die Basis-Referenz) +Der klassische Obsidian-Link. + + Wir nutzen [[Qdrant]] als Vektordatenbank. + +* **Bedeutung:** "Diese Notiz erwähnt Qdrant." +* **Edge-Typ:** `references` + +### 4.2 Inline-Relationen (Semantische Verknüpfung) +Dies ist die **mächtigste** Methode. Du sagst dem System explizit, **wie** Dinge zusammenhängen. + + Daher [[rel:depends_on Qdrant]]. + Dieses Konzept ist [[rel:similar_to Pinecone]]. + +* **Syntax:** `[[rel:RELATION ZIEL]]`. +* **Gültige Relationen:** + * `depends_on`: Hängt ab von / Benötigt. (Trigger für hohe Graph-Relevanz). + * `similar_to`: Ähnelt / Ist vergleichbar mit. + * `related_to`: Hat zu tun mit (allgemein). + * `caused_by`: Wurde verursacht durch. + * `solves`: Löst (Problem). + +### 4.3 Callout-Edges (Kuratierte Listen) +Für Zusammenfassungen oder "Siehe auch"-Blöcke am Ende einer Notiz. + + > [!edge] related_to: [[Vector Embeddings]] [[AI Agents]] + +* **Funktion:** Erzeugt `related_to`-Kanten zu allen genannten Zielen in dieser Zeile. + +--- + +## 5. Schreiben für den KI-Zwilling (New in v2.3) + +Damit der **RAG-Chat (WP05/06)** nicht nur dumm Fakten wiedergibt, sondern dich berät, musst du "Futter" für die Decision Engine und das Empathie-Modul liefern. + +### 5.1 Futter für die Decision Engine (`DECISION`) +Das System soll abwägen: "Passt Tool X zu mir?". Dazu muss es wissen, was "Du" bist. + +**Best Practice: Werte definieren** +Erstelle Notizen mit `type: value`. + + --- + type: value + title: Prinzip: Datensparsamkeit + --- + # Prinzip: Datensparsamkeit + Wir speichern nur das Minimum an Daten. Cloud-Uploads persönlicher Daten sind verboten, es sei denn, sie sind E2E-verschlüsselt. + +**Best Practice: Ziele definieren** +Erstelle Notizen mit `type: goal`. + + --- + type: goal + title: Ziel: Unabhängigkeit 2026 + --- + # Ziel: Unabhängigkeit 2026 + Bis Ende 2026 wollen wir alle SaaS-Abos durch Self-Hosted Lösungen ersetzt haben. + +*Effekt:* Wenn du fragst "Soll ich Notion nutzen?", lädt die Engine diese beiden Notizen und antwortet: *"Nein, Notion ist SaaS und nicht E2E-verschlüsselt. Das verletzt dein Prinzip der Datensparsamkeit und dein Ziel der Unabhängigkeit."* + +### 5.2 Futter für den Empathie-Modus (`EMPATHY`) +Das System soll dich verstehen, wenn du sagst: "Alles ist grau." Dazu braucht es deine Resonanzerfahrungen. + +**Best Practice: Erfahrungen & Bridging** +Erstelle Notizen mit `type: experience`. Nutze im Text **emotionale Brückenwörter**, damit der Retriever auch bei abstrakten Gefühlen ("grau") einen Treffer landet. + + --- + type: experience + title: Erfahrung: Der Durchbruch nach der Krise + tags: [krise, hoffnung, grau, angst] + --- + # Erfahrung: Der Durchbruch nach der Krise + Es gibt Projektphasen, da wirkt alles **sinnlos** und **grau**. + Ich habe gelernt: Das ist oft das Zeichen kurz vor dem Durchbruch. + Mein Mantra in solchen Zeiten: "Einfach weitermachen, der Nebel lichtet sich." + +*Effekt:* Wenn du im Chat jammerst ("Alles ist sinnlos"), findet das System diese Notiz und spiegelt dir deine eigene Erfahrung zurück. + +--- + +## 6. Best Practices & Beispiele (Klassik) + +### 6.1 Beispiel: Projekt-Notiz +Projekte profitieren von `depends_on`, um Abhängigkeiten zu klären. + + --- + id: 20251115-proj-mindnet + title: Mindnet Implementierung + type: project + status: active + --- + + # Mindnet Implementierung + + Wir bauen ein persönliches Wissensnetz. + + ## Tech Stack + Wir nutzen [[rel:depends_on Qdrant]] für die Vektorsuche und [[rel:depends_on FastAPI]] für das Backend. + + ## Architektur + Das Konzept basiert auf [[RAG Architecture]]. (Automatisch 'depends_on' durch Typ-Default). + +### 6.2 Beispiel: Entscheidung (Decision Record) +Entscheidungen sind hoch gewichtet (`retriever_weight: 1.0`). + + --- + id: 20251120-adr-vektordb + title: ADR: Wahl von Qdrant + type: decision + status: final + tags: [architektur, db] + --- + + # Entscheidung: Qdrant + + Wir haben uns für Qdrant entschieden. + + ## Alternativen + Wir haben auch [[rel:similar_to Pinecone]] und [[rel:similar_to Weaviate]] betrachtet. + + ## Begründung + Qdrant erlaubt lokalen Betrieb und [[rel:solves Payload Filtering Requirements]]. + +--- + +## 7. Langfristige Stabilität & Virtual Schema Layer + +Mindnet ist auf Langlebigkeit ausgelegt. + +### 7.1 Das "Virtual Schema" Prinzip +Wir vermeiden es, Logik in den Markdown-Dateien hart zu kodieren. +* Statt in jeder Notiz zu schreiben `chunk_size: 500`, schreiben wir nur `type: essay`. +* Wie groß ein Chunk für ein Essay ist, definieren wir in der Konfiguration (`types.yaml`). + +### 7.2 Was bedeutet das für dich? +* Du kannst dich auf den Inhalt konzentrieren. +* Wenn wir in Zukunft (WP08) basierend auf Feedback lernen, dass "Projekte" noch wichtiger sind, ändern wir **eine Zeile** in der Konfiguration, und das gesamte System passt sich beim nächsten Import an. \ No newline at end of file diff --git a/docs/mindnet_v2_implementation_playbook.md b/docs/archiv/mindnet_v2_implementation_playbook.md similarity index 100% rename from docs/mindnet_v2_implementation_playbook.md rename to docs/archiv/mindnet_v2_implementation_playbook.md diff --git a/docs/wp04_retriever_scoring.md b/docs/archiv/wp04_retriever_scoring.md similarity index 100% rename from docs/wp04_retriever_scoring.md rename to docs/archiv/wp04_retriever_scoring.md diff --git a/docs/dev_workflow.md b/docs/dev_workflow.md index 6d1cf9d..a1362d6 100644 --- a/docs/dev_workflow.md +++ b/docs/dev_workflow.md @@ -1,6 +1,6 @@ # Mindnet v2.2 – Entwickler-Workflow **Datei:** `DEV_WORKFLOW.md` -**Stand:** 2025-12-08 (Aktualisiert: Systemd Services & Sync-First) +**Stand:** 2025-12-09 (Aktualisiert: LLM Timeouts & Systemd) Dieses Handbuch beschreibt den Entwicklungszyklus zwischen **Windows PC** (IDE), **Raspberry Pi** (Gitea) und **Beelink** (Runtime/Server). @@ -31,14 +31,14 @@ Hier erstellst du die neue Funktion in einer sicheren Umgebung. 2. **Branch erstellen:** * Klicke wieder unten links auf `main`. * Wähle `+ Create new branch...`. - * Gib den Namen ein: `feature/was-ich-tue` (z.B. `feature/wp05-chat`). + * Gib den Namen ein: `feature/was-ich-tue` (z.B. `feature/wp06-decision`). * Drücke **Enter**. 3. **Sicherheits-Check:** * Steht unten links jetzt dein Feature-Branch? **Nur dann darfst du Code ändern!** 4. **Coden:** - * Nimm deine Änderungen vor. + * Nimm deine Änderungen vor (z.B. neue YAML-Configs). 5. **Sichern & Hochladen:** * **Source Control** Icon (Gabel-Symbol) -> Nachricht eingeben -> **Commit**. @@ -60,7 +60,7 @@ Hier prüfst du, ob dein neuer Code auf dem echten Server läuft. ```bash git fetch # Tipp: 'git branch -r' zeigt alle verfügbaren Branches an - git checkout feature/wp05-chat + git checkout feature/wp06-decision git pull ``` @@ -101,8 +101,8 @@ Hier prüfst du, ob dein neuer Code auf dem echten Server läuft. 6. **Validieren:** Führe deine Tests in einem **zweiten Terminal** aus: ```bash - # Beispiel für Smoke-Test gegen Dev-Port - python3 tests/test_chat_smoke.py --url http://localhost:8002/chat + # Beispiel für Decision Engine Test + python tests/test_wp06_decision.py -p 8002 -q "Soll ich...?" ``` --- @@ -148,9 +148,8 @@ Damit das Chaos nicht wächst, löschen wir den fertigen Branch. cd ~/mindnet_dev git checkout main git pull - git branch -d feature/wp05-chat + git branch -d feature/wp06-decision ``` - *Hinweis: Der `mindnet-dev` Service läuft jetzt mit dem Code von `main`, was okay ist.* 3. **VS Code:** * Auf `main` wechseln. * Sync drücken. @@ -164,24 +163,24 @@ Damit das Chaos nicht wächst, löschen wir den fertigen Branch. | :--- | :--- | :--- | | **VS Code** | `Sync (auf main)` | **WICHTIG:** Holt neuesten Code vom Server. | | **Beelink** | `git fetch` | Aktualisiert Liste der Remote-Branches. | -| **Beelink** | `git checkout ` | Wechsle Branch. | -| **Beelink** | `git pull` | Aktualisiere aktuellen Branch. | | **Beelink** | `sudo systemctl restart mindnet-dev` | **Neustart Dev-Server (Port 8002).** | -| **Beelink** | `sudo systemctl stop mindnet-dev` | **Stoppt Dev-Server (macht Port frei).** | -| **Beelink** | `sudo systemctl restart mindnet-prod`| **Neustart Prod-Server (Port 8001).** | | **Beelink** | `journalctl -u mindnet-dev -f` | **Live-Logs vom Dev-Server sehen.** | --- ## 4. Troubleshooting -**"Port 8002 already in use"** -* Du willst `uvicorn` manuell starten, aber der Service läuft noch. -* **Lösung:** `sudo systemctl stop mindnet-dev` - -**"Hilfe, in meinem neuen Branch fehlen Dateien!"** -* Das passiert, wenn du beim Erstellen nicht aktuell warst. +**"Read timed out (120s)" / 500 Error beim Chat** +* **Ursache:** Das LLM (Ollama) braucht zu lange zum Laden ("Cold Start"). * **Lösung:** - ```bash - git checkout feature/mein-kaputter-branch - git merge main \ No newline at end of file + 1. Erhöhe in `.env` den Wert: `MINDNET_LLM_TIMEOUT=300.0`. + 2. Starte den Server neu (`sudo systemctl restart mindnet-dev`). + 3. Stelle sicher, dass dein Test-Skript (Client) auch ein hohes Timeout hat. + +**"Port 8002 already in use"** +* **Ursache:** Du willst `uvicorn` manuell starten, aber der Service läuft noch. +* **Lösung:** `sudo systemctl stop mindnet-dev`. + +**"UnicodeDecodeError in .env"** +* **Ursache:** Umlaute oder Sonderzeichen in der `.env` Datei. +* **Lösung:** `.env` bereinigen (nur ASCII nutzen) und sicherstellen, dass sie UTF-8 ohne BOM ist. \ No newline at end of file diff --git a/docs/developer_guide.md b/docs/developer_guide.md index 7006039..a6758ce 100644 --- a/docs/developer_guide.md +++ b/docs/developer_guide.md @@ -1,15 +1,37 @@ # 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) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Inkl. RAG, Decision Engine & 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. --- +- [Mindnet v2.2 – Developer Guide](#mindnet-v22--developer-guide) + - [1. Projektstruktur (Post-WP06)](#1-projektstruktur-post-wp06) + - [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 (Systemd bevorzugt)](#24-dienste-starten-systemd-bevorzugt) + - [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) + - [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) + - [Fazit](#fazit) + - [6. Nützliche Einzeiler](#6-nützliche-einzeiler) -## 1. Projektstruktur (Aktualisiert) +--- + +## 1. Projektstruktur (Post-WP06) Der Code ist modular in `app` (Logik), `scripts` (CLI) und `config` (Steuerung) getrennt. @@ -25,17 +47,18 @@ Der Code ist modular in `app` (Logik), `scripts` (CLI) und `config` (Steuerung) │ │ └── dto.py # Zentrale DTO-Definition │ ├── routers/ # FastAPI Endpoints │ │ ├── query.py # Suche - │ │ ├── chat.py # RAG-Chat (WP05) + │ │ ├── chat.py # Hybrid Router & Decision Engine (WP06) │ │ ├── feedback.py # Feedback (WP04c) │ │ └── ... │ ├── services/ # Interne & Externe Dienste - │ │ ├── llm_service.py # Ollama Client (WP05) + │ │ ├── llm_service.py # Ollama Client (Mit Timeout & Raw-Mode) │ │ ├── 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) + │ ├── prompts.yaml # LLM Prompts & RAG Templates (WP06) + │ ├── decision_engine.yaml # Router-Strategien (WP06) │ └── retriever.yaml # Scoring-Regeln & Kantengewichte ├── data/ │ └── logs/ # Lokale Logs (search_history.jsonl, feedback.jsonl) @@ -71,7 +94,7 @@ Der Code ist modular in `app` (Logik), `scripts` (CLI) und `config` (Steuerung) ollama pull phi3:mini ### 2.3 Konfiguration (Environment) -Erstelle eine `.env` Datei im Root-Verzeichnis. +Erstelle eine `.env` Datei im Root-Verzeichnis. Die Timeout-Settings sind kritisch für CPU-Inference. # Qdrant Verbindung QDRANT_URL="http://localhost:6333" @@ -82,10 +105,12 @@ Erstelle eine `.env` Datei im Root-Verzeichnis. MINDNET_TYPES_FILE="./config/types.yaml" MINDNET_RETRIEVER_CONFIG="./config/retriever.yaml" - # LLM / RAG Settings (WP05) + # LLM / RAG Settings (WP06) MINDNET_LLM_MODEL="phi3:mini" MINDNET_OLLAMA_URL="http://127.0.0.1:11434" + MINDNET_LLM_TIMEOUT=300.0 MINDNET_PROMPTS_PATH="./config/prompts.yaml" + MINDNET_DECISION_CONFIG="./config/decision_engine.yaml" # Import-Strategie MINDNET_HASH_COMPARE="Body" @@ -97,7 +122,7 @@ Auf dem Entwicklungsserver (Beelink) nutzen wir Systemd. # Starten / Neustarten sudo systemctl restart mindnet-dev - # Logs prüfen + # Logs prüfen (Wichtig für LLM Debugging) journalctl -u mindnet-dev -f Falls du lokal auf Windows entwickelst: @@ -119,14 +144,16 @@ Dies ist das komplexeste Modul. * **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.2 Der Hybrid Router (`app.routers.chat`) +Hier liegt die Logik für Intent Detection (WP06). +* **Logic:** `_classify_intent` prüft zuerst Keywords (Fast Path) und fällt auf `llm_service.generate_raw_response` zurück (Slow Path), wenn konfiguriert. +* **Config:** Gesteuert durch `decision_engine.yaml`. +* **Erweiterung:** Um neue Intents hinzuzufügen, editiere nur die YAML, nicht den Python-Code (Late Binding). -### 3.3 Der Retriever & Chat (`app.core.retriever` / `app.routers.chat`) -Hier passiert das Scoring und die Generation. +### 3.3 Der Retriever (`app.core.retriever`) +Hier passiert das Scoring. * **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). +* **Strategic Retrieval:** In `chat.py` wird der Retriever *zweimal* aufgerufen, wenn ein Intent (z.B. `DECISION`) eine Injection (`value`) erfordert. --- @@ -157,11 +184,15 @@ 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 + # 2. Decision Engine Test (WP06) + # Prüft Intent, Retrieval und Reasoning (mit Timeout-Handling) + python tests/test_wp06_decision.py -p 8002 -e DECISION -q "Soll ich X tun?" - # 3. Feedback Test (WP04c) + # 3. Empathy Test (WP06) + # Prüft LLM-Router Fallback + python tests/test_wp06_decision.py -p 8002 -e EMPATHY -q "Alles ist grau" + + # 4. Feedback Test (WP04c) python tests/test_feedback_smoke.py --url http://localhost:8002/query --- @@ -180,19 +211,20 @@ Definiere die "Physik" des Typs (Import-Regeln und Basis-Wichtigkeit). 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. Strategie-Ebene (`config/decision_engine.yaml`)** +Damit dieser Typ aktiv geladen wird, musst du ihn einer Strategie zuordnen. -**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. + 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, was `[RISK]` bedeutet. Ergänze den `system_prompt`: +Erkläre dem LLM im Template, was es damit tun soll. - system_prompt: | + decision_template: | ... - REGELN FÜR TYPEN: - - [RISK]: Warnung! Wenn ein [RISK] im Kontext ist, weise den User darauf hin. + - Prüfe auf [RISK]: Wenn vorhanden, warne mich davor! ### B. Workflow: Neue Beziehungen (Edges) nutzen (z. B. `beeinflusst_von`) @@ -203,30 +235,17 @@ Du musst dem System keinen neuen Edge-Typ "beibringen" (Schema-less). Du nutzt i 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. +Standardmäßig werden alle expliziten Kanten gleich behandelt. Wenn Kausalität wichtiger ist als Ähnlichkeit, konfiguriere 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). +* **Config:** Liefert die Strategie (Router & Weights). * **Prompt:** Liefert die Interpretation. --- @@ -241,6 +260,6 @@ Nur wenn **Daten** (Vault), **Physik** (Config) und **Semantik** (Prompt) zusamm python3 tests/inspect_one_note.py --file ./vault/MeinFile.md -**Live-Logs sehen (Beelink):** +**Live-Logs sehen (Beelink) - inkl. LLM Thoughts:** journalctl -u mindnet-dev -f \ No newline at end of file diff --git a/docs/knowledge_design.md b/docs/knowledge_design.md deleted file mode 100644 index 615c8d9..0000000 --- a/docs/knowledge_design.md +++ /dev/null @@ -1,216 +0,0 @@ -# mindnet – Knowledge Design -**Version:** 1.5.0 (aktualisiert 2025-11-09) - -> Dieses Dokument beschreibt das Ziel, die Architektur, die Datenmodelle sowie die Regeln und Prozesse für den Aufbau von **mindnet** – einem persönlichen, lokal betriebenen Wissensnetz, das auf Markdown-Quellen, Graph-Beziehungen und Vektor-Suche basiert. Es soll die Persönlichkeit, Werte und Erfahrungen des Besitzers widerspiegeln und künftig Antworten generieren, die diese Perspektive authentisch berücksichtigen. - ---- - -## 1. Ziel von mindnet - -**1.1 Zweck** -- mindnet dient als persönliches Wissensnetz, das Erfahrungen, Werte, Prinzipien, Ziele und prägenden Ereignisse langfristig strukturiert. -- Es ermöglicht spätere Einsichten in Entscheidungen und Entwicklungen und kann in Zukunft für die Familie (z. B. Kinder) eine nachvollziehbare Quelle sein. - -**1.2 Leitidee** -- Statt einer reinen Dokumentablage wird Wissen durch **Knoten (Notes/Chunks)** und **Kanten (Edges)** vernetzt. -- Antworten sollen **persönlich** kontextualisiert werden (Perspektive, Konditionierung, Persönlichkeit). - -**1.3 Langfristigkeit** -- Stabiler, zukunftsfähiger Entwurf; spätere Massenmigrationen sollen vermieden werden. -- Architektur unterstützt schrittweise Erweiterung (neue Quellen, neue Agenten, neue Regeln). - ---- - -## 2. Zielarchitektur (High Level) - -- **Datenquellen:** Markdown-Vault (Obsidian-kompatibel), perspektivisch weitere Quellen (MediaWiki, PDFs, Web-Exporte, E-Mail-Auszüge). -- **Import-Pipeline:** Parser → Frontmatter/Body → Chunking → Embedding → Qdrant (Notes/Chunks/Edges). -- **Speicher:** Qdrant (Vektoren + Payload + Textindex), Dateien bleiben im Filesystem (Quelle ist Referenz). -- **Graph-Schicht:** Edges explizit modelliert (Typ, Richtung, Evidenz, Confidence); optionale abgeleitete Edges per Batch-Job. -- **Retriever/Composer:** Hybrid-Retrieval (Vektor + Filter + optional Volltext), Komposition zu Antwortkandidaten. -- **Erklärbarkeit:** Begründungspfade (Top-Chunks, Graph-Kette, Provenienz). -- **Schnittstellen:** REST/CLI, n8n-Glue, lokale LLM-Anbindung (Ollama). - ---- - -## 3. Collections in Qdrant - -- `mindnet_notes` – Note-Metadaten (id, title, type, path, timestamps, tags, …). -- `mindnet_chunks` – inhaltstragende Segmente inkl. Vektoren und Textindex. -- `mindnet_edges` – Beziehungen (src/dst, relation, direction, evidence, confidence, …). -- (optional) `mindnet_people` – strukturierte Personenobjekte (Eigen-/Fremdbezug). - ---- - -## 4. Identitäten & IDs - -- **Deterministische IDs** für Notes (z. B. Namespace-basierte UUIDv5) und stabile, ableitbare IDs für Chunks/Edges. -- ID-Stabilität ist Voraussetzung für Idempotenz (Re-Imports ohne Duplikate). - ---- - -## 5. Frontmatter & Typen - -- Pflichtfelder: `id`, `title`, `type`, `created`, `updated`, `tags`, `source_path`. -- Note-Typen (Auszug): `experience`, `principle`, `value`, `goal`, `role`, `persona`, `plan`, `project`, `journal`, `reference`, `translation`. -- **types.yaml** definiert Regeln/Defaults je Typ und für Relationstypen (siehe Abschnitt 10). - ---- - -## 6. Chunking-Strategie - -- Satz- bis Absatz-Chunks, moderate Überlappung; Meta-Felder verweisen auf Note/Quelle. -- Named Vectors (z. B. `content`, optional `title`, `tags`) ermöglichen hybride Scores. - ---- - -## 7. Embeddings & Vektoren - -- Einheitliche Metrik (cosine), reproduzierbares Embedding-Setup. -- Konsistenz über Zeit durch Versionsfeld (`embedding_model`, `embedding_version`). - ---- - -## 8. Volltext & Filter - -- Textindex auf `mindnet_chunks.body` für exakte Term/Operator-Queries. -- Payload-Filter zur schnellen Einschränkung (tags, types, time-buckets, visibility u. a.). - ---- - -## 9. Edges – Beziehungen - -- **Explizit**: Jede tatsächliche Beziehung wird als Kante gespeichert (kein Workaround). -- Felder u. a.: `src_id`, `dst_id`, `relation`, `direction`, `confidence (0–1)`, `evidence` (Chunk-IDs), `created_at`, `updated_at`. -- **edge_defaults** liefern **Interpretations-Hints** (Gewichte, Symmetrie, Transitivität) und parametrisieren abgeleitete Edges; sie **ersetzen** keine Originalkanten. - ---- - -## 10. Regeln & Policies (types.yaml) - -- Per Typ/Relation: - - Default-Eigenschaften (Gewicht, Directedness, Symmetrie, Transitivität). - - Scoring-Hooks für Graph-Kontext im Retriever. - - (später) Privacy-Hooks je Relation (Mindest-Visibility). - ---- - -## 11. Retrieval & Ranking (Komposition) - -- Hybrid: Vektor-Score + Filter + optional BM25/Volltext. -- Zeitgewicht (Decays) und Graph-Kontext werden komponiert (Formel siehe 16.3). -- Konfiguration über `.env`/`config.yaml` (gewichts- und halbwertszeit-basiert). - ---- - -## 12. Erklärbarkeit - -- „Warum-Pfad“: Top-Chunks mit Score-Zerlegung (Vektor/Time/Graph), Graph-Kette, Provenienz. -- Mehrschichtige Narrative (Kindheit/Erlebnisse, Werte/Prinzipien, Ziele/Leitbild, Gegenwart). - ---- - -## 13. Betrieb & Sicherheit - -- Lokal auf Single-Node starten (Backups via Snapshots). -- Zugriff nur intern/Reverse-Proxy; Festplattenverschlüsselung OS-seitig. -- Migrationspfad zu Qdrant-Distributed (Shards, Replikation) einplanen. - ---- - -## 14. Qualität & Monitoring - -- Offline-Eval-Sets, Telemetrie (lokal), Drift-Checks, manuelle Reviews. -- Kennzahlen: Hit-Rate, Overlap, Quellen-Alter, Erklärungspfad-Nutzung. - ---- - -## 15. Offene Punkte - -- Ausdetaillierung `types.yaml` (Relationen, Hooks). -- UI-Oberfläche für Erklärpfade und Provenienz. -- Batch-Jobs für abgeleitete Edges. - ---- - -## 16. Ergänzungen 2025-11-09 (v1.5.0) - -**Kontext:** Basierend auf den neuen Rahmenbedingungen (nur Deutsch; perspektivische externe Abfragen; einheitliche Vertraulichkeit mit Option auf feinere Stufen; Recency-Priorisierung als Default; Regeln später konfigurierbar; zunächst lokale Speicherung mit optionaler Migration; heutige Hardware, später skalierbar; hohe Erklärbarkeit mit mehreren Erklärungsebenen) werden folgende Entscheidungen und Erweiterungen getroffen. Alle bisherigen Inhalte bleiben gültig und werden **nicht** verändert. - -### 16.1 Sprach- und Inhaltsrichtlinie (nur Deutsch) -- `lang: "de"` als verpflichtendes Feld in allen Note-, Chunk- und Edge-Payloads. -- Für spätere Mehrsprachigkeit **nicht** die Collection splitten, sondern ein Feld `lang` + optional `lang_original` behalten; Translation-Artefakte als eigener `type: translation` (verweisend auf `source_id`). - -### 16.2 Vertraulichkeit & Sichtbarkeit -- Heute: einheitliche Stufe `visibility: "internal"`. -- Vorausschauend: reservierte Felder in allen Payloads - - `visibility`: `"public" | "internal" | "restricted"` - - `sensitivity`: Integer 0–3 (0 = unkritisch, 3 = hochsensibel) - - `acl`: Liste erlaubter Rollen/Personen-IDs (App-Layer erzwingt Filter vor Query). -- Access-Control erfolgt **im Applikations-Layer** mittels Qdrant-Payload-Filtern (`must: [ { key: "visibility", match: { any: [...] }}, ... ]`); Qdrant bleibt „dumm“ in Bezug auf ACL. - -### 16.3 Recency-Modell & Ranking (konfigurierbar) -- Default: **Zeitnähe** priorisieren (sanfte Abwertung älterer Inhalte). -- Im Retrieval kombinieren wir: - 1) Vektor-Score (cosine) aus Qdrant - 2) Zeitgewicht `time_decay = exp( - ln(2) * age_days / half_life_days )` - 3) Graph-Kontext aus Edges (z. B. Degree, Path-Hops zum Anker „Ich/Persona“) -- Konfigurierbare Gewichte (per `.env` oder `config.yaml`): - ```text - FINAL_SCORE = w_vec * norm(vec_score) - + w_time * time_decay - + w_graph * graph_context_score - # Vorschlag: w_vec=0.70, w_time=0.20, w_graph=0.10; half_life_days=365 - ``` -- Für Fragen, die „zeitlos“ sind, kann `half_life_days = inf` gesetzt werden (kein Decay). - -### 16.4 Erklärbarkeit („Warum diese Antwort?“) -- Jeder Antwort wird ein **Erklärpfad** mitgegeben (optional im UI): - - Top-Chunks (mit Score-Zerlegung w_vec/w_time/w_graph) - - **Kausalpfad** im Graphen: `Note → Edge(relation, confidence) → Note …` - - **Provenienz** (Quelle, Erstellungszeit, letzte Änderung). -- Ein **Multi-Layer-Explanations**-Modul ordnet Beiträge zu: Kindheit/Erlebnisse, Werte & Prinzipien, aktuelle Ziele/Leitbild, Gegenwartskontext. - -### 16.5 Qdrant-Schemata (Ergänzungen, rückwärtskompatibel) -- **Collections** bleiben: `mindnet_notes`, `mindnet_chunks`, `mindnet_edges` (+ `mindnet_people` falls noch nicht vorhanden). -- Gemeinsame Zusatzfelder (alle Payloads): - - `lang: "de"` - - `visibility`/`sensitivity`/`acl` (s. 16.2) - - `created_at` (ISO-8601), `updated_at` (ISO-8601), `age_days` (App-seitig berechnet) -- **Chunks**: - - Named-Vectors (z. B. `"content"`, optional `"title"`, `"tags"` für Hybrid-Scores). - - `text_index` auf `body` für BM25-ähnliche Volltextsuche (Qdrant-Textindex). - - `recency_group`: Jahr-Monat `YYYY-MM` (ermöglicht Pre-Filter für „letzte N Monate“). -- **Edges** (explizit, keine Workarounds): - - Felder: `src_id`, `dst_id`, `relation`, `direction`, `confidence` (0–1), `evidence` (Chunk-IDs), `created_at`, `updated_at`. - - **edge_defaults** bleiben als **Interpretations-Hints**: z. B. `default_weight`, `symmetry`, `transitivity`. Sie ersetzen **nicht** echte Kanten, sondern parametrisieren abgeleitete/zusätzliche Kantenbildung. - - Abgeleitete Edges: optionaler Batch-Job erzeugt *ergänzende* Kanten entlang `types.yaml`-Regeln (z. B. Backlinks, „inspired_by“ aus Zitaten), niemals statt der Originalkanten. - -### 16.6 Regeln & Typen (konfigurierbar) -- `types.yaml` erweitert um: - - Relationstypen mit Default-Eigenschaften (`weight`, `directed`, `symmetric`, `transitive`). - - **Scoring-Hooks**: pro Relation optionaler Einfluss auf `graph_context_score`. - - **Privacy-Hooks**: pro Relation Minimal-Visibility (z. B. Beziehungen zu Personen sind mindestens `internal`). - -### 16.7 Speicher- & Betriebsstrategie (heute lokal, später skalierbar) -- **Heute**: Single-Node Qdrant mit HNSW-Index, Text-Index und Payload-Filtern; regelmäßiges Backup (Snapshots). -- **Morgen**: Migrationspfad in **Qdrant-Distributed** (Shards, ggf. Replikation) bei Bedarf; Parameter-Gleichheit sichern (named-vectors, Metrik, HNSW-Param). -- **Sicherheit**: Zugriff nur über internes Netz/Reverse-Proxy, Auth vor Qdrant; Festplatten-Verschlüsselung auf OS-Ebene (z. B. LUKS). - -### 16.8 Persona-Layer („meine Essenz“) -- Eigenständiger **Persona-Knoten** (z. B. Note `person/lars`), verbunden mit: - - Werten/Prinzipien, Leitbild, prägenden Erlebnissen, Zielen, Rollen. - - Jede Antwort kann gegen diesen Knoten **kontextualisiert** werden (Graph-Pfadnähe). -- Feld `persona_weight` in Chunks/Notes zur Priorisierung persönlicher Relevanz. - -### 16.9 Evaluierung & Qualitätssicherung -- **Offline-Sets** aus echten Fragen (inkl. gewünschter Perspektiven) mit erwarteten Top-Quellen. -- **Telemetrie** (lokal): Query-Arten, Treffer-Overlaps, Zeitgewicht-Effekte, „Warum-Pfad“ genutzt/ignoriert. -- **Drift-Checks**: Anteil sehr alter vs. neuer Quellen in Antworten; manuelle Reviews. - -### 16.10 Offene Punkte / Nächste Schritte -1) `types.yaml` um Relationseigenschaften erweitern (s. 16.6). -2) Retriever-Komposition inkl. Zeitgewicht (s. 16.3) implementieren. -3) Explanations-Pfad inkl. Provenienzoberfläche (s. 16.4) im UI. -4) Feld-Erweiterungen in Import-Pipelines (`lang`, `visibility`, Zeitfelder). -5) Optional: Batch-Job für abgeleitete Edges nach Regeln (ergänzend, nicht ersetzend). diff --git a/docs/mindnet_functional_architecture.md b/docs/mindnet_functional_architecture.md index cafd9c7..aa93f76 100644 --- a/docs/mindnet_functional_architecture.md +++ b/docs/mindnet_functional_architecture.md @@ -1,15 +1,16 @@ # Mindnet v2.2 – Fachliche Architektur **Datei:** `docs/mindnet_functional_architecture_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Integrierter Stand WP01–WP05) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Integrierter Stand WP01–WP06) -> Dieses Dokument beschreibt **was** Mindnet fachlich tut und **warum** – mit Fokus auf die Erzeugung und Nutzung von **Edges** (Kanten), die Logik des Retrievers und den neuen **RAG-Chat** (Persönlichkeit). Die technische Umsetzung wird im technischen Dokument detailliert. +> Dieses Dokument beschreibt **was** Mindnet fachlich tut und **warum** – mit Fokus auf die Erzeugung und Nutzung von **Edges** (Kanten), die Logik des Retrievers und den neuen **RAG-Chat** (Decision Engine & Persönlichkeit). Die technische Umsetzung wird im technischen Dokument detailliert. ---
📖 Inhaltsverzeichnis (Klicken zum Öffnen) - [Mindnet v2.2 – Fachliche Architektur](#mindnet-v22--fachliche-architektur) + - [](#) - [0) Zielbild \& Grundprinzip](#0-zielbild--grundprinzip) - [1) Notizen \& Chunks (fachliche Perspektive)](#1-notizen--chunks-fachliche-perspektive) - [1.1 Notiz (Note)](#11-notiz-note) @@ -25,21 +26,27 @@ - [5) Der Retriever (Funktionaler Layer)](#5-der-retriever-funktionaler-layer) - [5.1 Scoring-Modell](#51-scoring-modell) - [5.2 Erklärbarkeit (Explainability) – WP04b](#52-erklärbarkeit-explainability--wp04b) - - [6) Der RAG-Chat \& Persönlichkeit (WP05)](#6-der-rag-chat--persönlichkeit-wp05) - - [6.1 Stil \& Tonfall (System Prompt)](#61-stil--tonfall-system-prompt) - - [6.2 Strategische Persönlichkeit (Ausblick WP06)](#62-strategische-persönlichkeit-ausblick-wp06) - - [7) Erweiterbarkeit \& Teaching (Context Intelligence)](#7-erweiterbarkeit--teaching-context-intelligence) + - [6) Context Intelligence \& Intent Router (WP06)](#6-context-intelligence--intent-router-wp06) + - [6.1 Das Problem: Statische vs. Dynamische Antworten](#61-das-problem-statische-vs-dynamische-antworten) + - [6.2 Der Intent-Router (Keyword \& Semantik)](#62-der-intent-router-keyword--semantik) + - [6.3 Strategic Retrieval (Injektion von Werten)](#63-strategic-retrieval-injektion-von-werten) + - [6.4 Reasoning (Das Gewissen)](#64-reasoning-das-gewissen) + - [7) Future Concepts: The Empathic Digital Twin (Ausblick)](#7-future-concepts-the-empathic-digital-twin-ausblick) + - [7.1 Antizipation durch Erfahrung](#71-antizipation-durch-erfahrung) + - [7.2 Empathie \& "Ich"-Modus](#72-empathie--ich-modus) + - [7.3 Glaubenssätze \& Rituale](#73-glaubenssätze--rituale) + - [8) Erweiterbarkeit \& Teaching (Context Intelligence)](#8-erweiterbarkeit--teaching-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 nutzen (z. B. `beeinflusst_von`)](#b-workflow-neue-beziehungen-nutzen-z-b-beeinflusst_von) - - [8) Feedback \& Lernen – WP04c](#8-feedback--lernen--wp04c) - - [8.1 Der Feedback-Loop](#81-der-feedback-loop) - - [9) Confidence \& Provenance – wozu?](#9-confidence--provenance--wozu) - - [10) Semantik ausgewählter `kind`-Werte](#10-semantik-ausgewählter-kind-werte) - - [11) Frontmatter-Eigenschaften – Rolle \& Empfehlung](#11-frontmatter-eigenschaften--rolle--empfehlung) - - [12) Lösch-/Update-Garantien (Idempotenz)](#12-lösch-update-garantien-idempotenz) - - [13) Beispiel – Von Markdown zu Kanten (v2.2)](#13-beispiel--von-markdown-zu-kanten-v22) - - [14) Referenzen (Projektdateien \& Leitlinien)](#14-referenzen-projektdateien--leitlinien) - - [15) Workpackage Status (v2.3.0)](#15-workpackage-status-v230) + - [9) Feedback \& Lernen – WP04c](#9-feedback--lernen--wp04c) + - [9.1 Der Feedback-Loop](#91-der-feedback-loop) + - [10) Confidence \& Provenance – wozu?](#10-confidence--provenance--wozu) + - [11) Semantik ausgewählter `kind`-Werte](#11-semantik-ausgewählter-kind-werte) + - [12) Frontmatter-Eigenschaften – Rolle \& Empfehlung](#12-frontmatter-eigenschaften--rolle--empfehlung) + - [13) Lösch-/Update-Garantien (Idempotenz)](#13-lösch-update-garantien-idempotenz) + - [14) Beispiel – Von Markdown zu Kanten (v2.2)](#14-beispiel--von-markdown-zu-kanten-v22) + - [15) Referenzen (Projektdateien \& Leitlinien)](#15-referenzen-projektdateien--leitlinien) + - [16) Workpackage Status (v2.3.1)](#16-workpackage-status-v231)
--- @@ -201,24 +208,62 @@ Die API gibt diese Analysen als menschenlesbare Sätze (`reasons`) und als Daten --- -## 6) Der RAG-Chat & Persönlichkeit (WP05) +## 6) Context Intelligence & Intent Router (WP06) -Seit WP-05 kann Mindnet nicht nur suchen, sondern als **KI-Zwilling** antworten. Die Persönlichkeit entsteht dabei auf zwei Ebenen: +Seit WP06 agiert Mindnet nicht mehr statisch, sondern passt seine Suchstrategie dem **Intent** (der Absicht) des Nutzers an. Dies ist die Transformation vom reinen Wissens-Abrufer zum strategischen Entscheidungspartner. -### 6.1 Stil & Tonfall (System Prompt) -In `config/prompts.yaml` wird die Persona definiert. -* **System Prompt:** Definiert die Rolle ("Ich bin dein digitales Gedächtnis..."). -* **Werte im Prompt:** Pragmatismus, Transparenz (kein Halluzinieren), Vernetztes Denken. -* **Context Intelligence:** Dem LLM werden Metadaten (Typ, Score) injiziert, damit es komplexe Zusammenhänge erkennt (z.B. dass eine `[DECISION]` wichtiger ist als ein `[CONCEPT]`). +### 6.1 Das Problem: Statische vs. Dynamische Antworten +* **Früher (Pre-WP06):** Jede Frage ("Was ist X?" oder "Soll ich X?") wurde gleich behandelt -> Fakten-Retrieval. +* **Heute (WP06):** Das System erkennt, *was* der User will, und lädt unterschiedliche Wissensbausteine. -### 6.2 Strategische Persönlichkeit (Ausblick WP06) -Ein echter KI-Zwilling spiegelt nicht nur den Stil, sondern die **Werte** des Users wider. -* **Logik:** Bei komplexen Fragen oder Entscheidungen ("Soll ich X tun?") lädt das System gezielt Notizen vom Typ `[VALUE]` und `[PRINCIPLE]` in den Kontext. -* **Effekt:** Das System wägt die Fakten (aus der Suche) gegen die Werte (aus dem Profil) ab. +### 6.2 Der Intent-Router (Keyword & Semantik) +Der Router prüft vor jeder Antwort die Absicht über konfigurierbare Strategien (`config/decision_engine.yaml`): + +1. **FACT:** Reine Wissensfrage ("Was ist Qdrant?"). → Standard RAG. +2. **DECISION:** Frage nach Rat oder Strategie ("Soll ich Qdrant nutzen?"). → Aktiviert die Decision Engine. +3. **EMPATHY:** Emotionale Zustände ("Ich bin gestresst"). → Aktiviert den empathischen Modus. +4. **CODING:** Technische Anfragen. + +**Erkennung:** +* **Fast Path:** Prüfung auf Schlüsselwörter (z.B. "soll ich"). +* **Slow Path (Smart Fallback):** Wenn kein Keyword passt, prüft ein LLM (Phi-3) die Semantik des Satzes. + +### 6.3 Strategic Retrieval (Injektion von Werten) +Im Modus `DECISION` führt das System eine **zweite Suchstufe** aus. Es sucht nicht nur nach semantisch passenden Texten zur Frage, sondern erzwingt das Laden von strategischen Notizen wie: +* **Values (`type: value`):** Moralische Werte (z.B. "Privacy First"). +* **Principles (`type: principle`):** Handlungsanweisungen. +* **Goals (`type: goal`):** Strategische Ziele. + +Dies wird über **Late Binding** in `config/decision_engine.yaml` gesteuert. Neue Facetten der Persönlichkeit können dort konfiguriert werden, ohne den Code zu ändern. + +### 6.4 Reasoning (Das Gewissen) +Das LLM erhält im Prompt die explizite Anweisung: *"Wäge die Fakten (aus der Suche) gegen die injizierten Werte ab."* +Dadurch entstehen Antworten, die nicht nur technisch korrekt sind, sondern subjektiv passend ("Tool X passt nicht zu deinem Ziel Z"). --- -## 7) Erweiterbarkeit & Teaching (Context Intelligence) +## 7) Future Concepts: The Empathic Digital Twin (Ausblick) + +Um Mindnet von einer Entscheidungsmaschine zu einem echten **Spiegel der Persönlichkeit** zu entwickeln, sind folgende Erweiterungen konzeptionell vorgesehen: + +### 7.1 Antizipation durch Erfahrung +* **Konzept:** Das System soll Konsequenzen vorhersagen ("Was passiert, wenn...?"). +* **Umsetzung:** Neben Werten werden vergangene Erfahrungen (`type: experience`) geladen. +* **Logik:** *"In einer ähnlichen Situation (Projekt A) hat Entscheidung X zu Ergebnis Y geführt."* + +### 7.2 Empathie & "Ich"-Modus +* **Konzept:** Das System antwortet nicht wie ein Roboter, sondern im Tonfall und Stil des Nutzers. +* **Umsetzung (Few-Shot Prompting):** Der System-Prompt wird dynamisch mit Beispielen gefüttert, wie der Nutzer typischerweise auf E-Mails oder Fragen antwortet. +* **Datenbasis:** `type: profile` oder `type: manifesto` definieren das Selbstbild. + +### 7.3 Glaubenssätze & Rituale +* **Konzept:** Berücksichtigung weicher Faktoren und Gewohnheiten. +* **Umsetzung:** Erweiterung der `decision_engine.yaml` um `inject_types: ["belief", "ritual"]`. +* **Szenario:** Bei Terminplanungen werden Rituale ("Keine Meetings vor 10 Uhr") automatisch als harte Restriktion gegen Anfragen geprüft. + +--- + +## 8) Erweiterbarkeit & Teaching (Context Intelligence) Mindnet lernt nicht durch klassisches Training (Fine-Tuning), sondern durch **Konfiguration**, **Vernetzung** und **Prompting**. Dies ist das **"Teach-the-AI" Paradigma**: Wenn du dem System ein neues Konzept beibringen willst, musst du an drei Stellen eingreifen. @@ -234,15 +279,8 @@ Mindnet lernt nicht durch klassisches Training (Fine-Tuning), sondern durch **Ko ``` *Effekt:* Der Retriever spült diese Notizen bei relevanten Anfragen nach oben. -2. **Semantik erklären (`config/prompts.yaml`)** - Bringe dem LLM bei, wie es mit diesem Typ umgehen soll. - ```yaml - system_prompt: | - ... - REGELN FÜR TYPEN: - - [RISK]: Warnung! Wenn ein Chunk vom Typ 'risk' im Kontext ist, weise den User explizit darauf hin. - ``` - *Effekt:* Der Chatbot ignoriert das Risiko nicht nur, sondern "versteht" die Warnfunktion. +2. **Semantik erklären (`config/prompts.yaml` / `decision_engine.yaml`)** + Bringe dem LLM bei, wie es mit diesem Typ umgehen soll. Füge `risk` zur `DECISION`-Strategie hinzu (`inject_types`), damit es bei Entscheidungen geladen wird. ### B. Workflow: Neue Beziehungen nutzen (z. B. `beeinflusst_von`) @@ -270,11 +308,11 @@ Beziehungen sind der Klebstoff für logische Schlussfolgerungen. --- -## 8) Feedback & Lernen – WP04c +## 9) Feedback & Lernen – WP04c Das System verfügt nun über ein **Kurzzeitgedächtnis für Interaktionen**, das die Basis für zukünftiges Lernen bildet. -### 8.1 Der Feedback-Loop +### 9.1 Der Feedback-Loop 1. **Suche (Situation):** Wenn ein Nutzer eine Anfrage stellt, loggt Mindnet die "Situation": * Den Query-Text. @@ -291,7 +329,7 @@ Das System verfügt nun über ein **Kurzzeitgedächtnis für Interaktionen**, da --- -## 9) Confidence & Provenance – wozu? +## 10) Confidence & Provenance – wozu? Der Retriever kann Edges gewichten: - **provenance**: *explicit* > *rule* @@ -303,7 +341,7 @@ Eine typische Gewichtung (konfigurierbar in `retriever.yaml`) ist: --- -## 10) Semantik ausgewählter `kind`-Werte +## 11) Semantik ausgewählter `kind`-Werte - `references` – „Nutzt/erwähnt“; neutral, aber stützend für Kontext. - `related_to` – Ähnlichkeit/Verwandtschaft (symmetrisch interpretierbar). @@ -315,7 +353,7 @@ Eine typische Gewichtung (konfigurierbar in `retriever.yaml`) ist: --- -## 11) Frontmatter-Eigenschaften – Rolle & Empfehlung +## 12) Frontmatter-Eigenschaften – Rolle & Empfehlung Frontmatter-Eigenschaften (Properties) bleiben **minimiert**: - **type** – steuert Typ-Defaults via Registry (Pflicht für differenziertes Verhalten). @@ -325,7 +363,7 @@ Frontmatter-Eigenschaften (Properties) bleiben **minimiert**: --- -## 12) Lösch-/Update-Garantien (Idempotenz) +## 13) Lösch-/Update-Garantien (Idempotenz) - Jede Note hat einen stabilen **note_id** (Frontmatter/Hash). - Vor einem Upsert können *alte Chunks/Edges einer Note* gefiltert gelöscht werden (`note_id`-Filter) – das hält Collections sauber bei Re-Imports. @@ -333,7 +371,7 @@ Frontmatter-Eigenschaften (Properties) bleiben **minimiert**: --- -## 13) Beispiel – Von Markdown zu Kanten (v2.2) +## 14) Beispiel – Von Markdown zu Kanten (v2.2) **Markdown (Auszug)** # Relations Showcase @@ -352,18 +390,19 @@ Frontmatter-Eigenschaften (Properties) bleiben **minimiert**: --- -## 14) Referenzen (Projektdateien & Leitlinien) +## 15) Referenzen (Projektdateien & Leitlinien) - Import-Pipeline & Registry-Auflösung: `scripts/import_markdown.py`. - Kantenbildung (V2-Logic): `app/core/derive_edges.py`. - Typ-Registry: `config/types.yaml` & `TYPE_REGISTRY_MANUAL.md`. - Retriever-Scoring & Explanation: `app/core/retriever.py`. - Persönlichkeit & Chat: `config/prompts.yaml` & `app/routers/chat.py`. +- Decision Engine: `config/decision_engine.yaml`. - Logging Service: `app/services/feedback_service.py`. --- -## 15) Workpackage Status (v2.3.0) +## 16) Workpackage Status (v2.3.1) Aktueller Implementierungsstand der Module. @@ -376,5 +415,5 @@ Aktueller Implementierungsstand der Module. | **WP04b**| Explanation Layer | 🟢 Live | API liefert Reasons & Breakdown. | | **WP04c**| Feedback Loop | 🟢 Live | Logging (JSONL) & Traceability aktiv. | | **WP05** | Persönlichkeit / Chat | 🟢 Live | RAG-Integration mit Context Enrichment. | -| **WP06** | Decision Engine | 🟡 Geplant | Fokus: Strategic Retrieval von Werten. | +| **WP06** | Decision Engine | 🟢 Live | Intent-Router & Strategic Retrieval. | | **WP08** | Self-Tuning | 🔴 Geplant | Auto-Adjustment der Gewichte. | \ No newline at end of file diff --git a/docs/mindnet_technical_architecture.md b/docs/mindnet_technical_architecture.md index dcf6d70..3fb41da 100644 --- a/docs/mindnet_technical_architecture.md +++ b/docs/mindnet_technical_architecture.md @@ -1,11 +1,11 @@ # Mindnet v2.2 – Technische Architektur **Datei:** `docs/mindnet_technical_architecture_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Integrierter Stand WP01–WP05) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Integrierter Stand WP01–WP06) **Quellen:** `Programmplan_V2.2.md`, `Handbuch.md`, `chunking_strategy.md`, `wp04_retriever_scoring.md`. > **Ziel dieses Dokuments:** -> Vollständige Beschreibung der technischen Architektur inkl. Graph-Datenbank, Retrieval-Logik und der **neuen RAG-Komponenten (LLM/Chat)**. +> Vollständige Beschreibung der technischen Architektur inkl. Graph-Datenbank, Retrieval-Logik und der **neuen RAG-Komponenten (Decision Engine & Hybrid Router)**. ---
@@ -15,7 +15,7 @@ - [](#) - [1. Systemüberblick](#1-systemüberblick) - [1.1 Architektur-Zielbild](#11-architektur-zielbild) - - [1.2 Verzeichnisstruktur \& Komponenten (Post-WP05)](#12-verzeichnisstruktur--komponenten-post-wp05) + - [1.2 Verzeichnisstruktur \& Komponenten (Post-WP06)](#12-verzeichnisstruktur--komponenten-post-wp06) - [2. Datenmodell \& Collections (Qdrant)](#2-datenmodell--collections-qdrant) - [2.1 Notes Collection (`_notes`)](#21-notes-collection-prefix_notes) - [2.2 Chunks Collection (`_chunks`)](#22-chunks-collection-prefix_chunks) @@ -23,8 +23,9 @@ - [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 Prompts (`config/prompts.yaml`)](#33-prompts-configpromptsyaml) - - [3.4 Environment (`.env`)](#34-environment-env) + - [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](#41-verarbeitungsschritte) - [5. Retriever-Architektur \& Scoring](#5-retriever-architektur--scoring) @@ -32,11 +33,12 @@ - [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 (WP05)](#6-rag--chat-architektur-wp05) - - [6.1 Schritt 1: Intent \& Retrieval](#61-schritt-1-intent--retrieval) - - [6.2 Schritt 2: Context Enrichment (Das "Context Intelligence" Pattern)](#62-schritt-2-context-enrichment-das-context-intelligence-pattern) - - [6.3 Schritt 3: Generation (LLM Service)](#63-schritt-3-generation-llm-service) - - [6.4 Schritt 4: Response \& Traceability](#64-schritt-4-response--traceability) + - [6. RAG \& Chat Architektur (WP06 Hybrid Router)](#6-rag--chat-architektur-wp06-hybrid-router) + - [6.1 Architektur-Pattern: Intent Router](#61-architektur-pattern-intent-router) + - [6.2 Schritt 1: Intent Detection (Hybrid)](#62-schritt-1-intent-detection-hybrid) + - [6.3 Schritt 2: Strategy Resolution (Late Binding)](#63-schritt-2-strategy-resolution-late-binding) + - [6.4 Schritt 3: Multi-Stage Retrieval](#64-schritt-3-multi-stage-retrieval) + - [6.5 Schritt 4: Generation \& Response](#65-schritt-4-generation--response) - [7. Feedback \& Logging Architektur (WP04c)](#7-feedback--logging-architektur-wp04c) - [7.1 Komponenten](#71-komponenten) - [7.2 Log-Dateien](#72-log-dateien) @@ -60,9 +62,9 @@ Mindnet ist ein **lokales RAG-System (Retrieval Augmented Generation)**. 4. **Service:** Eine FastAPI-Anwendung stellt Endpunkte für **Semantische** und **Hybride Suche** sowie **Feedback** bereit. 5. **Inference:** Lokales LLM (Ollama: Phi-3 Mini) für RAG-Chat und Antwortgenerierung. -Das System arbeitet **deterministisch** (stabile IDs) und ist **konfigurationsgetrieben** (`types.yaml`, `retriever.yaml`, `prompts.yaml`). +Das System arbeitet **deterministisch** (stabile IDs) und ist **konfigurationsgetrieben** (`types.yaml`, `retriever.yaml`, `decision_engine.yaml`, `prompts.yaml`). -### 1.2 Verzeichnisstruktur & Komponenten (Post-WP05) +### 1.2 Verzeichnisstruktur & Komponenten (Post-WP06) /mindnet/ ├── app/ @@ -77,20 +79,21 @@ Das System arbeitet **deterministisch** (stabile IDs) und ist **konfigurationsge │ │ ├── derive_edges.py # Logik der Kantenableitung (WP03) │ │ ├── graph_adapter.py # Subgraph & Reverse-Lookup (WP04b) │ │ └── retriever.py # Scoring, Expansion & Explanation (WP04a/b) - │ ├── models/ # Pydantic DTOs (QueryHit, Explanation, FeedbackRequest, ChatRequest) + │ ├── models/ # Pydantic DTOs │ ├── routers/ │ │ ├── query.py # Such-Endpunkt - │ │ ├── chat.py # RAG-Chat Endpunkt (WP05) + │ │ ├── chat.py # Hybrid Router & Decision Engine (WP06) │ │ ├── feedback.py # Feedback-Endpunkt (WP04c) │ │ └── ... │ ├── services/ - │ │ ├── llm_service.py # Ollama Client (WP05) + │ │ ├── llm_service.py # Ollama Client mit Timeout & Raw-Mode │ │ ├── feedback_service.py # JSONL Logging (WP04c) │ │ └── embeddings_client.py ├── config/ │ ├── types.yaml # Typ-Definitionen (Import-Zeit) │ ├── retriever.yaml # Scoring-Gewichte (Laufzeit) - │ └── prompts.yaml # LLM System-Prompts & Templates (WP05) + │ ├── decision_engine.yaml # Strategien & Keywords (WP06) + │ └── prompts.yaml # LLM System-Prompts & Templates (WP06) ├── data/ │ └── logs/ # Lokale JSONL-Logs (WP04c) ├── scripts/ @@ -181,20 +184,23 @@ Steuert das Scoring zur Laufzeit (WP04a). edge_weight: 0.7 centrality_weight: 0.5 -### 3.3 Prompts (`config/prompts.yaml`) -Steuert die LLM-Persönlichkeit (WP05). -* **Inhalt (Beispiel):** +### 3.3 Decision Engine (`config/decision_engine.yaml`) +**Neu in WP06:** Steuert den Intent-Router. +* Definiert Strategien (`DECISION`, `EMPATHY`, `CODING`, `FACT`). +* Definiert `trigger_keywords` und `inject_types` (Late Binding). +* Definiert LLM-Router-Settings (`llm_fallback_enabled`). - system_prompt: | - Du bist 'mindnet', das KI-Gedächtnis. - rag_template: | - QUELLEN (WISSEN): {context_str} +### 3.4 Prompts (`config/prompts.yaml`) +Steuert die LLM-Persönlichkeit und Templates. +* Enthält Templates für alle Strategien (z.B. `decision_template`, `empathy_template`, `technical_template`). -### 3.4 Environment (`.env`) +### 3.5 Environment (`.env`) Erweiterung für LLM-Steuerung: MINDNET_LLM_MODEL=phi3:mini MINDNET_OLLAMA_URL=http://127.0.0.1:11434 + MINDNET_LLM_TIMEOUT=300.0 # Neu: Erhöht für CPU-Inference Cold-Starts + MINDNET_DECISION_CONFIG="config/decision_engine.yaml" --- @@ -259,30 +265,45 @@ Der Hybrid-Modus lädt dynamisch die Nachbarschaft der Top-K Vektor-Treffer ("Se --- -## 6. RAG & Chat Architektur (WP05) +## 6. RAG & Chat Architektur (WP06 Hybrid Router) -Der Flow für eine Chat-Anfrage (`/chat`) ist eine Pipeline aus vier Schritten. +Der Flow für eine Chat-Anfrage (`/chat`) wurde in WP06 auf eine **Configuration-Driven Architecture** umgestellt. Der `ChatRouter` (`app/routers/chat.py`) fungiert als zentraler Dispatcher. -### 6.1 Schritt 1: Intent & Retrieval -* Der `ChatRouter` ruft den `Retriever` im **Hybrid-Modus** auf. -* Dies stellt sicher, dass logisch verknüpfte Notizen (z.B. Entscheidungen zu einem Projekt) gefunden werden. +### 6.1 Architektur-Pattern: Intent Router +Die Behandlung einer Anfrage ist nicht mehr hartkodiert, sondern wird dynamisch zur Laufzeit entschieden. +* **Input:** User Message. +* **Config:** `config/decision_engine.yaml` (Strategien & Keywords). +* **Komponenten:** + * **Fast Path:** Keyword Matching (CPU-schonend). + * **Slow Path:** LLM-basierter Semantic Router (für subtile Intents). -### 6.2 Schritt 2: Context Enrichment (Das "Context Intelligence" Pattern) -* Der Router (`_build_enriched_context`) reichert die Chunks mit Metadaten an: - * **Typ-Injection:** `[DECISION]`, `[PROJECT]`, `[CONCEPT]`. - * **Score-Transparenz:** `(Score: 0.75)`. - * **Formatierung:** Markdown-Header pro Quelle. -* *Ziel:* Kleine Modelle (SLMs wie Phi-3) benötigen diese expliziten Signale, um komplexe Zusammenhänge ("Warum nutzen wir X?") aus den Texten abzuleiten. +### 6.2 Schritt 1: Intent Detection (Hybrid) +Der Router ermittelt die Absicht (`Intent`) des Nutzers. +1. **Keyword Scan (Fast Path):** + * Iteration über alle Strategien in `decision_engine.yaml`. + * Prüfung auf `trigger_keywords`. + * **Best Match:** Bei mehreren Treffern gewinnt das längste/spezifischste Keyword (Robustheit gegen Shadowing). +2. **LLM Fallback (Slow Path):** + * Nur aktiv, wenn `llm_fallback_enabled: true`. + * Greift, wenn keine Keywords gefunden wurden. + * Sendet die Query an das LLM mit einem Klassifizierungs-Prompt (`llm_router_prompt`). + * Ergebnis: `EMPATHY`, `DECISION`, `CODING` oder `FACT` (Default). -### 6.3 Schritt 3: Generation (LLM Service) -* **Service:** `app/services/llm_service.py` nutzt `httpx` (async). -* **Backend:** Ollama (lokal). -* **Modell:** `phi3:mini` (3.8B Parameter). -* **Timeout:** Erhöht auf 300s für CPU-Inference Sicherheit. +### 6.3 Schritt 2: Strategy Resolution (Late Binding) +Basierend auf dem Intent lädt der Router die Parameter: +* **inject_types:** Liste der Notiz-Typen, die erzwungen werden sollen (z.B. `["value", "goal"]` bei `DECISION`). +* **prompt_template:** Schlüssel für das Template in `prompts.yaml` (z.B. `decision_template`, `empathy_template`). -### 6.4 Schritt 4: Response & Traceability -* Die Antwort enthält die generierte Nachricht **und** die verwendeten Quellen (`sources`). -* Eine `query_id` wird generiert und durchgereicht, um späteres Feedback (WP04c) zu ermöglichen. +### 6.4 Schritt 3: Multi-Stage Retrieval +1. **Primary Retrieval:** Hybride Suche nach der User-Query (findet Fakten). +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. + +### 6.5 Schritt 4: Generation & Response +* **Context Enrichment:** Metadaten (`[VALUE]`, `[GOAL]`, `[SCORE]`) werden in den Context-String injiziert, um dem LLM die Rolle des Textstücks zu signalisieren. +* **Templating:** Das LLM erhält den Prompt basierend auf dem gewählten Template. +* **Execution:** Der `LLMService` führt den Call aus. Ein konfigurierbarer Timeout (`MINDNET_LLM_TIMEOUT`) fängt Cold-Start-Verzögerungen auf CPU-Hardware ab. +* **Response:** Rückgabe enthält Antworttext, Quellenliste und den erkannten `intent` (für Debugging/Frontend). --- diff --git a/docs/pipeline_playbook.md b/docs/pipeline_playbook.md index 78de362..dcd3c40 100644 --- a/docs/pipeline_playbook.md +++ b/docs/pipeline_playbook.md @@ -1,7 +1,7 @@ # mindnet v2.2 – Pipeline Playbook **Datei:** `docs/mindnet_pipeline_playbook_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Inkl. WP05 RAG Pipeline) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Inkl. WP06 Decision Engine) **Quellen:** `mindnet_v2_implementation_playbook.md`, `Handbuch.md`, `chunking_strategy.md`, `docs_mindnet_retriever.md`, `mindnet_admin_guide_v2.2.md`. --- @@ -9,6 +9,7 @@ 📖 Inhaltsverzeichnis (Klicken zum Öffnen) - [mindnet v2.2 – Pipeline Playbook](#mindnet-v22--pipeline-playbook) + - [](#) - [1. Zweck \& Einordnung](#1-zweck--einordnung) - [2. Die Import-Pipeline (Runbook)](#2-die-import-pipeline-runbook) - [2.1 Der 12-Schritte-Prozess](#21-der-12-schritte-prozess) @@ -23,28 +24,27 @@ - [4.2 Typ-Defaults](#42-typ-defaults) - [5. Retriever, Chat \& Generation (RAG Pipeline)](#5-retriever-chat--generation-rag-pipeline) - [5.1 Retrieval (Hybrid)](#51-retrieval-hybrid) - - [5.2 Context Enrichment (Das "Context Intelligence" Pattern)](#52-context-enrichment-das-context-intelligence-pattern) - - [5.3 Generation (LLM)](#53-generation-llm) - - [5.4 Explanation Mode (WP04b)](#54-explanation-mode-wp04b) + - [5.2 Intent Router (WP06)](#52-intent-router-wp06) + - [5.3 Context Enrichment](#53-context-enrichment) + - [5.4 Generation (LLM)](#54-generation-llm) - [6. Feedback \& Lernen (WP04c)](#6-feedback--lernen-wp04c) - [7. Quality Gates \& Tests](#7-quality-gates--tests) - [7.1 Pflicht-Tests vor Commit](#71-pflicht-tests-vor-commit) - [7.2 Smoke-Test (E2E)](#72-smoke-test-e2e) - [8. Ausblick \& Roadmap (Technische Skizzen)](#8-ausblick--roadmap-technische-skizzen) - - [8.1 WP-06: Decision Engine (Skizze)](#81-wp-06-decision-engine-skizze) - - [8.2 WP-08: Self-Tuning (Skizze)](#82-wp-08-self-tuning-skizze) - + - [8.1 WP-08: Self-Tuning (Skizze)](#81-wp-08-self-tuning-skizze) +
--- ## 1. Zweck & Einordnung -Dieses Playbook ist das zentrale operative Handbuch für die **mindnet-Pipeline**. Es beschreibt, wie Daten vom Markdown-Vault in den Wissensgraphen (Qdrant) gelangen, wie der Retriever betrieben wird und wie die **RAG-Generierung** funktioniert. +Dieses Playbook ist das zentrale operative Handbuch für die **mindnet-Pipeline**. Es beschreibt, wie Daten vom Markdown-Vault in den Wissensgraphen (Qdrant) gelangen, wie der Retriever betrieben wird und wie die **RAG-Generierung** (inkl. Decision Engine) funktioniert. **Zielgruppe:** Dev/Ops, Tech-Leads. **Scope:** -* **Ist-Stand (WP01–WP05):** Import, Chunking, Edge-Erzeugung, Hybrider Retriever, RAG-Chat, Feedback Loop. -* **Roadmap (Ausblick):** Technische Skizzen für Self-Healing (WP06) und Self-Tuning (WP08). +* **Ist-Stand (WP01–WP06):** Import, Chunking, Edge-Erzeugung, Hybrider Retriever, RAG-Chat (Hybrid Router), Feedback Loop. +* **Roadmap (Ausblick):** Technische Skizze für Self-Tuning (WP08). --- @@ -92,7 +92,7 @@ Nach einem Import oder Code-Update muss der API-Prozess neu gestartet werden. # Neustart des Produktions-Services sudo systemctl restart mindnet-prod - + # Prüfung sudo systemctl status mindnet-prod @@ -152,26 +152,24 @@ Wenn in `types.yaml` für einen Typ `edge_defaults` definiert sind, werden diese Der Datenfluss endet nicht beim Finden. Er geht weiter bis zur Antwort. ### 5.1 Retrieval (Hybrid) - total_score = - semantic_weight * semantic_score - + edge_weight * edge_bonus - + centrality_weight * centrality_bonus - + type_weight * retriever_weight - Der `/chat` Endpunkt nutzt **Hybrid Retrieval** (Semantic + Graph), um auch logisch verbundene, aber textlich unterschiedliche Notizen zu finden (z.B. Decisions zu einem Projekt). -### 5.2 Context Enrichment (Das "Context Intelligence" Pattern) -Bevor der Text an das LLM geht, reichert der Router (`chat.py`) ihn an. -* **Metadaten-Injection:** `[DECISION]`, `[PROJECT]`, `[SCORE: 0.9]`. +### 5.2 Intent Router (WP06) +Der Request durchläuft den **Hybrid Router**: +1. **Fast Path:** Prüfung auf `trigger_keywords` aus `decision_engine.yaml`. +2. **Slow Path:** Falls kein Keyword matched und `llm_fallback_enabled=true`, klassifiziert das LLM den Intent (`DECISION`, `EMPATHY`, `FACT`, `CODING`). +3. **Result:** Auswahl der Strategie und der `inject_types` (z.B. Values & Goals). + +### 5.3 Context Enrichment +Der Router (`chat.py`) reichert die gefundenen Chunks mit Metadaten an: +* **Typ-Injection:** `[DECISION]`, `[PROJECT]`. +* **Reasoning-Infos:** `(Score: 0.75)`. * **Zweck:** Ermöglicht kleinen Modellen (Phi-3) das Erkennen von logischen Rollen ("Warum?" vs "Was?"). -### 5.3 Generation (LLM) +### 5.4 Generation (LLM) * **Engine:** Ollama (lokal). * **Modell:** `phi3:mini` (Standard). -* **Prompting:** Gesteuert über `config/prompts.yaml`. - -### 5.4 Explanation Mode (WP04b) -Wird `/query` mit `explain=True` aufgerufen, führt der Retriever eine Post-Processing-Analyse durch und liefert `reasons` ("Verweist auf...", "Hoher Typ-Bonus"). +* **Prompting:** Template wird basierend auf Intent gewählt (`decision_template` vs `empathy_template`). --- @@ -205,8 +203,8 @@ Prüft am laufenden System (Prod oder Dev), ob Semantik, Graph und Feedback funk # Retriever Test python scripts/test_retriever_smoke.py --mode hybrid --top-k 5 - # Chat Test (Neu WP05) - python tests/test_chat_wp05.py + # Chat / Decision Engine Test (Neu WP06) + python tests/test_wp06_decision.py -p 8002 -e EMPATHY -q "Alles ist grau" # Feedback Test python tests/test_feedback_smoke.py --url http://localhost:8001/query @@ -217,11 +215,7 @@ Prüft am laufenden System (Prod oder Dev), ob Semantik, Graph und Feedback funk Wie entwickeln wir die Pipeline weiter? -### 8.1 WP-06: Decision Engine (Skizze) -**Ziel:** Aktive Entscheidungsberatung. -**Erweiterung:** Der Chat-Router lädt bei Entscheidungfragen gezielt `type: value` Notizen nach, um Optionen gegen Werte abzuwägen. - -### 8.2 WP-08: Self-Tuning (Skizze) +### 8.1 WP-08: Self-Tuning (Skizze) **Ziel:** Die Gewichte in `retriever.yaml` basierend auf `feedback.jsonl` optimieren. **Ansatz:** Ein Offline-Learning-Skript `scripts/optimize_weights.py`. 1. **Load:** Liest `search_history.jsonl` und joint mit `feedback.jsonl` via `query_id`. diff --git a/docs/user_guide.md b/docs/user_guide.md index b91293a..9bab874 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -1,85 +1,95 @@ # Mindnet v2.2 – User Guide **Datei:** `docs/mindnet_user_guide_v2.2.md` -**Stand:** 2025-12-08 -**Status:** **FINAL** (Inkl. RAG & Chat) +**Stand:** 2025-12-09 +**Status:** **FINAL** (Inkl. RAG & Multi-Personality Chat) **Quellen:** `knowledge_design.md`, `wp04_retriever_scoring.md`, `Programmplan_V2.2.md`, `Handbuch.md`. > **Willkommen bei Mindnet.** -> Dies ist dein persönliches Wissensnetzwerk. Im Gegensatz zu einer normalen Suche (wie Google Drive), die nur Texte findet, "denkt" Mindnet mit. Es erklärt dir, warum es etwas gefunden hat, und kann dir im Chat Fragen beantworten. +> Dies ist dein persönliches Wissensnetzwerk und dein Digitaler Zwilling. Es hilft dir beim Erinnern, beim Entscheiden und beim Reflektieren. --- ## 1. Was Mindnet für dich tut -Mindnet ist ein **assoziatives Gedächtnis**. Es verbindet deine Notizen zu einem Graphen. +Mindnet ist ein **assoziatives Gedächtnis** mit Persönlichkeit. Es unterscheidet sich von einer reinen Suche (wie Google) dadurch, dass es **kontextsensitiv** agiert. -### 1.1 Mehr als nur Stichworte -Wenn du nach "Projekt Alpha" suchst, findet Mindnet nicht nur das Dokument mit diesem Titel. Es findet auch: -* **Abhängigkeiten:** "Technologie X wird benötigt" (weil sie verlinkt ist). -* **Entscheidungen:** "Warum nutzen wir X?" (weil eine Decision-Note existiert). -* **Ähnliches:** "Projekt Beta war ähnlich" (weil es strukturell verwandt ist). +### 1.1 Das Gedächtnis (Der Graph) +Wenn du nach "Projekt Alpha" suchst, findet Mindnet nicht nur das Dokument. Es findet auch: +* **Abhängigkeiten:** "Technologie X wird benötigt". +* **Entscheidungen:** "Warum nutzen wir X?". +* **Ähnliches:** "Projekt Beta war ähnlich". -### 1.2 Dein KI-Zwilling (Vision) -Mindnet speichert nicht nur Fakten, sondern deine **Perspektive**. Durch die Gewichtung von Typen (z.B. "Prinzipien sind wichtiger als Quellen") lernt das System, Antworten so zu priorisieren, wie du es tun würdest. +### 1.2 Der Zwilling (Die Personas) +Seit Version 2.3.1 passt Mindnet seinen Charakter dynamisch an deine Frage an: +1. **Der Bibliothekar (FACT):** Liefert präzise Fakten und Definitionen. +2. **Der Berater (DECISION):** Hilft dir beim Abwägen, basierend auf deinen Werten und Zielen. +3. **Der Spiegel (EMPATHY):** Hört zu und antwortet basierend auf deinen Erfahrungen ("Ich"-Perspektive). +4. **Der Coder (CODING):** Liefert technische Schnipsel ohne Smalltalk. --- -## 2. Gute Fragen an Mindnet stellen +## 2. Den Chat steuern (Intents) -Mindnet nutzt eine **Hybride Suche**. Das heißt, es schaut auf deine Worte (Semantik) und auf das Netzwerk (Graph). +Du steuerst die Persönlichkeit von Mindnet durch deine Wortwahl. Das System nutzt einen **Hybrid Router**, der sowohl auf Schlüsselwörter als auch auf die Bedeutung achtet. -### 2.1 Frage-Muster -Um gute Antworten zu erhalten, formuliere deine Anfragen präzise: +### 2.1 Modus: Entscheidung ("Der Berater") +Wenn du vor einer Wahl stehst, hilft Mindnet dir, konform zu deinen Prinzipien zu bleiben. -* **Faktensuche:** "Wie installiere ich Qdrant?" - * *Mindnet sucht:* Chunks mit technischer Anleitung. -* **Zusammenhänge:** "Womit hängt Projekt Alpha zusammen?" - * *Mindnet sucht:* Den Projekt-Knoten und folgt den Kanten (`depends_on`, `related_to`). -* **Entscheidungen:** "Warum nutzen wir Vektordatenbanken?" - * *Mindnet sucht:* Notizen vom Typ `decision` oder `principle`. +* **Auslöser (Keywords):** "Soll ich...", "Was ist deine Meinung?", "Strategie für...", "Vor- und Nachteile". +* **Was passiert:** Mindnet lädt deine **Werte** (`type: value`) und **Ziele** (`type: goal`) in den Kontext und prüft die Fakten dagegen. +* **Beispiel-Dialog:** + * *Du:* "Soll ich Tool X nutzen?" + * *Mindnet:* "Nein. Tool X speichert Daten in den USA. Das verstößt gegen dein Prinzip 'Privacy First' und dein Ziel 'Digitale Autarkie'." -### 2.2 Tipps für bessere Ergebnisse -1. **Nutze deine Sprache:** Verwende die Begriffe, die du auch in deinen Notizen benutzt hast. -2. **Kontext geben:** Statt nur "Qdrant" zu tippen, frage "Qdrant Setup für Mindnet", um den Kontext einzuschränken. +### 2.2 Modus: Empathie ("Der Spiegel") +Wenn du frustriert bist oder reflektieren willst, wechselt Mindnet in den "Ich"-Modus. + +* **Auslöser (Keywords & Semantik):** "Ich fühle mich...", "Traurig", "Gestresst", "Alles ist sinnlos", "Ich bin überfordert". +* **Was passiert:** Mindnet lädt deine **Erfahrungen** (`type: experience`) und **Glaubenssätze** (`type: belief`). Es antwortet verständnisvoll und zitiert deine eigenen Lektionen. +* **Beispiel-Dialog:** + * *Du:* "Ich bin total überfordert, nichts funktioniert." + * *Mindnet:* "Das Gefühl kenne ich. Erinnere dich an die Situation im Projekt X ('Der Durchbruch nach der Krise'). Damals hat uns das Mantra 'Einfach weitermachen, der Nebel lichtet sich' geholfen." + +### 2.3 Modus: Coding ("Der Techniker") +* **Auslöser:** "Code", "Python", "Funktion", "Syntax". +* **Was passiert:** Mindnet antwortet kurz, prägnant und liefert Code-Blöcke. Smalltalk wird reduziert. + +### 2.4 Modus: Fakten (Standard) +* **Auslöser:** Alles andere. "Was ist Qdrant?", "Zusammenfassung von X". +* **Was passiert:** Standard-Suche nach Wissen ohne spezielle Filter. --- ## 3. Ergebnisse interpretieren (Explanation Layer) -Mindnet liefert nicht einfach nur Treffer. Es liefert eine **Begründung** (Explanation). Achte auf diese Hinweise in der Antwort: +Mindnet liefert nicht einfach nur Treffer. Es liefert eine **Begründung** (Explanation), warum es etwas gefunden hat. ### 3.1 Die Gründe ("Reasons") Das System sagt dir in natürlicher Sprache, warum ein Treffer relevant ist: -* *"Hohe textuelle Übereinstimmung."* (Semantik war stark) -* *"Bevorzugt aufgrund des Typs 'decision'."* (Typ war wichtig) -* *"Verweist auf 'Projekt X' via 'depends_on'."* (Dieser Treffer ist eine wichtige Grundlage für deine Suche) -* *"Wird referenziert von 'Wichtige Notiz Y'."* (Dieser Treffer ist eine Autorität im Netzwerk) +* *"Hohe textuelle Übereinstimmung."* (Semantik) +* *"Bevorzugt aufgrund des Typs 'decision'."* (Wichtigkeit) +* *"Verweist auf 'Projekt X' via 'depends_on'."* (Graph-Kontext) ### 3.2 Der Score Breakdown Wenn du es genau wissen willst, schau auf die Aufschlüsselung: - Score = (Text) + (Typ-Bonus) + (Vernetzungs-Bonus) -Ein Treffer mit niedrigem Text-Score kann trotzdem auf Platz 1 landen, wenn er extrem gut vernetzt ist ("Hidden Champion"). + Score = (Text) + (Typ-Bonus) + (Vernetzungs-Bonus) --- ## 4. Neues Wissen beisteuern (Authoring) -Mindnet lebt von deinem Input. Du musst kein Techniker sein, um gutes Wissen zu designen. Du schreibst einfach Markdown. +Mindnet lebt von deinem Input. Du musst kein Techniker sein, um gutes Wissen zu designen. Siehe dazu das **Knowledge Design Manual** für Details. ### 4.1 Die Goldene Regel: "Verlinke semantisch" Statt einfach nur `[[Link]]` zu schreiben, versuche zu sagen, *wie* es zusammenhängt. * Hängt es davon ab? -> `[[rel:depends_on Ziel]]` * Ist es ähnlich? -> `[[rel:similar_to Ziel]]` -* Ist es eine Folge davon? -> `[[rel:caused_by Ziel]]` -### 4.2 Struktur hilft dem Chunker -Mindnet zerlegt deinen Text in Häppchen ("Chunks"). Hilf dabei: -* Verwende **Überschriften** (##), um Themen zu trennen. -* Schreibe **Absätze**, die einen Gedanken fassen. - -### 4.3 Typen nutzen -Setze im Frontmatter deiner Notizen den richtigen Typ (z.B. `type: project`, `type: decision`). Das steuert automatisch, wie wichtig die Notiz ist. +### 4.2 Typen nutzen (Wichtig!) +Setze im Frontmatter deiner Notizen den richtigen Typ. Das ist der wichtigste Hebel für den Chat: +* Willst du, dass Mindnet etwas als **Regel** nutzt? -> `type: principle` +* Willst du, dass Mindnet dich an eine **Lektion** erinnert? -> `type: experience` --- @@ -88,34 +98,11 @@ Setze im Frontmatter deiner Notizen den richtigen Typ (z.B. `type: project`, `ty Mindnet wird schlauer, wenn du es pflegst. ### 5.1 Feedback geben (Data Flywheel) -Das System zeichnet nun auf, welche Ergebnisse es liefert (`search_history`). -Du kannst Treffer bewerten (1-5 Sterne oder Daumen hoch/runter). -* **Was passiert damit?** Mindnet speichert "Situation" (Query) und "Reaktion" (Rating). -* **Wozu?** In Zukunft analysiert das System diese Daten, um zu lernen: "Aha, der Nutzer mag Entscheidungen lieber als Quellen". Es passt seine Gewichte dann selbstständig an (Self-Tuning). +Das System zeichnet auf, welche Ergebnisse es liefert. Du kannst Treffer bewerten (geplant für WP-10 UI). +In Zukunft analysiert das System diese Daten, um seine Gewichte selbstständig anzupassen (Self-Tuning). -### 5.2 Ergebnis fehlt? -* Existiert die Notiz im Vault? -* Ist sie isoliert (keine Links)? Isolierte Notizen haben keinen Graph-Bonus. **Verlinke sie!** - ---- - -## 6. Chat mit Mindnet (Neu in v2.2) - -Neben der Suche (`/query`) gibt es jetzt den Chat (`/chat`). - -### 6.1 Wann Chat, wann Suche? -* **Suche:** Wenn du ein konkretes Dokument oder einen Link brauchst. -* **Chat:** Wenn du eine Frage hast, die sich aus mehreren Dokumenten zusammensetzt. - * *Frage:* "Was ist der Status von Projekt X und welche Risiken gibt es?" - * *Antwort:* Mindnet liest die Projekt-Notiz UND verknüpfte Risiko-Notizen und fasst sie zusammen. - -### 6.2 Die Persönlichkeit -Der Chatbot agiert als dein "Digitaler Zwilling". Er versucht: -1. **Pragmatisch** zu sein (Lösungen statt Theorie). -2. **Transparent** zu sein (er sagt, wenn er etwas nicht weiß). -3. **Wertebasiert** zu handeln (er bevorzugt Lösungen, die deinen `type: value` Notizen entsprechen). - -### 6.3 Quellen-Check -Der Chatbot halluziniert nicht (oder sehr selten). Unter jeder Antwort listet er die **Quellen** auf, die er genutzt hat. -* Prüfe immer: Hat er die richtige `[DECISION]`-Notiz gefunden? -* Falls nein: Füge in deinem Vault einen Link (`[[rel:depends_on]]`) hinzu, damit er den Zusammenhang beim nächsten Mal sieht. \ No newline at end of file +### 5.2 Ergebnis fehlt? Troubleshooting +Wenn Mindnet etwas nicht findet: +1. **Existiert** die Notiz im Vault? (Dateiname korrekt?) +2. **Typ korrekt?** (Eine Erfahrung als `concept` getaggt wird im Empathie-Modus vielleicht übersehen). +3. **Keywords?** (Wenn du "grau" sagst, aber in der Notiz nur "schlecht" steht, füge das Wort "grau" zur Notiz hinzu). \ No newline at end of file diff --git a/tests/test_wp06_decision.py b/tests/test_wp06_decision.py new file mode 100644 index 0000000..f8a2d76 --- /dev/null +++ b/tests/test_wp06_decision.py @@ -0,0 +1,103 @@ +""" +tests/test_wp06_decision.py — Flexibler Integrationstest für WP-06 +Update: Timeout auf 300s erhöht für CPU-Inference Cold-Starts. +""" +import requests +import json +import sys +import argparse + +def test_decision_engine(query: str, port: int, expected_intent: str): + api_url = f"http://localhost:{port}" + print(f"🔵 Starte WP-06 Decision Engine Test gegen {api_url}...\n") + + payload = { + "message": query, + "top_k": 3, + "explain": True + } + + try: + # Request senden + print(f"FRAGE: '{query}'") + print("... warte auf LLM (kann auf CPU >120s dauern) ...") + + # FIX: Timeout auf 300 erhöht, passend zur Server-Config + response = requests.post(f"{api_url}/chat/", json=payload, timeout=300) + response.raise_for_status() + data = response.json() + + # --- CHECKS --- + + # 1. Intent Check + intent = data.get("intent", "UNKNOWN") + match = intent == expected_intent + print(f"\n1. INTENT DETECTION: [{'✅' if match else '❌'}]") + print(f" Erkannt: {intent} (Erwartet: {expected_intent})") + + # 2. Source Check (Strategic Retrieval) + sources = data.get("sources", []) + strategic_hits = [] + fact_hits = [] + + print(f"\n2. RETRIEVED SOURCES:") + if not sources: + print(" (Keine Quellen gefunden)") + + for i, source in enumerate(sources): + # Safe access auf Source-Dict + src_meta = source.get("source", {}) + node_type = src_meta.get("type", "unknown") + title = source.get("note_id", "Unknown") + score = source.get("total_score", 0.0) + + # Marker für Ausgabe + marker = " " + if node_type in ["value", "principle", "goal", "experience", "belief", "profile"]: + marker = "🎯" # Strategischer Treffer + strategic_hits.append(title) + else: + marker = "📄" + fact_hits.append(title) + + print(f" {marker} [{i+1}] {title} (Typ: {node_type}, Score: {score:.2f})") + + # Analyse der Strategie + if strategic_hits: + print(f"\n ✅ ERFOLG: Strategische Quellen geladen: {strategic_hits}") + else: + print(f"\n ℹ️ INFO: Keine strategischen Quellen (Value/Experience/etc.) gefunden.") + + # 3. Reasoning Check (LLM Antwort) + answer = data.get("answer", "") + print(f"\n3. REASONING (LLM Antwort):") + print("-" * 60) + print(answer) + print("-" * 60) + + except requests.exceptions.ReadTimeout: + print(f"\n❌ TIMEOUT: Der Server hat nicht innerhalb von 300s geantwortet.") + print(" Tipp: Prüfe die Server-Logs. Lädt er noch das Modell?") + sys.exit(1) + except requests.exceptions.ConnectionError: + print(f"\n❌ FEHLER: Keine Verbindung zu {api_url}. Läuft der Server?") + sys.exit(1) + except Exception as e: + print(f"\n❌ CRITICAL ERROR: {e}") + sys.exit(1) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Testet die WP-06 Decision Engine.") + parser.add_argument("--query", "-q", type=str, + default="Soll ich SuperCloud Sync für meine privaten Tagebücher nutzen?", + help="Die Frage, die an das System gestellt wird.") + parser.add_argument("--port", "-p", type=int, + default=8002, + help="Der Port der API (Default: 8002 für Dev).") + parser.add_argument("--expect", "-e", type=str, + default="DECISION", + help="Der erwartete Intent (z.B. DECISION, EMPATHY).") + + args = parser.parse_args() + + test_decision_engine(args.query, args.port, args.expect) \ No newline at end of file