From d224b268a1a42bde19d64b4431df5e7dca903699 Mon Sep 17 00:00:00 2001 From: Sam Goto Date: Fri, 26 Dec 2025 11:28:05 -0600 Subject: [PATCH 1/2] feat: record usage metadata on compaction events --- src/google/adk/apps/llm_event_summarizer.py | 4 +++ .../apps/test_llm_event_summarizer.py | 35 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/google/adk/apps/llm_event_summarizer.py b/src/google/adk/apps/llm_event_summarizer.py index fffb2ab547..4f8bf4c169 100644 --- a/src/google/adk/apps/llm_event_summarizer.py +++ b/src/google/adk/apps/llm_event_summarizer.py @@ -104,9 +104,12 @@ async def maybe_summarize_events( contents=[Content(role='user', parts=[Part(text=prompt)])], ) summary_content = None + usage_metadata = None async for llm_response in self._llm.generate_content_async( llm_request, stream=False ): + if llm_response.usage_metadata is not None: + usage_metadata = llm_response.usage_metadata if llm_response.content: summary_content = llm_response.content break @@ -132,4 +135,5 @@ async def maybe_summarize_events( author='user', actions=actions, invocation_id=Event.new_id(), + usage_metadata=usage_metadata, ) diff --git a/tests/unittests/apps/test_llm_event_summarizer.py b/tests/unittests/apps/test_llm_event_summarizer.py index 4ced5d3f0b..b4296142cf 100644 --- a/tests/unittests/apps/test_llm_event_summarizer.py +++ b/tests/unittests/apps/test_llm_event_summarizer.py @@ -25,6 +25,7 @@ from google.genai.types import Content from google.genai.types import FunctionCall from google.genai.types import FunctionResponse +from google.genai.types import GenerateContentResponseUsageMetadata from google.genai.types import Part import pytest @@ -57,7 +58,9 @@ async def test_maybe_compact_events_success(self): expected_prompt = self.compactor._DEFAULT_PROMPT_TEMPLATE.format( conversation_history=expected_conversation_history ) - mock_llm_response = Mock(content=Content(parts=[Part(text='Summary')])) + mock_llm_response = Mock( + content=Content(parts=[Part(text='Summary')]), usage_metadata=None + ) async def async_gen(): yield mock_llm_response @@ -90,11 +93,39 @@ async def async_gen(): self.assertEqual(llm_request.contents[0].parts[0].text, expected_prompt) self.assertFalse(kwargs['stream']) + async def test_maybe_compact_events_includes_usage_metadata(self): + events = [ + self._create_event(1.0, 'Hello', 'user'), + self._create_event(2.0, 'Hi there!', 'model'), + ] + usage_metadata = GenerateContentResponseUsageMetadata( + prompt_token_count=10, + candidates_token_count=5, + total_token_count=15, + ) + mock_llm_response = Mock( + content=Content(parts=[Part(text='Summary')]), + usage_metadata=usage_metadata, + ) + + async def async_gen(): + yield mock_llm_response + + self.mock_llm.generate_content_async.return_value = async_gen() + + compacted_event = await self.compactor.maybe_summarize_events(events=events) + + self.assertIsNotNone(compacted_event) + self.assertIsNotNone(compacted_event.usage_metadata) + self.assertEqual(compacted_event.usage_metadata.prompt_token_count, 10) + self.assertEqual(compacted_event.usage_metadata.candidates_token_count, 5) + self.assertEqual(compacted_event.usage_metadata.total_token_count, 15) + async def test_maybe_compact_events_empty_llm_response(self): events = [ self._create_event(1.0, 'Hello', 'user'), ] - mock_llm_response = Mock(content=None) + mock_llm_response = Mock(content=None, usage_metadata=None) async def async_gen(): yield mock_llm_response From be6a2e8eef726db16c63ed23eccee6159fd1e6ef Mon Sep 17 00:00:00 2001 From: Osamu Goto Date: Fri, 26 Dec 2025 11:40:00 -0600 Subject: [PATCH 2/2] feat: address review comment to capture summary_content and usage_metadata in the same if branch Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/google/adk/apps/llm_event_summarizer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/google/adk/apps/llm_event_summarizer.py b/src/google/adk/apps/llm_event_summarizer.py index 4f8bf4c169..176f8742f5 100644 --- a/src/google/adk/apps/llm_event_summarizer.py +++ b/src/google/adk/apps/llm_event_summarizer.py @@ -108,10 +108,9 @@ async def maybe_summarize_events( async for llm_response in self._llm.generate_content_async( llm_request, stream=False ): - if llm_response.usage_metadata is not None: - usage_metadata = llm_response.usage_metadata if llm_response.content: summary_content = llm_response.content + usage_metadata = llm_response.usage_metadata break if summary_content is None: