fix(vertex realtime): warn when dropping guardrail turn-detection update

In non-deferred mode the auto-setup is sent on connect, so the audio-transcription
guardrail's subsequent session.update carrying turn_detection.create_response=False
cannot be forwarded as a second setup (Vertex Live closes the WebSocket with 1007).
Surface a warning when this specific drop happens so operators know the model
will auto-respond before the guardrail can gate it, instead of failing silently
at debug level.
This commit is contained in:
mateo-berri 2026-05-22 22:04:19 +00:00
parent 0780e5f69f
commit d56d875ea6
No known key found for this signature in database
2 changed files with 80 additions and 2 deletions

View file

@ -226,9 +226,29 @@ class VertexAIRealtimeConfig(GeminiRealtimeConfig):
)
return [gemini_setup_msg]
verbose_logger.debug(
"Vertex AI Realtime: Ignoring session.update (setup already sent)"
# A follow-up session.update can't be forwarded as a second setup
# (Vertex Live closes the WebSocket with 1007). If this drop is
# silencing the audio-transcription guardrail's create_response
# disable, surface a warning so operators know the model will
# auto-respond before the guardrail can gate it on Vertex AI.
client_turn_detection = GeminiRealtimeConfig._extract_turn_detection(
json_message.get("session") or {}
)
if (
isinstance(client_turn_detection, dict)
and client_turn_detection.get("create_response") is False
):
verbose_logger.warning(
"Vertex AI Realtime: Dropping subsequent session.update "
"(turn_detection.create_response=False) — Vertex Live "
"rejects a second setup message. Audio-transcription "
"guardrails cannot suppress the model's auto-response on "
"Vertex AI in non-deferred mode."
)
else:
verbose_logger.debug(
"Vertex AI Realtime: Ignoring session.update (setup already sent)"
)
return []
return super().transform_realtime_request(

View file

@ -288,3 +288,61 @@ async def test_vertex_realtime_text_in_text_out():
# response.done should have been forwarded
done_msgs = [m for m in sent_to_client if '"response.done"' in m]
assert done_msgs, "Expected response.done to be sent to client"
def test_vertex_warns_when_dropping_guardrail_turn_detection_update(caplog):
"""A subsequent session.update carrying the guardrail's
``create_response: False`` cannot be forwarded as a follow-up setup on
Vertex AI (1007). Surface a warning so operators know the auto-response
suppression is being silently dropped."""
import logging
cfg = VertexAIRealtimeConfig(
access_token="tok", project="my-proj", location="us-central1"
)
session_update = {
"type": "session.update",
"session": {"turn_detection": {"create_response": False}},
}
with caplog.at_level(logging.WARNING, logger="LiteLLM"):
result = cfg.transform_realtime_request(
json.dumps(session_update),
"gemini-live-2.5-flash-native-audio",
session_configuration_request=json.dumps({"setup": {"model": "x"}}),
)
assert result == []
assert any(
"Vertex AI Realtime" in record.message
and "create_response=False" in record.message
for record in caplog.records
)
def test_vertex_does_not_warn_when_dropping_non_guardrail_session_update(caplog):
"""A subsequent session.update without ``create_response: False`` is a
routine drop and should stay at debug level (no warning)."""
import logging
cfg = VertexAIRealtimeConfig(
access_token="tok", project="my-proj", location="us-central1"
)
session_update = {
"type": "session.update",
"session": {"instructions": "Be concise."},
}
with caplog.at_level(logging.WARNING, logger="LiteLLM"):
cfg.transform_realtime_request(
json.dumps(session_update),
"gemini-live-2.5-flash-native-audio",
session_configuration_request=json.dumps({"setup": {"model": "x"}}),
)
assert not any(
"Vertex AI Realtime" in record.message and "session.update" in record.message
for record in caplog.records
)