Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/my-website/docs/providers/gemini.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ Note: Reasoning cannot be turned off on Gemini 2.5 Pro models.
For **Gemini 3+ models** (e.g., `gemini-3-pro-preview`), LiteLLM automatically maps `reasoning_effort` to the new `thinking_level` parameter instead of `thinking_budget`. The `thinking_level` parameter uses `"low"` or `"high"` values for better control over reasoning depth.
:::

:::warning Image Models
**Gemini image models** (e.g., `gemini-3-pro-image-preview`, `gemini-2.0-flash-exp-image-generation`) do **not** support the `thinking_level` parameter. LiteLLM automatically excludes image models from receiving thinking configuration to prevent API errors.
:::

**Mapping for Gemini 2.5 and earlier models**

| reasoning_effort | thinking | Notes |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -904,13 +904,15 @@ def map_openai_params( # noqa: PLR0915
if VertexGeminiConfig._is_gemini_3_or_newer(model):
if "temperature" not in optional_params:
optional_params["temperature"] = 1.0
thinking_config = optional_params.get("thinkingConfig", {})
if (
"thinkingLevel" not in thinking_config
and "thinkingBudget" not in thinking_config
):
thinking_config["thinkingLevel"] = "low"
optional_params["thinkingConfig"] = thinking_config
# Only add thinkingLevel if model supports it (exclude image models)
if "image" not in model.lower():
thinking_config = optional_params.get("thinkingConfig", {})
if (
"thinkingLevel" not in thinking_config
and "thinkingBudget" not in thinking_config
):
thinking_config["thinkingLevel"] = "low"
optional_params["thinkingConfig"] = thinking_config

return optional_params

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1967,3 +1967,98 @@ def test_media_resolution_per_part():
assert "inline_data" in image2_part
assert image2_part["inline_data"]["mediaResolution"] == "high"


def test_gemini_3_image_models_no_thinking_config():
"""
Test that Gemini 3 image models do NOT receive automatic thinkingConfig.

Related issue: https://github.com/BerriAI/litellm/issues/17013
gemini-3-pro-image-preview does not support thinking_level parameter
and returns BadRequestError: "Thinking level is not supported for this model"
"""
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (
VertexGeminiConfig,
)

v = VertexGeminiConfig()

# Test gemini-3-pro-image-preview (the specific model from the bug report)
model = "gemini-3-pro-image-preview"
optional_params = {}
non_default_params = {}

result = v.map_openai_params(
non_default_params=non_default_params,
optional_params=optional_params,
model=model,
drop_params=False,
)

# Should NOT have thinkingConfig automatically added
assert "thinkingConfig" not in result
# But should still get temperature=1.0 for Gemini 3
assert result["temperature"] == 1.0


def test_gemini_3_text_models_get_thinking_config():
"""
Test that Gemini 3 text models DO receive automatic thinkingConfig.
This ensures we didn't break the existing behavior for non-image models.
"""
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (
VertexGeminiConfig,
)

v = VertexGeminiConfig()

# Test gemini-3-pro-preview (text model, should get thinking)
model = "gemini-3-pro-preview"
optional_params = {}
non_default_params = {}

result = v.map_openai_params(
non_default_params=non_default_params,
optional_params=optional_params,
model=model,
drop_params=False,
)

# Should have thinkingConfig automatically added
assert "thinkingConfig" in result
assert result["thinkingConfig"]["thinkingLevel"] == "low"
assert result["temperature"] == 1.0


def test_gemini_image_models_excluded_from_thinking():
"""
Test that any Gemini model with 'image' in the name is excluded from thinking config.
This covers current and future image models.
"""
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (
VertexGeminiConfig,
)

v = VertexGeminiConfig()

# Test various image model patterns
image_models = [
"gemini-3-pro-image-preview",
"gemini-3-pro-image-generation",
"gemini-3-flash-image-preview",
"gemini/gemini-3-image-edit",
]

for model in image_models:
optional_params = {}
non_default_params = {}

result = v.map_openai_params(
non_default_params=non_default_params,
optional_params=optional_params,
model=model,
drop_params=False,
)

# None of these should have thinkingConfig
assert "thinkingConfig" not in result, f"Model {model} should not have thinkingConfig"

Loading