mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
Normalize Anthropic messages xhigh output_config
This commit is contained in:
parent
bcbae93ecc
commit
aa0088743f
2 changed files with 91 additions and 16 deletions
|
|
@ -212,6 +212,11 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
|
|||
),
|
||||
status_code=400,
|
||||
)
|
||||
mapped_effort = (
|
||||
AnthropicMessagesConfig._normalize_xhigh_effort_for_max_model(
|
||||
model, mapped_effort
|
||||
)
|
||||
)
|
||||
gate_error = AnthropicConfig._validate_effort_for_model(
|
||||
model, mapped_effort
|
||||
)
|
||||
|
|
@ -223,6 +228,35 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
|
|||
existing_output_config.setdefault("effort", mapped_effort)
|
||||
optional_params["output_config"] = existing_output_config
|
||||
|
||||
@staticmethod
|
||||
def _normalize_xhigh_effort_for_max_model(model: str, effort: str) -> str:
|
||||
"""Return ``max`` when a model supports max effort but not xhigh."""
|
||||
from litellm.llms.anthropic.chat.transformation import AnthropicConfig
|
||||
|
||||
if effort != "xhigh":
|
||||
return effort
|
||||
if AnthropicConfig._supports_effort_level(model, "xhigh"):
|
||||
return effort
|
||||
if AnthropicConfig._supports_effort_level(model, "max"):
|
||||
return "max"
|
||||
return effort
|
||||
|
||||
@staticmethod
|
||||
def _normalize_explicit_output_config_xhigh_effort(
|
||||
model: str, optional_params: Dict
|
||||
) -> None:
|
||||
"""Normalize explicit ``output_config.effort=xhigh`` when ``max`` is supported."""
|
||||
output_config = optional_params.get("output_config")
|
||||
if not isinstance(output_config, dict):
|
||||
return
|
||||
effort = output_config.get("effort")
|
||||
if not isinstance(effort, str):
|
||||
return
|
||||
|
||||
output_config["effort"] = (
|
||||
AnthropicMessagesConfig._normalize_xhigh_effort_for_max_model(model, effort)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _translate_legacy_thinking_for_adaptive_model(
|
||||
model: str, optional_params: Dict
|
||||
|
|
@ -274,6 +308,11 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
|
|||
status_code=400,
|
||||
)
|
||||
|
||||
self._normalize_explicit_output_config_xhigh_effort(
|
||||
model=model,
|
||||
optional_params=anthropic_messages_optional_request_params,
|
||||
)
|
||||
|
||||
self._translate_reasoning_effort_to_anthropic(
|
||||
model=model,
|
||||
optional_params=anthropic_messages_optional_request_params,
|
||||
|
|
|
|||
|
|
@ -99,28 +99,27 @@ def test_invalid_reasoning_effort_raises_400(bad_effort):
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model,bad_effort",
|
||||
"model",
|
||||
[
|
||||
("claude-opus-4-6", "xhigh"),
|
||||
("bedrock/invoke/us.anthropic.claude-opus-4-6-v1", "xhigh"),
|
||||
("claude-sonnet-4-6", "xhigh"),
|
||||
"claude-opus-4-6",
|
||||
"bedrock/invoke/us.anthropic.claude-opus-4-6-v1",
|
||||
"claude-sonnet-4-6",
|
||||
],
|
||||
)
|
||||
def test_reasoning_effort_unsupported_tier_raises_400_messages(model, bad_effort):
|
||||
def test_reasoning_effort_xhigh_normalizes_to_max_messages(model):
|
||||
config = AnthropicMessagesConfig()
|
||||
optional_params = {"max_tokens": 1024, "reasoning_effort": bad_effort}
|
||||
optional_params = {"max_tokens": 1024, "reasoning_effort": "xhigh"}
|
||||
|
||||
with pytest.raises(AnthropicError) as exc_info:
|
||||
config.transform_anthropic_messages_request(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
anthropic_messages_optional_request_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
anthropic_messages_optional_request_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
assert "not supported by this model" in str(exc_info.value)
|
||||
output_config = result.get("output_config")
|
||||
assert isinstance(output_config, dict) and output_config.get("effort") == "max"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -146,6 +145,43 @@ def test_reasoning_effort_max_accepted_on_sonnet_46_messages(model):
|
|||
assert isinstance(output_config, dict) and output_config.get("effort") == "max"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model",
|
||||
[
|
||||
"claude-sonnet-4-6",
|
||||
"bedrock/invoke/us.anthropic.claude-sonnet-4-6",
|
||||
],
|
||||
)
|
||||
def test_explicit_output_config_xhigh_normalizes_to_max_messages(model):
|
||||
config = AnthropicMessagesConfig()
|
||||
optional_params = {"max_tokens": 1024, "output_config": {"effort": "xhigh"}}
|
||||
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
anthropic_messages_optional_request_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
|
||||
assert result.get("output_config") == {"effort": "max"}
|
||||
|
||||
|
||||
def test_explicit_output_config_xhigh_preserved_when_supported_messages():
|
||||
config = AnthropicMessagesConfig()
|
||||
optional_params = {"max_tokens": 1024, "output_config": {"effort": "xhigh"}}
|
||||
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model="claude-opus-4-7",
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
anthropic_messages_optional_request_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
|
||||
assert result.get("output_config") == {"effort": "xhigh"}
|
||||
|
||||
|
||||
def test_explicit_output_config_wins_over_reasoning_effort():
|
||||
config = AnthropicMessagesConfig()
|
||||
optional_params = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue