Skip to content

Commit 9ed9594

Browse files
author
Lin-Nikaido
committed
fix
1 parent d0aef8a commit 9ed9594

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

src/google/adk/models/google_llm.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,50 @@
5757
"""
5858

5959

60+
_SUPPORTED_FILE_CONTENT_MIME_TYPES = frozenset({
61+
# Images
62+
"image/png",
63+
"image/jpeg",
64+
"image/webp",
65+
"image/heic",
66+
"image/heif",
67+
68+
# Documents & Text
69+
"application/pdf",
70+
"text/plain",
71+
"text/csv",
72+
"text/html",
73+
"text/md",
74+
"text/x-python",
75+
"text/javascript",
76+
77+
# Audio
78+
"audio/wav",
79+
"audio/mp3",
80+
"audio/aiff",
81+
"audio/aac",
82+
"audio/ogg",
83+
"audio/flac",
84+
"audio/mpeg",
85+
"audio/mpga",
86+
"audio/m4a",
87+
"audio/pcm",
88+
"audio/webm",
89+
90+
# Video
91+
"video/mp4",
92+
"video/mpeg",
93+
"video/mov",
94+
"video/quicktime",
95+
"video/avi",
96+
"video/x-flv",
97+
"video/mpg",
98+
"video/webm",
99+
"video/wmv",
100+
"video/3gpp"
101+
})
102+
103+
60104
class _ResourceExhaustedError(ClientError):
61105
"""Represents an resources exhausted error received from the Model."""
62106

@@ -440,9 +484,20 @@ async def _preprocess_request(self, llm_request: LlmRequest) -> None:
440484
for part in content.parts:
441485
# Create copies to avoid mutating the original objects
442486
if part.inline_data:
487+
mime_type = (part.inline_data.mime_type or "").lower()
488+
if mime_type not in _SUPPORTED_FILE_CONTENT_MIME_TYPES:
489+
identifier = part.inline_data.display_name or "inline_file"
490+
part.text = (part.text or "") + f'\n[File reference: "{identifier}"]'
491+
part.inline_data = None
443492
part.inline_data = copy.copy(part.inline_data)
444493
_remove_display_name_if_present(part.inline_data)
494+
445495
if part.file_data:
496+
mime_type = (part.file_data.mime_type or "").lower()
497+
identifier = part.file_data.display_name or part.file_data.file_uri
498+
if mime_type not in _SUPPORTED_FILE_CONTENT_MIME_TYPES:
499+
part.text = (part.text or "") + f'\n[File reference: "{identifier}"]'
500+
part.file_data = None
446501
part.file_data = copy.copy(part.file_data)
447502
_remove_display_name_if_present(part.file_data)
448503

tests/unittests/models/test_google_llm.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,3 +2139,50 @@ async def __aexit__(self, *args):
21392139
# Verify the final speech_config is still None
21402140
assert config_arg.speech_config is None
21412141
assert isinstance(connection, GeminiLlmConnection)
2142+
2143+
2144+
@pytest.mark.asyncio
2145+
async def test_preprocess_request_unsupported_mime_type(gemini_llm):
2146+
"""Verifies that MS Office files are escaped to a text reference."""
2147+
unsupported_part = types.Part(
2148+
file_data=types.FileData(
2149+
mime_type="application/vnd.ms-excel",
2150+
file_uri="gs://bucket/data.xls",
2151+
display_name="data.xls"
2152+
)
2153+
)
2154+
req = LlmRequest(
2155+
model="gemini-2.0-flash",
2156+
contents=[types.Content(parts=[unsupported_part])]
2157+
)
2158+
2159+
await gemini_llm._preprocess_request(req)
2160+
2161+
processed_part = req.contents[0].parts[0]
2162+
# File_data should be stripped to avoid the 400 error
2163+
assert processed_part.file_data is None
2164+
# Text fallback should be present
2165+
assert '[File reference: "data.xls"]' in processed_part.text
2166+
2167+
2168+
@pytest.mark.asyncio
2169+
async def test_preprocess_request_supported_mime_type(gemini_llm):
2170+
"""Verifies that PDF files are passed through without modification."""
2171+
supported_part = types.Part(
2172+
file_data=types.FileData(
2173+
mime_type="application/pdf",
2174+
file_uri="gs://bucket/doc.pdf",
2175+
display_name="doc.pdf"
2176+
)
2177+
)
2178+
req = LlmRequest(
2179+
model="gemini-2.0-flash",
2180+
contents=[types.Content(parts=[supported_part])]
2181+
)
2182+
2183+
await gemini_llm._preprocess_request(req)
2184+
2185+
processed_part = req.contents[0].parts[0]
2186+
# file_data should still be intact
2187+
assert processed_part.file_data is not None
2188+
assert processed_part.file_data.mime_type == "application/pdf"

0 commit comments

Comments
 (0)