fix(voice): stop thinking continuation on silence
This commit is contained in:
@@ -1694,6 +1694,81 @@ def test_media_runtime_merges_thinking_continuation_into_current_utterance():
|
||||
assert merged.endswith(continuation_pcm + continuation_pcm)
|
||||
|
||||
|
||||
def test_media_runtime_thinking_continuation_is_not_kept_alive_by_silence():
|
||||
runtime = AudioSocketMediaRuntime(
|
||||
enabled=True,
|
||||
host="127.0.0.1",
|
||||
port=0,
|
||||
frame_ms=20,
|
||||
idle_timeout_seconds=2.0,
|
||||
registration_wait_timeout_seconds=0.5,
|
||||
min_speech_ms=40,
|
||||
trailing_silence_ms=40,
|
||||
max_turn_ms=2000,
|
||||
asr_provider=_StubASRProvider(),
|
||||
streaming_asr_provider=StreamingASRProvider(),
|
||||
tts_provider=_StubTTSProvider(),
|
||||
load_registration_by_media_uuid=lambda value: None,
|
||||
mark_media_connected=lambda session_id, value: None,
|
||||
mark_media_ended=lambda session_id, reason: None,
|
||||
touch_media_frame=lambda session_id: None,
|
||||
set_state=lambda session_id, state, handoff_reason, metadata: None,
|
||||
get_pending_greeting=lambda session_id: None,
|
||||
mark_reply_delivered=lambda session_id, text, is_greeting: None,
|
||||
plan_reply=lambda session_id, text, metadata, kind: None,
|
||||
process_turn=lambda session_id, transcript_text, language, barge_in, metadata: VoiceAITurnDecisionOut(
|
||||
language=language or "ru",
|
||||
intent="clarification",
|
||||
reply_text="Подскажите подробнее, пожалуйста.",
|
||||
confidence=0.8,
|
||||
needs_handoff=False,
|
||||
handoff_reason=None,
|
||||
case_action="keep_open",
|
||||
kb_refs=[],
|
||||
summary_text="reply ready",
|
||||
model="stub-voice",
|
||||
latency_ms=1,
|
||||
status="active",
|
||||
),
|
||||
request_handoff=lambda session_id, customer_request_text, decision: None,
|
||||
handle_media_error=lambda session_id, message, metadata: None,
|
||||
)
|
||||
base_pcm = (1000).to_bytes(2, "little", signed=True) * 160
|
||||
continuation_pcm = (900).to_bytes(2, "little", signed=True) * 160
|
||||
silence_frame = b"\x00\x00" * 160
|
||||
|
||||
async def _scenario() -> bytes:
|
||||
actor = MediaActor(
|
||||
registration=MediaRegistration(
|
||||
voice_session_id="avs_media_runtime_thinking_silence_tail",
|
||||
call_id="call_media_runtime_thinking_silence_tail",
|
||||
interaction_id="int_media_runtime_thinking_silence_tail",
|
||||
ai_session_id="ais_media_runtime_thinking_silence_tail",
|
||||
language="ru",
|
||||
media_uuid=str(uuid.uuid4()),
|
||||
),
|
||||
reader=asyncio.StreamReader(),
|
||||
writer=None, # type: ignore[arg-type]
|
||||
vad=EnergyVAD(frame_ms=20, min_speech_ms=40, trailing_silence_ms=40, max_turn_ms=2000),
|
||||
frame_ms=20,
|
||||
frame_bytes=320,
|
||||
state="thinking",
|
||||
)
|
||||
merge_task = asyncio.create_task(runtime._extend_with_thinking_continuation(actor, base_pcm))
|
||||
await runtime._handle_pcm(actor, continuation_pcm)
|
||||
for _ in range(40):
|
||||
await runtime._handle_pcm(actor, silence_frame)
|
||||
await asyncio.sleep(0.02)
|
||||
merged = await asyncio.wait_for(merge_task, timeout=0.2)
|
||||
assert actor.thinking_continuation_pcm == bytearray()
|
||||
return merged
|
||||
|
||||
merged = asyncio.run(_scenario())
|
||||
|
||||
assert len(merged) > len(base_pcm)
|
||||
assert continuation_pcm in merged
|
||||
|
||||
|
||||
def _legacy_test_media_runtime_voice_v2_uses_streaming_sidecar_for_partial_and_final_asr():
|
||||
registrations: dict[str, MediaRegistration] = {}
|
||||
reply_starts: list[tuple[str, str | None, float]] = []
|
||||
|
||||
Reference in New Issue
Block a user