fix(bedrock): stop leaking thinking/reasoning_effort into additionalModelRequestFields for DeepSeek

This commit is contained in:
Devin AI 2026-07-15 17:11:16 +00:00
parent be658d5d29
commit f06fdab04b
2 changed files with 70 additions and 11 deletions

View file

@ -493,6 +493,23 @@ class AmazonConverseConfig(BaseConfig):
)
thinking["budget_tokens"] = BEDROCK_MIN_THINKING_BUDGET_TOKENS
def _model_accepts_anthropic_thinking_param(self, model: str, base_model: str) -> bool:
"""Whether the model accepts the Anthropic-shaped ``thinking`` / ``reasoning_effort`` request field.
The Converse mapping serializes ``thinking`` into ``additionalModelRequestFields`` in Anthropic's
shape. Only Anthropic Claude reasoning models accept that field; DeepSeek models reason natively
and reject it (a 400 when it leaks through), even though they advertise ``supports_reasoning``.
"""
if "deepseek" in model or "deepseek" in base_model:
return False
return (
"claude-3-7" in model
or "claude-sonnet-4" in model
or "claude-opus-4" in model
or supports_reasoning(model=model, custom_llm_provider=self.custom_llm_provider)
or supports_reasoning(model=base_model, custom_llm_provider=self.custom_llm_provider)
)
def get_supported_openai_params(self, model: str) -> List[str]:
from litellm.utils import supports_function_calling
@ -553,17 +570,7 @@ class AmazonConverseConfig(BaseConfig):
# Nova 2 models support reasoning_effort (transformed to reasoningConfig)
# These models use a different reasoning structure than Anthropic's thinking parameter
supported_params.append("reasoning_effort")
elif (
"claude-3-7" in model
or "claude-sonnet-4" in model
or "claude-opus-4" in model
or "deepseek.r1" in model
or supports_reasoning(
model=model,
custom_llm_provider=self.custom_llm_provider,
)
or supports_reasoning(model=base_model, custom_llm_provider=self.custom_llm_provider)
):
elif self._model_accepts_anthropic_thinking_param(model=model, base_model=base_model):
supported_params.append("thinking")
supported_params.append("reasoning_effort")

View file

@ -553,6 +553,58 @@ def test_get_supported_openai_params():
assert "reasoning_effort" in supported_params
@pytest.mark.parametrize(
"model",
[
"bedrock/us.deepseek.r1-v1:0",
"bedrock/converse/us.deepseek.r1-v1:0",
"bedrock/deepseek.v3-v1:0",
"bedrock/deepseek.v3.2",
],
)
def test_bedrock_deepseek_does_not_advertise_thinking(model):
"""DeepSeek reasons natively on Bedrock and rejects the Anthropic-shaped
`thinking`/`reasoning_effort` field, so it must not be advertised as supported
(otherwise it leaks into additionalModelRequestFields and Bedrock 400s)."""
config = AmazonConverseConfig()
supported_params = config.get_supported_openai_params(model=model)
assert "thinking" not in supported_params
assert "reasoning_effort" not in supported_params
def test_bedrock_deepseek_r1_thinking_raises_without_drop_params():
"""Passing `thinking` to Bedrock DeepSeek R1 must fail client-side with a clear
UnsupportedParamsError instead of leaking through and hitting a Bedrock 400."""
with pytest.raises(litellm.UnsupportedParamsError):
litellm.utils.get_optional_params(
model="us.deepseek.r1-v1:0",
custom_llm_provider="bedrock",
thinking={"type": "enabled", "budget_tokens": 1024},
)
def test_bedrock_deepseek_r1_thinking_dropped_does_not_leak_into_request():
"""With drop_params, `thinking` is dropped rather than forwarded into
additionalModelRequestFields for Bedrock DeepSeek R1."""
optional_params = litellm.utils.get_optional_params(
model="us.deepseek.r1-v1:0",
custom_llm_provider="bedrock",
thinking={"type": "enabled", "budget_tokens": 1024},
drop_params=True,
)
assert "thinking" not in optional_params
config = AmazonConverseConfig()
request = config._transform_request(
model="bedrock/converse/us.deepseek.r1-v1:0",
messages=[{"role": "user", "content": "Say hi in one word."}],
optional_params=optional_params,
litellm_params={},
headers={},
)
assert "thinking" not in request.get("additionalModelRequestFields", {})
def test_get_supported_openai_params_bedrock_converse():
"""
Test that all documented bedrock converse models have the same set of supported openai params when using