fix(voice): stop repeating failed clarifications

This commit is contained in:
Yera All
2026-04-19 01:19:54 +05:00
parent 77df41bce0
commit 294d30a797
2 changed files with 118 additions and 1 deletions
+54
View File
@@ -1247,6 +1247,60 @@ def test_voice_decision_handoffs_after_repeated_clarification_loop():
assert "нескольких попыток" in decision["handoff_reason"].lower()
def test_voice_decision_uses_repair_prompt_after_repeated_unknown_request():
transcript_window = [
SimpleNamespace(speaker="assistant", text=voice_module._voice_greeting("ru"), sequence_no=1),
SimpleNamespace(speaker="caller", text=_u(r"\u041d\u0443 \u043c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043a \u0432\u0430\u043c \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f."), sequence_no=2),
SimpleNamespace(speaker="assistant", text=_u(r"\u0415\u0440\u043d\u0443\u0440. \u0427\u0435\u043c \u043c\u043e\u0433\u0443 \u043f\u043e\u043c\u043e\u0447\u044c?"), sequence_no=3),
SimpleNamespace(speaker="caller", text=_u(r"\u041c\u043d\u0435 \u043d\u0430\u0434\u043e \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0437-"), sequence_no=4),
SimpleNamespace(speaker="assistant", text=_u(r"\u0415\u0440\u043d\u0443\u0440, \u043e \u0447\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0437\u043d\u0430\u0442\u044c?"), sequence_no=5),
SimpleNamespace(speaker="caller", text=_u(r"\u042f \u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u044e, \u043c\u043d\u0435 \u043d\u0430\u0434\u043e \u0443\u0437\u043d\u0430\u0442\u044c, \u0433\u0434\u0435--"), sequence_no=6),
]
decision = voice_module._voice_decision(
language="ru",
customer=None,
interaction=SimpleNamespace(interaction_id="int_voice_repair"),
transcript_text=_u(r"\u042f \u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u044e, \u043c\u043d\u0435 \u043d\u0430\u0434\u043e \u0443\u0437\u043d\u0430\u0442\u044c, \u0433\u0434\u0435--"),
transcript_window=transcript_window,
kb_results=[],
disclosure_required=False,
request_metadata={"voice_v2_enabled": True, "response_plan_id": "rsp_repair"},
)
normalized = decision["reply_text"].lower()
assert decision["model"] == "voice_policy_repair"
assert decision["needs_handoff"] is False
assert "назовите один вариант" in normalized
assert "график работы" in normalized
assert "оператор" in normalized
assert "о чем именно" not in normalized
def test_voice_decision_handoffs_after_frustrated_repair_loop():
transcript_window = [
SimpleNamespace(speaker="assistant", text=voice_module._voice_greeting("ru"), sequence_no=1),
SimpleNamespace(speaker="assistant", text=_u(r"\u0415\u0440\u043d\u0443\u0440. \u0427\u0435\u043c \u043c\u043e\u0433\u0443 \u043f\u043e\u043c\u043e\u0447\u044c?"), sequence_no=2),
SimpleNamespace(speaker="assistant", text=_u(r"\u0415\u0440\u043d\u0443\u0440, \u043e \u0447\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0437\u043d\u0430\u0442\u044c?"), sequence_no=3),
SimpleNamespace(speaker="assistant", text=_u(r"\u041f\u043b\u043e\u0445\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441. \u041d\u0430\u0437\u043e\u0432\u0438\u0442\u0435 \u043e\u0434\u0438\u043d \u0432\u0430\u0440\u0438\u0430\u043d\u0442: \u0433\u0440\u0430\u0444\u0438\u043a \u0440\u0430\u0431\u043e\u0442\u044b, \u0430\u0434\u0440\u0435\u0441, \u0442\u0430\u0440\u0438\u0444, \u0437\u0430\u044f\u0432\u043a\u0430 \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440."), sequence_no=4),
]
decision = voice_module._voice_decision(
language="ru",
customer=None,
interaction=SimpleNamespace(interaction_id="int_voice_repair_handoff"),
transcript_text=_u(r"\u0422\u0430\u043a \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0439."),
transcript_window=transcript_window,
kb_results=[],
disclosure_required=False,
request_metadata={"voice_v2_enabled": True, "response_plan_id": "rsp_repair_handoff"},
)
assert decision["intent"] == "handoff_request"
assert decision["needs_handoff"] is True
assert "оператор" in decision["reply_text"].lower()
def test_voice_kb_search_matches_relaxed_phrase_and_returns_kb_answer():
query = _u(r"\u0425\u043e\u0447\u0443 \u0443\u0437\u043d\u0430\u0442\u044c \u0442\u0430\u0440\u0438\u0444 relaxbasicx")
seed_kb_article(