fix(responses): reject unsupported reasoning effort

This commit is contained in:
Onat Özmen 2026-08-30 17:12:30 +03:00
parent 5e4b3838aa
commit e0027bdc53
2 changed files with 67 additions and 5 deletions

View file

@ -121,9 +121,8 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
) -> dict:
"""No mapping applied since inputs are in OpenAI spec already.
GPT-5 models have restrictions on temperature (only temperature=1
is accepted unless reasoning_effort='none' on models that support it).
Apply the same validation used by the chat completions path.
GPT-5 models have restrictions on temperature and reasoning effort.
Apply the same capability checks used by the chat completions path.
"""
params: Final = dict(response_api_optional_params)
@ -131,10 +130,33 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
params["max_output_tokens"] = self._enforce_min_max_output_tokens(params.get("max_output_tokens"))
if self._is_gpt_5_model(model=model):
reasoning: Final = params.get("reasoning") or {}
effort: Final = reasoning.get("effort") if isinstance(reasoning, dict) else None
if isinstance(effort, str):
from litellm.llms.openai.chat.gpt_5_transformation import OpenAIGPT5Config
unsupported_effort: Final = (
effort == "xhigh" and not OpenAIGPT5Config._supports_reasoning_effort_level(model, effort)
) or (
effort in ("minimal", "low")
and OpenAIGPT5Config._is_reasoning_effort_level_explicitly_disabled(model, effort)
)
if unsupported_effort:
if drop_params or litellm.drop_params:
updated_reasoning: Final = dict(reasoning)
updated_reasoning.pop("effort", None)
if updated_reasoning:
params["reasoning"] = updated_reasoning
else:
params.pop("reasoning", None)
else:
raise litellm.UnsupportedParamsError(
message=f"reasoning.effort={effort} is not supported for this model.",
status_code=400,
)
temperature: Final = params.get("temperature")
if temperature is not None and temperature != 1:
reasoning: Final = params.get("reasoning") or {}
effort: Final = reasoning.get("effort") if isinstance(reasoning, dict) else None
supports_none: Final = self._supports_reasoning_effort_none(model=model)
if supports_none and self._effort_resolves_to_none(model, effort):
pass # flexible temperature allowed

View file

@ -0,0 +1,40 @@
import pytest
import litellm
from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig
@pytest.mark.parametrize("effort", ["minimal", "low"])
def test_rejects_explicitly_unsupported_lower_reasoning_effort(effort: str) -> None:
config = OpenAIResponsesAPIConfig()
with pytest.raises(litellm.UnsupportedParamsError, match=f"reasoning.effort={effort}"):
config.map_openai_params(
response_api_optional_params={"reasoning": {"effort": effort}},
model="gpt-5.5-pro",
drop_params=False,
)
def test_keeps_supported_reasoning_effort() -> None:
config = OpenAIResponsesAPIConfig()
result = config.map_openai_params(
response_api_optional_params={"reasoning": {"effort": "medium"}},
model="gpt-5.5-pro",
drop_params=False,
)
assert result["reasoning"] == {"effort": "medium"}
def test_drop_params_removes_only_unsupported_effort() -> None:
config = OpenAIResponsesAPIConfig()
result = config.map_openai_params(
response_api_optional_params={"reasoning": {"effort": "minimal", "summary": "detailed"}},
model="gpt-5.5-pro",
drop_params=True,
)
assert result["reasoning"] == {"summary": "detailed"}