diff --git a/python/semantic_kernel/connectors/ai/google/google_ai/services/utils.py b/python/semantic_kernel/connectors/ai/google/google_ai/services/utils.py index 0fd460b32433..26b2a4598248 100644 --- a/python/semantic_kernel/connectors/ai/google/google_ai/services/utils.py +++ b/python/semantic_kernel/connectors/ai/google/google_ai/services/utils.py @@ -31,6 +31,18 @@ logger: logging.Logger = logging.getLogger(__name__) +# Finish reasons where Gemini stopped the response for the content, not for length or a natural end. +_GOOGLE_AI_CONTENT_FILTER_REASONS = frozenset({ + FinishReason.SAFETY, + FinishReason.RECITATION, + FinishReason.BLOCKLIST, + FinishReason.PROHIBITED_CONTENT, + FinishReason.SPII, + FinishReason.IMAGE_SAFETY, + FinishReason.IMAGE_PROHIBITED_CONTENT, +}) + + def finish_reason_from_google_ai_to_semantic_kernel( finish_reason: FinishReason | None, ) -> SemanticKernelFinishReason | None: @@ -47,7 +59,7 @@ def finish_reason_from_google_ai_to_semantic_kernel( if finish_reason == FinishReason.MAX_TOKENS: return SemanticKernelFinishReason.LENGTH - if finish_reason == FinishReason.SAFETY: + if finish_reason in _GOOGLE_AI_CONTENT_FILTER_REASONS: return SemanticKernelFinishReason.CONTENT_FILTER return None diff --git a/python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_utils.py b/python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_utils.py index 181d9f5d470e..f3d28fd2453b 100644 --- a/python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_utils.py +++ b/python/tests/unit/connectors/ai/google/google_ai/services/test_google_ai_utils.py @@ -33,6 +33,22 @@ def test_finish_reason_from_google_ai_to_semantic_kernel(): assert finish_reason_from_google_ai_to_semantic_kernel(None) is None +@pytest.mark.parametrize( + "reason", + [ + FinishReason.RECITATION, + FinishReason.BLOCKLIST, + FinishReason.PROHIBITED_CONTENT, + FinishReason.SPII, + FinishReason.IMAGE_SAFETY, + FinishReason.IMAGE_PROHIBITED_CONTENT, + ], +) +def test_content_filter_finish_reasons_from_google_ai(reason): + """Responses Gemini stopped for their content are reported as content filtered.""" + assert finish_reason_from_google_ai_to_semantic_kernel(reason) == SemanticKernelFinishReason.CONTENT_FILTER + + def test_format_user_message(): """Test format_user_message.""" user_message = ChatMessageContent(role=AuthorRole.USER, content="User message")