Capture file IDs from code interpreter in streaming responses (#2741)

This commit is contained in:
Evan Mattson
2025-12-11 16:30:19 +09:00
committed by GitHub
Unverified
parent 4c6a5d4aa1
commit 3481914981
10 changed files with 785 additions and 13 deletions
@@ -14,6 +14,7 @@ This folder contains examples demonstrating different ways to create and use age
| [`azure_ai_with_bing_custom_search.py`](azure_ai_with_bing_custom_search.py) | Shows how to use Bing Custom Search with Azure AI agents to search custom search instances and provide responses with relevant results. Requires a Bing Custom Search connection and instance configured in your Azure AI project. |
| [`azure_ai_with_browser_automation.py`](azure_ai_with_browser_automation.py) | Shows how to use Browser Automation with Azure AI agents to perform automated web browsing tasks and provide responses based on web interactions. Requires a Browser Automation connection configured in your Azure AI project. |
| [`azure_ai_with_code_interpreter.py`](azure_ai_with_code_interpreter.py) | Shows how to use the `HostedCodeInterpreterTool` with Azure AI agents to write and execute Python code for mathematical problem solving and data analysis. |
| [`azure_ai_with_code_interpreter_file_generation.py`](azure_ai_with_code_interpreter_file_generation.py) | Shows how to retrieve file IDs from code interpreter generated files using both streaming and non-streaming approaches. |
| [`azure_ai_with_existing_agent.py`](azure_ai_with_existing_agent.py) | Shows how to work with a pre-existing agent by providing the agent name and version to the Azure AI client. Demonstrates agent reuse patterns for production scenarios. |
| [`azure_ai_with_existing_conversation.py`](azure_ai_with_existing_conversation.py) | Demonstrates how to use an existing conversation created on the service side with Azure AI agents. Shows two approaches: specifying conversation ID at the client level and using AgentThread with an existing conversation ID. |
| [`azure_ai_with_application_endpoint.py`](azure_ai_with_application_endpoint.py) | Demonstrates calling the Azure AI application-scoped endpoint. |
@@ -0,0 +1,111 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework import (
CitationAnnotation,
HostedCodeInterpreterTool,
HostedFileContent,
TextContent,
)
from agent_framework._agents import AgentRunResponseUpdate
from agent_framework.azure import AzureAIClient
from azure.identity.aio import AzureCliCredential
"""
Azure AI V2 Code Interpreter File Generation Sample
This sample demonstrates how the V2 AzureAIClient handles file annotations
when code interpreter generates text files. It shows both non-streaming
and streaming approaches to verify file ID extraction.
"""
QUERY = (
"Write a simple Python script that creates a text file called 'sample.txt' containing "
"'Hello from the code interpreter!' and save it to disk."
)
async def test_non_streaming() -> None:
"""Test non-streaming response - should have annotations on TextContent."""
print("=== Testing Non-Streaming Response ===")
async with (
AzureCliCredential() as credential,
AzureAIClient(credential=credential).create_agent(
name="V2CodeInterpreterFileAgent",
instructions="You are a helpful assistant that can write and execute Python code to create files.",
tools=HostedCodeInterpreterTool(),
) as agent,
):
print(f"User: {QUERY}\n")
result = await agent.run(QUERY)
print(f"Agent: {result.text}\n")
# Check for annotations in the response
annotations_found: list[str] = []
# AgentRunResponse has messages property, which contains ChatMessage objects
for message in result.messages:
for content in message.contents:
if isinstance(content, TextContent) and content.annotations:
for annotation in content.annotations:
if isinstance(annotation, CitationAnnotation) and annotation.file_id:
annotations_found.append(annotation.file_id)
print(f"Found file annotation: file_id={annotation.file_id}")
if annotations_found:
print(f"SUCCESS: Found {len(annotations_found)} file annotation(s)")
else:
print("WARNING: No file annotations found in non-streaming response")
async def test_streaming() -> None:
"""Test streaming response - check if file content is captured via HostedFileContent."""
print("\n=== Testing Streaming Response ===")
async with (
AzureCliCredential() as credential,
AzureAIClient(credential=credential).create_agent(
name="V2CodeInterpreterFileAgentStreaming",
instructions="You are a helpful assistant that can write and execute Python code to create files.",
tools=HostedCodeInterpreterTool(),
) as agent,
):
print(f"User: {QUERY}\n")
annotations_found: list[str] = []
text_chunks: list[str] = []
file_ids_found: list[str] = []
async for update in agent.run_stream(QUERY):
if isinstance(update, AgentRunResponseUpdate):
for content in update.contents:
if isinstance(content, TextContent):
if content.text:
text_chunks.append(content.text)
if content.annotations:
for annotation in content.annotations:
if isinstance(annotation, CitationAnnotation) and annotation.file_id:
annotations_found.append(annotation.file_id)
print(f"Found streaming annotation: file_id={annotation.file_id}")
elif isinstance(content, HostedFileContent):
file_ids_found.append(content.file_id)
print(f"Found streaming HostedFileContent: file_id={content.file_id}")
print(f"\nAgent response: {''.join(text_chunks)[:200]}...")
if annotations_found or file_ids_found:
total = len(annotations_found) + len(file_ids_found)
print(f"SUCCESS: Found {total} file reference(s) in streaming")
else:
print("WARNING: No file annotations found in streaming response")
async def main() -> None:
print("AzureAIClient Code Interpreter File Generation Test\n")
await test_non_streaming()
await test_streaming()
if __name__ == "__main__":
asyncio.run(main())
@@ -9,6 +9,7 @@ This folder contains examples demonstrating different ways to create and use age
| [`azure_ai_basic.py`](azure_ai_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureAIAgentClient`. It automatically handles all configuration using environment variables. |
| [`azure_ai_with_bing_custom_search.py`](azure_ai_with_bing_custom_search.py) | Shows how to use Bing Custom Search with Azure AI agents to find real-time information from the web using custom search configurations. Demonstrates how to set up and use HostedWebSearchTool with custom search instances. |
| [`azure_ai_with_bing_grounding.py`](azure_ai_with_bing_grounding.py) | Shows how to use Bing Grounding search with Azure AI agents to find real-time information from the web. Demonstrates web search capabilities with proper source citations and comprehensive error handling. |
| [`azure_ai_with_code_interpreter_file_generation.py`](azure_ai_with_code_interpreter_file_generation.py) | Shows how to retrieve file IDs from code interpreter generated files using both streaming and non-streaming approaches. |
| [`azure_ai_with_code_interpreter.py`](azure_ai_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure AI agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`azure_ai_with_existing_agent.py`](azure_ai_with_existing_agent.py) | Shows how to work with a pre-existing agent by providing the agent ID to the Azure AI chat client. This example also demonstrates proper cleanup of manually created agents. |
| [`azure_ai_with_existing_thread.py`](azure_ai_with_existing_thread.py) | Shows how to work with a pre-existing thread by providing the thread ID to the Azure AI chat client. This example also demonstrates proper cleanup of manually created threads. |
@@ -0,0 +1,102 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework import AgentRunResponseUpdate, ChatAgent, HostedCodeInterpreterTool, HostedFileContent
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
"""
Azure AI Agent Code Interpreter File Generation Example
This sample demonstrates using HostedCodeInterpreterTool with AzureAIAgentClient
to generate a text file and then retrieve it.
The test flow:
1. Create an agent with code interpreter tool
2. Ask the agent to generate a txt file using Python code
3. Capture the file_id from HostedFileContent in the response
4. Retrieve the file using the agents_client.files API
"""
async def main() -> None:
"""Test file generation and retrieval with code interpreter."""
async with AzureCliCredential() as credential:
client = AzureAIAgentClient(credential=credential)
try:
async with ChatAgent(
chat_client=client,
instructions=(
"You are a Python code execution assistant. "
"ALWAYS use the code interpreter tool to execute Python code when asked to create files. "
"Write actual Python code to create files, do not just describe what you would do."
),
tools=[HostedCodeInterpreterTool()],
) as agent:
# Be very explicit about wanting code execution and a download link
query = (
"Use the code interpreter to execute this Python code and then provide me "
"with a download link for the generated file:\n"
"```python\n"
"with open('/mnt/data/sample.txt', 'w') as f:\n"
" f.write('Hello, World! This is a test file.')\n"
"'/mnt/data/sample.txt'\n" # Return the path so it becomes downloadable
"```"
)
print(f"User: {query}\n")
print("=" * 60)
# Collect file_ids from the response
file_ids: list[str] = []
async for chunk in agent.run_stream(query):
if not isinstance(chunk, AgentRunResponseUpdate):
continue
for content in chunk.contents:
if content.type == "text":
print(content.text, end="", flush=True)
elif content.type == "hosted_file":
if isinstance(content, HostedFileContent):
file_ids.append(content.file_id)
print(f"\n[File generated: {content.file_id}]")
print("\n" + "=" * 60)
# Attempt to retrieve discovered files
if file_ids:
print(f"\nAttempting to retrieve {len(file_ids)} file(s):")
for file_id in file_ids:
try:
file_info = await client.agents_client.files.get(file_id)
print(f" File {file_id}: Retrieved successfully")
print(f" Filename: {file_info.filename}")
print(f" Purpose: {file_info.purpose}")
print(f" Bytes: {file_info.bytes}")
except Exception as e:
print(f" File {file_id}: FAILED to retrieve - {e}")
else:
print("No file IDs were captured from the response.")
# List all files to see if any exist
print("\nListing all files in the agent service:")
try:
files_list = await client.agents_client.files.list()
count = 0
for file_info in files_list.data:
count += 1
print(f" - {file_info.id}: {file_info.filename} ({file_info.purpose})")
if count == 0:
print(" No files found.")
except Exception as e:
print(f" Failed to list files: {e}")
finally:
await client.close()
if __name__ == "__main__":
asyncio.run(main())