From 1a10746e95ed021f3657b47207094f7660410516 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 3 May 2026 17:30:26 +0000 Subject: [PATCH] fix(databricks): validate reasoning_effort and set output_config on adaptive Claude The Databricks path called `AnthropicConfig._map_reasoning_effort` for Claude models but never validated the effort string nor set `output_config.effort` for adaptive models (Claude 4.6/4.7). Since `_map_reasoning_effort` returns `type=adaptive` for ANY non-None / non-"none" string on adaptive models (including "disabled", "invalid", ""), Databricks silently accepted garbage and emitted a request without an `output_config.effort`, collapsing every adaptive tier to identical behavior. Match the Anthropic native, Bedrock Converse, Bedrock Invoke, and /v1/messages paths: when the resolved `thinking` is non-None on a 4.6/4.7 model, look up the value in `REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT` and either raise a clean `BadRequestError` or set `optional_params["output_config"]`. --- .../llms/databricks/chat/transformation.py | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/litellm/llms/databricks/chat/transformation.py b/litellm/llms/databricks/chat/transformation.py index 8ac438bbf01..a0b1ec3d692 100644 --- a/litellm/llms/databricks/chat/transformation.py +++ b/litellm/llms/databricks/chat/transformation.py @@ -21,6 +21,7 @@ from typing import ( import httpx from pydantic import BaseModel +import litellm from litellm.constants import RESPONSE_FORMAT_TOOL_NAME from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import ( _handle_invalid_parallel_tool_calls, @@ -56,7 +57,10 @@ from litellm.types.utils import ( Usage, ) -from ...anthropic.chat.transformation import AnthropicConfig +from ...anthropic.chat.transformation import ( + REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT, + AnthropicConfig, +) from ...openai_like.chat.transformation import OpenAILikeChatConfig from ..common_utils import DatabricksBase, DatabricksException @@ -335,11 +339,40 @@ class DatabricksConfig(DatabricksBase, OpenAILikeChatConfig, AnthropicConfig): # so the surfaced error carries the correct provider name (the # default is ``"anthropic"``, which would mislead users routing # via Databricks Foundation Model APIs). - optional_params["thinking"] = AnthropicConfig._map_reasoning_effort( - reasoning_effort=non_default_params.get("reasoning_effort"), + reasoning_effort_value = non_default_params.get("reasoning_effort") + mapped_thinking = AnthropicConfig._map_reasoning_effort( + reasoning_effort=reasoning_effort_value, model=model, llm_provider="databricks", ) + if mapped_thinking is None: + optional_params.pop("thinking", None) + optional_params.pop("output_config", None) + else: + optional_params["thinking"] = mapped_thinking + # For Claude 4.6/4.7 adaptive models, ``_map_reasoning_effort`` + # returns ``type=adaptive`` for ANY non-None / non-"none" + # string without validating the value, so reject unmapped + # efforts here and set ``output_config.effort`` (matching the + # Anthropic native / Bedrock Converse / Bedrock Invoke / + # /v1/messages paths). + if AnthropicConfig._is_claude_4_6_model( + model + ) or AnthropicConfig._is_claude_4_7_model(model): + mapped_effort = REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT.get( + reasoning_effort_value + ) + if mapped_effort is None: + raise litellm.exceptions.BadRequestError( + message=( + f"Invalid reasoning_effort: {reasoning_effort_value!r}. " + f"Must be one of: 'minimal', 'low', " + f"'medium', 'high', 'xhigh', 'max', 'none'" + ), + model=model, + llm_provider="databricks", + ) + optional_params["output_config"] = {"effort": mapped_effort} optional_params.pop("reasoning_effort", None) ## handle thinking tokens self.update_optional_params_with_thinking_tokens(