Hausmeister: Session-Summary, schaerfere memory_suggest, strafferer Antwortstil
This commit is contained in:
parent
99ebbc0d68
commit
e35a4da201
4 changed files with 83 additions and 18 deletions
|
|
@ -323,7 +323,12 @@ def _tool_session_search(query):
|
|||
return "\n".join(lines)
|
||||
|
||||
|
||||
def get_tool_handlers() -> dict:
|
||||
def _tool_session_summary(session_id):
|
||||
import memory_client
|
||||
return memory_client.get_session_summary(session_id, limit=20)
|
||||
|
||||
|
||||
def get_tool_handlers(session_id: str = None) -> dict:
|
||||
"""Registry: Tool-Name -> Handler-Funktion. Wird von llm.ask_with_tools() genutzt."""
|
||||
return {
|
||||
"get_all_containers": lambda: gather_status(),
|
||||
|
|
@ -349,4 +354,5 @@ def get_tool_handlers() -> dict:
|
|||
"memory_read": lambda scope="": _tool_memory_read(scope),
|
||||
"memory_suggest": lambda scope, kind, content: _tool_memory_suggest(scope, kind, content),
|
||||
"session_search": lambda query: _tool_session_search(query),
|
||||
"session_summary": lambda: _tool_session_summary(session_id) if session_id else "Keine Session aktiv.",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,16 +15,32 @@ from core import config
|
|||
MODEL = "openai/gpt-4o-mini"
|
||||
MAX_TOOL_ROUNDS = 3
|
||||
|
||||
SYSTEM_PROMPT = """Du bist der Hausmeister-Bot für ein Homelab mit mehreren Proxmox-Servern.
|
||||
Du antwortest kurz, präzise und auf Deutsch.
|
||||
Du hast Tools um Live-Daten abzufragen. Nutze sie um Fragen zu beantworten.
|
||||
Wenn alles in Ordnung ist, sag das kurz. Bei Problemen erkläre was los ist und schlage Lösungen vor.
|
||||
Nutze Emojis sparsam. Formatiere für Telegram (kein Markdown, nur einfacher Text).
|
||||
SYSTEM_PROMPT = """Du bist der Hausmeister-Bot fuer ein Homelab. Deutsch, kurz, direkt, operativ.
|
||||
|
||||
WICHTIG — Gedaechtnis:
|
||||
- Wenn der User persoenliche Infos teilt (Reiseplaene, Vorlieben, Gewohnheiten, Korrekturen), nutze SOFORT memory_suggest um es als Kandidat zu speichern.
|
||||
- Wenn der User fragt was frueher besprochen wurde, nutze session_search.
|
||||
- Du darfst KEINE Passwoerter, Tokens oder API-Keys in memory_suggest speichern."""
|
||||
STIL:
|
||||
- So wenig Worte wie moeglich, solange nichts Wichtiges fehlt.
|
||||
- KEINE Abschlussformeln ("Wenn du weitere Informationen benoetigst...").
|
||||
- KEINE kuenstlichen Wuensche ("Guten Flug!", "Viel Erfolg!").
|
||||
- KEINE Rueckfragen ob der User mehr wissen will.
|
||||
- Emojis nur wenn sie Information tragen. Telegram-Format (kein Markdown).
|
||||
|
||||
GEDAECHTNIS — memory_suggest:
|
||||
Du MUSST memory_suggest aufrufen wenn der User etwas sagt das spaeter nuetzlich ist:
|
||||
- Reiseplaene ("fliege nach...", "bin naechste Woche in...")
|
||||
- Zeitliche Plaene ("Montag mache ich...", "ab Mai...")
|
||||
- Neue stabile Fakten ("mein neuer Server...", "IP hat sich geaendert...")
|
||||
- Projektstatus ("Jarvis ist jetzt aktiv", "Flugscanner laeuft wieder")
|
||||
- Vorlieben/Korrekturen ("nenn mich...", "ich bevorzuge...")
|
||||
Nach dem Aufruf sagst du kurz: "Notiert." — kein langes Erklaeren.
|
||||
NICHT speichern: Passwoerter, Tokens, Smalltalk, Hoeflichkeiten, reine Fragen.
|
||||
|
||||
SESSION-RUECKBLICK:
|
||||
- "Was haben wir besprochen?" → session_summary aufrufen (liefert alle Themen der aktuellen Session)
|
||||
- "Erinnerst du dich an X?" mit konkretem Stichwort → session_search
|
||||
- Antworte mit 2-5 knappen Kernthemen, nicht mit einem einzelnen Fakt.
|
||||
|
||||
TOOLS:
|
||||
Nutze Tools fuer Live-Daten. Wenn alles OK: kurz sagen. Bei Problemen: erklaeren + Loesung."""
|
||||
|
||||
TOOLS = [
|
||||
{
|
||||
|
|
@ -265,13 +281,13 @@ TOOLS = [
|
|||
"type": "function",
|
||||
"function": {
|
||||
"name": "memory_suggest",
|
||||
"description": "Schlage vor, einen neuen Fakt zu merken. Nutze dieses Tool PROAKTIV wenn der User etwas sagt das dauerhaft relevant ist (Vorlieben, Gewohnheiten, Umgebungsfakten). Der Vorschlag wird als Kandidat gespeichert.",
|
||||
"description": "Speichert einen neuen Fakt als Kandidat. IMMER aufrufen wenn der User Reiseplaene, zeitliche Vorhaben, Projektstatus, Vorlieben oder stabile Fakten mitteilt. Beispiele: 'Ich fliege nach X', 'Ab Mai nutze ich Y', 'Mein neuer Server heisst Z'. NICHT fuer Smalltalk, Fragen oder Passwoerter.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"scope": {"type": "string", "enum": ["user", "environment", "project"], "description": "Kategorie des Fakts"},
|
||||
"kind": {"type": "string", "enum": ["fact", "preference", "rule", "note"], "description": "Art des Eintrags"},
|
||||
"content": {"type": "string", "description": "Der Fakt der gemerkt werden soll (kurz, praezise)"},
|
||||
"scope": {"type": "string", "enum": ["user", "environment", "project"], "description": "user=persoenlich, environment=Infrastruktur, project=Projekt"},
|
||||
"kind": {"type": "string", "enum": ["fact", "preference", "rule", "note"], "description": "fact=Tatsache, preference=Vorliebe, note=Notiz"},
|
||||
"content": {"type": "string", "description": "Der Fakt (kurz, 3. Person, z.B. 'Fliegt naechste Woche nach Frankfurt')"},
|
||||
},
|
||||
"required": ["scope", "kind", "content"],
|
||||
},
|
||||
|
|
@ -281,16 +297,24 @@ TOOLS = [
|
|||
"type": "function",
|
||||
"function": {
|
||||
"name": "session_search",
|
||||
"description": "Durchsucht vergangene Gespraeche nach Stichworten. Nutze dieses Tool wenn der User fragt 'was haben wir besprochen', 'erinnerst du dich', 'letzte Woche' oder aehnlich.",
|
||||
"description": "Volltextsuche in vergangenen Sessions nach konkreten Stichworten. Fuer gezielte Suche wie 'Was habe ich ueber Backup gesagt?' oder 'Wann war das mit Seafile?'.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {"type": "string", "description": "Suchbegriffe (Woerter mit Leerzeichen getrennt)"},
|
||||
"query": {"type": "string", "description": "Suchbegriffe"},
|
||||
},
|
||||
"required": ["query"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "session_summary",
|
||||
"description": "Zusammenfassung aller Themen der aktuellen Session. Nutze dieses Tool bei Fragen wie 'Was haben wir besprochen?', 'Worüber haben wir geredet?', 'Was war heute Thema?'. Liefert alle Frage-Antwort-Paare kompakt.",
|
||||
"parameters": {"type": "object", "properties": {}, "required": []},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -360,7 +384,7 @@ def ask_with_tools(question: str, tool_handlers: dict, session_id: str = None) -
|
|||
if session_id:
|
||||
try:
|
||||
import memory_client
|
||||
history = memory_client.get_session_messages(session_id, limit=10)
|
||||
history = memory_client.get_session_messages(session_id, limit=20)
|
||||
for msg in history:
|
||||
if msg.get("role") in ("user", "assistant") and msg.get("content"):
|
||||
messages.append({"role": msg["role"], "content": msg["content"]})
|
||||
|
|
|
|||
|
|
@ -121,3 +121,38 @@ def get_session_messages(session_id: str, limit: int = 10) -> list[dict]:
|
|||
if result and "messages" in result:
|
||||
return result["messages"]
|
||||
return []
|
||||
|
||||
|
||||
def get_session_summary(session_id: str, limit: int = 20) -> str:
|
||||
"""Kompakte Zusammenfassung der aktuellen Session als Themen-Liste."""
|
||||
if not session_id:
|
||||
return "Keine aktive Session."
|
||||
messages = get_session_messages(session_id, limit=limit)
|
||||
if not messages:
|
||||
return "Noch keine Nachrichten in dieser Session."
|
||||
|
||||
exchanges = []
|
||||
current_q = None
|
||||
for msg in messages:
|
||||
role = msg.get("role", "")
|
||||
content = (msg.get("content") or "").strip()
|
||||
if not content:
|
||||
continue
|
||||
if role == "user":
|
||||
current_q = content[:120]
|
||||
elif role == "assistant" and current_q:
|
||||
exchanges.append((current_q, content[:120]))
|
||||
current_q = None
|
||||
if current_q:
|
||||
exchanges.append((current_q, None))
|
||||
|
||||
if not exchanges:
|
||||
return "Keine Themen in dieser Session."
|
||||
|
||||
lines = [f"Session ({len(exchanges)} Themen):"]
|
||||
for i, (q, a) in enumerate(exchanges, 1):
|
||||
line = f"{i}. Frage: {q}"
|
||||
if a:
|
||||
line += f"\n Antwort: {a}"
|
||||
lines.append(line)
|
||||
return "\n".join(lines)
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
|||
|
||||
await update.message.reply_text("🤔 Denke nach...")
|
||||
try:
|
||||
handlers = context.get_tool_handlers()
|
||||
handlers = context.get_tool_handlers(session_id=session_id)
|
||||
answer = llm.ask_with_tools(text, handlers, session_id=session_id)
|
||||
if session_id:
|
||||
memory_client.log_message(session_id, "assistant", answer)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue