From 55f4c8d2033d891810b5f3253878acfef0b9147d Mon Sep 17 00:00:00 2001 From: Chesars Date: Tue, 10 Mar 2026 19:02:44 -0300 Subject: [PATCH] fix: address Greptile review feedback - Filter get_finish_reason_mapping() to Gemini-only keys instead of returning the full cross-provider _FINISH_REASON_MAP - Shallow-copy caller-supplied provider_specific_fields before mutating to avoid unexpected side-effects --- .../vertex_and_google_ai_studio_gemini.py | 20 +++++++++++++------ litellm/types/utils.py | 2 +- 2 files changed, 15 insertions(+), 7 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 74d5ad330e5..dd22669ac21 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 @@ -1230,18 +1230,26 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): "IMAGE_PROHIBITED_CONTENT": "The token generation was stopped as the response was flagged for prohibited image content.", } + _GEMINI_FINISH_REASON_KEYS = frozenset({ + "STOP", "MAX_TOKENS", "SAFETY", "RECITATION", "FINISH_REASON_UNSPECIFIED", + "MALFORMED_FUNCTION_CALL", "LANGUAGE", "OTHER", "BLOCKLIST", + "PROHIBITED_CONTENT", "SPII", "IMAGE_SAFETY", "IMAGE_PROHIBITED_CONTENT", + "TOO_MANY_TOOL_CALLS", "MALFORMED_RESPONSE", + }) + @staticmethod def get_finish_reason_mapping() -> Dict[str, OpenAIChatCompletionFinishReason]: """ - Return Dictionary of finish reasons which indicate response was flagged - - and what it means. - - Delegates to the centralized _FINISH_REASON_MAP to avoid duplication. + Return Dictionary of Gemini/Vertex AI finish reasons and their + OpenAI-compatible mappings. """ from litellm.litellm_core_utils.core_helpers import _FINISH_REASON_MAP - return dict(_FINISH_REASON_MAP) + return { + k: v + for k, v in _FINISH_REASON_MAP.items() + if k in VertexGeminiConfig._GEMINI_FINISH_REASON_KEYS + } def translate_exception_str(self, exception_string: str): if ( diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 50960134695..ecf4669f3d0 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -1329,7 +1329,7 @@ class Choices(SafeAttributeModel, OpenAIObject): mapped = map_finish_reason(finish_reason) params["finish_reason"] = mapped if finish_reason != mapped: - provider_specific_fields = provider_specific_fields or {} + provider_specific_fields = dict(provider_specific_fields) if provider_specific_fields else {} provider_specific_fields["native_finish_reason"] = finish_reason else: params["finish_reason"] = "stop"