mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Capture file IDs from code interpreter in streaming responses (#2741)
This commit is contained in:
committed by
GitHub
Unverified
parent
4c6a5d4aa1
commit
3481914981
@@ -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. |
|
||||
|
||||
+111
@@ -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. |
|
||||
|
||||
+102
@@ -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())
|
||||
Reference in New Issue
Block a user