mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(vertex): floor reasoning_effort to low on gemini-3.7-flash
gemini-3.7-flash dropped THINKING_LEVEL_MINIMAL support on Vertex; only LOW, MEDIUM, and HIGH are accepted. reasoning_effort values minimal, none, and disable previously mapped to "minimal" via the broad gemini-3.x-flash substring match and returned HTTP 400. They now floor to "low" so they resolve to a level Vertex accepts. Fixes #37314
This commit is contained in:
parent
c696fdfb05
commit
5b41fc9b11
2 changed files with 83 additions and 9 deletions
|
|
@ -272,6 +272,21 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _is_gemini3_flash_supports_minimal(model: str) -> bool:
|
||||
"""
|
||||
Whether a gemini-3.x-flash model accepts THINKING_LEVEL_MINIMAL.
|
||||
|
||||
gemini-3.7-flash dropped MINIMAL support: Vertex only accepts LOW, MEDIUM, and
|
||||
HIGH for it, while earlier 3.x-flash models (3.0, 3.1, 3.5, 3.6) still accept it.
|
||||
"""
|
||||
lowered: Final = model.lower()
|
||||
return (
|
||||
"flash" in lowered
|
||||
and "gemini-3" in lowered
|
||||
and "gemini-3.7" not in lowered
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _forward_gemini_function_call_id(model: str) -> bool:
|
||||
"""
|
||||
|
|
@ -856,10 +871,8 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
Returns:
|
||||
GeminiThinkingConfig with thinkingLevel and includeThoughts
|
||||
"""
|
||||
# Check if this is gemini-3-flash which supports MINIMAL thinking level
|
||||
# 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_gemini3flash: Final = bool(model) and VertexGeminiConfig._is_gemini3_flash_supports_minimal(model)
|
||||
is_gemini3_flash_family: Final = bool(model) and "flash" in model.lower() and "gemini-3" in model.lower()
|
||||
is_gemini31pro: Final = model and ("gemini-3.1-pro-preview" in model.lower())
|
||||
if reasoning_effort == "minimal":
|
||||
if is_gemini3flash:
|
||||
|
|
@ -869,20 +882,20 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
elif reasoning_effort == "low":
|
||||
return {"thinkingLevel": "low", "includeThoughts": True}
|
||||
elif reasoning_effort == "medium":
|
||||
if is_gemini31pro or is_gemini3flash:
|
||||
if is_gemini31pro or is_gemini3_flash_family:
|
||||
return {"thinkingLevel": "medium", "includeThoughts": True}
|
||||
else:
|
||||
return {"thinkingLevel": "high", "includeThoughts": True}
|
||||
elif reasoning_effort == "high":
|
||||
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
|
||||
# Gemini 3 cannot fully disable thinking, so we use "minimal" for the models that accept it, "low" for others.
|
||||
if is_gemini3flash:
|
||||
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"
|
||||
# Same as disable: "minimal" where accepted, "low" otherwise.
|
||||
if is_gemini3flash:
|
||||
return {"thinkingLevel": "minimal", "includeThoughts": False}
|
||||
else:
|
||||
|
|
@ -953,8 +966,11 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
params["includeThoughts"] = True
|
||||
# Follow provider defaults unless explicitly opted into legacy behavior.
|
||||
if litellm.enable_gemini_default_thinking_level_low is True:
|
||||
is_gemini3flash: Final = "gemini-3" in model.lower() and "flash" in model.lower()
|
||||
params["thinkingLevel"] = "minimal" if is_gemini3flash else "low"
|
||||
params["thinkingLevel"] = (
|
||||
"minimal"
|
||||
if VertexGeminiConfig._is_gemini3_flash_supports_minimal(model)
|
||||
else "low"
|
||||
)
|
||||
else:
|
||||
# Thinking disabled
|
||||
params["includeThoughts"] = False
|
||||
|
|
|
|||
|
|
@ -1806,6 +1806,64 @@ def test_gemini_31_flash_lite_reasoning_effort_minimal():
|
|||
), "gemini-3.1-flash-lite-preview should use thinkingLevel, not thinkingBudget"
|
||||
|
||||
|
||||
def test_gemini_37_flash_reasoning_effort_no_minimal():
|
||||
"""
|
||||
gemini-3.7-flash dropped THINKING_LEVEL_MINIMAL support on Vertex; only LOW, MEDIUM,
|
||||
and HIGH are accepted. reasoning_effort values that previously mapped to "minimal"
|
||||
(minimal, none, disable) must resolve to "low" instead so they return 200.
|
||||
|
||||
Regression test for: https://github.com/BerriAI/litellm/issues/37314
|
||||
"""
|
||||
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (
|
||||
VertexGeminiConfig,
|
||||
)
|
||||
|
||||
# Values that used to map to "minimal" must now floor at "low" on 3.7.
|
||||
for reasoning_effort in ("minimal", "none", "disable"):
|
||||
result = VertexGeminiConfig._map_reasoning_effort_to_thinking_level(
|
||||
reasoning_effort=reasoning_effort,
|
||||
model="gemini-3.7-flash",
|
||||
)
|
||||
assert (
|
||||
result["thinkingLevel"] == "low"
|
||||
), f"gemini-3.7-flash {reasoning_effort} should map to 'low', got '{result['thinkingLevel']}'"
|
||||
assert result["includeThoughts"] is (reasoning_effort != "none" and reasoning_effort != "disable")
|
||||
|
||||
# Explicit low/medium/high are unaffected.
|
||||
for reasoning_effort, expected_level in (
|
||||
("low", "low"),
|
||||
("medium", "medium"),
|
||||
("high", "high"),
|
||||
):
|
||||
result = VertexGeminiConfig._map_reasoning_effort_to_thinking_level(
|
||||
reasoning_effort=reasoning_effort,
|
||||
model="gemini-3.7-flash",
|
||||
)
|
||||
assert (
|
||||
result["thinkingLevel"] == expected_level
|
||||
), f"gemini-3.7-flash {reasoning_effort} should map to '{expected_level}', got '{result['thinkingLevel']}'"
|
||||
|
||||
|
||||
def test_gemini_36_flash_reasoning_effort_minimal_still_supported():
|
||||
"""
|
||||
gemini-3.6-flash still accepts THINKING_LEVEL_MINIMAL, so the fix for 3.7 must not
|
||||
regress the earlier 3.x-flash models.
|
||||
"""
|
||||
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (
|
||||
VertexGeminiConfig,
|
||||
)
|
||||
|
||||
for model in ("gemini-3.6-flash", "gemini-3.5-flash"):
|
||||
result = VertexGeminiConfig._map_reasoning_effort_to_thinking_level(
|
||||
reasoning_effort="minimal",
|
||||
model=model,
|
||||
)
|
||||
assert (
|
||||
result["thinkingLevel"] == "minimal"
|
||||
), f"{model} should keep thinkingLevel='minimal', got '{result['thinkingLevel']}'"
|
||||
assert result["includeThoughts"] is True
|
||||
|
||||
|
||||
def test_gemini_image_size_limit_exceeded(monkeypatch):
|
||||
"""
|
||||
Test that large images exceeding MAX_IMAGE_URL_DOWNLOAD_SIZE_MB are rejected.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue