Memory: Fallback-Matching bei Duplikaten wenn LLM Tool nicht aufruft

This commit is contained in:
root 2026-03-15 13:25:09 +07:00
parent 00e0bede99
commit e091f79f0a

View file

@ -286,6 +286,32 @@ async def cmd_feeds(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
except Exception as e:
await update.message.reply_text(f"Fehler: {e}")
_STOP_WORDS = {"ich", "bin", "ist", "der", "die", "das", "ein", "eine", "und", "oder",
"in", "auf", "an", "fuer", "für", "von", "zu", "mit", "nach", "mein",
"meine", "meinem", "meinen", "hat", "habe", "wird", "will", "soll",
"nicht", "auch", "noch", "schon", "nur", "aber", "wenn", "weil", "dass"}
def _find_matching_candidate(user_text: str, candidates: list[dict]) -> dict | None:
"""Findet den Kandidaten mit der besten Wort-Ueberlappung zum User-Text."""
words = {w.lower().strip(".,!?") for w in user_text.split() if len(w) > 2}
words -= _STOP_WORDS
if not words:
return None
best, best_score = None, 0
for c in candidates:
content_words = {w.lower().strip(".,!?") for w in c["content"].split() if len(w) > 2}
content_words -= _STOP_WORDS
if not content_words:
continue
overlap = len(words & content_words)
score = overlap / max(len(words), 1)
if score > best_score and score >= 0.3:
best, best_score = c, score
return best
def _memory_buttons(item_id: int) -> InlineKeyboardMarkup:
return InlineKeyboardMarkup([[
InlineKeyboardButton("🕒 Temporär", callback_data=f"mem_temp:{item_id}"),
@ -395,6 +421,8 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
suggest = context.last_suggest_result
log.info("suggest_result: type=%s candidate_id=%s", suggest.get("type"), suggest.get("candidate_id"))
sent = False
if suggest["type"] == "existing_candidate" and suggest["candidate_id"]:
candidates = memory_client.get_candidates()
item = next((c for c in candidates if c["id"] == suggest["candidate_id"]), None)
@ -403,8 +431,7 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
answer[:4000] + "\n\n" + _format_candidate(item),
reply_markup=_memory_buttons(item["id"]),
)
else:
await update.message.reply_text(answer[:4000], reply_markup=KEYBOARD)
sent = True
elif suggest["type"] == "new_candidate":
candidates_after = memory_client.get_candidates()
@ -416,9 +443,19 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
answer[:4000] + "\n\n" + type_icon + " " + c["content"],
reply_markup=_memory_buttons(c["id"]),
)
else:
await update.message.reply_text(answer[:4000], reply_markup=KEYBOARD)
else:
sent = True
if not sent and suggest["type"] is None:
matched = _find_matching_candidate(text, memory_client.get_candidates())
if matched:
log.info("Fallback-Match: Kandidat ID=%s fuer User-Text", matched["id"])
await update.message.reply_text(
answer[:4000] + "\n\n" + _format_candidate(matched),
reply_markup=_memory_buttons(matched["id"]),
)
sent = True
if not sent:
await update.message.reply_text(answer[:4000], reply_markup=KEYBOARD)
except Exception as e:
log.exception("Fehler bei Freitext")