mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-14 04:09:09 +00:00
fix(bedrock): fill default maxTokens for anthropic converse models from the cost map
bedrock applies a 4096 output token default when inferenceConfig.maxTokens is omitted, which silently truncates anthropic models whose documented maximum is far higher fill maxTokens from the litellm cost map when the request has no max_tokens, the thinking branch did not set one, and the model is an anthropic id, unknown models stay unchanged fixes #41529
This commit is contained in:
parent
7a659973e3
commit
8f9ed91db6
2 changed files with 103 additions and 10 deletions
|
|
@ -1186,6 +1186,16 @@ class AmazonConverseConfig(BaseConfig):
|
|||
non_default_params=non_default_params, optional_params=optional_params
|
||||
)
|
||||
|
||||
# Bedrock applies a 4096 output-token default when maxTokens is omitted, silently truncating anthropic models
|
||||
if (
|
||||
not self.is_max_tokens_in_request(non_default_params) # pyright: ignore[reportUnknownMemberType] # is_max_tokens_in_request accepts an untyped params dict
|
||||
and "maxTokens" not in optional_params
|
||||
and "anthropic" in model
|
||||
):
|
||||
default_max_tokens: Final = self._get_default_max_tokens_for_model(model)
|
||||
if default_max_tokens is not None:
|
||||
optional_params["maxTokens"] = default_max_tokens # rebind-ok: out-param store like siblings
|
||||
|
||||
final_is_thinking_enabled: Final = self.is_thinking_enabled(optional_params)
|
||||
if final_is_thinking_enabled and "tool_choice" in optional_params:
|
||||
tool_choice_block: Final = optional_params["tool_choice"]
|
||||
|
|
@ -1328,6 +1338,33 @@ class AmazonConverseConfig(BaseConfig):
|
|||
if thinking_token_budget is not None:
|
||||
optional_params["maxTokens"] = thinking_token_budget + DEFAULT_MAX_TOKENS
|
||||
|
||||
@staticmethod
|
||||
def _get_default_max_tokens_for_model(model: str) -> int | None:
|
||||
"""
|
||||
Resolve the model's documented max output tokens from the litellm cost map.
|
||||
|
||||
Returns None when the model is not mapped, so the request stays unchanged.
|
||||
Bedrock model ids carry an optional cross-region prefix that cost map keys do
|
||||
not include, so strip it and retry.
|
||||
"""
|
||||
|
||||
cost_map: Final = cast("Mapping[str, Mapping[str, object]]", litellm.model_cost) # cast-ok: untyped cost map
|
||||
|
||||
def lookup(candidate: str) -> int | None:
|
||||
entry: Final = cost_map.get(candidate)
|
||||
if entry is None:
|
||||
return None
|
||||
max_output_tokens: Final = entry.get("max_output_tokens")
|
||||
if isinstance(max_output_tokens, int):
|
||||
return max_output_tokens
|
||||
max_tokens: Final = entry.get("max_tokens")
|
||||
return max_tokens if isinstance(max_tokens, int) else None
|
||||
|
||||
first_segment, separator, rest = model.partition(".")
|
||||
region_prefixed: Final = separator == "." and first_segment in ("us", "eu", "apac", "global", "ca", "sa")
|
||||
candidates: Final = (model, rest) if region_prefixed else (model,)
|
||||
return next((value for value in map(lookup, candidates) if value is not None), None)
|
||||
|
||||
@overload
|
||||
def get_cache_point_block(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -8178,16 +8178,6 @@ def test_supports_sampling_params_prefixed_and_anthropic_fallback(monkeypatch: p
|
|||
assert AmazonConverseConfig._supports_sampling_params("anthropic.claude-custom-unregistered") is True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("fake_provider_credentials")
|
||||
def test_bedrock_tools_pt_valid_names():
|
||||
"""
|
||||
|
|
@ -9482,3 +9472,69 @@ def test_bedrock_nova_web_search_options_ignored_for_non_nova():
|
|||
system_tool2 = result2.get("systemTool")
|
||||
assert system_tool2 is not None
|
||||
assert system_tool2["name"] == "nova_grounding"
|
||||
|
||||
|
||||
def test_anthropic_converse_default_max_tokens_from_cost_map(local_model_cost_map):
|
||||
"""Bedrock caps output at 4096 when maxTokens is omitted; fill the model max from the cost map instead."""
|
||||
config = AmazonConverseConfig()
|
||||
|
||||
optional_params = config.map_openai_params(
|
||||
model="us.anthropic.claude-sonnet-5",
|
||||
non_default_params={},
|
||||
optional_params={},
|
||||
drop_params=False,
|
||||
)
|
||||
assert optional_params["maxTokens"] == 128000
|
||||
|
||||
data = config._transform_request_helper(
|
||||
model="us.anthropic.claude-sonnet-5",
|
||||
system_content_blocks=[],
|
||||
optional_params=optional_params,
|
||||
messages=None,
|
||||
)
|
||||
assert data["inferenceConfig"]["maxTokens"] == 128000
|
||||
|
||||
|
||||
def test_anthropic_converse_explicit_max_tokens_still_wins(local_model_cost_map):
|
||||
config = AmazonConverseConfig()
|
||||
optional_params = config.map_openai_params(
|
||||
model="us.anthropic.claude-sonnet-5",
|
||||
non_default_params={"max_tokens": 111},
|
||||
optional_params={},
|
||||
drop_params=False,
|
||||
)
|
||||
assert optional_params["maxTokens"] == 111
|
||||
|
||||
|
||||
def test_anthropic_converse_default_max_tokens_strips_region_prefix(local_model_cost_map):
|
||||
config = AmazonConverseConfig()
|
||||
optional_params = config.map_openai_params(
|
||||
model="eu.anthropic.claude-3-7-sonnet-20240620-v1:0",
|
||||
non_default_params={},
|
||||
optional_params={},
|
||||
drop_params=False,
|
||||
)
|
||||
assert optional_params["maxTokens"] == 8192
|
||||
|
||||
|
||||
def test_non_anthropic_converse_gets_no_default_max_tokens(local_model_cost_map):
|
||||
config = AmazonConverseConfig()
|
||||
optional_params = config.map_openai_params(
|
||||
model="us.meta.llama4-maverick-17b-instruct-v1:0",
|
||||
non_default_params={},
|
||||
optional_params={},
|
||||
drop_params=False,
|
||||
)
|
||||
assert "maxTokens" not in optional_params
|
||||
|
||||
|
||||
def test_anthropic_converse_unknown_model_gets_no_default_max_tokens(local_model_cost_map):
|
||||
config = AmazonConverseConfig()
|
||||
optional_params = config.map_openai_params(
|
||||
model="us.anthropic.not-a-real-model-v1:0",
|
||||
non_default_params={},
|
||||
optional_params={},
|
||||
drop_params=False,
|
||||
)
|
||||
assert "maxTokens" not in optional_params
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue