From c2c7ecc3a43be40ddc74e138e818a069dd99a9fc Mon Sep 17 00:00:00 2001 From: Kathy Wu Date: Wed, 6 May 2026 16:32:10 -0700 Subject: [PATCH] fix: Filter out video events with inline data from being stored in session Co-authored-by: Kathy Wu PiperOrigin-RevId: 911614336 --- src/google/adk/flows/llm_flows/contents.py | 18 +++++++------- src/google/adk/runners.py | 8 +++---- tests/unittests/test_runners.py | 28 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/google/adk/flows/llm_flows/contents.py b/src/google/adk/flows/llm_flows/contents.py index feeb8ef972..027a79bdf4 100644 --- a/src/google/adk/flows/llm_flows/contents.py +++ b/src/google/adk/flows/llm_flows/contents.py @@ -795,8 +795,8 @@ def _is_request_input_event(event: Event) -> bool: return _is_function_call_event(event, REQUEST_INPUT_FUNCTION_CALL_NAME) -def _is_live_model_audio_event_with_inline_data(event: Event) -> bool: - """Check if the event is a live/bidi audio event with inline data. +def _is_live_model_media_event_with_inline_data(event: Event) -> bool: + """Check if the event is a live/bidi media event (audio, video, image) with inline data. There are two possible cases and we only care about the second case: content=Content( @@ -826,12 +826,14 @@ def _is_live_model_audio_event_with_inline_data(event: Event) -> bool: if not event.content or not event.content.parts: return False for part in event.content.parts: - if ( - part.inline_data - and part.inline_data.mime_type - and part.inline_data.mime_type.startswith('audio/') - ): - return True + if part.inline_data and part.inline_data.mime_type: + mime = part.inline_data.mime_type.lower() + if ( + mime.startswith('audio/') + or mime.startswith('video/') + or mime.startswith('image/') + ): + return True return False diff --git a/src/google/adk/runners.py b/src/google/adk/runners.py index 0f36d6389d..314faaf0f9 100644 --- a/src/google/adk/runners.py +++ b/src/google/adk/runners.py @@ -786,17 +786,17 @@ async def _compute_artifact_delta_for_rewind( def _should_append_event(self, event: Event, is_live_call: bool) -> bool: """Checks if an event should be appended to the session.""" - # Don't append audio response from model in live mode to session. + # Don't append media (audio/video/image) response from model in live mode to session. # The data is appended to artifacts with a reference in file_data in the - # event. + # event if save_live_blob is True. # We should append non-partial events only.For example, non-finished(partial) # transcription events should not be appended. # Function call and function response events should be appended. # Other control events should be appended. - if is_live_call and contents._is_live_model_audio_event_with_inline_data( + if is_live_call and contents._is_live_model_media_event_with_inline_data( event ): - # We don't append live model audio events with inline data to avoid + # We don't append live model media events with inline data to avoid # storing large blobs in the session. However, events with file_data # (references to artifacts) should be appended. return False diff --git a/tests/unittests/test_runners.py b/tests/unittests/test_runners.py index 08336204f9..aa3fc030f3 100644 --- a/tests/unittests/test_runners.py +++ b/tests/unittests/test_runners.py @@ -1188,6 +1188,34 @@ def test_should_append_event_other_event(self): ) assert self.runner._should_append_event(event, is_live_call=True) is True + def test_should_not_append_event_live_model_video(self): + event = Event( + invocation_id="inv1", + author="model", + content=types.Content( + parts=[ + types.Part( + inline_data=types.Blob(data=b"123", mime_type="video/mp4") + ) + ] + ), + ) + assert self.runner._should_append_event(event, is_live_call=True) is False + + def test_should_append_event_non_live_model_video(self): + event = Event( + invocation_id="inv1", + author="model", + content=types.Content( + parts=[ + types.Part( + inline_data=types.Blob(data=b"123", mime_type="video/mp4") + ) + ] + ), + ) + assert self.runner._should_append_event(event, is_live_call=False) is True + @pytest.fixture def user_agent_module(tmp_path, monkeypatch):