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