mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Add Code Interpreter container file download samples (#5014)
* Add Code Interpreter container file download samples (#3081) - Add Agent_OpenAI_Step06_CodeInterpreterFileDownload (Public OpenAI) - Add Agent_Step24_CodeInterpreterFileDownload (Microsoft Foundry) - Both samples demonstrate downloading cfile_/cntr_ container files via ContainerClient instead of the standard Files API - Update solution file and parent READMEs * Address review feedback: flatten nested foreach loops using SelectMany Addresses https://github.com/microsoft/agent-framework/pull/5014#discussion_r3046908449 and https://github.com/microsoft/agent-framework/pull/5014#discussion_r3046920209 --------- Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Co-authored-by: rogerbarreto <rogerbarreto@users.noreply.github.com>
This commit is contained in:
co-authored by
Roger Barreto
rogerbarreto
parent
c85d24da44
commit
52303a8d07
+15
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to download files generated by Code Interpreter using the Containers API.
|
||||
// Code Interpreter generates files inside containers (cfile_ / cntr_ IDs) which cannot be
|
||||
// downloaded via the standard Files API. Use ContainerClient instead.
|
||||
|
||||
#pragma warning disable OPENAI001
|
||||
|
||||
using System.ClientModel;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI;
|
||||
using OpenAI.Containers;
|
||||
using OpenAI.Responses;
|
||||
|
||||
string apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
string model = Environment.GetEnvironmentVariable("OPENAI_CHAT_MODEL_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
var openAIClient = new OpenAIClient(new ApiKeyCredential(apiKey));
|
||||
|
||||
// Create an agent with Code Interpreter tool enabled
|
||||
AIAgent agent = openAIClient
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(
|
||||
model: model,
|
||||
instructions: "You are a helpful assistant that can generate files using code.",
|
||||
name: "CodeInterpreterAgent",
|
||||
tools: [new HostedCodeInterpreterTool()]);
|
||||
|
||||
// Ask the agent to generate a file
|
||||
AgentResponse response = await agent.RunAsync(
|
||||
"Create a CSV file with the multiplication times tables from 1 to 12. Include headers.");
|
||||
|
||||
// Display the text response
|
||||
foreach (TextContent textContent in response.Messages.SelectMany(x => x.Contents).OfType<TextContent>())
|
||||
{
|
||||
Console.WriteLine(textContent.Text);
|
||||
}
|
||||
|
||||
// Extract container file citations from response annotations and download
|
||||
ContainerClient containerClient = openAIClient.GetContainerClient();
|
||||
|
||||
HashSet<string> downloadedFiles = [];
|
||||
bool foundContainerFiles = false;
|
||||
|
||||
foreach (AIContent content in response.Messages.SelectMany(x => x.Contents))
|
||||
{
|
||||
if (content.Annotations is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (AIAnnotation annotation in content.Annotations)
|
||||
{
|
||||
// Container files from Code Interpreter have ContainerFileCitationMessageAnnotation as raw representation
|
||||
if (annotation is CitationAnnotation citation
|
||||
&& citation.RawRepresentation is ContainerFileCitationMessageAnnotation containerCitation)
|
||||
{
|
||||
foundContainerFiles = true;
|
||||
|
||||
// Deduplicate by container+file ID in case the same file is cited multiple times
|
||||
string key = $"{containerCitation.ContainerId}/{containerCitation.FileId}";
|
||||
if (!downloadedFiles.Add(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"\nDownloading container file: {containerCitation.Filename}");
|
||||
Console.WriteLine($" Container ID: {containerCitation.ContainerId}");
|
||||
Console.WriteLine($" File ID: {containerCitation.FileId}");
|
||||
|
||||
BinaryData fileData = await containerClient.DownloadContainerFileAsync(
|
||||
containerCitation.ContainerId,
|
||||
containerCitation.FileId);
|
||||
|
||||
// Sanitize filename to prevent path traversal
|
||||
string safeFilename = Path.GetFileName(containerCitation.Filename);
|
||||
string outputPath = Path.Combine(Directory.GetCurrentDirectory(), safeFilename);
|
||||
await File.WriteAllBytesAsync(outputPath, fileData.ToArray());
|
||||
Console.WriteLine($" Saved to: {outputPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundContainerFiles)
|
||||
{
|
||||
Console.WriteLine("\nNo container file citations found in the response.");
|
||||
Console.WriteLine("The model may not have generated a downloadable file for this prompt.");
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
# Code Interpreter File Download (OpenAI)
|
||||
|
||||
This sample demonstrates how to download files generated by Code Interpreter when using the OpenAI Responses API.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating an agent with Code Interpreter tool using `ResponsesClient.AsAIAgent()`
|
||||
- Generating files through Code Interpreter (e.g., CSV, Excel, images)
|
||||
- Extracting container file citations from agent response annotations
|
||||
- Downloading container files using the `ContainerClient` API
|
||||
|
||||
## Container files vs regular files
|
||||
|
||||
When Code Interpreter generates a file, the file is stored inside a **container** with a `cntr_` prefixed ID. The file itself gets a `cfile_` prefixed ID.
|
||||
|
||||
These container files **cannot** be downloaded using the standard Files API (`GetOpenAIFileClient`), which returns 404 for `cfile_` IDs. Instead, you must use the **Containers API** (`GetContainerClient`) to download them:
|
||||
|
||||
```csharp
|
||||
// ❌ This does NOT work for container files
|
||||
var filesClient = openAIClient.GetOpenAIFileClient();
|
||||
await filesClient.DownloadFileAsync("cfile_..."); // Returns 404
|
||||
|
||||
// ✅ Use ContainerClient instead
|
||||
var containerClient = openAIClient.GetContainerClient();
|
||||
await containerClient.DownloadContainerFileAsync("cntr_...", "cfile_...");
|
||||
```
|
||||
|
||||
The container ID and file ID are available from the `ContainerFileCitationMessageAnnotation` annotation in the response, accessible via `CitationAnnotation.RawRepresentation`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- OpenAI API key with access to a model that supports Code Interpreter
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:OPENAI_API_KEY="sk-..."
|
||||
$env:OPENAI_CHAT_MODEL_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Code Interpreter File Download with Foundry](../../../02-agents/AgentsWithFoundry/Agent_Step24_CodeInterpreterFileDownload/) — same scenario using Microsoft Foundry
|
||||
- [Code Interpreter](../../../02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/) — Code Interpreter without file download
|
||||
Reference in New Issue
Block a user