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 91a32d981c..b8370d5fef 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 @@ -543,40 +543,33 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): else: budget = DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET - return VertexGeminiConfig._build_thinking_config(budget) + return { + "thinkingBudget": budget, + "includeThoughts": True, + } elif reasoning_effort == "low": - return VertexGeminiConfig._build_thinking_config( - DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET - ) + return { + "thinkingBudget": DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET, + "includeThoughts": True, + } elif reasoning_effort == "medium": - return VertexGeminiConfig._build_thinking_config( - DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET - ) + return { + "thinkingBudget": DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET, + "includeThoughts": True, + } elif reasoning_effort == "high": - return VertexGeminiConfig._build_thinking_config( - DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET - ) + return { + "thinkingBudget": DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET, + "includeThoughts": True, + } elif reasoning_effort == "disable": - return VertexGeminiConfig._build_thinking_config( - DEFAULT_REASONING_EFFORT_DISABLE_THINKING_BUDGET, - include_thoughts=False, - ) + return { + "thinkingBudget": DEFAULT_REASONING_EFFORT_DISABLE_THINKING_BUDGET, + "includeThoughts": False, + } else: raise ValueError(f"Invalid reasoning effort: {reasoning_effort}") - @staticmethod - def _build_thinking_config( - budget: int, include_thoughts: Optional[bool] = None - ) -> GeminiThinkingConfig: - safe_budget = max(budget, 0) - include_thoughts = ( - safe_budget > 0 if include_thoughts is None else include_thoughts - ) - return { - "thinkingBudget": safe_budget, - "includeThoughts": include_thoughts, - } - @staticmethod def _is_thinking_budget_zero(thinking_budget: Optional[int]) -> bool: return thinking_budget is not None and thinking_budget == 0 diff --git a/tests/llm_translation/test_gemini.py b/tests/llm_translation/test_gemini.py index b6ff80b473..f4100d9e8a 100644 --- a/tests/llm_translation/test_gemini.py +++ b/tests/llm_translation/test_gemini.py @@ -948,14 +948,10 @@ def test_gemini_reasoning_effort_minimal(): actual_budget == expected_min_budget ), f"Model {model} should map 'minimal' to {expected_min_budget} tokens, got {actual_budget}" - # Verify that includeThoughts aligns with whether the budget is greater than zero - expected_include_thoughts = expected_min_budget > 0 + # Verify that includeThoughts is True for minimal reasoning effort assert thinking_config.get( - "includeThoughts" - ) == expected_include_thoughts, ( - f"Model {model} should set includeThoughts={expected_include_thoughts} " - f"when reasoning_effort is 'minimal'" - ) + "includeThoughts", True + ), f"Model {model} should have includeThoughts=True for minimal reasoning effort" # Test with unknown model (should use generic fallback) try: @@ -982,75 +978,6 @@ def test_gemini_reasoning_effort_minimal(): pass -def test_gemini_reasoning_effort_zero_budget_disables_thoughts(monkeypatch): - """Ensure zero thinking budget turns off includeThoughts.""" - from litellm.utils import return_raw_request - from litellm.types.utils import CallTypes - - monkeypatch.setattr( - "litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini.DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH", - 0, - ) - - raw_request = return_raw_request( - endpoint=CallTypes.completion, - kwargs={ - "model": "gemini/gemini-2.5-flash", - "messages": [{"role": "user", "content": "Hello"}], - "reasoning_effort": "minimal", - }, - ) - - request_body = raw_request["raw_request_body"] - generation_config = request_body["generationConfig"] - thinking_config = generation_config["thinkingConfig"] - - assert ( - thinking_config.get("thinkingBudget") == 0 - ), "Zero reasoning budget should be preserved in request" - assert ( - thinking_config.get("includeThoughts") is False - ), "includeThoughts should be False when thinking budget is zero" - - -def test_gemini_reasoning_effort_env_override(monkeypatch): - """Verify env vars override default minimal thinking budget.""" - import importlib - - monkeypatch.setenv( - "DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH", "0" - ) - - import litellm.constants as constants_module - import litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini as gemini_module - - importlib.reload(constants_module) - importlib.reload(gemini_module) - - from litellm.utils import return_raw_request - from litellm.types.utils import CallTypes - - raw_request = return_raw_request( - endpoint=CallTypes.completion, - kwargs={ - "model": "gemini/gemini-2.5-flash", - "messages": [{"role": "user", "content": "Hello"}], - "reasoning_effort": "minimal", - }, - ) - - request_body = raw_request["raw_request_body"] - generation_config = request_body["generationConfig"] - thinking_config = generation_config["thinkingConfig"] - - assert ( - thinking_config.get("thinkingBudget") == 0 - ), "Env override should set thinkingBudget to 0" - assert ( - thinking_config.get("includeThoughts") is False - ), "Env override should disable includeThoughts" - - def test_gemini_exception_message_format(): """ Test that Gemini provider exceptions show as 'GeminiException' not 'VertexAIException'.