refactor(anthropic): make effort='max' data-driven via model map

Address review feedback on #25958:

1. @greptile-apps (P2): replace hardcoded `_is_opus_4_6_model OR
   _is_opus_4_7_model` substring check with the same data-driven
   `_supports_effort_level(model, 'max')` pattern already used for
   `xhigh` one line below. Adding support for a new model is now a
   pure model-map change.

2. @congqiao: per Anthropic's effort docs[1], `max` is supported by
   Claude Opus 4.6, Opus 4.7, AND Sonnet 4.6 — the previous patch
   only enabled 4.7. This commit also enables max on Sonnet 4.6.

Changes:
* litellm/llms/anthropic/chat/transformation.py
  - swap substring guard for `_supports_effort_level(model, 'max')`
* model_prices_and_context_window.json (+ backup)
  - add `supports_max_reasoning_effort: true` to the 10 Opus 4.7
    entries (anthropic / bedrock_converse / azure_ai / vertex_ai)
  - add `supports_max_reasoning_effort: true` to the 9 Sonnet 4.6
    entries (anthropic / bedrock_converse / azure_ai / vertex_ai)
* litellm/types/utils.py + litellm/utils.py
  - add `supports_max_reasoning_effort` to ModelInfoBase / ModelInfo
    so `get_model_info()` surfaces the new flag (mirrors the
    existing xhigh handling)
* tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py
  - flip `test_max_effort_rejected_for_sonnet_46` to
    `test_max_effort_accepted_for_sonnet_46`
  - update opus-4.5 rejection test to match new error message
  - point the opus-4.6 acceptance test at a SKU that exists in the
    model map (claude-opus-4-6-20260205)

[1] https://platform.claude.com/docs/en/build-with-claude/effort
    "The effort parameter is supported by ... Claude Opus 4.7,
    Claude Opus 4.6, and Claude Sonnet 4.6."
This commit is contained in:
shang309073819 2026-04-17 23:13:36 +00:00
parent de196e4c41
commit 364a556062
6 changed files with 86 additions and 43 deletions

View file

