This commit is contained in:
Mrunmayee Daware 2026-10-28 03:16:34 -04:00 • committed by GitHub
commit dbf5ee3734
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 3 deletions

View file

@ -376,6 +376,8 @@ def _build_anthropic_tool_name_maps(
return forward, reverse
_CLAUDE_MAJOR_VERSION: Final = re.compile(r"claude-[a-z]+-(\d+)")
REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT: Final[dict[str, str]] = {
"low": "low",
"minimal": "low",
@ -1565,7 +1567,23 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
llm_provider: str = "anthropic",
) -> AnthropicThinkingParam | None:
"""Capability probes read the cost map under ``custom_llm_provider``; ``llm_provider`` only tags raised exceptions."""
if reasoning_effort is None or reasoning_effort == "none":
if reasoning_effort is None:
return None
if reasoning_effort == "none":
# An explicit "none" asks for thinking off. On Claude 5-generation
# models that default thinking on (Opus 5, Sonnet 5, Haiku 5.5),
# omission leaves the model's default in effect, so translate
# "none" to thinking.type="disabled", which those models accept.
# Models that default thinking off keep omission, which already
# honors "none"; always-on-thinking models reject "disabled" and
# are handled downstream by maybe_drop_disabled_thinking.
major: Final = _CLAUDE_MAJOR_VERSION.search(model)
if (
major is not None
and int(major.group(1)) >= 5
and AnthropicConfig._is_adaptive_thinking_model(model, custom_llm_provider)
):
return AnthropicThinkingParam(type="disabled")
return None
if AnthropicConfig._is_adaptive_thinking_model(model, custom_llm_provider):
# without display, Anthropic defaults adaptive thinking to
@ -1962,7 +1980,10 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
optional_params.pop("output_config", None)
else:
optional_params["thinking"] = mapped_thinking
if AnthropicConfig._is_adaptive_thinking_model(model, self._resolved_provider):
# "none" disables thinking outright; there is no matching output_config effort.
if effort_value != "none" and AnthropicConfig._is_adaptive_thinking_model(
model, self._resolved_provider
):
mapped_effort = REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT.get(effort_value)
if mapped_effort is None:
AnthropicConfig._raise_invalid_reasoning_effort(

View file

@ -552,7 +552,8 @@ class AmazonConverseConfig(BaseConfig):
optional_params.pop("output_config", None)
else:
optional_params["thinking"] = mapped_thinking
if AnthropicConfig.is_adaptive_thinking_model(model, "bedrock"):
# "none" disables thinking outright; there is no matching output_config effort.
if reasoning_effort != "none" and AnthropicConfig.is_adaptive_thinking_model(model, "bedrock"):
mapped_effort = REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT.get(reasoning_effort)
if mapped_effort is None:
AnthropicConfig.raise_invalid_reasoning_effort(

View file

@ -74,3 +74,58 @@ class TestMapReasoningEffort:
reasoning_effort="none", model="claude-4-sonnet-20250514", custom_llm_provider="anthropic"
)
assert result is None
def test_none_string_returns_disabled_for_haiku_5_5(self):
"""reasoning_effort='none' must explicitly disable thinking on Claude
models that default thinking on (Haiku 5.5); omission leaves the
model's default in effect."""
result = AnthropicConfig.map_reasoning_effort(
reasoning_effort="none", model="claude-haiku-5-5", custom_llm_provider="anthropic"
)
assert result == {"type": "disabled"}
def test_none_string_returns_disabled_for_opus_5(self):
result = AnthropicConfig.map_reasoning_effort(
reasoning_effort="none", model="claude-opus-5", custom_llm_provider="anthropic"
)
assert result == {"type": "disabled"}
def test_none_string_returns_disabled_for_always_on_model(self):
"""Always-on models map to 'disabled' too; transform_request drops it
via maybe_drop_disabled_thinking (the API-documented remedy)."""
result = AnthropicConfig.map_reasoning_effort(
reasoning_effort="none", model="claude-sonnet-5-5", custom_llm_provider="anthropic"
)
assert result == {"type": "disabled"}
def test_none_string_map_openai_params_sets_thinking_without_output_config(self):
params = AnthropicConfig().map_openai_params(
non_default_params={"reasoning_effort": "none"},
optional_params={},
model="claude-haiku-5-5",
drop_params=False,
)
assert params.get("thinking") == {"type": "disabled"}
assert "output_config" not in params
def test_disabled_thinking_dropped_for_always_on_model(self):
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
optional_params = {"thinking": {"type": "disabled"}}
AnthropicModelInfo.maybe_drop_disabled_thinking(
model="claude-sonnet-5-5",
optional_params=optional_params,
custom_llm_provider="anthropic",
)
assert "thinking" not in optional_params
def test_disabled_thinking_kept_for_haiku_5_5(self):
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
optional_params = {"thinking": {"type": "disabled"}}
AnthropicModelInfo.maybe_drop_disabled_thinking(
model="claude-haiku-5-5",
optional_params=optional_params,
custom_llm_provider="anthropic",
)
assert optional_params["thinking"] == {"type": "disabled"}