fix(bedrock): cap max_tokens to model limit in Converse transformation

This commit is contained in:
Ishaan Jaffer 2026-03-07 17:32:09 -08:00
parent 2b8db87a35
commit 52ff05dd21
2 changed files with 53 additions and 0 deletions

View file

@ -888,6 +888,16 @@ class AmazonConverseConfig(BaseConfig):
is_thinking_enabled=is_thinking_enabled,
)
if param == "max_tokens" or param == "max_completion_tokens":
try:
model_info = litellm.get_model_info(model=model)
model_max = model_info.get("max_output_tokens")
if model_max is not None and isinstance(model_max, int) and isinstance(value, int) and value > model_max:
verbose_logger.debug(
f"Capping max_tokens from {value} to model limit {model_max} for {model}"
)
value = model_max
except Exception:
pass
optional_params["maxTokens"] = value
if param == "stream":
optional_params["stream"] = value

View file

@ -4235,3 +4235,46 @@ def test_bedrock_nova_grounding_request_transformation():
assert system_tool_found, "systemTool with nova_grounding should be present"
print("✓ web_search_options correctly transformed to systemTool")
def test_bedrock_converse_max_tokens_capped_to_model_limit():
"""
Nova Pro has a max_output_tokens of 10000. If a caller sends max_tokens=16000,
the Converse transformation should silently cap it to 10000 before the request
reaches Bedrock, preventing a 400 error.
"""
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
litellm.model_cost = litellm.get_model_cost_map(url="")
os.environ.pop("LITELLM_LOCAL_MODEL_COST_MAP", None)
from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig
config = AmazonConverseConfig()
# Over the limit — should be capped
result = config.map_openai_params(
non_default_params={"max_tokens": 16000},
optional_params={},
model="us.amazon.nova-pro-v1:0",
drop_params=False,
)
assert result["maxTokens"] == 10000, f"Expected 10000, got {result['maxTokens']}"
# Under the limit — should be unchanged
result2 = config.map_openai_params(
non_default_params={"max_tokens": 5000},
optional_params={},
model="us.amazon.nova-pro-v1:0",
drop_params=False,
)
assert result2["maxTokens"] == 5000, f"Expected 5000, got {result2['maxTokens']}"
# Model with no known limit — should be passed through unchanged
result3 = config.map_openai_params(
non_default_params={"max_tokens": 16000},
optional_params={},
model="anthropic.claude-3-sonnet-20240229-v1:0",
drop_params=False,
)
assert result3["maxTokens"] == 16000, f"Expected 16000, got {result3['maxTokens']}"