RAG v2: Klassifizierung (6 Typen, 3 Confidence), source_type, Auto-Supersede, /memory erweitert
This commit is contained in:
parent
91a6180b5a
commit
7ae6ac0e4c
4 changed files with 108 additions and 94 deletions
|
|
@ -297,20 +297,34 @@ def _tool_memory_read(scope=""):
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
_log = _logging.getLogger("context")
|
_log = _logging.getLogger("context")
|
||||||
|
|
||||||
last_suggest_result = {"type": None, "candidate_id": None}
|
last_suggest_result = {"type": None}
|
||||||
|
|
||||||
|
VALID_MEMORY_TYPES = {"fact", "preference", "relationship", "plan", "temporary", "uncertain"}
|
||||||
|
VALID_CONFIDENCE = {"high", "medium", "low"}
|
||||||
|
NEEDS_EXPIRY = {"plan", "temporary"}
|
||||||
|
|
||||||
|
_current_source_type = "telegram_text"
|
||||||
|
|
||||||
|
|
||||||
def _tool_memory_suggest(scope, kind, content, memory_type="temporary", expires_at=None):
|
def set_source_type(st: str):
|
||||||
|
global _current_source_type
|
||||||
|
_current_source_type = st
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_memory_suggest(scope, kind, content, memory_type="fact", confidence="high", expires_at=None):
|
||||||
import memory_client
|
import memory_client
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
global last_suggest_result
|
global last_suggest_result
|
||||||
_log.info("memory_suggest aufgerufen: scope=%s kind=%s type=%s content=%s", scope, kind, memory_type, content[:80])
|
|
||||||
|
|
||||||
if memory_type not in ("temporary", "permanent"):
|
if memory_type not in VALID_MEMORY_TYPES:
|
||||||
memory_type = "temporary"
|
memory_type = "fact"
|
||||||
|
if confidence not in VALID_CONFIDENCE:
|
||||||
|
confidence = "high"
|
||||||
|
|
||||||
|
_log.info("memory_suggest: type=%s conf=%s src=%s content=%s", memory_type, confidence, _current_source_type, content[:80])
|
||||||
|
|
||||||
exp_epoch = None
|
exp_epoch = None
|
||||||
if memory_type == "temporary":
|
if memory_type in NEEDS_EXPIRY:
|
||||||
if expires_at:
|
if expires_at:
|
||||||
exp_epoch = memory_client.parse_expires_from_text(expires_at)
|
exp_epoch = memory_client.parse_expires_from_text(expires_at)
|
||||||
if not exp_epoch:
|
if not exp_epoch:
|
||||||
|
|
@ -323,53 +337,34 @@ def _tool_memory_suggest(scope, kind, content, memory_type="temporary", expires_
|
||||||
"kind": kind,
|
"kind": kind,
|
||||||
"content": content,
|
"content": content,
|
||||||
"source": "bot-suggest",
|
"source": "bot-suggest",
|
||||||
"status": "candidate",
|
"status": "active",
|
||||||
|
"confidence": confidence,
|
||||||
"memory_type": memory_type,
|
"memory_type": memory_type,
|
||||||
|
"source_type": _current_source_type,
|
||||||
}
|
}
|
||||||
if exp_epoch:
|
if exp_epoch:
|
||||||
data["expires_at"] = exp_epoch
|
data["expires_at"] = exp_epoch
|
||||||
|
|
||||||
result = memory_client._post("/memory", data)
|
result = memory_client._post("/memory", data)
|
||||||
prev_type = last_suggest_result.get("type")
|
|
||||||
|
|
||||||
if result and result.get("duplicate"):
|
if result and result.get("duplicate"):
|
||||||
ex_status = result.get("existing_status", "?")
|
|
||||||
ex_type = result.get("existing_memory_type", "")
|
ex_type = result.get("existing_memory_type", "")
|
||||||
ex_exp = result.get("existing_expires_at")
|
ex_exp = result.get("existing_expires_at")
|
||||||
ex_id = result.get("existing_id")
|
last_suggest_result = {"type": "duplicate"}
|
||||||
|
if ex_type in NEEDS_EXPIRY and ex_exp:
|
||||||
if ex_status == "candidate":
|
return f"Weiss ich schon (bis {datetime.fromtimestamp(ex_exp).strftime('%d.%m.%Y')})."
|
||||||
if prev_type != "new_candidate":
|
return "Weiss ich schon."
|
||||||
last_suggest_result = {"type": "existing_candidate", "candidate_id": ex_id}
|
|
||||||
_log.info("Duplikat: bestehender Kandidat ID=%s (prev=%s)", ex_id, prev_type)
|
|
||||||
return "Noch nicht bestaetigt — zeige Auswahl erneut."
|
|
||||||
elif ex_status == "active":
|
|
||||||
if ex_type == "temporary" and ex_exp:
|
|
||||||
exp_str = datetime.fromtimestamp(ex_exp).strftime("%d.%m.%Y")
|
|
||||||
if prev_type != "new_candidate":
|
|
||||||
last_suggest_result = {"type": "active_temporary", "candidate_id": None}
|
|
||||||
return f"Schon temporaer gespeichert bis {exp_str}."
|
|
||||||
elif ex_type == "permanent":
|
|
||||||
if prev_type != "new_candidate":
|
|
||||||
last_suggest_result = {"type": "active_permanent", "candidate_id": None}
|
|
||||||
return "Schon dauerhaft gespeichert."
|
|
||||||
else:
|
|
||||||
if prev_type != "new_candidate":
|
|
||||||
last_suggest_result = {"type": "active_other", "candidate_id": None}
|
|
||||||
return "Bereits aktiv gespeichert."
|
|
||||||
elif ex_status == "archived":
|
|
||||||
if prev_type != "new_candidate":
|
|
||||||
last_suggest_result = {"type": "existing_candidate", "candidate_id": ex_id}
|
|
||||||
memory_client._patch(f"/memory/{ex_id}", {"status": "candidate"})
|
|
||||||
return "War archiviert — erneut als Kandidat vorgeschlagen."
|
|
||||||
else:
|
|
||||||
return "Bereits vorhanden."
|
|
||||||
|
|
||||||
if result and result.get("ok"):
|
if result and result.get("ok"):
|
||||||
last_suggest_result = {"type": "new_candidate", "candidate_id": None}
|
sup = result.get("superseded_id")
|
||||||
type_label = "temporaer" if memory_type == "temporary" else "dauerhaft"
|
last_suggest_result = {"type": "saved", "item_id": result.get("id"), "superseded": sup}
|
||||||
return f"Vorschlag gespeichert als Kandidat ({type_label})."
|
msg = f"Gemerkt ({memory_type}, {confidence})."
|
||||||
return "Konnte Vorschlag nicht speichern."
|
if sup:
|
||||||
|
msg += f" Alten Eintrag #{sup} ersetzt."
|
||||||
|
_log.info("Superseded: #%s -> #%s", sup, result.get("id"))
|
||||||
|
_log.info("Gespeichert: ID=%s type=%s conf=%s", result.get("id"), memory_type, confidence)
|
||||||
|
return msg
|
||||||
|
return "Konnte nicht speichern."
|
||||||
|
|
||||||
|
|
||||||
def _tool_session_search(query):
|
def _tool_session_search(query):
|
||||||
|
|
@ -414,7 +409,7 @@ def get_tool_handlers(session_id: str = None) -> dict:
|
||||||
"get_todays_mails": lambda: _tool_get_todays_mails(),
|
"get_todays_mails": lambda: _tool_get_todays_mails(),
|
||||||
"get_smart_mail_digest": lambda hours=24: _tool_get_smart_mail_digest(hours=hours),
|
"get_smart_mail_digest": lambda hours=24: _tool_get_smart_mail_digest(hours=hours),
|
||||||
"memory_read": lambda scope="": _tool_memory_read(scope),
|
"memory_read": lambda scope="": _tool_memory_read(scope),
|
||||||
"memory_suggest": lambda scope, kind, content, memory_type="temporary", expires_at=None: _tool_memory_suggest(scope, kind, content, memory_type=memory_type, expires_at=expires_at),
|
"memory_suggest": lambda scope, kind, content, memory_type="fact", confidence="high", expires_at=None: _tool_memory_suggest(scope, kind, content, memory_type=memory_type, confidence=confidence, expires_at=expires_at),
|
||||||
"session_search": lambda query: _tool_session_search(query),
|
"session_search": lambda query: _tool_session_search(query),
|
||||||
"session_summary": lambda topic="": _tool_session_summary(session_id, topic=topic) if session_id else "Keine Session aktiv.",
|
"session_summary": lambda topic="": _tool_session_summary(session_id, topic=topic) if session_id else "Keine Session aktiv.",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,26 +30,28 @@ WICHTIG: Beantworte Fragen IMMER anhand dieser Fakten! Wenn der User z.B. fragt
|
||||||
Das Gedaechtnis ist deine primaere Wissensquelle ueber den User.
|
Das Gedaechtnis ist deine primaere Wissensquelle ueber den User.
|
||||||
|
|
||||||
GEDAECHTNIS — memory_suggest:
|
GEDAECHTNIS — memory_suggest:
|
||||||
Du MUSST memory_suggest aufrufen wenn der User etwas sagt das spaeter nuetzlich ist.
|
Du MUSST memory_suggest aufrufen wenn der User etwas Nuetzliches sagt.
|
||||||
Dabei IMMER memory_type angeben:
|
memory_suggest speichert DIREKT. Duplikate werden automatisch erkannt. Widersprueche werden automatisch aufgeloest (altes Item wird ersetzt).
|
||||||
|
|
||||||
TEMPORARY (memory_type="temporary") — hat ein Ablaufdatum:
|
MEMORY_TYPE — immer angeben:
|
||||||
- Reiseplaene ("fliege nach...", "bin naechste Woche in...")
|
- "preference" → Vorlieben ("Lieblingskaffee ist Flat White", "bevorzuge dunkles Theme")
|
||||||
- Termine ("morgen 14 Uhr Zahnarzt", "am Freitag Meeting")
|
- "relationship" → Beziehungen/Rollen ("Ali ist Ansprechpartner fuer Wohnung")
|
||||||
- Kurzfristige Aufenthalte ("bin bis Mittwoch in Berlin")
|
- "fact" → Stabile Fakten ("Server IP geaendert", "Jarvis aktiv seit...")
|
||||||
- Einmalige Vorhaben ("will diese Woche den Server migrieren")
|
- "plan" → Konkrete Vorhaben mit Zeitbezug ("Reise nach Frankfurt am 18.03.")
|
||||||
Bei temporary: expires_at mit dem relevanten Zeitausdruck angeben (z.B. "naechste Woche", "morgen", "am Freitag").
|
- "temporary" → Kurzfristige Zustaende ("bin bis Mittwoch in Berlin", "morgen Zahnarzt")
|
||||||
|
- "uncertain" → Vage Aussagen ("vielleicht fliege ich frueher", "glaube Ali kuemmert sich")
|
||||||
|
|
||||||
PERMANENT (memory_type="permanent") — bleibt dauerhaft:
|
CONFIDENCE — immer angeben:
|
||||||
- Persoenliche Praeferenzen ("ich bevorzuge...", "nenn mich...")
|
- "high" → Klare Aussage ("Mein Lieblingskaffee ist Flat White")
|
||||||
- Rollen/Beziehungen ("Ali ist mein Ansprechpartner fuer...")
|
- "medium" → Wahrscheinlich aber nicht 100% ("Ali kuemmert sich wohl darum")
|
||||||
- Stabile Infrastruktur-Fakten ("neuer Server heisst...", "IP geaendert auf...")
|
- "low" → Sehr vage ("vielleicht aendere ich das noch")
|
||||||
- Projektstatus ("Jarvis ist jetzt aktiv")
|
|
||||||
- Wiederkehrende Regeln ("API-Kosten monatlich beobachten")
|
|
||||||
|
|
||||||
Im Zweifel: lieber temporary als permanent.
|
REGELN:
|
||||||
memory_suggest speichert DIREKT — kein Bestaetigen noetig. Das System erkennt Duplikate automatisch. Bei Duplikaten sag kurz "Weiss ich schon." und beantworte die Frage.
|
- Bei plan/temporary: IMMER expires_at mit Zeitausdruck angeben ("naechste Woche", "morgen")
|
||||||
NICHT speichern: Passwoerter, Tokens, Smalltalk, Hoeflichkeiten, reine Fragen.
|
- Bei uncertain mit low confidence: NUR speichern wenn es trotzdem nuetzlich sein koennte
|
||||||
|
- Vages Gerede, Smalltalk, emotionale Kurzaeusserungen: NICHT speichern
|
||||||
|
- Passwoerter, Tokens: NIE speichern
|
||||||
|
- Bei Widerspruch zu bestehendem Wissen: trotzdem speichern, System erkennt und ersetzt automatisch
|
||||||
|
|
||||||
SESSION-RUECKBLICK:
|
SESSION-RUECKBLICK:
|
||||||
- "Was haben wir besprochen?" → session_summary OHNE topic
|
- "Was haben wir besprochen?" → session_summary OHNE topic
|
||||||
|
|
@ -303,17 +305,18 @@ TOOLS = [
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "memory_suggest",
|
"name": "memory_suggest",
|
||||||
"description": "Speichert einen neuen Fakt als Kandidat. IMMER aufrufen wenn der User Reiseplaene, zeitliche Vorhaben, Projektstatus, Vorlieben oder stabile Fakten mitteilt. IMMER memory_type angeben: 'temporary' fuer zeitlich begrenzte Dinge (Reisen, Termine, einmalige Vorhaben), 'permanent' fuer stabile Fakten (Praeferenzen, Rollen, Regeln, Infrastruktur). Im Zweifel temporary.",
|
"description": "Speichert einen Fakt direkt im Langzeitgedaechtnis. IMMER aufrufen wenn der User Reiseplaene, Termine, Vorlieben, Beziehungen, Projektstatus oder stabile Fakten mitteilt. System erkennt Duplikate und ersetzt Widersprueche automatisch.",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"scope": {"type": "string", "enum": ["user", "environment", "project"], "description": "user=persoenlich, environment=Infrastruktur, project=Projekt"},
|
"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"},
|
"kind": {"type": "string", "enum": ["fact", "preference", "rule", "note"], "description": "Grobe Kategorie"},
|
||||||
"content": {"type": "string", "description": "Der Fakt (kurz, 3. Person, z.B. 'Fliegt naechste Woche nach Frankfurt')"},
|
"content": {"type": "string", "description": "Der Fakt (kurz, 3. Person, z.B. 'Lieblingskaffee ist Flat White')"},
|
||||||
"memory_type": {"type": "string", "enum": ["temporary", "permanent"], "description": "temporary=zeitlich begrenzt (Reisen, Termine), permanent=dauerhaft (Praeferenzen, Rollen, Regeln)"},
|
"memory_type": {"type": "string", "enum": ["fact", "preference", "relationship", "plan", "temporary", "uncertain"], "description": "fact=stabiler Fakt, preference=Vorliebe, relationship=Beziehung/Rolle, plan=Vorhaben mit Zeitbezug, temporary=kurzfristiger Zustand, uncertain=vage Aussage"},
|
||||||
"expires_at": {"type": "string", "description": "Nur bei temporary: Zeitangabe wann es ablaeuft (z.B. 'naechste Woche', 'morgen', 'am Freitag', '22.03.2026'). Leer lassen wenn unklar."},
|
"confidence": {"type": "string", "enum": ["high", "medium", "low"], "description": "high=klare Aussage, medium=wahrscheinlich, low=vage"},
|
||||||
|
"expires_at": {"type": "string", "description": "Bei plan/temporary: Zeitangabe wann es ablaeuft (z.B. 'naechste Woche', 'morgen', '22.03.2026'). Leer bei dauerhaften Fakten."},
|
||||||
},
|
},
|
||||||
"required": ["scope", "kind", "content", "memory_type"],
|
"required": ["scope", "kind", "content", "memory_type", "confidence"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -402,7 +405,7 @@ def ask_with_tools(question: str, tool_handlers: dict, session_id: str = None) -
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import memory_client
|
import memory_client
|
||||||
memory_items = memory_client.get_active_memory()
|
memory_items = memory_client.get_relevant_memory(question, top_k=10)
|
||||||
memory_block = memory_client.format_memory_for_prompt(memory_items)
|
memory_block = memory_client.format_memory_for_prompt(memory_items)
|
||||||
except Exception:
|
except Exception:
|
||||||
memory_block = ""
|
memory_block = ""
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ def delete_candidate(item_id: int) -> bool:
|
||||||
|
|
||||||
|
|
||||||
def get_active_memory() -> list[dict]:
|
def get_active_memory() -> list[dict]:
|
||||||
"""Holt alle aktiven Memory-Items fuer den System-Prompt (ohne abgelaufene)."""
|
"""Holt alle aktiven Memory-Items (ohne abgelaufene). Fuer /memory-Befehl."""
|
||||||
result = _get("/memory", {"status": "active", "limit": 100})
|
result = _get("/memory", {"status": "active", "limit": 100})
|
||||||
if not result or "items" not in result:
|
if not result or "items" not in result:
|
||||||
return []
|
return []
|
||||||
|
|
@ -263,26 +263,32 @@ def get_active_memory() -> list[dict]:
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
def get_relevant_memory(query: str, top_k: int = 10) -> list[dict]:
|
||||||
|
"""RAG-Suche: Holt die relevantesten Memory-Items per Vektor-Aehnlichkeit."""
|
||||||
|
result = _get("/memory/search", {"q": query, "top_k": top_k, "status": "active"})
|
||||||
|
if not result or "items" not in result:
|
||||||
|
return get_active_memory()[:top_k]
|
||||||
|
return result["items"]
|
||||||
|
|
||||||
|
|
||||||
def format_memory_for_prompt(items: list[dict]) -> str:
|
def format_memory_for_prompt(items: list[dict]) -> str:
|
||||||
"""Formatiert Memory-Items als Text-Block fuer den System-Prompt."""
|
"""Formatiert Memory-Items als Text-Block fuer den System-Prompt."""
|
||||||
if not items:
|
if not items:
|
||||||
return ""
|
return ""
|
||||||
permanent = [i for i in items if i.get("memory_type") != "temporary"]
|
TYPE_ICON = {"fact": "📌", "preference": "⭐", "relationship": "👤", "plan": "📅", "temporary": "🕒", "uncertain": "❓"}
|
||||||
temporary = [i for i in items if i.get("memory_type") == "temporary"]
|
lines = ["", "=== GEDAECHTNIS (relevante Fakten) ==="]
|
||||||
|
for item in items:
|
||||||
lines = ["", "=== GEDAECHTNIS ==="]
|
mtype = item.get("memory_type", "fact")
|
||||||
if permanent:
|
icon = TYPE_ICON.get(mtype, "•")
|
||||||
lines.append("-- Dauerhaft --")
|
conf = item.get("confidence", "high")
|
||||||
for item in permanent:
|
exp = item.get("expires_at")
|
||||||
lines.append(f"[{item['scope']}/{item['kind']}] {item['content']}")
|
parts = [f"{icon} [{mtype}]"]
|
||||||
if temporary:
|
if conf != "high":
|
||||||
lines.append("-- Temporaer --")
|
parts.append(f"({conf})")
|
||||||
for item in temporary:
|
parts.append(item["content"])
|
||||||
exp = item.get("expires_at")
|
if exp:
|
||||||
exp_str = ""
|
parts.append(f"(bis {datetime.fromtimestamp(exp).strftime('%d.%m.%Y')})")
|
||||||
if exp:
|
lines.append(" ".join(parts))
|
||||||
exp_str = " (bis " + datetime.fromtimestamp(exp).strftime("%d.%m.%Y") + ")"
|
|
||||||
lines.append(f"[{item['scope']}/{item['kind']}] {item['content']}{exp_str}")
|
|
||||||
lines.append("=== ENDE GEDAECHTNIS ===")
|
lines.append("=== ENDE GEDAECHTNIS ===")
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -322,22 +322,30 @@ async def cmd_memory(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
if not items:
|
if not items:
|
||||||
await update.message.reply_text("Kein Gedaechtnis vorhanden.")
|
await update.message.reply_text("Kein Gedaechtnis vorhanden.")
|
||||||
return
|
return
|
||||||
permanent = [i for i in items if i.get("memory_type") != "temporary"]
|
TYPE_ICON = {"fact": "📌", "preference": "⭐", "relationship": "👤", "plan": "📅", "temporary": "🕒", "uncertain": "❓"}
|
||||||
temporary = [i for i in items if i.get("memory_type") == "temporary"]
|
CONF_ICON = {"high": "", "medium": " ⚠", "low": " ❔"}
|
||||||
|
groups = {}
|
||||||
|
for i in items:
|
||||||
|
mt = i.get("memory_type", "fact")
|
||||||
|
groups.setdefault(mt, []).append(i)
|
||||||
lines = [f"🧠 Gedaechtnis: {len(items)} Eintraege\n"]
|
lines = [f"🧠 Gedaechtnis: {len(items)} Eintraege\n"]
|
||||||
if permanent:
|
for mtype in ("fact", "preference", "relationship", "plan", "temporary", "uncertain"):
|
||||||
lines.append(f"📌 Dauerhaft ({len(permanent)}):")
|
group = groups.get(mtype, [])
|
||||||
for i in permanent:
|
if not group:
|
||||||
lines.append(f" • {i['content'][:100]}")
|
continue
|
||||||
if temporary:
|
icon = TYPE_ICON.get(mtype, "•")
|
||||||
lines.append(f"\n🕒 Temporaer ({len(temporary)}):")
|
lines.append(f"{icon} {mtype.upper()} ({len(group)}):")
|
||||||
for i in temporary:
|
for i in group:
|
||||||
|
conf = CONF_ICON.get(i.get("confidence", "high"), "")
|
||||||
|
src = i.get("source_type", "")
|
||||||
|
src_tag = f" [{src}]" if src and src != "manual" else ""
|
||||||
exp = i.get("expires_at")
|
exp = i.get("expires_at")
|
||||||
exp_str = ""
|
exp_str = ""
|
||||||
if exp:
|
if exp:
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
exp_str = f" (bis {datetime.fromtimestamp(exp).strftime('%d.%m.%Y')})"
|
exp_str = f" (bis {datetime.fromtimestamp(exp).strftime('%d.%m.%Y')})"
|
||||||
lines.append(f" • {i['content'][:100]}{exp_str}")
|
lines.append(f" • {i['content'][:90]}{conf}{exp_str}{src_tag}")
|
||||||
|
lines.append("")
|
||||||
text = "\n".join(lines)
|
text = "\n".join(lines)
|
||||||
await update.message.reply_text(text[:4000], reply_markup=KEYBOARD)
|
await update.message.reply_text(text[:4000], reply_markup=KEYBOARD)
|
||||||
|
|
||||||
|
|
@ -368,7 +376,8 @@ async def handle_voice(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
channel_key = str(update.effective_chat.id)
|
channel_key = str(update.effective_chat.id)
|
||||||
session_id = memory_client.get_or_create_session(channel_key, source="telegram")
|
session_id = memory_client.get_or_create_session(channel_key, source="telegram")
|
||||||
|
|
||||||
context.last_suggest_result = {"type": None, "candidate_id": None}
|
context.last_suggest_result = {"type": None}
|
||||||
|
context.set_source_type("telegram_voice")
|
||||||
handlers = context.get_tool_handlers(session_id=session_id)
|
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:
|
||||||
|
|
@ -416,6 +425,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:
|
||||||
context.last_suggest_result = {"type": None}
|
context.last_suggest_result = {"type": None}
|
||||||
|
context.set_source_type("telegram_text")
|
||||||
handlers = context.get_tool_handlers(session_id=session_id)
|
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:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue