litellm/tests/unit/proxy/common_utils/test_realtime_cache.py
mateo-berri c57d273aa6
fix(realtime): restore main behavior for guardrails, Azure transcription, and realtime clients
Streamed transcription runs unstreamed when a deployment post_call guardrail applies, so the
guardrail still sees the transcript. Azure transcription maps v1, latest and preview to the
default dated version on the deployments route for every model. The SDK client secret keeps
session.model ahead of model, realtime WebSockets connect to api_base again, realtime metadata
keeps only guardrails, and managed agents need an explicit transcription model. Reverts the two
unrelated streamed Responses error codes and the duplicate cached_tokens_details field, and the
gpt-transcribe format check only reads the request provider's cost map entry.
2026-10-21 21:30:18 -05:00

72 lines
2.8 KiB
Python

from collections.abc import Mapping
from typing import Any, Final, cast
import pytest
from pydantic import TypeAdapter
from litellm.proxy.common_utils.realtime_utils import realtime_request_body
from litellm.proxy.proxy_server import _realtime_query_params_template
@pytest.fixture(autouse=True)
def clear_realtime_caches():
realtime_request_body.cache_clear()
_realtime_query_params_template.cache_clear()
yield
realtime_request_body.cache_clear()
_realtime_query_params_template.cache_clear()
def test_realtime_request_body_returns_immutable_bytes():
cached_body = realtime_request_body("gpt-4o")
with pytest.raises(TypeError):
cast(Any, cached_body)[0] = ord("x")
def test_realtime_query_params_template_returns_immutable_tuples():
cached_tuple = _realtime_query_params_template("gpt-4o", "intent-a")
with pytest.raises(TypeError):
cast(Any, cached_tuple)[0] = ("model", "mutated")
def test_realtime_request_body_caches_each_model_separately():
gpt4o_body_first = realtime_request_body("gpt-4o")
gpt4o_body_second = realtime_request_body("gpt-4o")
gpt4o_mini_body = realtime_request_body("gpt-4o-mini")
assert gpt4o_body_first is gpt4o_body_second
assert gpt4o_body_first == b'{"model": "gpt-4o"}'
assert gpt4o_mini_body == b'{"model": "gpt-4o-mini"}'
assert gpt4o_body_first is not gpt4o_mini_body
@pytest.mark.parametrize("model", (None, "requested", 'model"with\\quotes', "model\nwith-newline"))
def test_realtime_request_body_preserves_model_names(model: str | None) -> None:
body: Final = TypeAdapter(Mapping[str, object]).validate_json(realtime_request_body(model))
assert body["model"] == model
def test_realtime_query_params_template_caches_each_pair_separately():
params_with_intent_first = _realtime_query_params_template("gpt-4o", "intent-a")
params_with_intent_second = _realtime_query_params_template("gpt-4o", "intent-a")
params_without_intent = _realtime_query_params_template("gpt-4o", None)
params_transcription_without_model = _realtime_query_params_template(None, "transcription")
assert params_with_intent_first is params_with_intent_second
assert params_with_intent_first == (("model", "gpt-4o"), ("intent", "intent-a"))
assert params_without_intent == (("model", "gpt-4o"),)
assert params_transcription_without_model == (("intent", "transcription"),)
assert params_with_intent_first is not params_without_intent
def test_realtime_query_params_dict_copies_do_not_leak_state():
params_dict_one = dict(_realtime_query_params_template("gpt-4o", "intent-a"))
params_dict_one["new"] = "value"
params_dict_two = dict(_realtime_query_params_template("gpt-4o", "intent-a"))
assert "new" not in params_dict_two
assert params_dict_two == {"model": "gpt-4o", "intent": "intent-a"}