From 2a34cd84f19d52fe530fa60c49141c44e9c142f9 Mon Sep 17 00:00:00 2001 From: Rio Yu <52408936+rioyu123@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:00:44 +0900 Subject: [PATCH] fix(tools): exclude thought text from preloaded memories --- src/google/adk/tools/_memory_entry_utils.py | 10 ++-- .../tools/test_preload_memory_tool.py | 52 +++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/google/adk/tools/_memory_entry_utils.py b/src/google/adk/tools/_memory_entry_utils.py index 576b2df3fbf..da8039cb6a7 100644 --- a/src/google/adk/tools/_memory_entry_utils.py +++ b/src/google/adk/tools/_memory_entry_utils.py @@ -22,9 +22,11 @@ def extract_text(memory: MemoryEntry, splitter: str = ' ') -> str: - """Extracts the text from the memory entry.""" + """Extracts text from the memory entry, excluding thought parts.""" if not memory.content.parts: return '' - return splitter.join( - [part.text for part in memory.content.parts if part.text] - ) + return splitter.join([ + part.text + for part in memory.content.parts + if part.text and not part.thought + ]) diff --git a/tests/unittests/tools/test_preload_memory_tool.py b/tests/unittests/tools/test_preload_memory_tool.py index 9587084a948..b595d93e61e 100644 --- a/tests/unittests/tools/test_preload_memory_tool.py +++ b/tests/unittests/tools/test_preload_memory_tool.py @@ -41,6 +41,58 @@ def _memory(text: str) -> MemoryEntry: ) +@pytest.mark.parametrize('thought', [True, False, None]) +@pytest.mark.asyncio +async def test_preload_memory_preserves_visible_text_only(thought): + """Recalled reasoning is not presented as a previous conversation answer.""" + memory = MemoryEntry( + content=types.Content( + role='model', + parts=[ + types.Part(text='Consider a zeppelin.', thought=thought), + types.Part(text='Take the train to Paris.'), + ], + ), + author='assistant', + ) + request = LlmRequest() + original_content = memory.content.model_copy(deep=True) + + await PreloadMemoryTool().process_llm_request( + tool_context=_tool_context(memory), llm_request=request + ) + + recalled_text = request.contents[0].parts[0].text + assert 'Take the train to Paris.' in recalled_text + assert ('Consider a zeppelin.' in recalled_text) == (not thought) + assert memory.content == original_content + + +@pytest.mark.parametrize( + 'parts', + [ + [], + [types.Part(text='Consider a zeppelin.', thought=True)], + [ + types.Part( + inline_data=types.Blob(data=b'hello', mime_type='text/plain') + ) + ], + ], +) +@pytest.mark.asyncio +async def test_preload_memory_omits_entries_without_visible_text(parts): + """Empty, non-text and thought-only memories do not add conversation text.""" + memory = MemoryEntry(content=types.Content(role='model', parts=parts)) + request = LlmRequest() + + await PreloadMemoryTool().process_llm_request( + tool_context=_tool_context(memory), llm_request=request + ) + + assert not request.contents + + @pytest.mark.asyncio async def test_preload_memory_keeps_system_prefix_stable(): """Recalled memory goes into contents, never into the system instruction."""