gateway: fix greeting UX and reduce false photo-intent fallbacks

This commit is contained in:
Apple
2026-02-21 00:05:09 -08:00
parent 0a87eadb8d
commit 2b0b142f95

View File

@@ -138,17 +138,6 @@ def _looks_like_photo_followup(text: str) -> bool:
if any(m in t for m in direct_markers):
return True
# If user is correcting previous visual interpretation, route to vision again.
correction_markers = [
"неправильна відповідь", "не правильна відповідь", "не видумуй", "це не так",
"ти помилився", "ти помилилась", "неправильно визначив",
"wrong answer", "you are wrong", "that is incorrect",
"неправильный ответ", "это не так", "ты ошибся",
]
photo_topic_markers = ["фото", "зображ", "рослин", "image", "photo", "plant", "растен"]
if any(c in t for c in correction_markers) and any(p in t for p in photo_topic_markers):
return True
# Flexible forms: "що на ... фото/зображенні/світлині"
if re.search(r"(що|what|что)\s+на\s+.*(фото|зображ|світлин|image|photo)", t):
# Exclude common meta-questions
@@ -158,6 +147,37 @@ def _looks_like_photo_followup(text: str) -> bool:
return False
def _needs_photo_only_response(text: str) -> bool:
"""
Return True only for explicit requests to analyze/describe image content.
Do not trigger on meta-dialogue about previous mistakes.
"""
t = (text or "").strip().lower()
if not t:
return False
explicit_patterns = [
r"(що|what|что).{0,24}(на|in).{0,24}(фото|зображ|світлин|image|photo)",
r"(опиши|describe|проаналізуй|analyz|анализируй).{0,32}(фото|зображ|image|photo)",
r"(яка|какая|what).{0,28}(рослин|plant|культура).{0,28}(на|in).{0,28}(фото|image|photo)",
]
return any(re.search(p, t) for p in explicit_patterns)
def _is_simple_greeting(text: str) -> bool:
t = (text or "").strip().lower()
if not t:
return False
compact = re.sub(r"[^a-zаіїєґ0-9 ]+", "", t).strip()
greetings = {
"привіт", "вітаю", "добрий день", "доброго дня", "доброго вечора",
"hello", "hi", "hey", "good morning", "good evening",
}
if compact in greetings:
return True
# Short greeting variants like "привіт!" / "hi!"
return len(compact.split()) <= 3 and any(g in compact for g in greetings)
def _extract_unanswered_user_messages(
memory_context: Dict[str, Any],
current_user_id: str,
@@ -2536,14 +2556,33 @@ async def handle_telegram_webhook(
text = update.message.get("text", "")
caption = update.message.get("caption", "")
# Friendly greeting fast-path for better UX and less mechanical replies.
if _is_simple_greeting(text):
greeting_reply = (
f"Привіт, {username or 'друже'}! Я {agent_config.name}. "
"Можу допомогти з фото рослин, Excel-звітами та короткими практичними порадами."
)
await send_telegram_message(chat_id, greeting_reply, telegram_token)
await memory_client.save_chat_turn(
agent_id=agent_config.agent_id,
team_id=dao_id,
user_id=f"tg:{user_id}",
message=text,
response=greeting_reply,
channel_id=chat_id,
scope="short_term",
save_agent_response=True,
agent_metadata={"greeting_fast_path": True},
username=username,
)
return {"ok": True, "agent": agent_config.agent_id, "mode": "greeting_fast_path"}
# Photo/image intent guard:
# if text references a photo/image, try to resolve latest file_id and route to vision.
photo_intent = False
if text:
tl = text.lower()
photo_intent = _looks_like_photo_followup(text) or any(
k in tl for k in ("фото", "зображ", "світлин", "image", "photo")
)
photo_intent = _looks_like_photo_followup(text)
if not photo_intent:
# Robust fallback for common formulations like "що на цьому фото?"
photo_intent = bool(
@@ -2590,8 +2629,7 @@ async def handle_telegram_webhook(
return followup_result
# Hard guard: don't send photo-related requests to text LLM path when image context is missing.
is_question_like = ("?" in text) or any(k in tl for k in ("що", "опиши", "проанал", "what", "describe", "analy", "что"))
if is_question_like:
if _needs_photo_only_response(text):
await send_telegram_message(
chat_id,
"Бачу питання про фото, але не знайшов зображення в історії сесії. Надішли фото ще раз з коротким питанням, і я одразу проаналізую.",