From ffb199d05c42f301d54a9df1da4a8a038ba0ee2a Mon Sep 17 00:00:00 2001 From: mateo Date: Sat, 31 Oct 2026 22:30:00 +0000 Subject: [PATCH] fix(gemini): set responseLogprobs when top_logprobs is the only logprob param Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../vertex_and_google_ai_studio_gemini.py | 1 + .../test_responses_params_gemini_logprobs.py | 8 ++++++-- .../llms/gemini/chat/test_transformation.py | 18 ++++++++++++++++-- 3 files changed, 23 insertions(+), 4 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 69580687048..9a83e15785f 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 @@ -1690,6 +1690,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): optional_params["responseLogprobs"] = value elif param == "top_logprobs": optional_params["logprobs"] = value + optional_params["responseLogprobs"] = True 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( diff --git a/tests/integration/translation/responses/params/test_responses_params_gemini_logprobs.py b/tests/integration/translation/responses/params/test_responses_params_gemini_logprobs.py index 0c034e52e71..fa51b99037f 100644 --- a/tests/integration/translation/responses/params/test_responses_params_gemini_logprobs.py +++ b/tests/integration/translation/responses/params/test_responses_params_gemini_logprobs.py @@ -14,7 +14,9 @@ GEMINI_3_5_FLASH_TOP_LOGPROBS_TEST_CASE: Final = replace( scenario="top_logprobs", litellm_request={**GEMINI_3_5_FLASH_TEST_CASE.litellm_request, "top_logprobs": 3}, expected_provider_request=with_field( - GEMINI_3_5_FLASH_TEST_CASE.expected_provider_request, ("generationConfig", "logprobs"), 3 + with_field(GEMINI_3_5_FLASH_TEST_CASE.expected_provider_request, ("generationConfig", "logprobs"), 3), + ("generationConfig", "responseLogprobs"), + True, ), ) @@ -22,5 +24,7 @@ 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: +def test_responses_params_gemini_logprobs( + case: TranslationTestCase, gateway: Gateway, provider: SharedProvider +) -> None: assert_translation(case, gateway, provider) diff --git a/tests/unit/llms/gemini/chat/test_transformation.py b/tests/unit/llms/gemini/chat/test_transformation.py index f6159649e67..31bb8cc6e0a 100644 --- a/tests/unit/llms/gemini/chat/test_transformation.py +++ b/tests/unit/llms/gemini/chat/test_transformation.py @@ -1,12 +1,14 @@ +from typing import Final + from litellm.llms.gemini.chat.transformation import GoogleAIStudioGeminiConfig def test_top_logprobs_maps_to_generation_config_logprobs(): - config = GoogleAIStudioGeminiConfig() + config: Final = GoogleAIStudioGeminiConfig() assert "top_logprobs" in config.get_supported_openai_params("gemini-3.5-flash") - optional_params = config.map_openai_params( + optional_params: Final = config.map_openai_params( non_default_params={"logprobs": True, "top_logprobs": 3}, optional_params={}, model="gemini-3.5-flash", @@ -15,3 +17,15 @@ def test_top_logprobs_maps_to_generation_config_logprobs(): 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