fix(voice): fast fallback for off-domain requests
This commit is contained in:
@@ -906,6 +906,97 @@ def _voice_generic_prompt(language: str) -> str:
|
||||
return "Чтобы помочь быстрее, скажите в двух словах, что вам нужно: график работы, статус заявки, тариф или оператор."
|
||||
|
||||
|
||||
def _voice_has_service_topic(text: str | None) -> bool:
|
||||
normalized = _voice_text_key(text)
|
||||
if not normalized:
|
||||
return False
|
||||
service_markers = (
|
||||
"график",
|
||||
"время работы",
|
||||
"режим работы",
|
||||
"статус",
|
||||
"заявк",
|
||||
"заказ",
|
||||
"обращен",
|
||||
"запрос",
|
||||
"тариф",
|
||||
"стоимост",
|
||||
"цен",
|
||||
"оплат",
|
||||
"услуг",
|
||||
"адрес",
|
||||
"филиал",
|
||||
"город",
|
||||
"офис",
|
||||
"отделени",
|
||||
"не работает",
|
||||
"ошибк",
|
||||
"проблем",
|
||||
"сбой",
|
||||
"интернет",
|
||||
"связь",
|
||||
"оператор",
|
||||
"менеджер",
|
||||
"сотрудник",
|
||||
"компан",
|
||||
"подключ",
|
||||
"доставк",
|
||||
)
|
||||
return any(marker in normalized for marker in service_markers)
|
||||
|
||||
|
||||
def _voice_is_off_domain_request(text: str | None) -> bool:
|
||||
normalized = _voice_text_key(text)
|
||||
if not normalized or _voice_has_service_topic(normalized):
|
||||
return False
|
||||
broad_markers = (
|
||||
"ядерн",
|
||||
"реактор",
|
||||
"космос",
|
||||
"планет",
|
||||
"математ",
|
||||
"теорем",
|
||||
"физик",
|
||||
"хими",
|
||||
"биолог",
|
||||
"истори",
|
||||
"рецепт",
|
||||
"борщ",
|
||||
"салат",
|
||||
"анекдот",
|
||||
"стих",
|
||||
"програм",
|
||||
"python",
|
||||
"java",
|
||||
"javascript",
|
||||
"погод",
|
||||
)
|
||||
if any(marker in normalized for marker in broad_markers):
|
||||
return True
|
||||
broad_openers = (
|
||||
"как работает",
|
||||
"как устроен",
|
||||
"что такое",
|
||||
"объясни",
|
||||
"расскажи про",
|
||||
"почему",
|
||||
)
|
||||
return any(normalized.startswith(prefix) for prefix in broad_openers)
|
||||
|
||||
|
||||
def _voice_off_domain_reply(language: str) -> tuple[str, str]:
|
||||
if language == "kz":
|
||||
return (
|
||||
"Men kompaniyamyzdyn qyzmetteri men otinishteri boiynsha komek bere alamyn. "
|
||||
"Eger suraq bizdin qyzmetke qatysty bolsa, qysqasha naqtylaңыз. Qalasaңыз, operatorga qosamyn.",
|
||||
"AI qongyraudyn taqyrybyn kompaniya qyzmetteri sheginde naqtylaudy usyndy.",
|
||||
)
|
||||
return (
|
||||
"Я помогу по вопросам наших услуг и обращений. Если вопрос связан с нашей компанией, скажите коротко, что именно нужно. Если хотите, сразу соединю с оператором.",
|
||||
"AI мягко вернул разговор к вопросам компании и предложил перевод на оператора.",
|
||||
)
|
||||
|
||||
|
||||
def _voice_confusion_prompt(language: str, caller_texts: list[str]) -> str:
|
||||
topic_prompt = _voice_topic_prompt(language, caller_texts)
|
||||
if topic_prompt:
|
||||
@@ -1504,6 +1595,26 @@ def _voice_decision(
|
||||
"latency_ms": 1,
|
||||
}
|
||||
|
||||
if not kb_results and _voice_is_off_domain_request(normalized):
|
||||
reply_text, summary_text = _voice_off_domain_reply(language)
|
||||
decision = {
|
||||
"language": language,
|
||||
"intent": "clarification",
|
||||
"reply_text": reply_text,
|
||||
"confidence": 0.58,
|
||||
"needs_handoff": False,
|
||||
"handoff_reason": None,
|
||||
"case_action": "keep_open",
|
||||
"kb_refs": [],
|
||||
"summary_text": summary_text,
|
||||
"model": "voice_policy_off_domain",
|
||||
"latency_ms": 1,
|
||||
}
|
||||
if v2_metadata:
|
||||
decision["reply_text"] = _voice_compact_reply_text(decision["reply_text"], language=language)
|
||||
decision["metadata"] = v2_metadata
|
||||
return decision
|
||||
|
||||
llm_decision = _voice_llm_decision(
|
||||
language=language,
|
||||
customer=customer,
|
||||
|
||||
Reference in New Issue
Block a user