diff --git a/Programmmanagement/Programmplan_V2.2.md b/Programmmanagement/Programmplan_V2.2.md index 152f1be..91ee315 100644 --- a/Programmmanagement/Programmplan_V2.2.md +++ b/Programmmanagement/Programmplan_V2.2.md @@ -1,5 +1,5 @@ # mindnet v2.2 — Programmplan -**Version:** 2.3.2 (Inkl. WP-10a GUI Evolution) +**Version:** 2.4.0 (Inkl. WP-07 Interview & WP-10a Draft Editor) **Stand:** 2025-12-10 **Status:** Aktiv @@ -24,11 +24,11 @@ - [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-07 – Interview-Assistent (abgeschlossen)](#wp-07--interview-assistent-abgeschlossen) - [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 (abgeschlossen)](#wp-10--chat-interface--writeback-abgeschlossen) - - [WP-10a – GUI Evolution: Interaktion \& Tools (geplant)](#wp-10a--gui-evolution-interaktion--tools-geplant) + - [WP-10a – GUI Evolution: Draft Editor (abgeschlossen)](#wp-10a--gui-evolution-draft-editor-abgeschlossen) - [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) @@ -39,13 +39,11 @@ - [10. Governance \& Versionierung](#10-governance--versionierung) - [11. Executive Summary](#11-executive-summary) - - --- ## 1. Programmauftrag -mindnet v2.2 entwickelt ein persönliches, wachsendes KI-Gedächtnis, das: +mindnet v2.4 entwickelt ein persönliches, wachsendes KI-Gedächtnis, das: - Wissen, Erfahrungen, Werte und Entscheidungen speichert, - diese Informationen semantisch verknüpft und rekonstruierbar macht, @@ -53,7 +51,7 @@ mindnet v2.2 entwickelt ein persönliches, wachsendes KI-Gedächtnis, das: - über mehrere Kanäle gefüttert wird: - Obsidian-Markdown (primäre Quelle), - Chat-basierter Agent (Decision Engine & RAG-Chat aktiv), - - später: Interview-Assistent (strukturierte Dialogerfassung), + - **Interview-Assistent (One-Shot Extraction aktiv)**, - automatisch neue Zusammenhänge erkennt und vernetzt (Edges, Typen, Hinweise), - sich durch Rückmeldungen (Feedback) selbst verbessert (Self-Tuning). @@ -88,7 +86,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`, `decision_engine.yaml`, Policies) festgelegt. Die Persönlichkeit entsteht durch das Config-Design, nicht durch Hardcoding. + Semantik wird überwiegend in Konfiguration (z. B. `types.yaml`, `prompts.yaml`, `decision_engine.yaml`) 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. @@ -117,6 +115,7 @@ Kernprinzipien der Vision: - **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). - **Chat Interface:** Web-basiertes Frontend (Streamlit) für einfache Interaktion und Feedback-Gabe (WP-10 abgeschlossen). +- **Interview-Assistent (WP-07):** One-Shot Extraction von Notizen ("Neues Projekt anlegen") ist live. - Technische Basis: FastAPI, Qdrant, Ollama (Local LLM), Streamlit. - Automatisierte Erkennung von Beziehungen: - Wikilinks, Inline-Relationen, Callout-Edges, Typ-Defaults. @@ -126,10 +125,9 @@ Kernprinzipien der Vision: ### 3.2 Mittelfristig (Nächste Schritte) -- **Interview-Assistent (WP-07):** Geführte Dialoge zur Erfassung neuer Notizen (Startbereit). -- mindnet erzeugt Vorschläge für neue Notes & Edges und bietet einen „Vernetzungs-Assistenten“ für manuell angelegte Notizen. +- **Self-Tuning (WP-08):** Optimierung der Gewichte in `retriever.yaml` basierend auf dem gesammelten Feedback. +- **Knowledge-Builder (WP-11):** Assistent zur Analyse und Vernetzung manuell erstellter Notizen. - Agenten können über MCP-Tools (`mindnet_query`, `mindnet_chat`) auf mindnet zugreifen. -- Self-Tuning optimiert die Gewichte in `retriever.yaml` basierend auf dem gesammelten Feedback (WP-08). ### 3.3 Langfristig @@ -191,10 +189,10 @@ 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 (Fertig) - Phase D – Agenten, MCP & Interaktion (Laufend) + Phase D – Agenten, MCP & Interaktion (Aktiv) Phase E – Review, Refactoring, Dokumentation -Alle Workpackages sind einer Phase zugeordnet. WP-01 bis WP-06 und WP-10 sind bereits erfolgreich abgeschlossen. +Alle Workpackages sind einer Phase zugeordnet. WP-01 bis WP-07 und WP-10/10a sind erfolgreich abgeschlossen. --- @@ -354,17 +352,18 @@ Transformation vom reinen Wissens-Abrufer zum strategischen Entscheidungspartner --- -### WP-07 – Interview-Assistent (geplant) +### WP-07 – Interview-Assistent (abgeschlossen) **Phase:** C/D -**Status:** 🟡 geplant (Nächster Fokus) +**Status:** 🟢 abgeschlossen **Ziel:** Dialogbasierter Erfassungs-Assistent, der strukturierte Interviews führt und daraus konsistente Markdown-Notizen generiert. -**Umfang:** -- Design von Interview-Flows (via Router-Strategie `INTERVIEW`). -- Konvertierung von Dialogtranskripten in typisierte Notes (Draft-Erstellung). +**Erreichte Ergebnisse:** +- **One-Shot Extractor:** Extrahiert Notiz-Inhalte aus einem Prompt. +- **Schema Injection:** Typspezifische Pflichtfelder (Late Binding). +- **Draft Generator:** Liefert validen Markdown-Codeblock mit `status: draft`. **Aufwand / Komplexität:** - Aufwand: Niedrig/Mittel @@ -375,7 +374,7 @@ Dialogbasierter Erfassungs-Assistent, der strukturierte Interviews führt und da ### WP-08 – Self-Tuning v1/v2 (geplant) **Phase:** B/C -**Status:** 🟡 geplant +**Status:** 🟡 geplant (Nächster Fokus) **Ziel:** Aufbau eines Self-Tuning-Mechanismus, der auf Basis von Feedback-Daten (WP-04c) Vorschläge für Retriever- und Policy-Anpassungen macht. @@ -429,18 +428,18 @@ Ablösung der Terminal-Interaktion durch ein grafisches Interface. --- -### WP-10a – GUI Evolution: Interaktion & Tools (geplant) +### WP-10a – GUI Evolution: Draft Editor (abgeschlossen) **Phase:** D -**Status:** 🟡 geplant (nach WP07/11) +**Status:** 🟢 abgeschlossen **Ziel:** Anpassung der GUI an komplexe Interaktionsmuster, die durch den Interview-Assistenten und Knowledge-Builder entstehen. -**Umfang:** -- **Draft-Editor:** Interaktive Bearbeitung und Bestätigung der Markdown-Entwürfe aus WP-07. -- **Suggestion-UI:** Checkboxen/Toggles für Kanten-Vorschläge aus WP-11 (Human-in-the-Loop). -- **Writeback:** Physisches Speichern der bestätigten Inhalte im Vault. +**Erreichte Ergebnisse:** +- **Draft Editor:** Interaktive `st.text_area` für generierte Entwürfe. +- **Sanitizer:** `normalize_meta_and_body` zur Korrektur von LLM-Fehlern. +- **Download/Copy:** Export-Funktionen für Markdown. **Aufwand / Komplexität:** - Aufwand: Mittel @@ -512,7 +511,7 @@ Aufräumen, dokumentieren, stabilisieren – insbesondere für Onboarding Dritte WP01 → WP02 → WP03 → WP04a WP04a → WP04b → WP04c → WP08 WP03 → WP05 → WP06 → WP07 - WP07/WP11 → WP10a + WP07 → WP10a WP03 → WP09 WP01/WP03 → WP10 → WP11 → WP12 WP03/WP04 → WP13 @@ -553,11 +552,11 @@ Aufräumen, dokumentieren, stabilisieren – insbesondere für Onboarding Dritte | WP05 | 🟢 | | WP05b | ⚪ | | WP06 | 🟢 | -| WP07 | 🟡 | +| WP07 | 🟢 | | WP08 | 🟡 | | WP09 | 🟡 | | WP10 | 🟢 | -| WP10a | 🟡 | +| WP10a | 🟢 | | WP11 | 🟡 | | WP12 | 🟡 | | WP13 | 🟡 | @@ -578,15 +577,15 @@ Aufräumen, dokumentieren, stabilisieren – insbesondere für Onboarding Dritte ## 11. Executive Summary -mindnet v2.2 ist so aufgesetzt, dass: +mindnet v2.4 ist so aufgesetzt, dass: -- du **schrittweise** Wissen erfassen kannst (Obsidian + Chat + später Interview-Assistent), +- du **schrittweise** Wissen erfassen kannst (Obsidian + Chat + Interview-Drafts), - 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** (Decision Engine, Empathie) existiert und den Tonfall situativ anpasst, -- eine **grafische Oberfläche** (WP-10) existiert, die komplexe Zusammenhänge (Intents, Quellen) visualisiert, +- eine **grafische Oberfläche** (WP-10/10a) existiert, die komplexe Zusammenhänge visualisiert und Co-Creation ermöglicht, - 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.1) für alle weiteren Arbeiten. \ No newline at end of file +Dieser Programmplan bildet die konsolidierte Grundlage (v2.4.0) für alle weiteren Arbeiten. \ No newline at end of file diff --git a/app/frontend/ui.py b/app/frontend/ui.py index 418e82c..d3e714b 100644 --- a/app/frontend/ui.py +++ b/app/frontend/ui.py @@ -3,6 +3,9 @@ import requests import uuid import os import json +import re +import yaml +from datetime import datetime from pathlib import Path from dotenv import load_dotenv @@ -18,15 +21,13 @@ timeout_setting = os.getenv("MINDNET_API_TIMEOUT") or os.getenv("MINDNET_LLM_TIM API_TIMEOUT = float(timeout_setting) if timeout_setting else 300.0 # --- PAGE SETUP --- -st.set_page_config(page_title="mindnet v2.3.1", page_icon="🧠", layout="wide") +st.set_page_config(page_title="mindnet v2.3.2", page_icon="🧠", layout="wide") # --- CSS STYLING --- st.markdown(""" """, unsafe_allow_html=True) # --- SESSION STATE --- if "messages" not in st.session_state: st.session_state.messages = [] if "user_id" not in st.session_state: st.session_state.user_id = str(uuid.uuid4()) -if "draft_note" not in st.session_state: st.session_state.draft_note = {"title": "", "content": "", "type": "concept"} # --- HELPER FUNCTIONS --- +def normalize_meta_and_body(meta, body): + """ + Sanitizer: Stellt sicher, dass nur erlaubte Felder im Frontmatter bleiben. + Alles andere wird in den Body verschoben (Repair-Strategie). + """ + ALLOWED_KEYS = {"title", "type", "status", "tags", "id", "created", "updated", "aliases", "lang"} + + clean_meta = {} + extra_content = [] + + # 1. Title/Titel Normalisierung + if "titel" in meta and "title" not in meta: + meta["title"] = meta.pop("titel") + + # 2. Tags Normalisierung (Synonyme) + tag_candidates = ["tags", "emotionale_keywords", "keywords", "schluesselwoerter"] + all_tags = [] + for key in tag_candidates: + if key in meta: + val = meta[key] + if isinstance(val, list): all_tags.extend(val) + elif isinstance(val, str): all_tags.extend([t.strip() for t in val.split(",")]) + + # 3. Filterung und Verschiebung + for key, val in meta.items(): + if key in ALLOWED_KEYS: + clean_meta[key] = val + elif key in tag_candidates: + pass # Schon oben behandelt + else: + # Unerlaubtes Feld (z.B. 'situation') -> Ab in den Body! + if val and isinstance(val, str): + header = key.replace("_", " ").title() + extra_content.append(f"## {header}\n{val}\n") + + if all_tags: + clean_meta["tags"] = list(set(all_tags)) + + # 4. Body Zusammenbau + if extra_content: + new_section = "\n".join(extra_content) + final_body = f"{new_section}\n{body}" + else: + final_body = body + + return clean_meta, final_body + +def parse_markdown_draft(full_text): + """ + Robustes Parsing + Sanitization. + """ + clean_text = full_text + + # Codeblock entfernen + pattern_block = r"```(?:markdown|md)?\s*(.*?)\s*```" + match_block = re.search(pattern_block, full_text, re.DOTALL | re.IGNORECASE) + if match_block: + clean_text = match_block.group(1).strip() + + # Frontmatter splitten + parts = re.split(r"^---+\s*$", clean_text, maxsplit=2, flags=re.MULTILINE) + + meta = {} + body = clean_text + + if len(parts) >= 3: + yaml_str = parts[1] + body_candidate = parts[2] + try: + parsed = yaml.safe_load(yaml_str) + if isinstance(parsed, dict): + meta = parsed + body = body_candidate.strip() + except Exception: + pass + + return normalize_meta_and_body(meta, body) + +def build_markdown_doc(meta, body): + """Baut das finale Dokument zusammen.""" + if "id" not in meta or meta["id"] == "generated_on_save": + safe_title = re.sub(r'[^a-zA-Z0-9]', '-', meta.get('title', 'note')).lower()[:30] + meta["id"] = f"{datetime.now().strftime('%Y%m%d')}-{safe_title}-{uuid.uuid4().hex[:4]}" + + meta["updated"] = datetime.now().strftime("%Y-%m-%d") + + # Sortierung für UX + ordered_meta = {} + prio_keys = ["id", "type", "title", "status", "tags"] + for k in prio_keys: + if k in meta: ordered_meta[k] = meta.pop(k) + ordered_meta.update(meta) + + try: + yaml_str = yaml.dump(ordered_meta, default_flow_style=None, sort_keys=False, allow_unicode=True).strip() + except: + yaml_str = "error: generating_yaml" + + return f"---\n{yaml_str}\n---\n\n{body}" + def load_history_from_logs(limit=10): - """Liest die letzten N Queries aus dem Logfile.""" queries = [] if HISTORY_FILE.exists(): try: @@ -65,8 +180,7 @@ def load_history_from_logs(limit=10): queries.append(q) if len(queries) >= limit: break except: continue - except Exception as e: - st.sidebar.warning(f"Log-Fehler: {e}") + except: pass return queries def send_chat_message(message: str, top_k: int, explain: bool): @@ -84,8 +198,7 @@ def send_chat_message(message: str, top_k: int, explain: bool): def submit_feedback(query_id, node_id, score, comment=None): try: requests.post(FEEDBACK_ENDPOINT, json={"query_id": query_id, "node_id": node_id, "score": score, "comment": comment}, timeout=2) - target = "Antwort" if node_id == "generated_answer" else "Quelle" - st.toast(f"Feedback für {target} gespeichert! (Score: {score})") + st.toast(f"Feedback ({score}) gesendet!") except: pass # --- UI COMPONENTS --- @@ -93,115 +206,170 @@ def submit_feedback(query_id, node_id, score, comment=None): def render_sidebar(): with st.sidebar: st.title("🧠 mindnet") - st.caption("v2.3.1 | WP-10 UI") - - mode = st.radio("Modus", ["💬 Chat", "📝 Neuer Eintrag (WP-07)"], index=0) - + st.caption("v2.3.2 | WP-10 UI") + mode = st.radio("Modus", ["💬 Chat", "📝 Manueller Editor"], index=0) st.divider() st.subheader("⚙️ Settings") top_k = st.slider("Quellen (Top-K)", 1, 10, 5) explain = st.toggle("Explanation Layer", True) - st.divider() st.subheader("🕒 Verlauf") - history = load_history_from_logs(8) - if not history: - st.caption("Noch keine Einträge.") - for q in history: - if st.button(f"🔎 {q[:30]}...", key=f"hist_{q}", help=q, use_container_width=True): + for q in load_history_from_logs(8): + if st.button(f"🔎 {q[:25]}...", key=f"hist_{q}", use_container_width=True): st.session_state.messages.append({"role": "user", "content": q}) st.rerun() - return mode, top_k, explain +def render_draft_editor(msg): + qid = msg.get('query_id', str(uuid.uuid4())) + key_base = f"draft_{qid}" + + # 1. Init + if f"{key_base}_init" not in st.session_state: + meta, body = parse_markdown_draft(msg["content"]) + + st.session_state[f"{key_base}_type"] = meta.get("type", "default") + st.session_state[f"{key_base}_title"] = meta.get("title", "") + + tags_raw = meta.get("tags", []) + st.session_state[f"{key_base}_tags"] = ", ".join(tags_raw) if isinstance(tags_raw, list) else str(tags_raw) + + st.session_state[f"{key_base}_body"] = body.strip() + st.session_state[f"{key_base}_meta"] = meta + st.session_state[f"{key_base}_init"] = True + + # 2. UI + st.markdown(f'
', unsafe_allow_html=True) + st.markdown("### 📝 Entwurf bearbeiten") + + # Metadata + c1, c2 = st.columns([2, 1]) + with c1: + new_title = st.text_input("Titel", value=st.session_state.get(f"{key_base}_title", ""), key=f"{key_base}_inp_title") + with c2: + known_types = ["concept", "project", "decision", "experience", "journal", "person", "value", "goal", "principle", "default"] + curr_type = st.session_state.get(f"{key_base}_type", "default") + if curr_type not in known_types: known_types.append(curr_type) + new_type = st.selectbox("Typ", known_types, index=known_types.index(curr_type), key=f"{key_base}_sel_type") + + new_tags = st.text_input("Tags (kommagetrennt)", value=st.session_state.get(f"{key_base}_tags", ""), key=f"{key_base}_inp_tags") + + # Tabs + tab_edit, tab_view = st.tabs(["✏️ Inhalt", "👁️ Vorschau"]) + + with tab_edit: + st.caption("Bearbeite hier den Inhalt. Metadaten (oben) werden automatisch hinzugefügt.") + new_body = st.text_area( + "Body", + value=st.session_state.get(f"{key_base}_body", ""), + height=500, + key=f"{key_base}_txt_body", + label_visibility="collapsed" + ) + + # Reassembly + final_tags_list = [t.strip() for t in new_tags.split(",") if t.strip()] + final_meta = st.session_state.get(f"{key_base}_meta", {}).copy() + final_meta.update({ + "id": "generated_on_save", + "type": new_type, + "title": new_title, + "status": "draft", + "tags": final_tags_list + }) + + final_doc = build_markdown_doc(final_meta, new_body) + + with tab_view: + st.markdown('
', unsafe_allow_html=True) + st.markdown(final_doc) + st.markdown('
', unsafe_allow_html=True) + + st.markdown("---") + + # Actions + b1, b2 = st.columns([1, 1]) + with b1: + fname = f"{datetime.now().strftime('%Y%m%d')}-{new_type}.md" + st.download_button("💾 Download .md", data=final_doc, file_name=fname, mime="text/markdown") + with b2: + if st.button("📋 Code anzeigen", key=f"{key_base}_btn_copy"): + st.code(final_doc, language="markdown") + + st.markdown("
", unsafe_allow_html=True) + + def render_chat_interface(top_k, explain): - # Render History - for msg in st.session_state.messages: + for idx, msg in enumerate(st.session_state.messages): with st.chat_message(msg["role"]): if msg["role"] == "assistant": - # Intent Badge MIT SOURCE (Fix für Debugging) - if "intent" in msg: - icon = {"EMPATHY": "❤️", "DECISION": "⚖️", "CODING": "💻", "FACT": "📚"}.get(msg["intent"], "🧠") - source_info = msg.get("intent_source", "Unknown") - # Hier wird die Quelle wieder angezeigt: - st.markdown(f'
{icon} Intent: {msg["intent"]} via {source_info}
', unsafe_allow_html=True) + # Meta + intent = msg.get("intent", "UNKNOWN") + src = msg.get("intent_source", "?") + icon = {"EMPATHY":"❤️", "DECISION":"⚖️", "CODING":"💻", "FACT":"📚", "INTERVIEW":"📝"}.get(intent, "🧠") + st.markdown(f'
{icon} Intent: {intent} ({src})
', unsafe_allow_html=True) - st.markdown(msg["content"]) + # Debugging (Always visible for safety) + with st.expander("🐞 Debug Raw Payload", expanded=False): + st.json(msg) + + # Logic + if intent == "INTERVIEW": + render_draft_editor(msg) + else: + st.markdown(msg["content"]) # Sources - if "sources" in msg: + if "sources" in msg and msg["sources"]: for hit in msg["sources"]: - score = hit.get('total_score', 0) - icon = "🟢" if score > 0.8 else "🟡" if score > 0.5 else "⚪" - with st.expander(f"{icon} {hit.get('note_id', '?')} ({score:.2f})"): + with st.expander(f"📄 {hit.get('note_id', '?')} ({hit.get('total_score', 0):.2f})"): st.markdown(f"_{hit.get('source', {}).get('text', '')[:300]}..._") if hit.get('explanation'): st.caption(f"Grund: {hit['explanation']['reasons'][0]['message']}") - - # Granular Feedback (Faces) - def _cb(qid=msg["query_id"], nid=hit['node_id']): + def _cb(qid=msg.get("query_id"), nid=hit.get('node_id')): val = st.session_state.get(f"fb_src_{qid}_{nid}") - if val is not None: submit_feedback(qid, nid, val+1, "Faces UI") - - st.feedback("faces", key=f"fb_src_{msg['query_id']}_{hit['node_id']}", on_change=_cb) + if val is not None: submit_feedback(qid, nid, val+1) + st.feedback("faces", key=f"fb_src_{msg.get('query_id')}_{hit.get('node_id')}", on_change=_cb) - # Global Feedback (Stars) - qid = msg["query_id"] - st.feedback("stars", key=f"fb_glob_{qid}", on_change=lambda: submit_feedback(qid, "generated_answer", st.session_state[f"fb_glob_{qid}"]+1)) - + if "query_id" in msg: + qid = msg["query_id"] + st.feedback("stars", key=f"fb_glob_{qid}", on_change=lambda: submit_feedback(qid, "generated_answer", st.session_state[f"fb_glob_{qid}"]+1)) else: st.markdown(msg["content"]) - # Input Logic - last_msg_is_user = len(st.session_state.messages) > 0 and st.session_state.messages[-1]["role"] == "user" - if prompt := st.chat_input("Frage Mindnet..."): st.session_state.messages.append({"role": "user", "content": prompt}) st.rerun() - if last_msg_is_user: - last_prompt = st.session_state.messages[-1]["content"] + if len(st.session_state.messages) > 0 and st.session_state.messages[-1]["role"] == "user": with st.chat_message("assistant"): with st.spinner("Thinking..."): - resp = send_chat_message(last_prompt, top_k, explain) - + resp = send_chat_message(st.session_state.messages[-1]["content"], top_k, explain) if "error" in resp: st.error(resp["error"]) else: - msg_data = { + st.session_state.messages.append({ "role": "assistant", "content": resp.get("answer"), "intent": resp.get("intent", "FACT"), - "intent_source": resp.get("intent_source", "Unknown"), # Wichtig für Anzeige + "intent_source": resp.get("intent_source", "Unknown"), "sources": resp.get("sources", []), "query_id": resp.get("query_id") - } - st.session_state.messages.append(msg_data) + }) st.rerun() -def render_creation_interface(): - st.header("📝 Neuer Wissens-Eintrag (WP-07/11)") - st.info("Hier kannst du strukturierte Notizen erstellen, die direkt in den Obsidian Vault gespeichert werden.") - - with st.form("new_entry"): - col1, col2 = st.columns([3, 1]) - title = col1.text_input("Titel der Notiz", placeholder="z.B. Projekt Gamma Meeting") - n_type = col2.selectbox("Typ", ["concept", "meeting", "person", "project", "decision"]) - - content = st.text_area("Inhalt (Markdown)", height=300, placeholder="# Protokoll\n\n- Punkt 1...") - - st.markdown("**Automatische Vernetzung:**") - st.caption("Verwende `[[Link]]` für Referenzen und `[[rel:depends_on X]]` für logische Kanten.") - - submitted = st.form_submit_button("💾 Speichern & Indizieren") - if submitted: - st.success(f"Mockup: Notiz '{title}' ({n_type}) wäre jetzt gespeichert worden!") - st.balloons() +def render_manual_editor(): + st.header("📝 Manueller Editor") + c1, c2 = st.columns([1, 2]) + n_type = c1.selectbox("Typ", ["concept", "project", "decision", "experience", "value", "goal"]) + tags = c2.text_input("Tags") + body = st.text_area("Inhalt", height=400, placeholder="# Titel\n\nText...") + if st.button("Code anzeigen"): + meta = {"type": n_type, "status": "draft", "tags": [t.strip() for t in tags.split(",")]} + st.code(build_markdown_doc(meta, body), language="markdown") -# --- MAIN LOOP --- mode, top_k, explain = render_sidebar() - if mode == "💬 Chat": render_chat_interface(top_k, explain) else: - render_creation_interface() \ No newline at end of file + render_manual_editor() \ No newline at end of file diff --git a/app/routers/chat.py b/app/routers/chat.py index 5ab2d3a..45cb679 100644 --- a/app/routers/chat.py +++ b/app/routers/chat.py @@ -1,10 +1,11 @@ """ -app/routers/chat.py — RAG Endpunkt (WP-06 Hybrid Router + WP-04c Feedback) -Version: 2.3.2 (Merged Stability Patch) +app/routers/chat.py — RAG Endpunkt (WP-06 Hybrid Router + WP-07 Interview Mode) +Version: 2.4.0 (Interview Support) Features: - Hybrid Intent Router (Keyword + LLM) - Strategic Retrieval (Late Binding via Config) +- Interview Loop (Schema-driven Data Collection) - Context Enrichment (Payload/Source Fallback) - Data Flywheel (Feedback Logging Integration) """ @@ -21,7 +22,6 @@ 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 -# [MERGE] Integration Feedback Service (WP-04c) from app.services.feedback_service import log_search router = APIRouter() @@ -62,6 +62,47 @@ def get_decision_strategy(intent: str) -> Dict[str, Any]: strategies = config.get("strategies", {}) return strategies.get(intent, strategies.get("FACT", {})) +# --- Helper: Target Type Detection (WP-07) --- + +def _detect_target_type(message: str, configured_schemas: Dict[str, Any]) -> str: + """ + Versucht zu erraten, welchen Notiz-Typ der User erstellen will. + Nutzt Keywords und Mappings. + """ + message_lower = message.lower() + + # 1. Direkter Match mit Schema-Keys (z.B. "projekt", "entscheidung") + # Ignoriere 'default' hier + for type_key in configured_schemas.keys(): + if type_key == "default": + continue + if type_key in message_lower: + return type_key + + # 2. Synonym-Mapping (Deutsch -> Schema Key) + # Dies verbessert die UX, falls User deutsche Begriffe nutzen + synonyms = { + "projekt": "project", + "vorhaben": "project", + "entscheidung": "decision", + "beschluss": "decision", + "ziel": "goal", + "erfahrung": "experience", + "lektion": "experience", + "wert": "value", + "prinzip": "principle", + "grundsatz": "principle", + "notiz": "default", + "idee": "default" + } + + for term, schema_key in synonyms.items(): + if term in message_lower: + # Prüfen, ob der gemappte Key auch konfiguriert ist + if schema_key in configured_schemas: + return schema_key + + return "default" # --- Dependencies --- @@ -167,67 +208,118 @@ async def chat_endpoint( # 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", - top_k=request.top_k, - explain=request.explain - ) - retrieve_result = await retriever.search(query_req) - hits = retrieve_result.results - # 3. Strategic Retrieval (WP-06 Kernfeature) - 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) + # --- SPLIT LOGIC: INTERVIEW vs. RAG --- + + sources_hits = [] + final_prompt = "" + + if intent == "INTERVIEW": + # --- WP-07: INTERVIEW MODE --- + # Kein Retrieval. Wir nutzen den Dialog-Kontext. + + # 1. Schema Loading (Late Binding) + schemas = strategy.get("schemas", {}) + target_type = _detect_target_type(request.message, schemas) + active_schema = schemas.get(target_type, schemas.get("default")) + + logger.info(f"[{query_id}] Starting Interview for Type: {target_type}") + + # Robustes Schema-Parsing (Dict vs List) + if isinstance(active_schema, dict): + fields_list = active_schema.get("fields", []) + hint_str = active_schema.get("hint", "") + else: + fields_list = active_schema # Fallback falls nur Liste definiert + hint_str = "" + + fields_str = "\n- " + "\n- ".join(fields_list) + + # 2. Context Logic + # Hinweis: In einer Stateless-API ist {context_str} idealerweise die History. + # Da ChatRequest (noch) kein History-Feld hat, nutzen wir einen Placeholder + # oder verlassen uns darauf, dass der Client die History im Prompt mitschickt + # (Streamlit Pattern: Appends history to prompt). + # Wir labeln es hier explizit. + context_str = "Bisheriger Verlauf (falls vorhanden): Siehe oben/unten." + + # 3. Prompt Assembly + template = llm.prompts.get(prompt_key, "") + final_prompt = template.replace("{context_str}", context_str) \ + .replace("{query}", request.message) \ + .replace("{target_type}", target_type) \ + .replace("{schema_fields}", fields_str) \ + .replace("{schema_hint}", hint_str) + + # Keine Hits im Interview + sources_hits = [] - 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) - - # 4. Context Building - if not hits: - context_str = "Keine relevanten Notizen gefunden." else: - context_str = _build_enriched_context(hits) + # --- WP-06: STANDARD RAG MODE --- + inject_types = strategy.get("inject_types", []) + prepend_instr = strategy.get("prepend_instruction", "") - # 5. Generation - template = llm.prompts.get(prompt_key, "{context_str}\n\n{query}") - system_prompt = llm.prompts.get("system_prompt", "") + # 2. Primary Retrieval + query_req = QueryRequest( + query=request.message, + mode="hybrid", + top_k=request.top_k, + explain=request.explain + ) + retrieve_result = await retriever.search(query_req) + hits = retrieve_result.results + + # 3. Strategic Retrieval (WP-06 Kernfeature) + 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) + + # 4. Context Building + if not hits: + context_str = "Keine relevanten Notizen gefunden." + else: + context_str = _build_enriched_context(hits) + + # 5. Generation Setup + template = llm.prompts.get(prompt_key, "{context_str}\n\n{query}") + + if prepend_instr: + context_str = f"{prepend_instr}\n\n{context_str}" + + final_prompt = template.replace("{context_str}", context_str).replace("{query}", request.message) + sources_hits = hits - if prepend_instr: - context_str = f"{prepend_instr}\n\n{context_str}" - - final_prompt = template.replace("{context_str}", context_str).replace("{query}", request.message) + # --- COMMON GENERATION --- + + system_prompt = llm.prompts.get("system_prompt", "") logger.info(f"[{query_id}] Sending to LLM (Intent: {intent}, Template: {prompt_key})...") - # System-Prompt separat übergeben (WP-06a Fix) + # System-Prompt separat übergeben answer_text = await llm.generate_raw_response(prompt=final_prompt, system=system_prompt) duration_ms = int((time.time() - start_time) * 1000) - # 6. Logging (Fire & Forget) - [MERGE POINT] - # Wir loggen alles für das Data Flywheel (WP-08 Self-Tuning) + # 6. Logging (Fire & Forget) try: log_search( query_id=query_id, query_text=request.message, - results=hits, - mode="chat_rag", + results=sources_hits, + mode="interview" if intent == "INTERVIEW" else "chat_rag", metadata={ "intent": intent, "intent_source": intent_source, @@ -242,7 +334,7 @@ async def chat_endpoint( return ChatResponse( query_id=query_id, answer=answer_text, - sources=hits, + sources=sources_hits, latency_ms=duration_ms, intent=intent, intent_source=intent_source diff --git a/config/decision_engine.yaml b/config/decision_engine.yaml index f0f9e2d..406ec25 100644 --- a/config/decision_engine.yaml +++ b/config/decision_engine.yaml @@ -1,17 +1,19 @@ # config/decision_engine.yaml -# Steuerung der Decision Engine (WP-06) +# Steuerung der Decision Engine (WP-06 + WP-07) # Hybrid-Modus: Keywords (Fast) + LLM Router (Smart Fallback) -version: 1.2 +version: 1.3 settings: llm_fallback_enabled: true # Few-Shot Prompting für bessere SLM-Performance + # Erweitert um INTERVIEW Beispiele llm_router_prompt: | Du bist ein Klassifikator. Analysiere die Nachricht und wähle die passende Strategie. Antworte NUR mit dem Namen der Strategie. STRATEGIEN: + - INTERVIEW: User will Wissen strukturieren, Notizen anlegen, Projekte starten ("Neu", "Festhalten"). - DECISION: Rat, Strategie, Vor/Nachteile, "Soll ich". - EMPATHY: Gefühle, Frust, Freude, Probleme, "Alles ist sinnlos", "Ich bin traurig". - CODING: Code, Syntax, Programmierung, Python. @@ -20,6 +22,8 @@ settings: BEISPIELE: User: "Wie funktioniert Qdrant?" -> FACT User: "Soll ich Qdrant nutzen?" -> DECISION + User: "Ich möchte ein neues Projekt anlegen" -> INTERVIEW + User: "Lass uns eine Entscheidung festhalten" -> INTERVIEW User: "Schreibe ein Python Script" -> CODING User: "Alles ist grau und sinnlos" -> EMPATHY User: "Mir geht es heute gut" -> EMPATHY @@ -86,4 +90,54 @@ strategies: - "yaml" inject_types: ["snippet", "reference", "source"] prompt_template: "technical_template" - prepend_instruction: null \ No newline at end of file + prepend_instruction: null + + # 5. Interview / Datenerfassung (WP-07) + INTERVIEW: + description: "Der User möchte strukturiertes Wissen erfassen (Projekt, Notiz, Idee)." + trigger_keywords: + - "neue notiz" + - "neues projekt" + - "neue entscheidung" + - "neues ziel" + - "festhalten" + - "entwurf erstellen" + - "interview" + - "dokumentieren" + - "erfassen" + - "idee speichern" + inject_types: [] # Keine RAG-Suche, reiner Kontext-Dialog + prompt_template: "interview_template" + prepend_instruction: null + + # LATE BINDING SCHEMAS: + # Definition der Pflichtfelder pro Typ (korrespondiert mit types.yaml) + # Wenn ein Typ hier fehlt, wird 'default' genutzt. + schemas: + default: + fields: ["Titel", "Thema/Inhalt", "Tags"] + hint: "Halte es einfach und übersichtlich." + + project: + fields: ["Titel", "Zielsetzung (Goal)", "Status (draft/active)", "Wichtige Stakeholder", "Nächste Schritte"] + hint: "Achte darauf, Abhängigkeiten zu anderen Projekten mit [[rel:depends_on]] zu erfragen." + + decision: + fields: ["Titel", "Kontext (Warum entscheiden wir?)", "Getroffene Entscheidung", "Betrachtete Alternativen", "Status (proposed/final)"] + hint: "Wichtig: Frage explizit nach den Gründen gegen die Alternativen." + + goal: + fields: ["Titel", "Zeitrahmen (Deadline)", "Messkriterien (KPIs)", "Verbundene Werte"] + hint: "Ziele sollten SMART formuliert sein." + + experience: + fields: ["Titel", "Situation (Kontext)", "Erkenntnis (Learning)", "Emotionale Keywords (für Empathie-Suche)"] + hint: "Fokussiere dich auf die persönliche Lektion." + + value: + fields: ["Titel (Name des Werts)", "Definition (Was bedeutet das für uns?)", "Anti-Beispiel (Was ist es nicht?)"] + hint: "Werte dienen als Entscheidungsgrundlage." + + principle: + fields: ["Titel", "Handlungsanweisung", "Begründung"] + hint: "Prinzipien sind härter als Werte." \ No newline at end of file diff --git a/config/prompts.yaml b/config/prompts.yaml index b36b12c..f192109 100644 --- a/config/prompts.yaml +++ b/config/prompts.yaml @@ -93,4 +93,48 @@ technical_template: | FORMAT: - Kurze Erklärung des Ansatzes. - Markdown Code-Block (Copy-Paste fertig). - - Wichtige Edge-Cases. \ No newline at end of file + - Wichtige Edge-Cases. +# --------------------------------------------------------- +# 5. INTERVIEW: Der "One-Shot Extractor" (Performance Mode) +# --------------------------------------------------------- + +interview_template: | + TASK: + Erstelle einen Markdown-Entwurf für eine Notiz vom Typ '{target_type}'. + + SCHEMA (Inhaltliche Pflichtfelder für den Body): + {schema_fields} + + USER INPUT: + "{query}" + + ANWEISUNG: + 1. Extrahiere Informationen aus dem Input. + 2. Generiere validen Markdown. + + OUTPUT REGELN (STRIKT BEACHTEN): + A. FRONTMATTER (YAML): + - Darf NUR folgende Felder enthalten: [type, status, title, tags]. + - Schreibe KEINE inhaltlichen Sätze (wie 'Situation', 'Ziel') in das YAML! + - Setze 'status: draft'. + + B. BODY (Markdown): + - Nutze für jedes Schema-Feld eine Markdown-Überschrift (## Feldname). + - Schreibe den Inhalt DARUNTER. + - Nutze "[TODO: Ergänzen]", wenn Infos fehlen. + + HINWEIS ZUM TYP: + {schema_hint} + + OUTPUT FORMAT BEISPIEL: + ```markdown + --- + type: {target_type} + status: draft + title: ... + tags: [...] + --- + # Titel der Notiz + + ## Erstes Schema Feld + Der Inhalt hier... \ No newline at end of file diff --git a/docs/Knowledge_Design_Manual.md b/docs/Knowledge_Design_Manual.md index 1175003..95de77e 100644 --- a/docs/Knowledge_Design_Manual.md +++ b/docs/Knowledge_Design_Manual.md @@ -1,7 +1,7 @@ -# mindnet v2.2 – Knowledge Design Manual -**Datei:** `docs/mindnet_knowledge_design_manual_v2.2.md` +# mindnet v2.4 – Knowledge Design Manual +**Datei:** `docs/mindnet_knowledge_design_manual_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Integrierter Stand WP01–WP10) +**Status:** **FINAL** (Integrierter Stand WP01–WP10a) **Quellen:** `knowledge_design.md`, `TYPE_REGISTRY_MANUAL.md`, `chunking_strategy.md`, `mindnet_functional_architecture.md`. --- @@ -28,6 +28,7 @@ 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). * **Web UI (WP10):** Du kannst direkt sehen, welche Quellen genutzt wurden. +* **Interview Modus (WP07):** Du kannst Notizen direkt im Chat entwerfen lassen. ### 1.2 Der Vault als „Source of Truth“ Die Markdown-Dateien in deinem Vault sind die **einzige Quelle der Wahrheit**. @@ -48,7 +49,7 @@ Jede Datei muss mindestens folgende Felder enthalten, um korrekt verarbeitet zu 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) + status: active # active, archived oder 'draft' (für generierte Notes) created: 2025-11-10 # Erstellungsdatum (ISO 8601 oder YYYY-MM-DD) updated: 2025-12-07 # Letzte Änderung tags: [ki, entwicklung] # Taxonomie für Filterung @@ -79,23 +80,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 steuert nicht nur das Gewicht bei der Suche, sondern seit WP-06 auch, **wann** eine Notiz aktiv in den Chat geholt wird ("Strategic Retrieval"). +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") und **welche Felder** im Interview abgefragt werden. ### 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) | +| Typ | Beschreibung & Einsatzzweck | Rolle im Chat (Intent) | Interview Schema (WP07) | +| :--- | :--- | :--- | :--- | +| **`concept`** | Fachbegriffe, Theorien. Zeitloses Wissen. | **FACT** | Titel, Definition, Tags | +| **`project`** | Ein Vorhaben mit Ziel, Dauer und Aufgaben. | **FACT / DECISION** | Ziel, Status, Stakeholder, Steps | +| **`experience`** | Persönliche Erfahrung, Lektion oder Erkenntnis. | **EMPATHY** | Situation, Erkenntnis, Emotionen | +| **`decision`** | Eine bewusst getroffene Entscheidung (ADR). | **DECISION** | Kontext, Entscheidung, Alternativen | +| **`value`** | Ein persönlicher Wert oder ein Prinzip. | **DECISION** | Definition, Anti-Beispiel | +| **`goal`** | Ein strategisches Ziel (kurz- oder langfristig). | **DECISION** | Zeitrahmen, KPIs, Werte | +| **`person`** | Eine reale Person (Netzwerk, Autor). | **FACT** | Rolle, Kontext | +| **`journal`** | Zeitbezogener Log-Eintrag, Daily Note. | **FACT** | Datum, Tags | +| **`source`** | Externe Quelle (Buch, PDF, Artikel). | **FACT** | Autor, URL | ### 3.2 Zusammenspiel mit `types.yaml` @@ -200,6 +201,14 @@ Da deine Notizen im Web-Interface (WP10) angezeigt werden: * **Kurze Absätze:** Das LLM liest besser, und der Mensch scannt schneller. * **Klare Headings:** Nutze H1/H2, um dem Chunker logische Trennlinien zu geben. +### 5.4 Der Interview-Modus (Auto-Drafting) +Seit v2.4 (WP07) kann Mindnet Notizen für dich entwerfen. + +* **Wie:** Schreibe im Chat einfach: *"Ich möchte ein neues Projekt 'Alpha' anlegen, Ziel ist die Markteroberung."* +* **Was passiert:** Mindnet erkennt den Wunsch (`INTERVIEW`), wählt das Schema für `project` und generiert **sofort** einen Markdown-Entwurf. +* **Ergebnis:** Du erhältst einen Code-Block mit `status: draft`. Diesen kannst du im Draft-Editor (UI) direkt bearbeiten und herunterladen. +* **Drafts:** Enthalten oft Platzhalter `[TODO]`. Das ist Absicht. Ergänze sie im Editor. + --- ## 6. Best Practices & Beispiele (Klassik) diff --git a/docs/Overview.md b/docs/Overview.md index 1162ee4..d8aacdc 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` +# Mindnet v2.4 – Overview & Einstieg +**Datei:** `docs/mindnet_overview_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Post-WP10 Release) -**Version:** 2.3.1 +**Status:** **FINAL** (Inkl. Interview-Assistent & Web-Editor) +**Version:** 2.4.0 --- @@ -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** situativ angepasst: Mal als harter Strategieberater, mal als empathischer Spiegel. +* Es **antwortet** situativ angepasst: Mal als Strategieberater, mal als empathischer Spiegel, und neu: **als Interviewer, der hilft, Wissen zu erfassen.** ### Die Vision -> „Ein System, das nicht nur speichert, was ich weiß, sondern auch wie ich denke und fühle.“ +> „Ein System, das nicht nur speichert, was ich weiß, sondern auch wie ich denke, fühle und arbeite.“ --- @@ -36,14 +36,16 @@ Mindnet arbeitet auf drei Schichten, die aufeinander aufbauen: * **Technik:** Hybrider Retriever (Graph + Vektor), Explanation Engine. * **Status:** 🟢 Live (WP04). -### 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." +### Ebene 3: Identität & Interaktion (Die Persönlichkeit) +* **Funktion:** Interaktion, Bewertung und Co-Creation. +* **Logik:** + * "Ich empfehle Lösung X, weil sie unserem Wert 'Datensparsamkeit' entspricht." + * "Ich sehe, du willst ein Projekt starten. Lass uns die Eckdaten erfassen." * **Technik:** - * **Intent Router:** Erkennt Absichten (Fakt vs. Gefühl vs. Entscheidung). + * **Intent Router:** Erkennt Absichten (Fakt vs. Gefühl vs. Entscheidung vs. Interview). * **Strategic Retrieval:** Lädt gezielt Werte oder Erfahrungen nach. - * **Multi-Persona:** Passt den Tonfall an. -* **Status:** 🟢 Live (WP05–WP06). + * **One-Shot Extraction:** Generiert Entwürfe für neue Notizen. +* **Status:** 🟢 Live (WP05–WP07, WP10). --- @@ -51,18 +53,20 @@ Mindnet arbeitet auf drei Schichten, die aufeinander aufbauen: Der Datenfluss in Mindnet ist zyklisch ("Data Flywheel"): -1. **Input:** Du schreibst Notizen in Obsidian. +1. **Input:** Du schreibst Notizen in Obsidian **ODER** lässt sie von Mindnet im Chat entwerfen. 2. **Ingest:** Ein Python-Skript importiert, zerlegt (Chunking) und vernetzt (Edges) die Daten in Qdrant. -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. +3. **Intent Recognition:** Der Router analysiert deine Frage: Willst du Fakten, Code, Empathie oder etwas dokumentieren? +4. **Retrieval / Action:** + * Bei Fragen: Das System sucht Inhalte passend zum Intent. + * Bei Interviews: Das System wählt das passende Schema (z.B. Projekt-Vorlage). +5. **Generation:** Ein lokales LLM (Ollama) formuliert die Antwort oder den Markdown-Draft. 6. **Feedback:** Du bewertest die Antwort. Das System lernt (langfristig) daraus. **Tech-Stack:** -* **Backend:** Python 3.12, FastAPI. +* **Backend:** Python 3.10+, FastAPI. * **Datenbank:** Qdrant (Vektor & Graph). -* **KI:** Ollama (Phi-3 Mini / Mistral) – 100% lokal. -* **Frontend:** Streamlit Web-UI (v2.3.1). +* **KI:** Ollama (Phi-3 Mini) – 100% lokal. +* **Frontend:** Streamlit Web-UI (v2.4). --- @@ -72,25 +76,25 @@ Wo findest du was? | Wenn du... | ...lies dieses Dokument | | :--- | :--- | -| **...wissen willst, wie man Notizen schreibt.** | `mindnet_knowledge_design_manual_v2.2.md` | -| **...das System installieren oder betreiben musst.** | `mindnet_admin_guide_v2.2.md` | -| **...am Python-Code entwickeln willst.** | `mindnet_developer_guide_v2.2.md` | -| **...die Pipeline (Import -> RAG) verstehen willst.** | `mindnet_pipeline_playbook_v2.2.md` | +| **...wissen willst, wie man Notizen schreibt.** | `mindnet_knowledge_design_manual_v2.4.md` | +| **...das System installieren oder betreiben musst.** | `mindnet_admin_guide_v2.4.md` | +| **...am Python-Code entwickeln willst.** | `mindnet_developer_guide_v2.4.md` | +| **...die Pipeline (Import -> RAG) verstehen willst.** | `mindnet_pipeline_playbook_v2.4.md` | | **...die genaue JSON-Struktur oder APIs suchst.** | `mindnet_technical_architecture.md` | | **...verstehen willst, was fachlich passiert.** | `mindnet_functional_architecture.md` | -| **...den aktuellen Projektstatus suchst.** | `Programmplan_V2.2.md` | +| **...den aktuellen Projektstatus suchst.** | `mindnet_appendices_v2.4.md` | --- ## 5. Rollen im System * **Mindmaster (User/Owner):** Du. Du erstellst Inhalte, stellst Fragen und gibst Feedback. Du definierst die Werte (`type: value`). -* **Mindnet (Der Agent):** Der digitale Zwilling. Er agiert als pragmatischer, transparenter Assistent im Chat. +* **Mindnet (Der Agent):** Der digitale Zwilling. Er agiert als pragmatischer, transparenter Assistent und Analyst. * **Administrator:** Verantwortlich für Docker-Container, Backups und LLM-Ressourcen. --- ## 6. Aktueller Fokus -Wir haben **Phase D (Interaktion)** mit WP10 (Chat Interface) begonnen und die UI erfolgreich deployed. -Das System ist nun für Endnutzer bedienbar. Als Nächstes folgt der **Interview-Assistent (WP07)**, um Wissen dialogisch zu erfassen. \ No newline at end of file +Wir haben den **Interview-Assistenten (WP07)** und den **Draft-Editor (WP10a)** erfolgreich integriert. +Das System kann nun aktiv helfen, Wissen zu strukturieren, anstatt es nur abzurufen. Der Fokus verschiebt sich nun in Richtung **Self-Tuning (WP08)**, um aus dem gesammelten Feedback automatisch zu lernen. \ No newline at end of file diff --git a/docs/admin_guide.md b/docs/admin_guide.md index 8603b3e..c9bafe8 100644 --- a/docs/admin_guide.md +++ b/docs/admin_guide.md @@ -1,8 +1,8 @@ -# Mindnet v2.2 – Admin Guide -**Datei:** `docs/mindnet_admin_guide_v2.2.md` +# Mindnet v2.4 – Admin Guide +**Datei:** `docs/mindnet_admin_guide_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Inkl. Frontend Deployment) -**Quellen:** `Handbuch.md`, `mindnet_developer_guide_v2.2.md`. +**Status:** **FINAL** (Inkl. Frontend Deployment & Interview Config) +**Quellen:** `Handbuch.md`, `mindnet_developer_guide_v2.4.md`. > Dieses Handbuch richtet sich an **Administratoren**. Es beschreibt Installation, Konfiguration, Backup-Strategien, Monitoring und den sicheren Betrieb der Mindnet-Instanz (API + UI + DB). @@ -66,7 +66,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. Die neuen Settings für WP-06 (Timeout, Decision Config) sind essenziell für stabilen Betrieb auf CPUs. +Erstelle eine `.env` Datei im Root-Verzeichnis. Die neuen Settings für WP-06/WP-07 (Timeout, Decision Config) sind essenziell für stabilen Betrieb auf CPUs. # Qdrant Verbindung QDRANT_URL="http://localhost:6333" @@ -77,7 +77,7 @@ Erstelle eine `.env` Datei im Root-Verzeichnis. Die neuen Settings für WP-06 (T # LLM / RAG Settings MINDNET_LLM_MODEL="phi3:mini" - MINDNET_OLLAMA_URL="[http://127.0.0.1:11434](http://127.0.0.1:11434)" + MINDNET_OLLAMA_URL="http://127.0.0.1:11434" # Config & Timeouts MINDNET_PROMPTS_PATH="./config/prompts.yaml" diff --git a/docs/appendix.md b/docs/appendix.md index 091d832..d9fc8f4 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` +# Mindnet v2.4 – Appendices & Referenzen +**Datei:** `docs/mindnet_appendices_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Integrierter Stand WP01–WP10) +**Status:** **FINAL** (Integrierter Stand WP01–WP10a) **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.3.1). +Diese Tabelle zeigt die Standard-Konfiguration der `types.yaml` (Stand v2.4). | Typ (`type`) | Chunk Profile | Retriever Weight | Edge Defaults (Auto-Kanten) | Beschreibung | | :--- | :--- | :--- | :--- | :--- | @@ -23,8 +23,8 @@ Diese Tabelle zeigt die Standard-Konfiguration der `types.yaml` (Stand v2.3.1). | **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). | +| **goal** | `medium` | 0.95 | `depends_on` | Strategische Ziele. | +| **belief** | `medium` | 0.90 | `related_to` | Glaubenssätze. | | **default** | `medium` | 1.00 | `references` | Fallback, wenn Typ unbekannt. | --- @@ -71,7 +71,7 @@ Diese sind die Felder, die effektiv in Qdrant gespeichert werden. { "chunk_id": "string (keyword)", // Format: {note_id}#c{index} "note_id": "string (keyword)", // FK zur Note - "type": "string (keyword)", // Typ-Kopie aus Note (Neu in WP06a) + "type": "string (keyword)", // Typ-Kopie aus Note "text": "string (text)", // Reintext für Anzeige (ohne Overlap) "window": "string (text)", // Text + Overlap (für Embedding) "ord": "integer", // Laufende Nummer (1..N) @@ -87,10 +87,10 @@ Diese sind die Felder, die effektiv in Qdrant gespeichert werden. "source_id": "string (keyword)", // Chunk-ID (Start) "target_id": "string (keyword)", // Chunk-ID oder Note-Titel (Ziel) "kind": "string (keyword)", // z.B. 'depends_on' - "scope": "string (keyword)", // Immer 'chunk' in v2.2 + "scope": "string (keyword)", // Immer 'chunk' "rule_id": "string (keyword)", // Traceability: 'inline:rel', 'explicit:wikilink' "confidence": "float", // 0.0 - 1.0 - "note_id": "string (keyword)" // Owner Note ID (für Löschung) + "note_id": "string (keyword)" // Owner Note ID } --- @@ -107,10 +107,11 @@ 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_DECISION_CONFIG` | `config/decision_engine.yaml` | Router & Interview 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_LLM_TIMEOUT` | `300.0` | Timeout für Ollama (Erhöht für CPU-Inference). | +| `MINDNET_API_TIMEOUT` | `300.0` | Frontend Timeout (Streamlit). | | `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). | @@ -119,16 +120,16 @@ Diese Variablen steuern das Verhalten der Skripte und Container. ## Anhang E: Glossar -* **Callout-Edge:** Kante via `> [!edge]`. * **Decision Engine:** Komponente, die den Intent prüft und Strategien wählt (WP06). +* **Draft Editor:** Web-Komponente zur Bearbeitung generierter Notizen (WP10a). * **Explanation Layer:** Komponente, die Scores und Graphen als Begründung liefert. * **Hybrid Router:** Kombination aus Keyword-Matching und LLM-Klassifizierung für Intents. +* **One-Shot Extractor:** LLM-Strategie zur sofortigen Generierung von Drafts ohne Rückfragen (WP07). * **RAG (Retrieval Augmented Generation):** Kombination aus Suche und Text-Generierung. -* **Strategic Retrieval:** Gezieltes Nachladen von Werten (`value`) bei Entscheidungfragen. --- -## Anhang F: Workpackage Status (v2.3.2) +## Anhang F: Workpackage Status (v2.4.0) Aktueller Implementierungsstand der Module. @@ -140,9 +141,9 @@ Aktueller Implementierungsstand der Module. | **WP04a**| Retriever Scoring | 🟢 Live | Hybrider Score (Semantik + Graph). | | **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 | 🟢 Live | Hybrid Router, Strategic Retrieval, Multi-Persona. | -| **WP07** | Interview Assistent | 🟡 Geplant | Dialog-Modus (Nächster Schritt). | +| **WP05** | Persönlichkeit / Chat | 🟢 Live | RAG-Integration mit Context Enrichment. | +| **WP06** | Decision Engine | 🟢 Live | Intent-Router & Strategic Retrieval. | +| **WP07** | Interview Assistent | 🟢 Live | **One-Shot Extractor & Schemas aktiv.** | | **WP08** | Self-Tuning | 🔴 Geplant | Auto-Adjustment der Gewichte. | | **WP10** | Chat Interface | 🟢 Live | Web-Interface (Streamlit). | -| **WP10a**| GUI Evolution | 🔴 Geplant | Interaktive Tools & Editor. | \ No newline at end of file +| **WP10a**| Draft Editor | 🟢 Live | **Interaktives UI für WP07 Drafts.** | \ No newline at end of file diff --git a/docs/dev_workflow.md b/docs/dev_workflow.md index 513aa98..70537eb 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-10 (Aktualisiert: Inkl. Frontend WP10) +# Mindnet v2.4 – Entwickler-Workflow +**Datei:** `docs/DEV_WORKFLOW.md` +**Stand:** 2025-12-10 (Aktualisiert: Inkl. Interview-Tests WP07) Dieses Handbuch beschreibt den Entwicklungszyklus zwischen **Windows PC** (IDE), **Raspberry Pi** (Gitea) und **Beelink** (Runtime/Server). @@ -35,14 +35,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/wp06-decision`). + * Gib den Namen ein: `feature/was-ich-tue` (z.B. `feature/wp07-interview`). * 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 (z.B. neue YAML-Configs). + * Nimm deine Änderungen vor (z.B. neue Schemas in `decision_engine.yaml`). 5. **Sichern & Hochladen:** * **Source Control** Icon (Gabel-Symbol) -> Nachricht eingeben -> **Commit**. @@ -64,7 +64,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/wp06-decision + git checkout feature/wp07-interview git pull ``` @@ -80,9 +80,9 @@ Hier prüfst du, ob dein neuer Code auf dem echten Server läuft. **Option A: Standard (Als Service laufen lassen)** Ideal, wenn du nur testen willst, ob es läuft. ```bash - # 1. API neustarten + # 1. API neustarten (Backend) sudo systemctl restart mindnet-dev - # 2. UI neustarten (falls Frontend-Änderungen) + # 2. UI neustarten (Frontend) sudo systemctl restart mindnet-ui-dev # Logs prüfen (um Fehler zu sehen): @@ -109,12 +109,21 @@ Hier prüfst du, ob dein neuer Code auf dem echten Server läuft. sudo systemctl start mindnet-ui-dev ``` -6. **Validieren:** - * **Browser:** Öffne `http://:8502` um die UI zu testen. +6. **Validieren (Smoke Tests):** + + * **Browser:** Öffne `http://:8502` um die UI zu testen (Intent Badge prüfen!). * **CLI:** Führe Testskripte in einem **zweiten Terminal** aus: + + **Test A: Decision Engine** ```bash - # Beispiel für Decision Engine Test - python tests/test_wp06_decision.py -p 8002 -q "Soll ich...?" + python tests/test_wp06_decision.py -p 8002 -q "Soll ich Qdrant nutzen?" + # Erwartung: Intent DECISION + ``` + + **Test B: Interview Modus (Neu!)** + ```bash + python tests/test_wp06_decision.py -p 8002 -q "Ich will ein neues Projekt starten" + # Erwartung: Intent INTERVIEW, Output ist Markdown Codeblock ``` --- @@ -165,7 +174,7 @@ Damit das Chaos nicht wächst, löschen wir den fertigen Branch. cd ~/mindnet_dev git checkout main git pull - git branch -d feature/wp06-decision + git branch -d feature/wp07-interview ``` 3. **VS Code:** * Auf `main` wechseln. @@ -189,12 +198,11 @@ Damit das Chaos nicht wächst, löschen wir den fertigen Branch. ## 4. Troubleshooting -**"Read timed out (120s)" / 500 Error beim Chat** -* **Ursache:** Das LLM (Ollama) braucht zu lange zum Laden ("Cold Start"). +**"Read timed out (300s)" / 500 Error beim Interview** +* **Ursache:** Das LLM (Ollama) braucht für den One-Shot Draft länger als das Timeout erlaubt. * **Lösung:** - 1. Erhöhe in `.env` den Wert: `MINDNET_LLM_TIMEOUT=300.0` (Backend) oder `MINDNET_API_TIMEOUT` (Frontend). + 1. Erhöhe in `.env` den Wert: `MINDNET_LLM_TIMEOUT=300.0`. 2. Starte die Server neu. - 3. Stelle sicher, dass dein Test-Skript (Client) auch ein hohes Timeout hat. **"Port 8002 / 8502 already in use"** * **Ursache:** Du willst `uvicorn` oder `streamlit` manuell starten, aber der Service läuft noch. diff --git a/docs/developer_guide.md b/docs/developer_guide.md index 14e33d9..e536dcd 100644 --- a/docs/developer_guide.md +++ b/docs/developer_guide.md @@ -1,14 +1,14 @@ -# Mindnet v2.2 – Developer Guide -**Datei:** `docs/mindnet_developer_guide_v2.2.md` +# Mindnet v2.4 – Developer Guide +**Datei:** `docs/mindnet_developer_guide_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Inkl. RAG, Decision Engine & Frontend WP10) +**Status:** **FINAL** (Inkl. RAG, Interview Mode & Frontend WP10) **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) +- [Mindnet v2.4 – Developer Guide](#mindnet-v24--developer-guide) - [1. Projektstruktur (Post-WP10)](#1-projektstruktur-post-wp10) - [2. Lokales Setup (Development)](#2-lokales-setup-development) - [2.1 Voraussetzungen](#21-voraussetzungen) @@ -27,6 +27,7 @@ - [5. Das "Teach-the-AI" Paradigma (Context Intelligence)](#5-das-teach-the-ai-paradigma-context-intelligence) - [A. Workflow: Einen neuen Typ implementieren (z. B. `type: risk`)](#a-workflow-einen-neuen-typ-implementieren-z-b-type-risk) - [B. Workflow: Neue Beziehungen (Edges) nutzen (z. B. `beeinflusst_von`)](#b-workflow-neue-beziehungen-edges-nutzen-z-b-beeinflusst_von) + - [C. Workflow: Interview-Schema anpassen (WP07)](#c-workflow-interview-schema-anpassen-wp07) - [Fazit](#fazit) - [6. Nützliche Einzeiler](#6-nützliche-einzeiler) @@ -48,7 +49,7 @@ 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 # Hybrid Router & Decision Engine (WP06) + │ │ ├── chat.py # Hybrid Router & Interview Logic (WP06/WP07) │ │ ├── feedback.py # Feedback (WP04c) │ │ └── ... │ ├── services/ # Interne & Externe Dienste @@ -56,12 +57,12 @@ Der Code ist modular in `app` (Logik), `scripts` (CLI) und `config` (Steuerung) │ │ ├── feedback_service.py # Logging (JSONL Writer) │ │ └── embeddings_client.py │ ├── frontend/ # NEU (WP10) - │ │ └── ui.py # Streamlit Application + │ │ └── ui.py # Streamlit Application inkl. Draft-Editor │ └── main.py # Entrypoint der API ├── config/ # YAML-Konfigurationen (Single Source of Truth) │ ├── types.yaml # Import-Regeln - │ ├── prompts.yaml # LLM Prompts & RAG Templates (WP06) - │ ├── decision_engine.yaml # Router-Strategien (WP06) + │ ├── prompts.yaml # LLM Prompts & Interview Templates (WP06/07) + │ ├── decision_engine.yaml # Router-Strategien & Schemas (WP06/07) │ └── retriever.yaml # Scoring-Regeln & Kantengewichte ├── data/ │ └── logs/ # Lokale Logs (search_history.jsonl, feedback.jsonl) @@ -108,7 +109,7 @@ Erstelle eine `.env` Datei im Root-Verzeichnis. MINDNET_TYPES_FILE="./config/types.yaml" MINDNET_RETRIEVER_CONFIG="./config/retriever.yaml" - # LLM / RAG Settings (WP06) + # LLM / RAG Settings (WP06/07) MINDNET_LLM_MODEL="phi3:mini" MINDNET_OLLAMA_URL="http://127.0.0.1:11434" MINDNET_LLM_TIMEOUT=300.0 @@ -148,9 +149,9 @@ Dies ist das komplexeste Modul. * **Debugging:** Nutze `--dry-run` oder `scripts/payload_dryrun.py`. ### 3.2 Der Hybrid Router (`app.routers.chat`) -Hier liegt die Logik für Intent Detection (WP06). +Hier liegt die Logik für Intent Detection (WP06) und Interview-Modus (WP07). * **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`. +* **One-Shot:** Wenn Intent `INTERVIEW` erkannt wird, wird **kein Retrieval** ausgeführt. Stattdessen wird ein Draft generiert. * **Erweiterung:** Um neue Intents hinzuzufügen, editiere nur die YAML, nicht den Python-Code (Late Binding). ### 3.3 Der Retriever (`app.core.retriever`) @@ -160,9 +161,9 @@ Hier passiert das Scoring. ### 3.4 Das Frontend (`app.frontend.ui`) Eine Streamlit-App (WP10). +* **Draft Editor:** Enthält einen YAML-Sanitizer (`normalize_meta_and_body`), der sicherstellt, dass LLM-Halluzinationen im Frontmatter nicht das File zerstören. * **State:** Nutzt `st.session_state` für Chat-History und Drafts. * **Logik:** Ruft `/chat` und `/feedback` Endpoints der API auf. -* **Anpassung:** CSS Styles sind direkt in `ui.py` eingebettet. --- @@ -204,7 +205,7 @@ Prüfen das laufende System gegen eine echte Qdrant-Instanz und Ollama. ## 5. Das "Teach-the-AI" Paradigma (Context Intelligence) -Mindnet lernt nicht durch Training (Fine-Tuning), sondern durch **Konfiguration**, **Vernetzung** und **Prompting**. Wenn du dem System ein neues Konzept beibringen willst, musst du in der Regel an drei Stellen eingreifen. Dies ist der **Core-Workflow** für Erweiterungen. +Mindnet lernt nicht durch Training (Fine-Tuning), sondern durch **Konfiguration**, **Vernetzung** und **Prompting**. Dies ist der **Core-Workflow** für Erweiterungen. ### A. Workflow: Einen neuen Typ implementieren (z. B. `type: risk`) @@ -227,26 +228,29 @@ Damit dieser Typ aktiv geladen wird, musst du ihn einer Strategie zuordnen. **3. Kognitive Ebene (`config/prompts.yaml`)** Erkläre dem LLM im Template, was es damit tun soll. - decision_template: | - ... - - Prüfe auf [RISK]: Wenn vorhanden, warne mich davor! - ### B. Workflow: Neue Beziehungen (Edges) nutzen (z. B. `beeinflusst_von`) Beziehungen sind der Klebstoff für die "Why"-Erklärungen. **1. Erfassung im Vault (Markdown)** -Du musst dem System keinen neuen Edge-Typ "beibringen" (Schema-less). Du nutzt ihn einfach. Nutze die Inline-Syntax im Fließtext: - - Die Entscheidung für Qdrant wurde [[rel:beeinflusst_von Budgetkürzung 2024]]. +> "Die Entscheidung für Qdrant wurde [[rel:beeinflusst_von Budgetkürzung 2024]]." **2. Gewichtung (`config/retriever.yaml`)** -Standardmäßig werden alle expliziten Kanten gleich behandelt. Wenn Kausalität wichtiger ist als Ähnlichkeit, konfiguriere dies hier. +Konfiguriere `edge_weights`, wenn Kausalität wichtiger ist als Ähnlichkeit. - scoring: - edge_type_weights: - beeinflusst_von: 1.5 # Sehr starker Einfluss auf das Ranking +### C. Workflow: Interview-Schema anpassen (WP07) + +Wenn Mindnet neue Fragen stellen soll: + +**1. Schema erweitern (`config/decision_engine.yaml`)** +Füge das Feld in die Liste ein. + + project: + fields: ["Titel", "Ziel", "Budget"] # <--- Budget neu + +**2. Keine Code-Änderung nötig** +Der `One-Shot Extractor` (Prompt Template) liest diese Liste dynamisch und weist das LLM an, das Budget zu extrahieren oder `[TODO]` zu setzen. ### Fazit * **Vault:** Liefert das Wissen. diff --git a/docs/mindnet_functional_architecture.md b/docs/mindnet_functional_architecture.md index a9b683f..25dfff5 100644 --- a/docs/mindnet_functional_architecture.md +++ b/docs/mindnet_functional_architecture.md @@ -1,15 +1,15 @@ -# Mindnet v2.2 – Fachliche Architektur -**Datei:** `docs/mindnet_functional_architecture_v2.2.md` +# Mindnet v2.4 – Fachliche Architektur +**Datei:** `docs/mindnet_functional_architecture_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Integrierter Stand WP01–WP10) +**Status:** **FINAL** (Integrierter Stand WP01–WP10 + WP07) -> 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 **RAG-Chat** (Decision Engine & 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 **RAG-Chat** (Decision Engine, Interview-Modus & Persönlichkeit). Die technische Umsetzung wird im technischen Dokument detailliert. ---
📖 Inhaltsverzeichnis (Klicken zum Öffnen) -- [Mindnet v2.2 – Fachliche Architektur](#mindnet-v22--fachliche-architektur) +- [Mindnet v2.4 – Fachliche Architektur](#mindnet-v24--fachliche-architektur) - [](#) - [0) Zielbild \& Grundprinzip](#0-zielbild--grundprinzip) - [1) Notizen \& Chunks (fachliche Perspektive)](#1-notizen--chunks-fachliche-perspektive) @@ -26,11 +26,12 @@ - [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) Context Intelligence \& Intent Router (WP06)](#6-context-intelligence--intent-router-wp06) + - [6) Context Intelligence \& Intent Router (WP06/WP07)](#6-context-intelligence--intent-router-wp06wp07) - [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) + - [6.5 Der Interview-Modus (One-Shot Extraction) – Neu in v2.4](#65-der-interview-modus-one-shot-extraction--neu-in-v24) - [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) @@ -46,7 +47,7 @@ - [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.2)](#16-workpackage-status-v232) + - [16) Workpackage Status (v2.4.0)](#16-workpackage-status-v240)
--- @@ -208,13 +209,13 @@ Die API gibt diese Analysen als menschenlesbare Sätze (`reasons`) und als Daten --- -## 6) Context Intelligence & Intent Router (WP06) +## 6) Context Intelligence & Intent Router (WP06/WP07) -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. +Seit WP06/WP07 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 Partner. ### 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. +* **Heute (WP06):** Das System erkennt, *was* der User will (Rat, Fakten oder Datenerfassung) und wechselt den Modus. ### 6.2 Der Intent-Router (Keyword & Semantik) Der Router prüft vor jeder Antwort die Absicht über konfigurierbare Strategien (`config/decision_engine.yaml`): @@ -222,11 +223,8 @@ Der Router prüft vor jeder Antwort die Absicht über konfigurierbare Strategien 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. +4. **INTERVIEW (Neu in WP07):** Wunsch, Wissen zu erfassen ("Neues Projekt anlegen"). → Aktiviert den Draft-Generator. +5. **CODING:** Technische Anfragen. ### 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: @@ -234,12 +232,18 @@ Im Modus `DECISION` führt das System eine **zweite Suchstufe** aus. Es sucht ni * **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"). +### 6.5 Der Interview-Modus (One-Shot Extraction) – Neu in v2.4 +Wenn der User Wissen erfassen will ("Ich möchte ein neues Projekt anlegen"), wechselt Mindnet in den **Interview-Modus**. + +* **Late Binding Schema:** Das System lädt ein konfiguriertes Schema für den Ziel-Typ (z.B. `project`: Pflichtfelder sind Titel, Ziel, Status). +* **One-Shot Extraction:** Statt eines langen Dialogs extrahiert das LLM **sofort** alle verfügbaren Infos aus dem Prompt und generiert einen validen Markdown-Draft mit Frontmatter. +* **Draft-Status:** Fehlende Pflichtfelder werden mit `[TODO]` markiert. +* **UI-Integration:** Das Frontend rendert statt einer Chat-Antwort einen **interaktiven Editor** (WP10), in dem der Entwurf finalisiert werden kann. + --- ## 7) Future Concepts: The Empathic Digital Twin (Ausblick) @@ -401,10 +405,11 @@ Frontmatter-Eigenschaften (Properties) bleiben **minimiert**: - Persönlichkeit & Chat: `config/prompts.yaml` & `app/routers/chat.py`. - Decision Engine: `config/decision_engine.yaml`. - Logging Service: `app/services/feedback_service.py`. +- Frontend UI: `app/frontend/ui.py`. --- -## 16) Workpackage Status (v2.3.2) +## 16) Workpackage Status (v2.4.0) Aktueller Implementierungsstand der Module. @@ -418,7 +423,7 @@ Aktueller Implementierungsstand der Module. | **WP04c**| Feedback Loop | 🟢 Live | Logging (JSONL) & Traceability aktiv. | | **WP05** | Persönlichkeit / Chat | 🟢 Live | RAG-Integration mit Context Enrichment. | | **WP06** | Decision Engine | 🟢 Live | Intent-Router & Strategic Retrieval. | -| **WP07** | Interview Assistent | 🟡 Geplant | Dialog-Modus (Nächster Schritt). | +| **WP07** | Interview Assistent | 🟢 Live | **One-Shot Extractor & Schemas aktiv.** | | **WP08** | Self-Tuning | 🔴 Geplant | Auto-Adjustment der Gewichte. | | **WP10** | Chat Interface | 🟢 Live | Web-UI mit Feedback & Intents. | -| **WP10a**| GUI Evolution | 🔴 Geplant | Erweiterte Interaktion. | \ No newline at end of file +| **WP10a**| Draft Editor | 🟢 Live | **Interaktiver Editor für WP07 Drafts.** | \ No newline at end of file diff --git a/docs/mindnet_technical_architecture.md b/docs/mindnet_technical_architecture.md index dcb3312..7636dd6 100644 --- a/docs/mindnet_technical_architecture.md +++ b/docs/mindnet_technical_architecture.md @@ -1,17 +1,17 @@ -# Mindnet v2.2 – Technische Architektur -**Datei:** `docs/mindnet_technical_architecture_v2.2.md` +# Mindnet v2.4 – Technische Architektur +**Datei:** `docs/mindnet_technical_architecture_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Integrierter Stand WP01–WP10) +**Status:** **FINAL** (Integrierter Stand WP01–WP10 + WP07) **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, der **neuen RAG-Komponenten (Decision Engine & Hybrid Router)** und dem **Frontend (Streamlit)**. +> Vollständige Beschreibung der technischen Architektur inkl. Graph-Datenbank, Retrieval-Logik, der **RAG-Komponenten (Decision Engine & Hybrid Router)**, des **Interview-Modus** und dem **Frontend (Streamlit)**. ---
📖 Inhaltsverzeichnis (Klicken zum Öffnen) -- [Mindnet v2.2 – Technische Architektur](#mindnet-v22--technische-architektur) +- [Mindnet v2.4 – Technische Architektur](#mindnet-v24--technische-architektur) - [](#) - [1. Systemüberblick](#1-systemüberblick) - [1.1 Architektur-Zielbild](#11-architektur-zielbild) @@ -33,16 +33,17 @@ - [5.2 Scoring-Formel (WP04a)](#52-scoring-formel-wp04a) - [5.3 Explanation Layer (WP04b)](#53-explanation-layer-wp04b) - [5.4 Graph-Expansion](#54-graph-expansion) - - [6. RAG \& Chat Architektur (WP06 Hybrid Router)](#6-rag--chat-architektur-wp06-hybrid-router) + - [6. RAG \& Chat Architektur (WP06 Hybrid Router + WP07 Interview)](#6-rag--chat-architektur-wp06-hybrid-router--wp07-interview) - [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.4 Schritt 3: Retrieval vs. Extraction](#64-schritt-3-retrieval-vs-extraction) - [6.5 Schritt 4: Generation \& Response](#65-schritt-4-generation--response) - [7. Frontend Architektur (WP10)](#7-frontend-architektur-wp10) - [7.1 Kommunikation](#71-kommunikation) - [7.2 Features \& UI-Logik](#72-features--ui-logik) - - [7.3 Deployment Ports](#73-deployment-ports) + - [7.3 Draft-Editor \& Sanitizer (Neu in WP10a)](#73-draft-editor--sanitizer-neu-in-wp10a) + - [7.4 Deployment Ports](#74-deployment-ports) - [8. Feedback \& Logging Architektur (WP04c)](#8-feedback--logging-architektur-wp04c) - [8.1 Komponenten](#81-komponenten) - [8.2 Log-Dateien](#82-log-dateien) @@ -64,7 +65,7 @@ Mindnet ist ein **lokales RAG-System (Retrieval Augmented Generation)** mit Web- * **Qdrant:** Vektor-Datenbank für Graph und Semantik (Collections: notes, chunks, edges). * **Local Files (JSONL):** Append-Only Logs für Feedback und Search-History (Data Flywheel). 4. **Backend:** Eine FastAPI-Anwendung stellt Endpunkte für **Semantische** und **Hybride Suche** sowie **Feedback** bereit. -5. **Frontend:** Streamlit-App (`ui.py`) für Interaktion und Visualisierung. +5. **Frontend:** Streamlit-App (`ui.py`) für Interaktion und Visualisierung inkl. **Draft Editor**. 6. **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`, `decision_engine.yaml`, `prompts.yaml`). @@ -87,7 +88,7 @@ Das System arbeitet **deterministisch** (stabile IDs) und ist **konfigurationsge │ ├── models/ # Pydantic DTOs │ ├── routers/ │ │ ├── query.py # Such-Endpunkt - │ │ ├── chat.py # Hybrid Router & Decision Engine (WP06) + │ │ ├── chat.py # Hybrid Router & Interview Logic (WP06/07) │ │ ├── feedback.py # Feedback-Endpunkt (WP04c) │ │ └── ... │ ├── services/ @@ -95,11 +96,11 @@ Das System arbeitet **deterministisch** (stabile IDs) und ist **konfigurationsge │ │ ├── feedback_service.py # JSONL Logging (WP04c) │ │ └── embeddings_client.py │ ├── frontend/ # NEU (WP10) - │ └── ui.py # Streamlit Application + │ └── ui.py # Streamlit Application inkl. Sanitizer ├── config/ │ ├── types.yaml # Typ-Definitionen (Import-Zeit) │ ├── retriever.yaml # Scoring-Gewichte (Laufzeit) - │ ├── decision_engine.yaml # Strategien & Keywords (WP06) + │ ├── decision_engine.yaml # Strategien & Schemas (WP06/WP07) │ └── prompts.yaml # LLM System-Prompts & Templates (WP06) ├── data/ │ └── logs/ # Lokale JSONL-Logs (WP04c) @@ -193,14 +194,14 @@ Steuert das Scoring zur Laufzeit (WP04a). centrality_weight: 0.5 ### 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). +**Neu in WP06/07:** Steuert den Intent-Router und die Interview-Schemas. +* Definiert Strategien (`DECISION`, `INTERVIEW`, etc.). +* Definiert `schemas` für den Interview-Modus (Pflichtfelder pro Typ). * Definiert LLM-Router-Settings (`llm_fallback_enabled`). ### 3.4 Prompts (`config/prompts.yaml`) Steuert die LLM-Persönlichkeit und Templates. -* Enthält Templates für alle Strategien (z.B. `decision_template`, `empathy_template`, `technical_template`). +* Enthält Templates für alle Strategien inkl. `interview_template` mit One-Shot Logik. ### 3.5 Environment (`.env`) Erweiterung für LLM-Steuerung: @@ -273,7 +274,7 @@ Der Hybrid-Modus lädt dynamisch die Nachbarschaft der Top-K Vektor-Treffer ("Se --- -## 6. RAG & Chat Architektur (WP06 Hybrid Router) +## 6. RAG & Chat Architektur (WP06 Hybrid Router + WP07 Interview) Der Flow für eine Chat-Anfrage (`/chat`) wurde in WP06 auf eine **Configuration-Driven Architecture** umgestellt. Der `ChatRouter` (`app/routers/chat.py`) fungiert als zentraler Dispatcher. @@ -295,46 +296,61 @@ Der Router ermittelt die Absicht (`Intent`) des Nutzers. * 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). + * Ergebnis: `EMPATHY`, `DECISION`, `INTERVIEW`, `CODING` oder `FACT`. ### 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`). +* **Bei RAG (FACT/DECISION):** `inject_types` für Strategic Retrieval. +* **Bei INTERVIEW (WP07):** `schemas` (Pflichtfelder) basierend auf der erkannten Ziel-Entität (`_detect_target_type`). -### 6.4 Schritt 3: Multi-Stage Retrieval -1. **Primary Retrieval:** Hybride Suche nach der User-Query (findet Fakten). +### 6.4 Schritt 3: Retrieval vs. Extraction +Der Router verzweigt hier: + +**A) RAG Modus (FACT, DECISION, EMPATHY):** +1. **Primary Retrieval:** Hybride Suche nach der User-Query. 2. **Strategic Retrieval (Conditional):** Wenn `inject_types` definiert sind, erfolgt eine zweite Suche, die explizit auf diese Typen filtert. 3. **Merge:** Ergebnisse werden dedupliziert zusammengeführt. +**B) Interview Modus (INTERVIEW):** +1. **Kein Retrieval:** Der Kontext ist der Chat-Verlauf (oder initial die Query). +2. **Schema Injection:** Das Schema für den erkannten Typ (z.B. "Project") wird geladen. +3. **Prompt Assembly:** Der `interview_template` Prompt wird mit der Schema-Definition ("Ziel", "Status") gefüllt. + ### 6.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). +* **Response:** Rückgabe enthält Antworttext (im Interview-Modus: Markdown Codeblock), Quellenliste und den erkannten `intent`. --- ## 7. Frontend Architektur (WP10) -Das Frontend ist eine **Streamlit-Anwendung**, die als separater Prozess läuft und via HTTP mit dem Backend kommuniziert. +Das Frontend ist eine **Streamlit-Anwendung** (`app/frontend/ui.py`), die als separater Prozess läuft und via HTTP mit dem Backend kommuniziert. ### 7.1 Kommunikation * **Backend-URL:** Konfiguriert via `MINDNET_API_URL` (Default: `http://localhost:8002`). * **Endpoints:** Nutzt `/chat` für Interaktion und `/feedback` für Bewertungen. -* **Resilienz:** Das Frontend implementiert eigene Timeouts (`MINDNET_API_TIMEOUT`, Default 300s), um lange Wartezeiten lokaler LLMs abzufangen. +* **Resilienz:** Das Frontend implementiert eigene Timeouts (`MINDNET_API_TIMEOUT`, Default 300s). ### 7.2 Features & UI-Logik -* **State Management:** Session-State speichert Chat-Verlauf und `query_id` für Feedback. +* **State Management:** Session-State speichert Chat-Verlauf und `query_id`. * **Visualisierung:** - * **Intent Badges:** Zeigt Router-Entscheidung (`DECISION`, `FACT`, etc.) und Quelle (`Keyword` vs. `LLM`). + * **Intent Badges:** Zeigt Router-Entscheidung (`DECISION`, `INTERVIEW`, etc.). * **Source Expanders:** Zeigt verwendete Chunks inkl. Score und "Why"-Explanation. * **Sidebar:** Zeigt Suchhistorie (Log-basiert) und Konfiguration. -* **Feedback:** - * Global (Antwort): 1-5 Sterne Rating. - * Granular (Quellen): Faces-Rating (Mapped auf 1-5 Score). -### 7.3 Deployment Ports +### 7.3 Draft-Editor & Sanitizer (Neu in WP10a) +Wenn der Intent `INTERVIEW` ist, rendert die UI statt einer Textblase den **Draft-Editor**. + +1. **Parsing:** Die Funktion `parse_markdown_draft` extrahiert den Codeblock aus der LLM-Antwort. +2. **Sanitization (`normalize_meta_and_body`):** + * Prüft den YAML-Frontmatter auf unerlaubte Felder (Halluzinationen des LLMs). + * Verschiebt ungültige Felder (z.B. "Situation") in den Body der Notiz. + * Stellt sicher, dass das Markdown valide bleibt. +3. **Editor Widget:** `st.text_area` erlaubt das Bearbeiten des Inhalts vor dem Speichern. +4. **Action:** Buttons zum Download oder Kopieren des fertigen Markdowns. + +### 7.4 Deployment Ports Zur sauberen Trennung von Prod und Dev laufen Frontend und Backend auf dedizierten Ports: | Umgebung | Backend (FastAPI) | Frontend (Streamlit) | diff --git a/docs/pipeline_playbook.md b/docs/pipeline_playbook.md index 1930cfe..2834ee3 100644 --- a/docs/pipeline_playbook.md +++ b/docs/pipeline_playbook.md @@ -1,14 +1,14 @@ -# mindnet v2.2 – Pipeline Playbook -**Datei:** `docs/mindnet_pipeline_playbook_v2.2.md` +# mindnet v2.4 – Pipeline Playbook +**Datei:** `docs/mindnet_pipeline_playbook_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Inkl. WP10 Frontend) -**Quellen:** `mindnet_v2_implementation_playbook.md`, `Handbuch.md`, `chunking_strategy.md`, `docs_mindnet_retriever.md`, `mindnet_admin_guide_v2.2.md`. +**Status:** **FINAL** (Inkl. WP07 Interview & WP10a Editor) +**Quellen:** `mindnet_v2_implementation_playbook.md`, `Handbuch.md`, `chunking_strategy.md`, `docs_mindnet_retriever.md`, `mindnet_admin_guide_v2.4.md`. ---
📖 Inhaltsverzeichnis (Klicken zum Öffnen) -- [mindnet v2.2 – Pipeline Playbook](#mindnet-v22--pipeline-playbook) +- [mindnet v2.4 – Pipeline Playbook](#mindnet-v24--pipeline-playbook) - [](#) - [1. Zweck \& Einordnung](#1-zweck--einordnung) - [2. Die Import-Pipeline (Runbook)](#2-die-import-pipeline-runbook) @@ -24,7 +24,7 @@ - [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 Intent Router (WP06)](#52-intent-router-wp06) + - [5.2 Intent Router (WP06/07)](#52-intent-router-wp0607) - [5.3 Context Enrichment](#53-context-enrichment) - [5.4 Generation (LLM)](#54-generation-llm) - [6. Feedback \& Lernen (WP04c)](#6-feedback--lernen-wp04c) @@ -33,18 +33,18 @@ - [7.2 Smoke-Test (E2E)](#72-smoke-test-e2e) - [8. Ausblick \& Roadmap (Technische Skizzen)](#8-ausblick--roadmap-technische-skizzen) - [8.1 WP-08: Self-Tuning (Skizze)](#81-wp-08-self-tuning-skizze) - - [16. Workpackage Status (v2.3.2)](#16-workpackage-status-v232) + - [16. Workpackage Status (v2.4.0)](#16-workpackage-status-v240)
--- ## 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** (inkl. Decision Engine) 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 & Interviewer) funktioniert. **Zielgruppe:** Dev/Ops, Tech-Leads. **Scope:** -* **Ist-Stand (WP01–WP10):** Import, Chunking, Edge-Erzeugung, Hybrider Retriever, RAG-Chat (Hybrid Router), Feedback Loop, Frontend. +* **Ist-Stand (WP01–WP10a):** Import, Chunking, Edge-Erzeugung, Hybrider Retriever, RAG-Chat (Hybrid Router), Feedback Loop, Frontend, Draft Editor. * **Roadmap (Ausblick):** Technische Skizze für Self-Tuning (WP08). --- @@ -156,22 +156,26 @@ Der Datenfluss endet nicht beim Finden. Er geht weiter bis zur Antwort. ### 5.1 Retrieval (Hybrid) 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 Intent Router (WP06) +### 5.2 Intent Router (WP06/07) 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). +2. **Slow Path:** Falls kein Keyword matched und `llm_fallback_enabled=true`, klassifiziert das LLM den Intent. + * `FACT`: Wissen abfragen. + * `DECISION`: Rat suchen. + * `EMPATHY`: Trost suchen. + * `INTERVIEW`: Wissen eingeben (Neu in WP07). +3. **Result:** Auswahl der Strategie und der `inject_types` oder `schemas`. ### 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.4 Generation (LLM) * **Engine:** Ollama (lokal). * **Modell:** `phi3:mini` (Standard). -* **Prompting:** Template wird basierend auf Intent gewählt (`decision_template` vs `empathy_template`). +* **Prompting:** Template wird basierend auf Intent gewählt (`decision_template`, `interview_template` etc.). +* **One-Shot (WP07):** Im Interview-Modus generiert das LLM direkt einen Markdown-Block ohne Rückfragen. --- @@ -208,6 +212,9 @@ Prüft am laufenden System (Prod oder Dev), ob Semantik, Graph und Feedback funk # Decision Engine Test (WP06) python tests/test_wp06_decision.py -p 8002 -e EMPATHY -q "Alles ist grau" + # Interview Test (WP07) + python tests/test_wp06_decision.py -p 8002 -e INTERVIEW -q "Neues Projekt starten" + # Feedback Test python tests/test_feedback_smoke.py --url http://localhost:8001/query @@ -226,7 +233,7 @@ Wie entwickeln wir die Pipeline weiter? --- -## 16. Workpackage Status (v2.3.2) +## 16. Workpackage Status (v2.4.0) Aktueller Implementierungsstand der Module. @@ -240,7 +247,7 @@ Aktueller Implementierungsstand der Module. | **WP04c**| Feedback Loop | 🟢 Live | Logging (JSONL) & Traceability aktiv. | | **WP05** | Persönlichkeit / Chat | 🟢 Live | RAG-Integration mit Context Enrichment. | | **WP06** | Decision Engine | 🟢 Live | Hybrid Router, Strategic Retrieval. | -| **WP07** | Interview Assistent | 🟡 Geplant | Nächster Schritt (Dialog-Modus). | +| **WP07** | Interview Assistent | 🟢 Live | **One-Shot Extractor & Schemas aktiv.** | | **WP08** | Self-Tuning | 🔴 Geplant | Auto-Adjustment der Gewichte. | -| **WP10** | Chat Interface | 🟢 Live | Streamlit Web-UI mit Feedback & Intents. | -| **WP10a**| GUI Evolution | 🔴 Geplant | Draft-Editor & Interaktionstools. | \ No newline at end of file +| **WP10** | Chat Interface | 🟢 Live | Web-Interface (Streamlit). | +| **WP10a**| Draft Editor | 🟢 Live | **Interaktives UI für WP07 Drafts.** | \ No newline at end of file diff --git a/docs/user_guide.md b/docs/user_guide.md index 10bec25..09756d2 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -1,11 +1,11 @@ -# Mindnet v2.2 – User Guide -**Datei:** `docs/mindnet_user_guide_v2.2.md` +# Mindnet v2.4 – User Guide +**Datei:** `docs/mindnet_user_guide_v2.4.md` **Stand:** 2025-12-10 -**Status:** **FINAL** (Inkl. RAG & Web-Interface) +**Status:** **FINAL** (Inkl. RAG, Web-Interface & Interview-Assistent) **Quellen:** `knowledge_design.md`, `wp04_retriever_scoring.md`, `Programmplan_V2.2.md`, `Handbuch.md`. > **Willkommen bei Mindnet.** -> Dies ist dein persönliches Wissensnetzwerk und dein Digitaler Zwilling. Es hilft dir beim Erinnern, beim Entscheiden und beim Reflektieren. +> Dies ist dein persönliches Wissensnetzwerk und dein Digitaler Zwilling. Es hilft dir beim Erinnern, beim Entscheiden, beim Reflektieren und beim **Erstellen von Inhalten**. --- @@ -24,7 +24,7 @@ Mindnet passt 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. +4. **Der Analyst (INTERVIEW):** Hilft dir, neue Notizen zu entwerfen und strukturiert zu erfassen. --- @@ -41,7 +41,7 @@ Seit Version 2.3.1 bedienst du Mindnet über eine grafische Oberfläche im Brows * **Klick darauf:** Zeigt den Textauszug und die **Begründung** ("Warum wurde das gefunden?"). ### 2.2 Die Sidebar (Einstellungen & Verlauf) -* **Modus-Wahl:** Umschalten zwischen "💬 Chat" und "📝 Neuer Eintrag" (Vorbereitung für WP07). +* **Modus-Wahl:** Umschalten zwischen "💬 Chat" und "📝 Manueller Editor". * **Verlauf:** Die letzten Suchanfragen sind hier gelistet. Ein Klick führt die Suche erneut aus. * **Settings:** * **Top-K:** Wie viele Quellen sollen gelesen werden? (Standard: 5). @@ -68,9 +68,11 @@ Wenn du frustriert bist oder reflektieren willst, wechselt Mindnet in den "Ich"- * **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. -### 3.3 Modus: Fakten (Standard) -* **Auslöser:** Alles andere. "Was ist Qdrant?", "Zusammenfassung von X". -* **Was passiert:** Standard-Suche nach Wissen ohne spezielle Filter. +### 3.3 Modus: Interview ("Der Analyst") – Neu! +Wenn du Wissen festhalten willst, statt zu suchen. + +* **Auslöser:** "Neues Projekt", "Notiz erstellen", "Ich will etwas festhalten", "Neue Entscheidung dokumentieren". +* **Was passiert:** Siehe Kapitel 6.3. --- @@ -115,4 +117,15 @@ Statt einfach nur `[[Link]]` zu schreiben, versuche zu sagen, *wie* es zusammenh ### 6.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` \ No newline at end of file +* Willst du, dass Mindnet dich an eine **Lektion** erinnert? -> `type: experience` + +### 6.3 Der Interview-Assistent (Drafting) +Mindnet kann dir helfen, Markdown-Notizen zu schreiben. + +1. **Start:** Schreibe im Chat: *"Ich möchte ein neues Projekt 'Apollo' starten, Ziel ist die Mondlandung."* +2. **Generierung:** Mindnet erkennt den Wunsch (`INTERVIEW`), analysiert den Satz und erstellt **sofort** einen Entwurf. +3. **Editor:** Die UI wechselt von der Chat-Blase zu einem **Draft-Editor**. + * Du siehst das generierte Frontmatter (`type: project`, `status: draft`). + * Du siehst den Body-Text mit Platzhaltern (`[TODO]`), wo Infos fehlten (z.B. Stakeholder). +4. **Finalisierung:** Ergänze die fehlenden Infos direkt im Editor und klicke auf **Download** oder **Kopieren**. +5. **Speichern:** Speichere die Datei in deinen Obsidian Vault. Beim nächsten Import ist sie im System. \ No newline at end of file diff --git a/tests/test_interview_intent.py b/tests/test_interview_intent.py new file mode 100644 index 0000000..b847984 --- /dev/null +++ b/tests/test_interview_intent.py @@ -0,0 +1,40 @@ +import requests +import sys + +API_URL = "http://localhost:8002/chat/" + +def test_intent(message): + print(f"📡 Sende: '{message}' ...") + payload = { + "message": message, + "top_k": 0, + "explain": False + } + + try: + # Timeout nach 30 Sekunden erzwingen + response = requests.post(API_URL, json=payload, timeout=30) + + if response.status_code != 200: + print(f"❌ Server Error {response.status_code}: {response.text}") + return + + data = response.json() + intent = data.get("intent") + source = data.get("intent_source") + answer = data.get("answer") + + print(f"✅ Ergebnis erhalten:") + print(f" Intent: {intent} (Quelle: {source})") + print(f" Antwort: {answer[:100]}...") # Nur die ersten 100 Zeichen + print("-" * 40) + + except requests.exceptions.Timeout: + print("❌ TIMEOUT: Das Backend antwortet nicht innerhalb von 30 Sekunden.") + print(" -> Prüfe das Terminal, wo uvicorn läuft. Gibt es dort Fehlermeldungen?") + except Exception as e: + print(f"❌ Fehler: {e}") + +if __name__ == "__main__": + # Testfall: Muss INTERVIEW auslösen + test_intent("Ich möchte ein neues Projekt anlegen") \ No newline at end of file