From 17cd787414ed51caf37a43813f4545291782acd7 Mon Sep 17 00:00:00 2001 From: Sunner Sun Date: Tue, 1 Sep 2026 19:16:24 +0800 Subject: [PATCH 1/2] fix(gemini): map Gemini 3.7 Flash minimum thinking to low --- .../gemini/vertex_and_google_ai_studio_gemini.py | 7 ++++--- .../test_vertex_and_google_ai_studio_gemini.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) 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 d8b1e7ba17c..f1fe2496f3d 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 @@ -862,9 +862,10 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): # Covers gemini-3-flash, gemini-3-flash-preview, gemini-3.1-flash, gemini-3.1-flash-lite-preview, # gemini-3.5-flash, and any future 3.x-flash variants. is_gemini3flash: Final = model and ("flash" in model.lower() and "gemini-3" in model.lower()) + is_gemini37flash: Final = model and "gemini-3.7-flash" in model.lower() is_gemini31pro: Final = model and ("gemini-3.1-pro-preview" in model.lower()) if reasoning_effort == "minimal": - if is_gemini3flash: + if is_gemini3flash and not is_gemini37flash: return {"thinkingLevel": "minimal", "includeThoughts": True} else: return {"thinkingLevel": "low", "includeThoughts": True} @@ -879,13 +880,13 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): return {"thinkingLevel": "high", "includeThoughts": True} elif reasoning_effort == "disable": # Gemini 3 cannot fully disable thinking, so we use "minimal" for gemini-3-flash-preview, "low" for others - if is_gemini3flash: + if is_gemini3flash and not is_gemini37flash: return {"thinkingLevel": "minimal", "includeThoughts": False} else: return {"thinkingLevel": "low", "includeThoughts": False} elif reasoning_effort == "none": # For gemini-3-flash-preview, use "minimal" instead of "low" - if is_gemini3flash: + if is_gemini3flash and not is_gemini37flash: return {"thinkingLevel": "minimal", "includeThoughts": False} else: return {"thinkingLevel": "low", "includeThoughts": False} 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 bd07bec900f..de198754103 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 @@ -2666,6 +2666,18 @@ def test_reasoning_effort_maps_to_thinking_level_gemini_3(): assert result["thinkingConfig"]["includeThoughts"] is False +@pytest.mark.parametrize("reasoning_effort", ["minimal", "disable", "none"]) +def test_gemini_37_flash_uses_low_minimum_thinking_level(reasoning_effort: str): + result = VertexGeminiConfig().map_openai_params( + non_default_params={"reasoning_effort": reasoning_effort}, + optional_params={}, + model="vertex_ai/gemini-3.7-flash", + drop_params=False, + ) + + assert result["thinkingConfig"]["thinkingLevel"] == "low" + + def test_reasoning_effort_dict_format_gemini_3(): """ Test that reasoning_effort works when passed as dict format from OpenAI Agents SDK. From fe9fcddfee2d87ed7711c9ae4295d568204139d4 Mon Sep 17 00:00:00 2001 From: Sunner Sun Date: Fri, 4 Sep 2026 12:07:53 +0800 Subject: [PATCH 2/2] fix(gemini): extend low minimum thinking mapping to Gemini 3.8 Flash --- .../gemini/vertex_and_google_ai_studio_gemini.py | 10 ++++++---- .../gemini/test_vertex_and_google_ai_studio_gemini.py | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) 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 f1fe2496f3d..a61ac7ab0f9 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 @@ -862,10 +862,12 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): # Covers gemini-3-flash, gemini-3-flash-preview, gemini-3.1-flash, gemini-3.1-flash-lite-preview, # gemini-3.5-flash, and any future 3.x-flash variants. is_gemini3flash: Final = model and ("flash" in model.lower() and "gemini-3" in model.lower()) - is_gemini37flash: Final = model and "gemini-3.7-flash" in model.lower() + requires_low_minimum_thinking: Final = model and ( + "gemini-3.7-flash" in model.lower() or "gemini-3.8-flash" in model.lower() + ) is_gemini31pro: Final = model and ("gemini-3.1-pro-preview" in model.lower()) if reasoning_effort == "minimal": - if is_gemini3flash and not is_gemini37flash: + if is_gemini3flash and not requires_low_minimum_thinking: return {"thinkingLevel": "minimal", "includeThoughts": True} else: return {"thinkingLevel": "low", "includeThoughts": True} @@ -880,13 +882,13 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): return {"thinkingLevel": "high", "includeThoughts": True} elif reasoning_effort == "disable": # Gemini 3 cannot fully disable thinking, so we use "minimal" for gemini-3-flash-preview, "low" for others - if is_gemini3flash and not is_gemini37flash: + if is_gemini3flash and not requires_low_minimum_thinking: return {"thinkingLevel": "minimal", "includeThoughts": False} else: return {"thinkingLevel": "low", "includeThoughts": False} elif reasoning_effort == "none": # For gemini-3-flash-preview, use "minimal" instead of "low" - if is_gemini3flash and not is_gemini37flash: + if is_gemini3flash and not requires_low_minimum_thinking: return {"thinkingLevel": "minimal", "includeThoughts": False} else: return {"thinkingLevel": "low", "includeThoughts": False} 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 de198754103..29b67df07e2 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 @@ -2666,16 +2666,18 @@ def test_reasoning_effort_maps_to_thinking_level_gemini_3(): assert result["thinkingConfig"]["includeThoughts"] is False +@pytest.mark.parametrize("model", ["vertex_ai/gemini-3.7-flash", "vertex_ai/gemini-3.8-flash"]) @pytest.mark.parametrize("reasoning_effort", ["minimal", "disable", "none"]) -def test_gemini_37_flash_uses_low_minimum_thinking_level(reasoning_effort: str): +def test_gemini_flash_uses_low_minimum_thinking_level(model: str, reasoning_effort: str): result = VertexGeminiConfig().map_openai_params( non_default_params={"reasoning_effort": reasoning_effort}, optional_params={}, - model="vertex_ai/gemini-3.7-flash", + model=model, drop_params=False, ) assert result["thinkingConfig"]["thinkingLevel"] == "low" + assert result["thinkingConfig"]["includeThoughts"] is (reasoning_effort == "minimal") def test_reasoning_effort_dict_format_gemini_3():