From dd8df73abd7a419e53d2611f6cee479640bd82a4 Mon Sep 17 00:00:00 2001 From: Michael Stolarz Date: Wed, 13 May 2026 16:50:01 -0700 Subject: [PATCH] fix livekit reasoning effort default --- src/blaxel/livekit/model.py | 17 ++++++++++ tests/integration/livekit/test_model.py | 42 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/blaxel/livekit/model.py b/src/blaxel/livekit/model.py index 2aea0b42..9848d7c0 100644 --- a/src/blaxel/livekit/model.py +++ b/src/blaxel/livekit/model.py @@ -9,6 +9,21 @@ logger = getLogger(__name__) +GPT_54_REASONING_MODELS = {"gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano"} + + +def _provider_type_value(provider_type): + return getattr(provider_type, "value", provider_type) + + +def _set_default_reasoning_effort(provider_type, model: str, kwargs: dict): + if ( + _provider_type_value(provider_type) == "openai" + and model in GPT_54_REASONING_MODELS + and "reasoning_effort" not in kwargs + ): + kwargs["reasoning_effort"] = "none" + class DynamicHeadersHTTPClient(httpx.AsyncClient): """Custom HTTP client that dynamically updates headers on each request.""" @@ -31,6 +46,8 @@ async def send(self, request, *args, **kwargs): async def get_livekit_model(url: str, type: str, model: str, **kwargs): + _set_default_reasoning_effort(type, model, kwargs) + # Create custom HTTP client with dynamic headers http_client = AsyncOpenAI( base_url=f"{url}/v1", diff --git a/tests/integration/livekit/test_model.py b/tests/integration/livekit/test_model.py index 9de017c3..c59c2917 100644 --- a/tests/integration/livekit/test_model.py +++ b/tests/integration/livekit/test_model.py @@ -1,6 +1,8 @@ """LiveKit Model Integration Tests.""" pytest_plugins = [] +from unittest.mock import Mock, patch + import pytest # noqa: E402 pytest.importorskip( @@ -10,12 +12,52 @@ from livekit.agents.llm import ChatContext # noqa: E402 from blaxel.livekit import bl_model # noqa: E402 +from blaxel.livekit.model import get_livekit_model # noqa: E402 TEST_MODELS = [ "sandbox-openai", ] +async def _created_livekit_kwargs(provider_type: str, model: str, **kwargs): + llm = Mock(name="llm") + http_client = Mock(name="http_client") + openai_client = Mock(name="openai_client") + + with ( + patch("blaxel.livekit.model.DynamicHeadersHTTPClient", return_value=http_client), + patch("blaxel.livekit.model.AsyncOpenAI", return_value=openai_client), + patch("blaxel.livekit.model.openai.LLM", return_value=llm) as llm_factory, + ): + result = await get_livekit_model("https://example.com/models/test", provider_type, model, **kwargs) + + assert result is llm + return llm_factory.call_args.kwargs + + +@pytest.mark.asyncio +async def test_gpt54_openai_models_default_reasoning_effort_to_none(): + for model_name in ["gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano"]: + kwargs = await _created_livekit_kwargs("openai", model_name) + + assert kwargs["model"] == model_name + assert kwargs["reasoning_effort"] == "none" + + +@pytest.mark.asyncio +async def test_livekit_reasoning_effort_override_is_preserved(): + kwargs = await _created_livekit_kwargs("openai", "gpt-5.4-mini", reasoning_effort="low") + + assert kwargs["reasoning_effort"] == "low" + + +@pytest.mark.asyncio +async def test_livekit_non_openai_provider_does_not_default_reasoning_effort(): + kwargs = await _created_livekit_kwargs("xai", "gpt-5.4-mini") + + assert "reasoning_effort" not in kwargs + + @pytest.mark.asyncio(loop_scope="class") class TestBlModel: """Test bl_model functionality."""