From f70eeb33a15098ec20919efec35b6890da896f4c Mon Sep 17 00:00:00 2001 From: happyryan Date: Sat, 25 Oct 2025 22:05:15 +0900 Subject: [PATCH 1/2] fix: warn about image only for non-user roles --- src/google/adk/models/anthropic_llm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/google/adk/models/anthropic_llm.py b/src/google/adk/models/anthropic_llm.py index 6c20b1b9a5..dad74688fa 100644 --- a/src/google/adk/models/anthropic_llm.py +++ b/src/google/adk/models/anthropic_llm.py @@ -142,7 +142,7 @@ def content_to_message_param( message_block = [] for part in content.parts or []: # Image data is not supported in Claude for model turns. - if _is_image_part(part): + if content.role != "user" and _is_image_part(part): logger.warning("Image data is not supported in Claude for model turns.") continue From b1319fc87569cabc06289fd5f7cc7bc54267b291 Mon Sep 17 00:00:00 2001 From: happyryan Date: Mon, 27 Oct 2025 00:39:35 +0900 Subject: [PATCH 2/2] test: Add test for content_to_message_param --- tests/unittests/models/test_anthropic_llm.py | 79 ++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tests/unittests/models/test_anthropic_llm.py b/tests/unittests/models/test_anthropic_llm.py index a81fbc7252..6824bc1b7d 100644 --- a/tests/unittests/models/test_anthropic_llm.py +++ b/tests/unittests/models/test_anthropic_llm.py @@ -20,6 +20,7 @@ from google.adk import version as adk_version from google.adk.models import anthropic_llm from google.adk.models.anthropic_llm import Claude +from google.adk.models.anthropic_llm import content_to_message_param from google.adk.models.anthropic_llm import function_declaration_to_tool_param from google.adk.models.llm_request import LlmRequest from google.adk.models.llm_response import LlmResponse @@ -346,3 +347,81 @@ async def mock_coro(): mock_client.messages.create.assert_called_once() _, kwargs = mock_client.messages.create.call_args assert kwargs["max_tokens"] == 4096 + + +content_to_message_param_test_cases = [ + ( + "user_role_with_text_and_image", + Content( + role="user", + parts=[ + Part.from_text(text="What's in this image?"), + Part( + inline_data=types.Blob( + mime_type="image/jpeg", data=b"fake_image_data" + ) + ), + ], + ), + "user", + 2, # Expected content length + False, # Should not log warning + ), + ( + "model_role_with_text_and_image", + Content( + role="model", + parts=[ + Part.from_text(text="I see a cat."), + Part( + inline_data=types.Blob( + mime_type="image/png", data=b"fake_image_data" + ) + ), + ], + ), + "assistant", + 1, # Image filtered out, only text remains + True, # Should log warning + ), + ( + "assistant_role_with_text_and_image", + Content( + role="assistant", + parts=[ + Part.from_text(text="Here's what I found."), + Part( + inline_data=types.Blob( + mime_type="image/webp", data=b"fake_image_data" + ) + ), + ], + ), + "assistant", + 1, # Image filtered out, only text remains + True, # Should log warning + ), +] + + +@pytest.mark.parametrize( + "_, content, expected_role, expected_content_length, should_log_warning", + content_to_message_param_test_cases, + ids=[case[0] for case in content_to_message_param_test_cases], +) +def test_content_to_message_param_with_images( + _, content, expected_role, expected_content_length, should_log_warning +): + """Test content_to_message_param handles images correctly based on role.""" + with mock.patch("google.adk.models.anthropic_llm.logger") as mock_logger: + result = content_to_message_param(content) + + assert result["role"] == expected_role + assert len(result["content"]) == expected_content_length + + if should_log_warning: + mock_logger.warning.assert_called_once_with( + "Image data is not supported in Claude for model turns." + ) + else: + mock_logger.warning.assert_not_called()