Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion litellm/llms/databricks/chat/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,15 @@ def map_openai_params(
) # unsupported for claude models - if json_schema -> convert to tool call

if "reasoning_effort" in non_default_params and self._uses_anthropic_thinking_param(model):
reasoning_effort_value: Final = non_default_params.get("reasoning_effort")
reasoning_effort_value = non_default_params.get("reasoning_effort")
# Accept both the string form ("low") and the dict form
# ({"effort": "low", "summary": "concise"}). The Responses->Chat
# parser keeps the full dict whenever `summary` is set (#28196),
# so a dict is the standard shape Responses-bridge callers send.
# Same coercion the direct Anthropic and Bedrock Converse
# adapters already do.
if isinstance(reasoning_effort_value, dict):
reasoning_effort_value = reasoning_effort_value.get("effort")
mapped_thinking: Final = AnthropicConfig._map_reasoning_effort(
reasoning_effort=reasoning_effort_value,
model=model,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ def test_map_openai_params_upgrades_legacy_thinking_on_adaptive_only_claude(
assert mapped.get("output_config") == expected_output_config


def _map_reasoning_effort(model: str, reasoning_effort: str):
def _map_reasoning_effort(model: str, reasoning_effort: str | dict):
return DatabricksConfig().map_openai_params(
non_default_params={"reasoning_effort": reasoning_effort},
optional_params={},
Expand Down Expand Up @@ -578,6 +578,22 @@ def test_unmapped_claude_endpoint_still_translates(_use_local_model_cost_map):
assert "reasoning_effort" not in params


@pytest.mark.parametrize(
"model",
["databricks-claude-3-7-sonnet", "my-claude-serving-endpoint"],
)
def test_reasoning_effort_dict_is_coerced(_use_local_model_cost_map, model):
"""The Responses->Chat parser keeps `reasoning_effort` as a dict whenever
`summary` is set (#28196). Without coercion the dict reaches
`_map_reasoning_effort` and no thinking payload is produced."""
params = _map_reasoning_effort(model, {"effort": "low", "summary": "concise"})
assert params.get("thinking") == {
"type": "enabled",
"budget_tokens": DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET,
}
assert "reasoning_effort" not in params


def test_gemini_2_5_low_translates_to_thinking_budget(_use_local_model_cost_map):
params = _map_reasoning_effort("databricks-gemini-2-5-flash", "low")
assert params.get("thinking") == {
Expand Down
Loading