From 6907f89be1fa40a29f779fa79b785513248e35d6 Mon Sep 17 00:00:00 2001 From: A Vertex SDK engineer Date: Mon, 9 Feb 2026 18:28:38 -0800 Subject: [PATCH] feat: Add filter_groups to PurgeMemories for metadata-based filtering PiperOrigin-RevId: 867864418 --- .../test_purge_agent_engine_memories.py | 34 ++++++++++++++++- vertexai/_genai/memories.py | 37 +++++++++++++++---- vertexai/_genai/types/common.py | 33 +++++++++++++++++ 3 files changed, 96 insertions(+), 8 deletions(-) diff --git a/tests/unit/vertexai/genai/replays/test_purge_agent_engine_memories.py b/tests/unit/vertexai/genai/replays/test_purge_agent_engine_memories.py index b4615b6b92..55a8bd5005 100644 --- a/tests/unit/vertexai/genai/replays/test_purge_agent_engine_memories.py +++ b/tests/unit/vertexai/genai/replays/test_purge_agent_engine_memories.py @@ -42,6 +42,15 @@ def test_purge_memories(client): scope={"user_id": "456"}, config={"wait_for_completion": True}, ) + client.agent_engines.memories.create( + name=agent_engine.api_resource.name, + fact="memory_fact_4", + scope={"user_id": "456"}, + config={ + "wait_for_completion": True, + "metadata": {"my_key": {"string_value": "my_value"}}, + }, + ) operation = client.agent_engines.memories.purge( name=agent_engine.api_resource.name, filter="scope.user_id=123", @@ -58,7 +67,7 @@ def test_purge_memories(client): ) ) ) - == 3 + == 4 ) # Now, actually purge the memories. operation = client.agent_engines.memories.purge( @@ -69,6 +78,29 @@ def test_purge_memories(client): ) assert operation.done assert operation.response.purge_count == 2 + assert ( + len( + list( + client.agent_engines.memories.list( + name=agent_engine.api_resource.name + ) + ) + ) + == 2 + ) + # Purge memories using filter groups. + operation = client.agent_engines.memories.purge( + name=agent_engine.api_resource.name, + force=True, + filter_groups=[ + {"filters": [{"key": "my_key", "value": {"string_value": "my_value"}}]} + ], + config={ + "wait_for_completion": True, + }, + ) + assert operation.done + assert operation.response.purge_count == 1 assert ( len( list( diff --git a/vertexai/_genai/memories.py b/vertexai/_genai/memories.py index ac8ddeb5a3..70a4a6369c 100644 --- a/vertexai/_genai/memories.py +++ b/vertexai/_genai/memories.py @@ -20,7 +20,7 @@ import json import logging import typing -from typing import Any, Iterator, Optional, Union +from typing import Any, Iterator, List, Optional, Union from urllib.parse import urlencode from google.genai import _api_module @@ -317,6 +317,13 @@ def _PurgeAgentEngineMemoriesRequestParameters_to_vertex( if getv(from_object, ["filter"]) is not None: setv(to_object, ["filter"], getv(from_object, ["filter"])) + if getv(from_object, ["filter_groups"]) is not None: + setv( + to_object, + ["filterGroups"], + [item for item in getv(from_object, ["filter_groups"])], + ) + if getv(from_object, ["force"]) is not None: setv(to_object, ["force"], getv(from_object, ["force"])) @@ -1072,7 +1079,8 @@ def _purge( self, *, name: str, - filter: str, + filter: Optional[str] = None, + filter_groups: Optional[list[types.MemoryConjunctionFilterOrDict]] = None, force: Optional[bool] = None, config: Optional[types.PurgeAgentEngineMemoriesConfigOrDict] = None, ) -> types.AgentEnginePurgeMemoriesOperation: @@ -1083,6 +1091,7 @@ def _purge( parameter_model = types._PurgeAgentEngineMemoriesRequestParameters( name=name, filter=filter, + filter_groups=filter_groups, force=force, config=config, ) @@ -1384,7 +1393,8 @@ def purge( self, *, name: str, - filter: str, + filter: Optional[str] = None, + filter_groups: Optional[List[types.MemoryConjunctionFilter]] = None, force: bool = False, config: Optional[types.PurgeAgentEngineMemoriesConfigOrDict] = None, ) -> types.AgentEnginePurgeMemoriesOperation: @@ -1394,7 +1404,11 @@ def purge( name (str): Required. The name of the Agent Engine to purge memories from. filter (str): - Required. The standard list filter to determine which memories to purge. + Optional. The standard list filter to determine which memories to purge. + filter_groups (list[MemoryConjunctionFilter]): + Optional. Metadata filters that will be applied to the memories' + `metadata` using OR logic. Filters are defined using disjunctive + normal form (OR of ANDs). force (bool): Optional. Whether to force the purge operation. If false, the operation will be staged but not executed. @@ -1412,6 +1426,7 @@ def purge( operation = self._purge( name=name, filter=filter, + filter_groups=filter_groups, force=force, config=config, ) @@ -2042,7 +2057,8 @@ async def _purge( self, *, name: str, - filter: str, + filter: Optional[str] = None, + filter_groups: Optional[list[types.MemoryConjunctionFilterOrDict]] = None, force: Optional[bool] = None, config: Optional[types.PurgeAgentEngineMemoriesConfigOrDict] = None, ) -> types.AgentEnginePurgeMemoriesOperation: @@ -2053,6 +2069,7 @@ async def _purge( parameter_model = types._PurgeAgentEngineMemoriesRequestParameters( name=name, filter=filter, + filter_groups=filter_groups, force=force, config=config, ) @@ -2356,7 +2373,8 @@ async def purge( self, *, name: str, - filter: str, + filter: Optional[str] = None, + filter_groups: Optional[List[types.MemoryConjunctionFilter]] = None, force: bool = False, config: Optional[types.PurgeAgentEngineMemoriesConfigOrDict] = None, ) -> types.AgentEnginePurgeMemoriesOperation: @@ -2366,7 +2384,11 @@ async def purge( name (str): Required. The name of the Agent Engine to purge memories from. filter (str): - Required. The standard list filter to determine which memories to purge. + Optional. The standard list filter to determine which memories to purge. + filter_groups (list[MemoryConjunctionFilter]): + Optional. Metadata filters that will be applied to the memories' + `metadata` using OR logic. Filters are defined using disjunctive + normal form (OR of ANDs). force (bool): Optional. Whether to force the purge operation. If false, the operation will be staged but not executed. @@ -2384,6 +2406,7 @@ async def purge( operation = await self._purge( name=name, filter=filter, + filter_groups=filter_groups, force=force, config=config, ) diff --git a/vertexai/_genai/types/common.py b/vertexai/_genai/types/common.py index 2716964936..d0cedc22e0 100644 --- a/vertexai/_genai/types/common.py +++ b/vertexai/_genai/types/common.py @@ -8447,6 +8447,23 @@ class _PurgeAgentEngineMemoriesRequestParameters(_common.BaseModel): description="""The standard list filter to determine which memories to purge. More detail in [AIP-160](https://google.aip.dev/160).""", ) + filter_groups: Optional[list[MemoryConjunctionFilter]] = Field( + default=None, + description="""Metadata filters that will be applied to the memories' + `metadata` using OR logic. Filters are defined using disjunctive normal + form (OR of ANDs). + + For example: + `filter_groups: [{filters: [{key: "author", value: {string_value: "agent + `123"}, op: EQUAL}]}, {filters: [{key: "label", value: {string_value: + "travel"}, op: EQUAL}, {key: "author", value: {string_value: "agent 321"}, + op: EQUAL}]}]` + + would be equivalent to the logical expression: + `(metadata.author = "agent 123" OR (metadata.label = "travel" AND + metadata.author = "agent 321"))`. + """, + ) force: Optional[bool] = Field( default=None, description="""If true, the memories will actually be purged. If false, the purge request will be validated but not executed.""", @@ -8466,6 +8483,22 @@ class _PurgeAgentEngineMemoriesRequestParametersDict(TypedDict, total=False): """The standard list filter to determine which memories to purge. More detail in [AIP-160](https://google.aip.dev/160).""" + filter_groups: Optional[list[MemoryConjunctionFilterDict]] + """Metadata filters that will be applied to the memories' + `metadata` using OR logic. Filters are defined using disjunctive normal + form (OR of ANDs). + + For example: + `filter_groups: [{filters: [{key: "author", value: {string_value: "agent + `123"}, op: EQUAL}]}, {filters: [{key: "label", value: {string_value: + "travel"}, op: EQUAL}, {key: "author", value: {string_value: "agent 321"}, + op: EQUAL}]}]` + + would be equivalent to the logical expression: + `(metadata.author = "agent 123" OR (metadata.label = "travel" AND + metadata.author = "agent 321"))`. + """ + force: Optional[bool] """If true, the memories will actually be purged. If false, the purge request will be validated but not executed."""