fix: Remove translation detection workflow from DM handler

The auto-detect language + translation menu was misidentifying regular
German messages and blocking normal responses. Bot now simply responds
in whatever language the user writes in, per updated system prompt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-02-28 08:47:33 +02:00
parent 5d730739b8
commit 40a99c73f7

124
bot.py
View File

@@ -80,7 +80,7 @@ MAX_TOOL_ITERATIONS = 5
SYSTEM_PROMPT = """You are a helpful AI assistant in a Matrix chat room.
Keep answers concise but thorough. Use markdown formatting when helpful.
Always respond in the same language the user writes in. If you have memories about the user's preferred language, use that language consistently.
Always respond in the same language the user writes in. Never switch languages unless the user explicitly asks you to. If a user writes in German, reply in German. If they write in English, reply in English. Do not offer to translate or change language on your own.
IMPORTANT RULES — FOLLOW THESE STRICTLY:
- When document context is provided below, use it to answer. Always include any links.
@@ -834,8 +834,6 @@ class Bot:
self._sync_token_received = False
self._verifications: dict[str, dict] = {} # txn_id -> verification state
self._pending_connects: dict[str, str] = {} # matrix_user_id -> device_code
self._pending_translate: dict[str, dict] = {} # sender -> {text, detected_lang, room_id}
self._pending_reply: dict[str, dict] = {} # sender -> {target_lang}
self._room_document_context: dict[str, list[dict]] = {} # room_id -> [{type, filename, text, timestamp}, ...]
@staticmethod
@@ -1201,62 +1199,6 @@ class Bot:
except Exception:
logger.warning("Memory extraction failed", exc_info=True)
async def _detect_language(self, text: str) -> str:
"""Detect the language of a text using a fast LLM call."""
if not self.llm:
return "Unknown"
try:
resp = await self.llm.chat.completions.create(
model=DEFAULT_MODEL,
messages=[
{"role": "system", "content": "What language is this text? Reply with ONLY the language name in English."},
{"role": "user", "content": text[:500]},
],
max_tokens=10,
)
return resp.choices[0].message.content.strip()
except Exception:
logger.debug("Language detection failed", exc_info=True)
return "Unknown"
async def _translate_text(self, text: str, target_language: str, model: str | None = None) -> str:
"""Translate text to the target language using LLM."""
if not self.llm:
return text
try:
resp = await self.llm.chat.completions.create(
model=model or DEFAULT_MODEL,
messages=[
{"role": "system", "content": f"Translate the following text to {target_language}. Return ONLY the translation."},
{"role": "user", "content": text},
],
max_tokens=1000,
)
return resp.choices[0].message.content.strip()
except Exception:
logger.debug("Translation failed", exc_info=True)
return f"[Translation failed] {text}"
async def _get_preferred_language(self, user_id: str) -> str:
"""Get user's preferred language from memories (last match = most recent)."""
memories = await self.memory.query(user_id, "preferred language", top_k=5)
known_langs = [
"English", "German", "French", "Spanish", "Italian", "Portuguese",
"Dutch", "Russian", "Chinese", "Japanese", "Korean", "Arabic",
"Turkish", "Polish", "Swedish", "Norwegian", "Danish", "Finnish",
"Greek", "Hebrew", "Hindi", "Thai", "Vietnamese", "Indonesian",
"Czech", "Romanian", "Hungarian", "Ukrainian", "Croatian", "Serbian",
]
result = "English"
for m in memories:
fact = m["fact"].lower()
if "language" in fact or "speaks" in fact or "prefers" in fact:
for lang in known_langs:
if lang.lower() in fact:
result = lang
break
return result
async def on_text_message(self, room, event: RoomMessageText):
"""Handle text messages: commands and AI responses."""
if event.sender == BOT_USER:
@@ -1298,43 +1240,6 @@ class Bot:
sender = event.sender
# --- DM translation workflow: handle pending reply composition ---
if is_dm and sender in self._pending_reply:
pending = self._pending_reply.pop(sender)
await self.client.room_typing(room.room_id, typing_state=True)
try:
translated = await self._translate_text(body, pending["target_lang"])
await self._send_text(room.room_id, translated)
finally:
await self.client.room_typing(room.room_id, typing_state=False)
return
# --- DM translation workflow: handle menu response ---
if is_dm and sender in self._pending_translate:
pending = self._pending_translate.pop(sender)
choice = body.strip().lower()
preferred_lang = await self._get_preferred_language(sender)
if choice in ("1", "1") or choice.startswith("translate"):
await self.client.room_typing(room.room_id, typing_state=True)
try:
translated = await self._translate_text(pending["text"], preferred_lang)
await self._send_text(room.room_id, translated)
finally:
await self.client.room_typing(room.room_id, typing_state=False)
return
elif choice in ("2", "2") or choice.startswith("reply"):
self._pending_reply[sender] = {"target_lang": pending["detected_lang"]}
await self._send_text(
room.room_id,
f"Type your message — I'll translate it to **{pending['detected_lang']}**.",
)
return
# choice "3" or anything else → proceed with normal AI response
# (fall through to normal flow below with original pending text context)
# Check if a recent image was sent in this room (within 60s)
image_data = None
cached = self._recent_images.get(room.room_id)
@@ -1344,31 +1249,6 @@ class Bot:
image_data = (b64, mime)
del self._recent_images[room.room_id]
# --- DM translation workflow: detect foreign language ---
if is_dm and not body.startswith("!ai") and not image_data:
preferred_lang = await self._get_preferred_language(sender)
detected_lang = await self._detect_language(body)
logger.info("Translation check: detected=%s, preferred=%s, len=%d", detected_lang, preferred_lang, len(body))
if (
detected_lang != "Unknown"
and len(detected_lang) < 30 # sanity check: language name, not a sentence
and detected_lang.lower() != preferred_lang.lower()
and len(body) > 10 # skip very short messages
):
self._pending_translate[sender] = {
"text": body,
"detected_lang": detected_lang,
"room_id": room.room_id,
}
menu = (
f"This looks like **{detected_lang}**. What would you like?\n"
f"1⃣ **Translate to {preferred_lang}**\n"
f"2⃣ **Help me reply in {detected_lang}** (type your response, I'll translate)\n"
f"3⃣ **Just respond normally**"
)
await self._send_text(room.room_id, menu)
return
# Detect Confluence page links → store page ID for voice session context
confluence_page_id = None
conf_long = re.search(r'agiliton\.atlassian\.net/wiki/.*?pages/(\d+)', body)
@@ -1885,8 +1765,6 @@ class Bot:
sender = event.sender if event else None
if sender:
deleted = await self.memory.delete_user(sender)
self._pending_translate.pop(sender, None)
self._pending_reply.pop(sender, None)
await self._send_text(room.room_id, f"All my memories about you have been deleted ({deleted} facts removed).")
else:
await self._send_text(room.room_id, "Could not identify user.")