Skip to content

Commit 987c809

Browse files
mimisuncopybara-github
authored andcommitted
feat: Add an option to prevent the SaveFilesAsArtifactsPlugin from attaching reference file parts to the message
Default is True to match existing behavior. Setting it to False prevents the model from loading artifact directly from a provided canonical URI, and makes the behavior consistent between InMemoryArtifactService and other services with canonical URIs. PiperOrigin-RevId: 901061080
1 parent fe48d87 commit 987c809

File tree

2 files changed

+51
-10
lines changed

2 files changed

+51
-10
lines changed

src/google/adk/plugins/save_files_as_artifacts_plugin.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,23 @@ class SaveFilesAsArtifactsPlugin(BasePlugin):
4747
tool to the agent, or load the artifacts in your own tool to use the files.
4848
"""
4949

50-
def __init__(self, name: str = 'save_files_as_artifacts_plugin'):
50+
def __init__(
51+
self,
52+
name: str = 'save_files_as_artifacts_plugin',
53+
*,
54+
attach_file_reference: bool = True,
55+
):
5156
"""Initialize the save files as artifacts plugin.
5257
5358
Args:
5459
name: The name of the plugin instance.
60+
attach_file_reference: Whether to attach a file reference to the
61+
user message. If False, only save the files as artifacts without
62+
adding a file reference, and the files will not be directly
63+
accessible to the model.
5564
"""
5665
super().__init__(name)
66+
self._attach_file_reference = attach_file_reference
5767

5868
async def on_user_message_callback(
5969
self,
@@ -108,15 +118,16 @@ async def on_user_message_callback(
108118
)
109119
new_parts.append(placeholder_part)
110120

111-
file_part = await self._build_file_reference_part(
112-
invocation_context=invocation_context,
113-
filename=file_name,
114-
version=version,
115-
mime_type=inline_data.mime_type,
116-
display_name=display_name,
117-
)
118-
if file_part:
119-
new_parts.append(file_part)
121+
if self._attach_file_reference:
122+
file_part = await self._build_file_reference_part(
123+
invocation_context=invocation_context,
124+
filename=file_name,
125+
version=version,
126+
mime_type=inline_data.mime_type,
127+
display_name=display_name,
128+
)
129+
if file_part:
130+
new_parts.append(file_part)
120131
pending_delta[file_name] = version
121132

122133
modified = True

tests/unittests/plugins/test_save_files_as_artifacts.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,36 @@ async def test_save_files_with_display_name(self):
9191
assert result.parts[1].file_data.display_name == "test_document.pdf"
9292
assert result.parts[1].file_data.mime_type == "application/pdf"
9393

94+
@pytest.mark.asyncio
95+
async def test_attach_file_reference_false(self):
96+
"""Test that file reference is not attached when attach_file_reference is False."""
97+
plugin = SaveFilesAsArtifactsPlugin(attach_file_reference=False)
98+
99+
inline_data = types.Blob(
100+
display_name="test_document.pdf",
101+
data=b"test data",
102+
mime_type="application/pdf",
103+
)
104+
105+
original_part = types.Part(inline_data=inline_data)
106+
user_message = types.Content(parts=[original_part])
107+
108+
result = await plugin.on_user_message_callback(
109+
invocation_context=self.mock_context, user_message=user_message
110+
)
111+
112+
self.mock_context.artifact_service.save_artifact.assert_called_once_with(
113+
app_name="test_app",
114+
user_id="test_user",
115+
session_id="test_session",
116+
filename="test_document.pdf",
117+
artifact=original_part,
118+
)
119+
120+
assert result
121+
assert len(result.parts) == 1
122+
assert result.parts[0].text == '[Uploaded Artifact: "test_document.pdf"]'
123+
94124
@pytest.mark.asyncio
95125
async def test_save_files_without_display_name(self):
96126
"""Test saving files when inline_data has no display_name."""

0 commit comments

Comments
 (0)