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)
|
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."""
|
"""Registry: Tool-Name -> Handler-Funktion. Wird von llm.ask_with_tools() genutzt."""
|
||||||
return {
|
return {
|
||||||
"get_all_containers": lambda: gather_status(),
|
"get_all_containers": lambda: gather_status(),
|
||||||
|
|
@ -349,4 +354,5 @@ def get_tool_handlers() -> dict:
|
||||||
"memory_read": lambda scope="": _tool_memory_read(scope),
|
"memory_read": lambda scope="": _tool_memory_read(scope),
|
||||||
"memory_suggest": lambda scope, kind, content: _tool_memory_suggest(scope, kind, content),
|
"memory_suggest": lambda scope, kind, content: _tool_memory_suggest(scope, kind, content),
|
||||||
"session_search": lambda query: _tool_session_search(query),
|
"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"
|
MODEL = "openai/gpt-4o-mini"
|
||||||
MAX_TOOL_ROUNDS = 3
|
MAX_TOOL_ROUNDS = 3
|
||||||
|
|
||||||
SYSTEM_PROMPT = """Du bist der Hausmeister-Bot für ein Homelab mit mehreren Proxmox-Servern.
|
SYSTEM_PROMPT = """Du bist der Hausmeister-Bot fuer ein Homelab. Deutsch, kurz, direkt, operativ.
|
||||||
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).
|
|
||||||
|
|
||||||
WICHTIG — Gedaechtnis:
|
STIL:
|
||||||
- Wenn der User persoenliche Infos teilt (Reiseplaene, Vorlieben, Gewohnheiten, Korrekturen), nutze SOFORT memory_suggest um es als Kandidat zu speichern.
|
- So wenig Worte wie moeglich, solange nichts Wichtiges fehlt.
|
||||||
- Wenn der User fragt was frueher besprochen wurde, nutze session_search.
|
- KEINE Abschlussformeln ("Wenn du weitere Informationen benoetigst...").
|
||||||
- Du darfst KEINE Passwoerter, Tokens oder API-Keys in memory_suggest speichern."""
|
- 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 = [
|
TOOLS = [
|
||||||
{
|
{
|
||||||
|
|
@ -265,13 +281,13 @@ TOOLS = [
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "memory_suggest",
|
"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": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"scope": {"type": "string", "enum": ["user", "environment", "project"], "description": "Kategorie des Fakts"},
|
"scope": {"type": "string", "enum": ["user", "environment", "project"], "description": "user=persoenlich, environment=Infrastruktur, project=Projekt"},
|
||||||
"kind": {"type": "string", "enum": ["fact", "preference", "rule", "note"], "description": "Art des Eintrags"},
|
"kind": {"type": "string", "enum": ["fact", "preference", "rule", "note"], "description": "fact=Tatsache, preference=Vorliebe, note=Notiz"},
|
||||||
"content": {"type": "string", "description": "Der Fakt der gemerkt werden soll (kurz, praezise)"},
|
"content": {"type": "string", "description": "Der Fakt (kurz, 3. Person, z.B. 'Fliegt naechste Woche nach Frankfurt')"},
|
||||||
},
|
},
|
||||||
"required": ["scope", "kind", "content"],
|
"required": ["scope", "kind", "content"],
|
||||||
},
|
},
|
||||||
|
|
@ -281,16 +297,24 @@ TOOLS = [
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "session_search",
|
"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": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"query": {"type": "string", "description": "Suchbegriffe (Woerter mit Leerzeichen getrennt)"},
|
"query": {"type": "string", "description": "Suchbegriffe"},
|
||||||
},
|
},
|
||||||
"required": ["query"],
|
"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:
|
if session_id:
|
||||||
try:
|
try:
|
||||||
import memory_client
|
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:
|
for msg in history:
|
||||||
if msg.get("role") in ("user", "assistant") and msg.get("content"):
|
if msg.get("role") in ("user", "assistant") and msg.get("content"):
|
||||||
messages.append({"role": msg["role"], "content": msg["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:
|
if result and "messages" in result:
|
||||||
return result["messages"]
|
return result["messages"]
|
||||||
return []
|
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...")
|
await update.message.reply_text("🤔 Denke nach...")
|
||||||
try:
|
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)
|
answer = llm.ask_with_tools(text, handlers, session_id=session_id)
|
||||||
if session_id:
|
if session_id:
|
||||||
memory_client.log_message(session_id, "assistant", answer)
|
memory_client.log_message(session_id, "assistant", answer)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue