fix(responses): only drop reasoning when it carries an effort and let an explicit map flag win
Some checks failed
LiteLLM Rust / rustfmt, clippy, test (push) Has been cancelled
LiteLLM Rust / release wheel (push) Has been cancelled
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled

This commit is contained in:
mateo-berri 2026-09-05 18:53:37 -07:00
parent 1975a54b04
commit d748cf40b7
2 changed files with 45 additions and 5 deletions

View file

@ -149,7 +149,17 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
)
except Exception:
return True
return info["key"] in _bundled_openai_reasoning_models() or info.get("supports_reasoning") is True
declared: Final = info.get("supports_reasoning")
if declared is not None:
return declared
return info["key"] in _bundled_openai_reasoning_models()
@staticmethod
def _requests_reasoning_effort(reasoning: object) -> bool:
effort: Final = (
reasoning.get("effort") if isinstance(reasoning, Mapping) else getattr(reasoning, "effort", None)
)
return effort is not None
@staticmethod
def _enforce_min_max_output_tokens(max_output_tokens: "int | None") -> "int | None":
@ -202,7 +212,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
if (
self.custom_llm_provider == LlmProviders.OPENAI
and params.get("reasoning") is not None
and self._requests_reasoning_effort(params.get("reasoning"))
and not self._supports_reasoning_param(model=model)
):
if drop_params or litellm.drop_params:
@ -210,7 +220,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
else:
raise litellm.UnsupportedParamsError(
message=(
f"{model} doesn't support the `reasoning` parameter "
f"{model} doesn't support `reasoning.effort` "
"(its model cost map entry lacks `supports_reasoning`). "
"To drop unsupported params set `litellm.drop_params = True`"
),

View file

@ -2086,12 +2086,42 @@ class TestReasoningFollowsModelSupport:
drop_params=False,
)
assert excinfo.value.status_code == 400
assert "reasoning.effort" in str(excinfo.value)
assert "cost map" in str(excinfo.value)
def test_azure_deployments_keep_reasoning(self, local_model_cost_map):
@pytest.mark.parametrize("drop_params", [True, False])
@pytest.mark.parametrize(
"reasoning",
[{"summary": "auto"}, {"effort": None, "summary": "auto"}, {}],
)
def test_reasoning_without_an_effort_passes_through_on_non_reasoning_models(
self, local_model_cost_map, monkeypatch, drop_params, reasoning
):
monkeypatch.setattr(litellm, "drop_params", drop_params)
mapped = OpenAIResponsesAPIConfig().map_openai_params(
response_api_optional_params={"reasoning": dict(reasoning)},
model="gpt-4o",
drop_params=drop_params,
)
assert mapped["reasoning"] == reasoning
def test_an_explicit_supports_reasoning_false_beats_the_bundled_floor(self, local_model_cost_map, monkeypatch):
overridden = {
name: ({**entry, "supports_reasoning": False} if name == "o3" else entry)
for name, entry in litellm.model_cost.items()
}
monkeypatch.setattr(litellm, "model_cost", overridden)
mapped = OpenAIResponsesAPIConfig().map_openai_params(
response_api_optional_params={"reasoning": {"effort": "medium"}},
model="o3",
drop_params=True,
)
assert "reasoning" not in mapped
def test_azure_deployments_keep_reasoning_even_on_a_non_reasoning_model_name(self, local_model_cost_map):
mapped = AzureOpenAIResponsesAPIConfig().map_openai_params(
response_api_optional_params={"reasoning": {"effort": "medium"}},
model="my-o3-deployment",
model="gpt-4o",
drop_params=True,
)
assert mapped["reasoning"] == {"effort": "medium"}