mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
fix(realtime): address P1 issues - guardrail timing and inputAudioTranscription default
- Remove early guardrail turn-detection update that consumed first setup slot - Add inputAudioTranscription default in Gemini deferred-mode setup - Add tests for both fixes Made-with: Cursor
This commit is contained in:
parent
817792c6cc
commit
86f5c21025
4 changed files with 72 additions and 1 deletions
|
|
@ -5167,7 +5167,6 @@ class BaseLLMHTTPHandler:
|
|||
if synthetic_session is not None:
|
||||
await websocket.send_text(json.dumps(synthetic_session))
|
||||
realtime_streaming._session_created_sent_to_client = True
|
||||
await realtime_streaming._maybe_send_guardrail_turn_detection_update()
|
||||
verbose_logger.debug(
|
||||
"Sent synthetic session.created to client to unblock connection"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ class GeminiRealtimeConfig(BaseRealtimeConfig):
|
|||
"generationConfig", {}
|
||||
)
|
||||
generation_config.setdefault("responseModalities", ["AUDIO"])
|
||||
client_session_configuration_request.setdefault("inputAudioTranscription", {})
|
||||
client_session_configuration_request["model"] = f"models/{model}"
|
||||
gemini_setup_msg = json.dumps({"setup": client_session_configuration_request})
|
||||
verbose_logger.debug(
|
||||
|
|
|
|||
|
|
@ -1080,3 +1080,40 @@ async def test_duplicate_session_created_still_triggers_guardrail_turn_detection
|
|||
sent_update = json.loads(streaming._send_to_backend.await_args_list[0].args[0])
|
||||
assert sent_update["type"] == "session.update"
|
||||
assert sent_update["session"]["turn_detection"]["create_response"] is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_guardrail_update_respects_idempotency_flag():
|
||||
"""Verify guardrail turn-detection update uses idempotency flag correctly."""
|
||||
client_ws = AsyncMock()
|
||||
backend_ws = MagicMock()
|
||||
backend_ws.send = AsyncMock()
|
||||
|
||||
logging_obj = MagicMock()
|
||||
logging_obj.litellm_trace_id = "trace_1"
|
||||
logging_obj.async_success_handler = AsyncMock()
|
||||
logging_obj.success_handler = MagicMock()
|
||||
|
||||
provider_config = MagicMock()
|
||||
provider_config.transform_realtime_request = MagicMock(
|
||||
side_effect=lambda msg, model, session_config: [msg]
|
||||
)
|
||||
|
||||
streaming = RealTimeStreaming(
|
||||
websocket=client_ws,
|
||||
backend_ws=backend_ws,
|
||||
logging_obj=logging_obj,
|
||||
provider_config=provider_config,
|
||||
model="gemini-2.5-flash",
|
||||
)
|
||||
streaming._has_audio_transcription_guardrails = MagicMock(return_value=True) # type: ignore[method-assign]
|
||||
|
||||
# First call should send the update
|
||||
assert streaming._guardrail_turn_detection_update_sent is False
|
||||
await streaming._maybe_send_guardrail_turn_detection_update()
|
||||
assert streaming._guardrail_turn_detection_update_sent is True
|
||||
assert backend_ws.send.await_count == 1
|
||||
|
||||
# Second call should be a no-op (idempotent)
|
||||
await streaming._maybe_send_guardrail_turn_detection_update()
|
||||
assert backend_ws.send.await_count == 1 # Still 1, not 2
|
||||
|
|
|
|||
|
|
@ -584,3 +584,37 @@ def test_gemini_realtime_multi_tool_calls_have_unique_item_ids():
|
|||
assert responses[0]["item_id"] != responses[1]["item_id"]
|
||||
assert responses[0]["output_index"] == 0
|
||||
assert responses[1]["output_index"] == 1
|
||||
|
||||
|
||||
def test_gemini_session_update_includes_input_audio_transcription_default():
|
||||
"""Verify _handle_session_update includes inputAudioTranscription default."""
|
||||
config = GeminiRealtimeConfig()
|
||||
session_update = {
|
||||
"type": "session.update",
|
||||
"session": {
|
||||
"modalities": ["text", "audio"],
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"name": "get_weather",
|
||||
"description": "Get weather",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"location": {"type": "string"}},
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
result = config.transform_realtime_request(
|
||||
json.dumps(session_update),
|
||||
"gemini-2.5-flash",
|
||||
session_configuration_request=None,
|
||||
)
|
||||
|
||||
assert len(result) == 1
|
||||
setup = json.loads(result[0])
|
||||
assert "setup" in setup
|
||||
assert "inputAudioTranscription" in setup["setup"]
|
||||
assert setup["setup"]["inputAudioTranscription"] == {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue