mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-15 09:12:18 +00:00
Merge c036669276 into add7dea9aa
This commit is contained in:
commit
c6ec075887
3 changed files with 191 additions and 13 deletions
|
|
@ -1341,18 +1341,28 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
return None
|
||||
|
||||
@staticmethod
|
||||
def _map_reasoning_effort(effort: str, model: str, reasoning_effort: object) -> GeminiThinkingConfig:
|
||||
def _map_reasoning_effort(
|
||||
effort: str,
|
||||
model: str,
|
||||
reasoning_effort: object,
|
||||
drop_params: bool = False,
|
||||
) -> GeminiThinkingConfig | None:
|
||||
include_thoughts: Final = VertexGeminiConfig._include_thoughts_requested_by_reasoning_effort(reasoning_effort)
|
||||
if VertexGeminiConfig._is_gemini_3_or_newer(model):
|
||||
return VertexGeminiConfig._map_reasoning_effort_to_thinking_level(effort, model, include_thoughts)
|
||||
return VertexGeminiConfig._map_reasoning_effort_to_thinking_budget(effort, model, include_thoughts)
|
||||
return VertexGeminiConfig._map_reasoning_effort_to_thinking_level(
|
||||
effort, model, include_thoughts, drop_params=drop_params
|
||||
)
|
||||
return VertexGeminiConfig._map_reasoning_effort_to_thinking_budget(
|
||||
effort, model, include_thoughts, drop_params=drop_params
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _map_reasoning_effort_to_thinking_budget(
|
||||
reasoning_effort: str,
|
||||
model: str | None = None,
|
||||
include_thoughts: bool | None = None,
|
||||
) -> GeminiThinkingConfig:
|
||||
drop_params: bool = False,
|
||||
) -> GeminiThinkingConfig | None:
|
||||
sends_thoughts: Final = VertexGeminiConfig._include_thoughts(include_thoughts)
|
||||
if reasoning_effort == "minimal":
|
||||
# Use model-specific minimum thinking budget or fallback
|
||||
|
|
@ -1396,6 +1406,9 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
"includeThoughts": False,
|
||||
}
|
||||
else:
|
||||
if drops_unsupported_params(drop_params):
|
||||
verbose_logger.debug("Dropping unsupported reasoning_effort: %s", reasoning_effort)
|
||||
return None
|
||||
raise _unsupported_reasoning_effort(reasoning_effort)
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -1411,7 +1424,8 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
reasoning_effort: str,
|
||||
model: str | None = None,
|
||||
include_thoughts: bool | None = None,
|
||||
) -> GeminiThinkingConfig:
|
||||
drop_params: bool = False,
|
||||
) -> GeminiThinkingConfig | None:
|
||||
"""
|
||||
Map reasoning_effort to thinking_level for Gemini 3+ models.
|
||||
Args:
|
||||
|
|
@ -1440,6 +1454,9 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
"includeThoughts": False,
|
||||
}
|
||||
else:
|
||||
if drops_unsupported_params(drop_params):
|
||||
verbose_logger.debug("Dropping unsupported reasoning_effort: %s", reasoning_effort)
|
||||
return None
|
||||
raise _unsupported_reasoning_effort(reasoning_effort)
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -1765,15 +1782,23 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
|||
effort_value = value.get("effort")
|
||||
|
||||
if effort_value is not None:
|
||||
# Validate no conflict with thinking_level
|
||||
VertexGeminiConfig._validate_thinking_config_conflicts(
|
||||
optional_params=optional_params,
|
||||
param_name="reasoning_effort",
|
||||
param_description="thinking_budget",
|
||||
should_drop: bool = drops_unsupported_params(drop_params) or (
|
||||
"drop_params" in optional_params and optional_params["drop_params"] in (True, "true", "True")
|
||||
)
|
||||
optional_params["thinkingConfig"] = VertexGeminiConfig._map_reasoning_effort(
|
||||
effort=effort_value, model=model, reasoning_effort=value
|
||||
thinking_config = VertexGeminiConfig._map_reasoning_effort(
|
||||
effort=effort_value,
|
||||
model=model,
|
||||
reasoning_effort=value,
|
||||
drop_params=should_drop,
|
||||
)
|
||||
if thinking_config is not None:
|
||||
# Validate no conflict with thinking_level
|
||||
VertexGeminiConfig._validate_thinking_config_conflicts(
|
||||
optional_params=optional_params,
|
||||
param_name="reasoning_effort",
|
||||
param_description="thinking_budget",
|
||||
)
|
||||
optional_params["thinkingConfig"] = thinking_config
|
||||
elif param == "thinking":
|
||||
# Validate no conflict with thinking_level
|
||||
VertexGeminiConfig._validate_thinking_config_conflicts(
|
||||
|
|
|
|||
|
|
@ -7298,7 +7298,7 @@ def test_invalid_reasoning_effort_is_a_400_not_a_500(custom_llm_provider, model,
|
|||
model=model,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
reasoning_effort=reasoning_effort,
|
||||
drop_params=True,
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
from typing import Final
|
||||
|
||||
import pytest
|
||||
|
||||
import litellm
|
||||
from litellm.exceptions import UnsupportedParamsError
|
||||
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import VertexGeminiConfig
|
||||
|
||||
|
||||
def test_vertex_gemini_unsupported_reasoning_effort_with_drop_params_true() -> None:
|
||||
"""Verifies that unsupported reasoning_effort (e.g., 'xhigh') is safely dropped
|
||||
|
||||
when drop_params=True is passed directly or inside optional_params.
|
||||
"""
|
||||
config: Final = VertexGeminiConfig()
|
||||
|
||||
# 1. Directly passing drop_params=True (string format)
|
||||
result_direct: Final = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": "xhigh"},
|
||||
optional_params={},
|
||||
model="gemini-2.5-flash",
|
||||
drop_params=True,
|
||||
)
|
||||
assert "thinkingConfig" not in result_direct
|
||||
assert "reasoning_effort" not in result_direct
|
||||
|
||||
# 2. Directly passing drop_params=True (dict format from Agents SDK)
|
||||
result_dict: Final = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": {"effort": "xhigh", "summary": "auto"}},
|
||||
optional_params={},
|
||||
model="gemini-2.5-flash",
|
||||
drop_params=True,
|
||||
)
|
||||
assert "thinkingConfig" not in result_dict
|
||||
|
||||
# 3. Passing drop_params=True in optional_params
|
||||
result_optional: Final = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": "xhigh"},
|
||||
optional_params={"drop_params": True},
|
||||
model="gemini-3-pro-preview",
|
||||
drop_params=False,
|
||||
)
|
||||
assert "thinkingConfig" not in result_optional
|
||||
|
||||
|
||||
def test_vertex_gemini_unsupported_reasoning_effort_with_global_drop_params(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Verifies that unsupported reasoning_effort (e.g., 'max') is safely dropped
|
||||
|
||||
when litellm.drop_params = True is globally active.
|
||||
"""
|
||||
monkeypatch.setattr(litellm, "drop_params", True)
|
||||
config: Final = VertexGeminiConfig()
|
||||
|
||||
# Test with Gemini 2.5 (budget-based thinking)
|
||||
result_gemini_25: Final = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": "max"},
|
||||
optional_params={},
|
||||
model="gemini-2.5-flash",
|
||||
drop_params=False,
|
||||
)
|
||||
assert "thinkingConfig" not in result_gemini_25
|
||||
|
||||
# Test with Gemini 3+ (level-based thinking)
|
||||
result_gemini_3: Final = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": "max"},
|
||||
optional_params={},
|
||||
model="gemini-3-pro-preview",
|
||||
drop_params=False,
|
||||
)
|
||||
assert "thinkingConfig" not in result_gemini_3
|
||||
|
||||
|
||||
def test_vertex_gemini_unsupported_reasoning_effort_raises_without_drop_params() -> None:
|
||||
"""Verifies that unsupported reasoning_effort values raise UnsupportedParamsError
|
||||
|
||||
when drop_params is False.
|
||||
"""
|
||||
config: Final = VertexGeminiConfig()
|
||||
|
||||
for effort in ("xhigh", "max", "unsupported_level"):
|
||||
with pytest.raises(UnsupportedParamsError):
|
||||
config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": effort},
|
||||
optional_params={},
|
||||
model="gemini-2.5-flash",
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
with pytest.raises(UnsupportedParamsError):
|
||||
config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": effort},
|
||||
optional_params={},
|
||||
model="gemini-3-pro-preview",
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
|
||||
def test_vertex_gemini_direct_reasoning_effort_mappers_drop_params() -> None:
|
||||
"""Verifies direct mapper methods honor drop_params=True and return None."""
|
||||
# Test _map_reasoning_effort_to_thinking_budget directly
|
||||
budget_result: Final = VertexGeminiConfig._map_reasoning_effort_to_thinking_budget(
|
||||
reasoning_effort="xhigh",
|
||||
model="gemini-2.5-flash",
|
||||
drop_params=True,
|
||||
)
|
||||
assert budget_result is None
|
||||
|
||||
# Test _map_reasoning_effort_to_thinking_level directly
|
||||
level_result: Final = VertexGeminiConfig._map_reasoning_effort_to_thinking_level(
|
||||
reasoning_effort="xhigh",
|
||||
model="gemini-3-pro-preview",
|
||||
drop_params=True,
|
||||
)
|
||||
assert level_result is None
|
||||
|
||||
# Test _map_reasoning_effort directly
|
||||
effort_result: Final = VertexGeminiConfig._map_reasoning_effort(
|
||||
effort="max",
|
||||
model="gemini-2.5-flash",
|
||||
reasoning_effort="max",
|
||||
drop_params=True,
|
||||
)
|
||||
assert effort_result is None
|
||||
|
||||
effort_level_result: Final = VertexGeminiConfig._map_reasoning_effort(
|
||||
effort="max",
|
||||
model="gemini-3-pro-preview",
|
||||
reasoning_effort="max",
|
||||
drop_params=True,
|
||||
)
|
||||
assert effort_level_result is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("effort", ["low", "medium", "high"])
|
||||
@pytest.mark.parametrize("model", ["gemini-2.5-flash", "gemini-3-pro-preview"])
|
||||
def test_vertex_gemini_valid_reasoning_effort_mapping(effort: str, model: str) -> None:
|
||||
"""Verifies that supported reasoning_effort values continue to map as expected."""
|
||||
config: Final = VertexGeminiConfig()
|
||||
result: Final = config.map_openai_params(
|
||||
non_default_params={"reasoning_effort": effort},
|
||||
optional_params={},
|
||||
model=model,
|
||||
drop_params=False,
|
||||
)
|
||||
assert "thinkingConfig" in result
|
||||
thinking_config: Final = result["thinkingConfig"]
|
||||
assert thinking_config is not None
|
||||
if "gemini-3" in model:
|
||||
assert thinking_config.get("thinkingLevel") == effort
|
||||
else:
|
||||
assert "thinkingBudget" in thinking_config
|
||||
Loading…
Add table
Reference in a new issue