diff --git a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py index e6e548ab98a..33036db3c68 100644 --- a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py +++ b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py @@ -929,13 +929,17 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): # Thinking disabled params["includeThoughts"] = False else: - # For older Gemini models, use thinkingBudget - if thinking_enabled and not VertexGeminiConfig._is_thinking_budget_zero( - thinking_budget - ): - params["includeThoughts"] = True - if thinking_budget is not None and isinstance(thinking_budget, int): - params["thinkingBudget"] = thinking_budget + # For older Gemini models, use thinkingBudget instead of thinkingLevel + if thinking_enabled: + if VertexGeminiConfig._is_thinking_budget_zero(thinking_budget): + # thinkingBudget: 0 is rejected by models with a minimum budget (e.g. gemini-2.5-pro). + params["includeThoughts"] = False + else: + params["includeThoughts"] = True + if thinking_budget is not None and isinstance(thinking_budget, int): + params["thinkingBudget"] = thinking_budget + else: + params["includeThoughts"] = False return params diff --git a/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py b/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py index ddc404cb8c7..0b5189ef659 100644 --- a/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py +++ b/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py @@ -898,13 +898,16 @@ def test_vertex_ai_usage_metadata_accumulates_duplicate_modalities(): def test_vertex_ai_map_thinking_param_with_budget_tokens_0(): """ - If budget_tokens is 0, do not set includeThoughts to True + budget_tokens=0 must produce includeThoughts: False with no thinkingBudget field. + Models with a minimum budget requirement (e.g. gemini-2.5-pro) reject thinkingBudget: 0. """ from litellm.types.llms.anthropic import AnthropicThinkingParam v = VertexGeminiConfig() thinking_param: AnthropicThinkingParam = {"type": "enabled", "budget_tokens": 0} - assert "includeThoughts" not in v._map_thinking_param(thinking_param=thinking_param) + result = v._map_thinking_param(thinking_param=thinking_param) + assert result == {"includeThoughts": False} + assert "thinkingBudget" not in result thinking_param: AnthropicThinkingParam = {"type": "enabled", "budget_tokens": 100} assert v._map_thinking_param(thinking_param=thinking_param) == { @@ -913,6 +916,19 @@ def test_vertex_ai_map_thinking_param_with_budget_tokens_0(): } +def test_vertex_ai_map_thinking_param_disabled(): + """ + type="adaptive" (non-enabled) must produce includeThoughts: False with no thinkingBudget field. + """ + from litellm.types.llms.anthropic import AnthropicThinkingParam + + v = VertexGeminiConfig() + thinking_param: AnthropicThinkingParam = {"type": "adaptive"} + result = v._map_thinking_param(thinking_param=thinking_param) + assert result == {"includeThoughts": False} + assert "thinkingBudget" not in result + + def test_vertex_ai_map_tools(): v = VertexGeminiConfig() optional_params = {}