fix(vertex_ai): don't send thinkingBudget: 0 for older Gemini models

Models with a minimum budget requirement (e.g. gemini-2.5-pro) reject
thinkingBudget: 0 at the API level. When budget_tokens=0, send
includeThoughts: False without a thinkingBudget field instead.
This commit is contained in:
Christian Flasshoff 2026-04-17 13:31:17 -07:00
parent b8f7d61400
commit b9d07cc346
2 changed files with 29 additions and 9 deletions

View file

@ -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

View file

@ -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 = {}