From 010a8dcab6bc4dae7c2d78e2d2b1f2c46781ab76 Mon Sep 17 00:00:00 2001 From: didar Date: Sun, 30 Aug 2026 12:49:26 +0500 Subject: [PATCH] fix: ensure emotive ack rotation and prebaked ack caching apply outside v2 queue eligibility --- services/ai_voice_runtime_service/app.py | 13 ++++++++----- tests/test_ai_voice_runtime_service.py | 10 +++++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/services/ai_voice_runtime_service/app.py b/services/ai_voice_runtime_service/app.py index 49f37ca..284d035 100644 --- a/services/ai_voice_runtime_service/app.py +++ b/services/ai_voice_runtime_service/app.py @@ -822,11 +822,14 @@ def _media_registration_from_row(row: VoiceAISessionRow, *, queue_code: str | No voice_v2_partial_asr=bool(voice_v2_for_session and _voice_v2_partial_asr_enabled()), voice_v2_duplex=bool(voice_v2_for_session and _voice_v2_duplex_enabled()), voice_v2_streaming_asr_backend=streaming_backend, - voice_v2_prebaked_ack=bool(voice_v2_for_session and _voice_v2_prebaked_ack_enabled()), - # Deliberately NOT gated on voice_v2_for_session: phrase-variant rotation only - # needs a text pool + live TTS, not the v2 duplex/partial-ASR pipeline, so calls - # outside the v2 queue allowlist still get varied fillers instead of always the - # single fixed "Секунду." fallback string. + # voice_v2_prebaked_ack and voice_v2_emotive_ack are deliberately NOT gated on + # voice_v2_for_session: filler-ack synthesis/caching and phrase-variant rotation + # only need a text pool + the ack bank, not the v2 duplex/partial-ASR pipeline. + # Without this, calls outside the v2 queue allowlist would synthesize every + # filler live via ElevenLabs before it could play — adding real TTS round-trip + # time to the one phrase whose whole job is to hide that latency — and would + # always get the single fixed "Секунду." fallback string instead of rotating. + voice_v2_prebaked_ack=bool(_voice_v2_prebaked_ack_enabled()), voice_v2_emotive_ack=bool(_voice_v2_emotive_ack_enabled()), voice_v2_emotive_ack_ru_only=bool(_voice_v2_emotive_ack_ru_only()), ) diff --git a/tests/test_ai_voice_runtime_service.py b/tests/test_ai_voice_runtime_service.py index 638f2d7..39546ef 100644 --- a/tests/test_ai_voice_runtime_service.py +++ b/tests/test_ai_voice_runtime_service.py @@ -859,11 +859,14 @@ def test_push_voice_ai_telephony_event_call_ended_returns_detached_safe_payload( def test_media_registration_emotive_ack_rotation_is_not_gated_on_v2_queue_eligibility(monkeypatch): # AI_VOICE_V2_QUEUE_CODES defaults to "voice_lab_ai" only, so a queue outside - # that allowlist runs the plain v1 ack path. Emotive-ack rotation must still - # apply there — otherwise every filler collapses to the single fixed - # "Секунду." fallback string instead of rotating through phrase variants. + # that allowlist runs the plain v1 ack path. Emotive-ack rotation and prebaked-ack + # caching must still apply there — otherwise every filler collapses to the single + # fixed "Секунду." fallback string instead of rotating, and gets synthesized live + # via ElevenLabs each time instead of served from the pre-cached ack bank, adding + # real TTS round-trip time to the one phrase whose job is to hide that latency. monkeypatch.delenv("AI_VOICE_V2_QUEUE_CODES", raising=False) monkeypatch.delenv("AI_VOICE_V2_EMOTIVE_ACK_ENABLED", raising=False) + monkeypatch.delenv("AI_VOICE_V2_PREBAKED_ACK_ENABLED", raising=False) row = VoiceAISessionRow( session_id="avs_runtime_emotive_ack_v1", call_id="call_runtime_emotive_ack_v1", @@ -879,3 +882,4 @@ def test_media_registration_emotive_ack_rotation_is_not_gated_on_v2_queue_eligib assert registration.voice_v2_enabled is False assert registration.voice_v2_emotive_ack is True + assert registration.voice_v2_prebaked_ack is True