Skip to content

Commit 55596a9

Browse files
authored
Python: Allow caller to specify file ids that already exist when creating assistant (microsoft#9434)
### Motivation and Context Today, when creating an OpenAI Assistant Agent, one can specify vector store file names or code interpreter files names (paths to files) that will be uploaded and used. If one wants to include a file ID that was already uploaded, this isn't possible. <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description This PR allows for users to specify file IDs that were already uploaded. - Closes microsoft#9159 <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X] The code builds clean without any errors or warnings - [X] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [X] All unit tests pass, and I have added new tests where possible - [X] I didn't break anyone 😄
1 parent e6427a6 commit 55596a9

File tree

5 files changed

+56
-26
lines changed

5 files changed

+56
-26
lines changed

Diff for: python/samples/concepts/agents/assistant_agent_file_manipulation_streaming.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121

2222
# A helper method to invoke the agent with the user input
23-
async def invoke_streaming_agent(agent: OpenAIAssistantAgent, thread_id: str, input: str) -> None:
23+
async def invoke_streaming_agent(agent: OpenAIAssistantAgent | AzureAssistantAgent, thread_id: str, input: str) -> None:
2424
"""Invoke the streaming agent with the user input."""
2525
await agent.add_chat_message(thread_id=thread_id, message=ChatMessageContent(role=AuthorRole.USER, content=input))
2626

Diff for: python/semantic_kernel/agents/open_ai/azure_assistant_agent.py

+25-10
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,10 @@ async def create(
192192
name: str | None = None,
193193
enable_code_interpreter: bool | None = None,
194194
code_interpreter_filenames: list[str] | None = None,
195+
code_interpreter_file_ids: list[str] | None = None,
195196
enable_file_search: bool | None = None,
196197
vector_store_filenames: list[str] | None = None,
198+
vector_store_file_ids: list[str] | None = None,
197199
enable_json_response: bool | None = None,
198200
temperature: float | None = None,
199201
top_p: float | None = None,
@@ -226,8 +228,10 @@ async def create(
226228
name: The Agent name. (optional)
227229
enable_code_interpreter: Enable the code interpreter. (optional)
228230
code_interpreter_filenames: The filenames/paths to use with the code interpreter. (optional)
231+
code_interpreter_file_ids: The existing file IDs to use with the code interpreter. (optional)
229232
enable_file_search: Enable the file search. (optional)
230233
vector_store_filenames: The filenames/paths for files to use with file search. (optional)
234+
vector_store_file_ids: The existing file IDs to use with file search. (optional)
231235
enable_json_response: Enable the JSON response. (optional)
232236
temperature: The temperature. (optional)
233237
top_p: The top p. (optional)
@@ -275,33 +279,44 @@ async def create(
275279

276280
assistant_create_kwargs: dict[str, Any] = {}
277281

282+
code_interpreter_file_ids_combined: list[str] = []
283+
284+
if code_interpreter_file_ids is not None:
285+
code_interpreter_file_ids_combined.extend(code_interpreter_file_ids)
286+
278287
if code_interpreter_filenames is not None:
279-
code_interpreter_file_ids: list[str] = []
280288
for file_path in code_interpreter_filenames:
281289
try:
282290
file_id = await agent.add_file(file_path=file_path, purpose="assistants")
283-
code_interpreter_file_ids.append(file_id)
291+
code_interpreter_file_ids_combined.append(file_id)
284292
except FileNotFoundError as ex:
285293
logger.error(
286294
f"Failed to upload code interpreter file with path: `{file_path}` with exception: {ex}"
287295
)
288296
raise AgentInitializationException("Failed to upload code interpreter files.", ex) from ex
289-
agent.code_interpreter_file_ids = code_interpreter_file_ids
290-
assistant_create_kwargs["code_interpreter_file_ids"] = code_interpreter_file_ids
297+
298+
if code_interpreter_file_ids_combined:
299+
agent.code_interpreter_file_ids = code_interpreter_file_ids_combined
300+
assistant_create_kwargs["code_interpreter_file_ids"] = code_interpreter_file_ids_combined
301+
302+
vector_store_file_ids_combined: list[str] = []
303+
304+
if vector_store_file_ids is not None:
305+
vector_store_file_ids_combined.extend(vector_store_file_ids)
291306

292307
if vector_store_filenames is not None:
293-
file_search_file_ids: list[str] = []
294308
for file_path in vector_store_filenames:
295309
try:
296310
file_id = await agent.add_file(file_path=file_path, purpose="assistants")
297-
file_search_file_ids.append(file_id)
311+
vector_store_file_ids_combined.append(file_id)
298312
except FileNotFoundError as ex:
299-
logger.error(f"Failed to upload file search file with path: `{file_path}` with exception: {ex}")
300-
raise AgentInitializationException("Failed to upload file search files.", ex) from ex
313+
logger.error(f"Failed to upload vector store file with path: `{file_path}` with exception: {ex}")
314+
raise AgentInitializationException("Failed to upload vector store files.", ex) from ex
301315

316+
if vector_store_file_ids_combined:
317+
agent.file_search_file_ids = vector_store_file_ids_combined
302318
if enable_file_search or agent.enable_file_search:
303-
vector_store_id = await agent.create_vector_store(file_ids=file_search_file_ids)
304-
agent.file_search_file_ids = file_search_file_ids
319+
vector_store_id = await agent.create_vector_store(file_ids=vector_store_file_ids_combined)
305320
agent.vector_store_id = vector_store_id
306321
assistant_create_kwargs["vector_store_id"] = vector_store_id
307322

Diff for: python/semantic_kernel/agents/open_ai/open_ai_assistant_agent.py

+28-13
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@ async def create(
165165
name: str | None = None,
166166
enable_code_interpreter: bool | None = None,
167167
code_interpreter_filenames: list[str] | None = None,
168+
code_interpreter_file_ids: list[str] | None = None,
168169
enable_file_search: bool | None = None,
169170
vector_store_filenames: list[str] | None = None,
171+
vector_store_file_ids: list[str] | None = None,
170172
enable_json_response: bool | None = None,
171173
temperature: float | None = None,
172174
top_p: float | None = None,
@@ -195,9 +197,11 @@ async def create(
195197
instructions: The assistant instructions. (optional)
196198
name: The assistant name. (optional)
197199
enable_code_interpreter: Enable code interpreter. (optional)
198-
code_interpreter_filenames: The filenames/paths for files to use with file search. (optional)
199-
enable_file_search: Enable file search. (optional)
200-
vector_store_filenames: The list of file paths to upload and attach to the file search. (optional)
200+
code_interpreter_filenames: The filenames/paths for files to use with code interpreter. (optional)
201+
code_interpreter_file_ids: The existing file IDs to use with the code interpreter. (optional)
202+
enable_file_search: Enable the file search. (optional)
203+
vector_store_filenames: The filenames/paths for files to use with file search. (optional)
204+
vector_store_file_ids: The existing file IDs to use with file search. (optional)
201205
enable_json_response: Enable JSON response. (optional)
202206
temperature: The temperature. (optional)
203207
top_p: The top p. (optional)
@@ -242,33 +246,44 @@ async def create(
242246

243247
assistant_create_kwargs: dict[str, Any] = {}
244248

249+
code_interpreter_file_ids_combined: list[str] = []
250+
251+
if code_interpreter_file_ids is not None:
252+
code_interpreter_file_ids_combined.extend(code_interpreter_file_ids)
253+
245254
if code_interpreter_filenames is not None:
246-
code_interpreter_file_ids: list[str] = []
247255
for file_path in code_interpreter_filenames:
248256
try:
249257
file_id = await agent.add_file(file_path=file_path, purpose="assistants")
250-
code_interpreter_file_ids.append(file_id)
258+
code_interpreter_file_ids_combined.append(file_id)
251259
except FileNotFoundError as ex:
252260
logger.error(
253261
f"Failed to upload code interpreter file with path: `{file_path}` with exception: {ex}"
254262
)
255263
raise AgentInitializationException("Failed to upload code interpreter files.", ex) from ex
256-
agent.code_interpreter_file_ids = code_interpreter_file_ids
257-
assistant_create_kwargs["code_interpreter_file_ids"] = code_interpreter_file_ids
264+
265+
if code_interpreter_file_ids_combined:
266+
agent.code_interpreter_file_ids = code_interpreter_file_ids_combined
267+
assistant_create_kwargs["code_interpreter_file_ids"] = code_interpreter_file_ids_combined
268+
269+
vector_store_file_ids_combined: list[str] = []
270+
271+
if vector_store_file_ids is not None:
272+
vector_store_file_ids_combined.extend(vector_store_file_ids)
258273

259274
if vector_store_filenames is not None:
260-
file_search_file_ids: list[str] = []
261275
for file_path in vector_store_filenames:
262276
try:
263277
file_id = await agent.add_file(file_path=file_path, purpose="assistants")
264-
file_search_file_ids.append(file_id)
278+
vector_store_file_ids_combined.append(file_id)
265279
except FileNotFoundError as ex:
266-
logger.error(f"Failed to upload file search file with path: `{file_path}` with exception: {ex}")
267-
raise AgentInitializationException("Failed to upload file search files.", ex) from ex
280+
logger.error(f"Failed to upload vector store file with path: `{file_path}` with exception: {ex}")
281+
raise AgentInitializationException("Failed to upload vector store files.", ex) from ex
268282

283+
if vector_store_file_ids_combined:
284+
agent.file_search_file_ids = vector_store_file_ids_combined
269285
if enable_file_search or agent.enable_file_search:
270-
vector_store_id = await agent.create_vector_store(file_ids=file_search_file_ids)
271-
agent.file_search_file_ids = file_search_file_ids
286+
vector_store_id = await agent.create_vector_store(file_ids=vector_store_file_ids_combined)
272287
agent.vector_store_id = vector_store_id
273288
assistant_create_kwargs["vector_store_id"] = vector_store_id
274289

Diff for: python/tests/unit/agents/test_azure_assistant_agent.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ async def test_create_agent_with_search_files_not_found_raises_exception(kernel:
167167
patch.object(AzureAssistantAgent, "create_assistant", new_callable=AsyncMock) as mock_create_assistant,
168168
):
169169
mock_create_assistant.return_value = MagicMock(spec=Assistant)
170-
with pytest.raises(AgentInitializationException, match="Failed to upload file search files."):
170+
with pytest.raises(AgentInitializationException, match="Failed to upload vector store files."):
171171
_ = await AzureAssistantAgent.create(
172172
kernel=kernel,
173173
service_id="test_service",

Diff for: python/tests/unit/agents/test_open_ai_assistant_agent.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ async def test_create_agent_with_search_files_not_found_raises_exception(kernel:
195195
patch.object(OpenAIAssistantAgent, "create_assistant", new_callable=AsyncMock) as mock_create_assistant,
196196
):
197197
mock_create_assistant.return_value = MagicMock(spec=Assistant)
198-
with pytest.raises(AgentInitializationException, match="Failed to upload file search files."):
198+
with pytest.raises(AgentInitializationException, match="Failed to upload vector store files."):
199199
_ = await OpenAIAssistantAgent.create(
200200
kernel=kernel,
201201
service_id="test_service",

0 commit comments

Comments
 (0)