This commit is contained in:
Mateo Wang 2026-11-06 18:28:17 +00:00 • committed by GitHub
commit 0120fd72b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 106 additions and 0 deletions

View file

@ -97,6 +97,7 @@ class GoogleAIStudioGeminiConfig(VertexGeminiConfig):
"n",
"stop",
"logprobs",
"top_logprobs",
"frequency_penalty",
"presence_penalty",
"seed",

View file

@ -1888,6 +1888,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
optional_params["responseLogprobs"] = value
elif param == "top_logprobs":
optional_params["logprobs"] = value
optional_params["responseLogprobs"] = True # rebind-ok: this mapping fills optional_params in place
elif (param == "tools" or param == "functions") and isinstance(value, list) and value:
# Pass optional_params so _map_function can add toolConfig if needed
mapped_tools = with_integer_enums_that_fit(

View file

@ -0,0 +1,30 @@
from dataclasses import replace
from typing import Final
import pytest
from integration._support.client import Gateway
from integration._support.provider import SharedProvider
from integration.translation.case import TranslationTestCase
from integration.translation.chat_completions.bases.gemini import GEMINI_3_5_FLASH_TEST_CASE
from integration.translation.params import with_field
from integration.translation.runner import assert_translation
GEMINI_3_5_FLASH_TOP_LOGPROBS_TEST_CASE: Final = replace(
GEMINI_3_5_FLASH_TEST_CASE,
scenario="logprobs_top_logprobs",
litellm_request={**GEMINI_3_5_FLASH_TEST_CASE.litellm_request, "logprobs": True, "top_logprobs": 3},
expected_provider_request=with_field(
with_field(GEMINI_3_5_FLASH_TEST_CASE.expected_provider_request, ("generationConfig", "responseLogprobs"), True),
("generationConfig", "logprobs"),
3,
),
)
CASES: Final = (GEMINI_3_5_FLASH_TOP_LOGPROBS_TEST_CASE,)
@pytest.mark.parametrize("case", CASES, ids=lambda case: case.id)
def test_chat_completions_params_gemini_logprobs(
case: TranslationTestCase, gateway: Gateway, provider: SharedProvider
) -> None:
assert_translation(case, gateway, provider)

View file

@ -0,0 +1,13 @@
from collections.abc import Mapping, Sequence
from typing import Final
from pydantic import JsonValue
def with_field(mapping: Mapping[str, JsonValue], path: Sequence[str], value: JsonValue) -> Mapping[str, JsonValue]:
"""Return a copy of `mapping` with the nested key `path` set to `value`, creating intermediate objects."""
head: Final = path[0]
if len(path) == 1:
return {**mapping, head: value}
inner: Final = mapping.get(head)
return {**mapping, head: with_field(inner if isinstance(inner, dict) else {}, path[1:], value)}

View file

@ -0,0 +1,30 @@
from dataclasses import replace
from typing import Final
import pytest
from integration._support.client import Gateway
from integration._support.provider import SharedProvider
from integration.translation.case import TranslationTestCase
from integration.translation.params import with_field
from integration.translation.responses.bases.gemini import GEMINI_3_5_FLASH_TEST_CASE
from integration.translation.runner import assert_translation
GEMINI_3_5_FLASH_TOP_LOGPROBS_TEST_CASE: Final = replace(
GEMINI_3_5_FLASH_TEST_CASE,
scenario="top_logprobs",
litellm_request={**GEMINI_3_5_FLASH_TEST_CASE.litellm_request, "top_logprobs": 3},
expected_provider_request=with_field(
with_field(GEMINI_3_5_FLASH_TEST_CASE.expected_provider_request, ("generationConfig", "logprobs"), 3),
("generationConfig", "responseLogprobs"),
True,
),
)
CASES: Final = (GEMINI_3_5_FLASH_TOP_LOGPROBS_TEST_CASE,)
@pytest.mark.parametrize("case", CASES, ids=lambda case: case.id)
def test_responses_params_gemini_logprobs(
case: TranslationTestCase, gateway: Gateway, provider: SharedProvider
) -> None:
assert_translation(case, gateway, provider)

View file

View file

@ -0,0 +1,31 @@
from typing import Final
from litellm.llms.gemini.chat.transformation import GoogleAIStudioGeminiConfig
def test_top_logprobs_maps_to_generation_config_logprobs():
config: Final = GoogleAIStudioGeminiConfig()
assert "top_logprobs" in config.get_supported_openai_params("gemini-3.5-flash")
optional_params: Final = config.map_openai_params(
non_default_params={"logprobs": True, "top_logprobs": 3},
optional_params={},
model="gemini-3.5-flash",
drop_params=False,
)
assert optional_params["responseLogprobs"] is True
assert optional_params["logprobs"] == 3
def test_top_logprobs_alone_enables_response_logprobs():
optional_params: Final = GoogleAIStudioGeminiConfig().map_openai_params(
non_default_params={"top_logprobs": 3},
optional_params={},
model="gemini-3.5-flash",
drop_params=False,
)
assert optional_params["responseLogprobs"] is True
assert optional_params["logprobs"] == 3