@ -1534,19 +1534,16 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
f"Invalid effort value: {effort}. Must be one of: "
f"'high', 'medium', 'low', 'xhigh', 'max'"
)
# ``max`` is supported by Claude Opus 4.6 and Opus 4.7 (not Sonnet 4.6,
# not Opus 4.5). The upstream Anthropic API accepts effort=max on both
# Opus 4.6 and 4.7, so we keep both substring checks here for
# date-variant tolerance (e.g. claude-opus-4-7-20260408). See #25957.
if effort == "max" and not (
self._is_opus_4_6_model(model) or self._is_opus_4_7_model(model)
):
# Both ``max`` and ``xhigh`` are data-driven via
# ``supports_{level}_reasoning_effort`` in the model map, mirroring the
# pattern used in ``openai/chat/gpt_5_transformation.py``. Enabling a
# new model for either level is therefore a pure model-map change.
# Per Anthropic's effort docs, ``max`` is currently accepted on Claude
# Opus 4.6, Opus 4.7, and Sonnet 4.6. See #25957 / #25958.
if effort == "max" and not self._supports_effort_level(model, "max"):
raise ValueError(
f"effort='max' is only supported by Claude Opus 4.6 and 4.7. "
f"Got model: {model}"
f"effort='max' is not supported by this model. Got model: {model}"
)
# ``xhigh`` is data-driven via ``supports_xhigh_reasoning_effort`` so
# enabling it for a new model is a pure model-map change.
if effort == "xhigh" and not self._supports_effort_level(model, "xhigh"):
raise ValueError(
f"effort='xhigh' is not supported by this model. Got model: {model}"

View file

@ -1145,6 +1145,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1173,6 +1174,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1201,6 +1203,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1229,6 +1232,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1257,6 +1261,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1285,7 +1290,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"global.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 3.75e-06,
@ -1312,7 +1318,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"us.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 4.125e-06,
@ -1339,7 +1346,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"eu.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 4.125e-06,
@ -1366,7 +1374,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"au.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 4.125e-06,
@ -1393,7 +1402,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"anthropic.claude-sonnet-4-20250514-v1:0": {
"cache_creation_input_token_cost": 3.75e-06,
@ -1939,6 +1949,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 159
},
"azure_ai/claude-opus-4-1": {
@ -2003,7 +2014,8 @@
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346
"tool_use_system_prompt_tokens": 346,
"supports_max_reasoning_effort": true
},
"azure/computer-use-preview": {
"input_cost_per_token": 3e-06,
@ -8909,7 +8921,8 @@
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346
"tool_use_system_prompt_tokens": 346,
"supports_max_reasoning_effort": true
},
"claude-sonnet-4-5-20250929-v1:0": {
"cache_creation_input_token_cost": 3.75e-06,
@ -9163,6 +9176,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"provider_specific_entry": {
"us": 1.1,
@ -9195,6 +9209,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"provider_specific_entry": {
"us": 1.1,
@ -31399,6 +31414,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346
},
"vertex_ai/claude-opus-4-7@default": {
@ -31426,6 +31442,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346
},
"vertex_ai/claude-sonnet-4-5": {
@ -31478,7 +31495,8 @@
"search_context_size_high": 0.01,
"search_context_size_low": 0.01,
"search_context_size_medium": 0.01
}
},
"supports_max_reasoning_effort": true
},
"vertex_ai/claude-sonnet-4-5@20250929": {
"cache_creation_input_token_cost": 3.75e-06,
@ -38345,7 +38363,8 @@
"search_context_size_high": 0.01,
"search_context_size_low": 0.01,
"search_context_size_medium": 0.01
}
},
"supports_max_reasoning_effort": true
},
"duckduckgo/search": {
"litellm_provider": "duckduckgo",

View file

@ -140,6 +140,7 @@ class ProviderSpecificModelInfo(TypedDict, total=False):
supports_url_context: Optional[bool]
supports_none_reasoning_effort: Optional[bool]
supports_xhigh_reasoning_effort: Optional[bool]
supports_max_reasoning_effort: Optional[bool]
class SearchContextCostPerQuery(TypedDict, total=False):

View file

@ -5896,6 +5896,9 @@ def _get_model_info_helper( # noqa: PLR0915
supports_xhigh_reasoning_effort=_model_info.get(
"supports_xhigh_reasoning_effort", None
),
supports_max_reasoning_effort=_model_info.get(
"supports_max_reasoning_effort", None
),
supports_computer_use=_model_info.get("supports_computer_use", None),
search_context_cost_per_query=_model_info.get(
"search_context_cost_per_query", None

View file

@ -1145,6 +1145,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1173,6 +1174,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1201,6 +1203,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1229,6 +1232,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1257,6 +1261,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
},
@ -1285,7 +1290,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"global.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 3.75e-06,
@ -1312,7 +1318,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"us.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 4.125e-06,
@ -1339,7 +1346,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"eu.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 4.125e-06,
@ -1366,7 +1374,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"au.anthropic.claude-sonnet-4-6": {
"cache_creation_input_token_cost": 4.125e-06,
@ -1393,7 +1402,8 @@
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
"supports_native_structured_output": true
"supports_native_structured_output": true,
"supports_max_reasoning_effort": true
},
"anthropic.claude-sonnet-4-20250514-v1:0": {
"cache_creation_input_token_cost": 3.75e-06,
@ -1939,6 +1949,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 159
},
"azure_ai/claude-opus-4-1": {
@ -2003,7 +2014,8 @@
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346
"tool_use_system_prompt_tokens": 346,
"supports_max_reasoning_effort": true
},
"azure/computer-use-preview": {
"input_cost_per_token": 3e-06,
@ -8909,7 +8921,8 @@
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346
"tool_use_system_prompt_tokens": 346,
"supports_max_reasoning_effort": true
},
"claude-sonnet-4-5-20250929-v1:0": {
"cache_creation_input_token_cost": 3.75e-06,
@ -9163,6 +9176,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"provider_specific_entry": {
"us": 1.1,
@ -9195,6 +9209,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346,
"provider_specific_entry": {
"us": 1.1,
@ -31399,6 +31414,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346
},
"vertex_ai/claude-opus-4-7@default": {
@ -31426,6 +31442,7 @@
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"supports_max_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346
},
"vertex_ai/claude-sonnet-4-5": {
@ -31478,7 +31495,8 @@
"search_context_size_high": 0.01,
"search_context_size_low": 0.01,
"search_context_size_medium": 0.01
}
},
"supports_max_reasoning_effort": true
},
"vertex_ai/claude-sonnet-4-5@20250929": {
"cache_creation_input_token_cost": 3.75e-06,
@ -38345,7 +38363,8 @@
"search_context_size_high": 0.01,
"search_context_size_low": 0.01,
"search_context_size_medium": 0.01
}
},
"supports_max_reasoning_effort": true
},
"duckduckgo/search": {
"litellm_provider": "duckduckgo",

View file

@ -1654,7 +1654,7 @@ def test_max_effort_rejected_for_opus_45():
messages = [{"role": "user", "content": "Test"}]
with pytest.raises(
ValueError, match="effort='max' is only supported by Claude Opus 4.6 and 4.7"
ValueError, match="effort='max' is not supported by this model"
):
optional_params = {"output_config": {"effort": "max"}}
config.transform_request(
@ -2212,21 +2212,25 @@ def test_reasoning_effort_does_not_set_output_config_for_older_models():
), f"output_config should not be set for {model}"
def test_max_effort_rejected_for_sonnet_46():
"""Test that effort='max' is rejected for Sonnet 4.6 (Sonnet 4.6 doesn't support max)."""
def test_max_effort_accepted_for_sonnet_46():
"""Per Anthropic's effort docs, ``max`` is supported by Sonnet 4.6.
Source: https://platform.claude.com/docs/en/build-with-claude/effort
> The ``max`` effort level is available on Claude Mythos Preview,
> Claude Opus 4.7, Claude Opus 4.6, and Claude Sonnet 4.6.
"""
config = AnthropicConfig()
messages = [{"role": "user", "content": "Test"}]
with pytest.raises(
ValueError, match="effort='max' is only supported by Claude Opus 4.6 and 4.7"
):
config.transform_request(
model="claude-sonnet-4-6-20260219",
messages=messages,
optional_params={"output_config": {"effort": "max"}},
litellm_params={},
headers={},
)
result = config.transform_request(
model="claude-sonnet-4-6",
messages=messages,
optional_params={"output_config": {"effort": "max"}},
litellm_params={},
headers={},
)
assert result["output_config"]["effort"] == "max"
def test_max_effort_accepted_for_opus_46():
@ -2235,7 +2239,7 @@ def test_max_effort_accepted_for_opus_46():
messages = [{"role": "user", "content": "Test"}]
result = config.transform_request(
model="claude-opus-4-6-20250514",
model="claude-opus-4-6-20260205",
messages=messages,
optional_params={"output_config": {"effort": "max"}},
litellm_params={},