@@ -144,125 +144,203 @@ for image_content in messages.image_contents:
144
144
145
145
:::zone pivot="csharp"
146
146
147
- ## Create a project client
147
+ ## Using the .NET SDK
148
148
149
- To use code interpreter, first you need to create a project client, which will contain a connection string to your AI project, and will be used to authenticate API calls.
149
+ In this example we will demonstrate the Agent streaming support, code interpreter creating an image and downloading and viewing the image.
150
+
151
+ 1 . First, we set up configuration using ` appsettings.json ` , create a ` PersistentAgentsClient ` , and then create a ` PersistentAgent ` with the Code Interpreter tool.
150
152
151
153
``` csharp
152
- var connectionString = Environment .GetEnvironmentVariable (" PROJECT_CONNECTION_STRING" );
153
- AgentsClient client = new AgentsClient (connectionString , new DefaultAzureCredential ());
154
+ using Azure ;
155
+ using Azure .AI .Agents .Persistent ;
156
+ using Azure .Identity ;
157
+ using Microsoft .Extensions .Configuration ;
158
+ using System .Diagnostics ;
159
+
160
+ IConfigurationRoot configuration = new ConfigurationBuilder ()
161
+ .SetBasePath (AppContext .BaseDirectory )
162
+ .AddJsonFile (" appsettings.json" , optional : false , reloadOnChange : true )
163
+ .Build ();
164
+
165
+ var projectEndpoint = configuration [" ProjectEndpoint" ];
166
+ var modelDeploymentName = configuration [" ModelDeploymentName" ];
167
+
168
+ PersistentAgentsClient client = new (projectEndpoint , new DefaultAzureCredential ());
154
169
```
155
170
156
- ## Upload a File
171
+ Synchronous sample:
157
172
158
- Files can be uploaded and then referenced by agents or messages. First, use the generalized upload API with a ` purpose ` of ` Agents ` to make a file ID available. Once uploaded, the file ID can then be provided to create a vector store for it. The vector store ID can then be provided to an agent upon creation.
173
+ ``` csharp
174
+ PersistentAgent agent = client .Administration .CreateAgent (
175
+ model : modelDeploymentName ,
176
+ name : " My Friendly Test Agent" ,
177
+ instructions : " You politely help with math questions. Use the code interpreter tool when asked to visualize numbers." ,
178
+ tools : [new CodeInterpreterToolDefinition ()]
179
+ );
180
+ ```
181
+
182
+ Asynchronous sample:
159
183
160
184
``` csharp
161
- // Upload a file and wait for it to be processed
162
- Response < AgentFile > uploadAgentFileResponse = await client .UploadFileAsync (
163
- filePath : " sample_file_for_upload.txt" ,
164
- purpose : AgentFilePurpose .Agents );
185
+ PersistentAgent agent = await client .Administration .CreateAgentAsync (
186
+ model : modelDeploymentName ,
187
+ name : " My Friendly Test Agent" ,
188
+ instructions : " You politely help with math questions. Use the code interpreter tool when asked to visualize numbers." ,
189
+ tools : [new CodeInterpreterToolDefinition ()]
190
+ );
191
+ ```
192
+
193
+ 2 . Next, we create a ` PersistentAgentThread ` and add a user message to it.
165
194
166
- AgentFile uploadedAgentFile = uploadAgentFileResponse . Value ;
195
+ Synchronous sample:
167
196
168
- // Create a vector store with the file and wait for it to be processed.
169
- // If you do not specify a vector store, create_message will create a vector store with a default expiration policy of seven days after they were last active
170
- VectorStore vectorStore = await client .CreateVectorStoreAsync (
171
- fileIds : new List <string > { uploadedAgentFile .Id },
172
- name : " my_vector_store" );
197
+ ``` csharp
198
+ PersistentAgentThread thread = client .Threads .CreateThread ();
173
199
174
- CodeInterpreterToolResource codeInterpreterToolResource = new CodeInterpreterToolResource ();
175
- CodeInterpreterToolResource .VectorStoreIds .Add (vectorStore .Id );
200
+ client .Messages .CreateMessage (
201
+ thread .Id ,
202
+ MessageRole .User ,
203
+ " Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9." );
176
204
```
177
205
178
- ## Create an Agent with the Code Interpreter Tool
206
+ Asynchronous sample:
179
207
180
208
``` csharp
181
- Response < Agent > agentResponse = await client .CreateAgentAsync (
182
- model : " gpt-4o-mini" ,
183
- name : " My agent" ,
184
- instructions : " You are a helpful agent." ,
185
- tools : new List <ToolDefinition > { new CodeInterpreterToolDefinition () },
186
- toolResources : new ToolResources () { CodeInterpreter = codeInterpreterToolResource });
187
- Agent agent = agentResponse .Value ;
209
+ PersistentAgentThread thread = await client .Threads .CreateThreadAsync ();
210
+
211
+ await client .Messages .CreateMessageAsync (
212
+ thread .Id ,
213
+ MessageRole .User ,
214
+ " Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9." );
188
215
```
189
216
190
- ## Create a Thread, Message, and Get the Agent Response
217
+ 3 . Then, we create a ` ThreadRun ` for the thread and agent, providing any additional instructions. We poll the run's status until it is no longer queued, in progress, or requires action.
191
218
192
- Next create a thread with ` CreateThreadAsync() ` and a thread with ` CreateMessageAsync() ` . After the thread is created, you can add messages to it with ` CreateMessageAsync() ` that will cause the code interpreter tool to trigger. Create a run, and then continue polling it until it reaches a terminal status. Assuming the run was successful, parse the agent's response by listing the messages.
219
+ Synchronous sample:
193
220
194
221
``` csharp
195
- // Create a thread
196
- Response < AgentThread > threadResponse = await client .CreateThreadAsync ();
197
- AgentThread thread = threadResponse .Value ;
198
-
199
- // With a thread created, messages can be created on it:
200
- Response < ThreadMessage > messageResponse = await client .CreateMessageAsync (
222
+ ThreadRun run = client .Runs .CreateRun (
201
223
thread .Id ,
202
- MessageRole .User ,
203
- " I need to solve the equation `3x + 11 = 14`. Can you help me?" );
204
- ThreadMessage message = messageResponse .Value ;
224
+ agent .Id ,
225
+ additionalInstructions : " Please address the user as Jane Doe. The user has a premium account." );
205
226
206
- // A run can then be started that evaluates the thread against an agent:
207
- Response < ThreadRun > runResponse = await client .CreateRunAsync (
227
+ do
228
+ {
229
+ Thread .Sleep (TimeSpan .FromMilliseconds (500 ));
230
+ run = client .Runs .GetRun (thread .Id , run .Id );
231
+ }
232
+ while (run .Status == RunStatus .Queued
233
+ || run .Status == RunStatus .InProgress
234
+ || run .Status == RunStatus .RequiresAction );
235
+ ```
236
+
237
+ Asynchronous sample:
238
+
239
+ ``` csharp
240
+ ThreadRun run = await client .Runs .CreateRunAsync (
208
241
thread .Id ,
209
242
agent .Id ,
210
243
additionalInstructions : " Please address the user as Jane Doe. The user has a premium account." );
211
- ThreadRun run = runResponse .Value ;
212
244
213
- // Once the run has started, it should then be polled until it reaches a terminal status:
214
245
do
215
246
{
216
247
await Task .Delay (TimeSpan .FromMilliseconds (500 ));
217
- runResponse = await client .GetRunAsync (thread .Id , runResponse . Value .Id );
248
+ run = await client .Runs . GetRunAsync (thread .Id , run .Id );
218
249
}
219
- while (runResponse .Value .Status == RunStatus .Queued
220
- || runResponse .Value .Status == RunStatus .InProgress );
250
+ while (run .Status == RunStatus .Queued
251
+ || run .Status == RunStatus .InProgress
252
+ || run .Status == RunStatus .RequiresAction );
253
+ ```
254
+
255
+ 4 . Once the run is finished, we retrieve all messages from the thread. We then iterate through the messages to display text content and handle any image files by saving them locally and opening them.
221
256
222
- // Assuming the run successfully completed, listing messages from the thread that was run will now reflect new information added by the agent :
257
+ Synchronous sample :
223
258
224
- Response < PageableList < ThreadMessage >> afterRunMessagesResponse
225
- = await client .GetMessagesAsync (thread .Id );
226
- IReadOnlyList < ThreadMessage > messages = afterRunMessagesResponse .Value .Data ;
259
+ ``` csharp
260
+ Pageable < ThreadMessage > messages = client .Messages .GetMessages (
261
+ threadId : thread .Id ,
262
+ order : ListSortOrder .Ascending );
227
263
228
- // Note: messages iterate from newest to oldest, with the messages[0] being the most recent
229
264
foreach (ThreadMessage threadMessage in messages )
230
265
{
231
- Console .Write ($" {threadMessage .CreatedAt : yyyy - MM - dd HH : mm : ss } - {threadMessage .Role ,10 }: " );
232
- foreach (MessageContent contentItem in threadMessage .ContentItems )
266
+ foreach (MessageContent content in threadMessage .ContentItems )
233
267
{
234
- if (contentItem is MessageTextContent textItem )
235
- {
236
- Console .Write (textItem .Text );
237
- }
238
- else if (contentItem is MessageImageFileContent imageFileItem )
268
+ switch (content )
239
269
{
240
- Console .Write ($" <image from ID: {imageFileItem .FileId }" );
270
+ case MessageTextContent textItem :
271
+ Console .WriteLine ($" [{threadMessage .Role }]: {textItem .Text }" );
272
+ break ;
273
+ case MessageImageFileContent imageFileContent :
274
+ Console .WriteLine ($" [{threadMessage .Role }]: Image content file ID = {imageFileContent .FileId }" );
275
+ BinaryData imageContent = client .Files .GetFileContent (imageFileContent .FileId );
276
+ string tempFilePath = Path .Combine (AppContext .BaseDirectory , $" {Guid .NewGuid ()}.png" );
277
+ File .WriteAllBytes (tempFilePath , imageContent .ToArray ());
278
+ client .Files .DeleteFile (imageFileContent .FileId );
279
+
280
+ ProcessStartInfo psi = new ()
281
+ {
282
+ FileName = tempFilePath ,
283
+ UseShellExecute = true
284
+ };
285
+ Process .Start (psi );
286
+ break ;
241
287
}
242
- Console .WriteLine ();
243
288
}
244
289
}
245
290
```
246
291
247
- ## Download Files Generated by Code Interpreter
248
-
249
- Files generated by code interpreter can be found in the Agent message responses. You can download image files generated by code interpreter by iterating through the response's messages and checking for an ` ImageFileId ` . If that field exists, use the following code:
292
+ Asynchronous sample:
250
293
251
294
``` csharp
252
- foreach (MessageContent contentItem in message .Content )
295
+ AsyncPageable < ThreadMessage > messages = client .Messages .GetMessagesAsync (
296
+ threadId : thread .Id ,
297
+ order : ListSortOrder .Ascending );
298
+
299
+ await foreach (ThreadMessage threadMessage in messages )
253
300
{
254
- if ( ! string . IsNullOrEmpty ( contentItem . ImageFileId ) )
301
+ foreach ( MessageContent content in threadMessage . ContentItems )
255
302
{
256
- OpenAIFileInfo imageInfo = await fileClient .GetFileAsync (contentItem .ImageFileId );
257
- BinaryData imageBytes = await fileClient .DownloadFileAsync (contentItem .ImageFileId );
258
- using FileStream stream = File .OpenWrite ($" {imageInfo .Filename }.png" );
259
- imageBytes .ToStream ().CopyTo (stream );
260
-
261
- Console .WriteLine ($" <image: {imageInfo .Filename }.png>" );
303
+ switch (content )
304
+ {
305
+ case MessageTextContent textItem :
306
+ Console .WriteLine ($" [{threadMessage .Role }]: {textItem .Text }" );
307
+ break ;
308
+ case MessageImageFileContent imageFileContent :
309
+ Console .WriteLine ($" [{threadMessage .Role }]: Image content file ID = {imageFileContent .FileId }" );
310
+ BinaryData imageContent = await client .Files .GetFileContentAsync (imageFileContent .FileId );
311
+ string tempFilePath = Path .Combine (AppContext .BaseDirectory , $" {Guid .NewGuid ()}.png" );
312
+ File .WriteAllBytes (tempFilePath , imageContent .ToArray ());
313
+ await client .Files .DeleteFileAsync (imageFileContent .FileId );
314
+
315
+ ProcessStartInfo psi = new ()
316
+ {
317
+ FileName = tempFilePath ,
318
+ UseShellExecute = true
319
+ };
320
+ Process .Start (psi );
321
+ break ;
322
+ }
262
323
}
263
324
}
264
325
```
265
326
327
+ 5 . Finally, we delete the thread and the agent to clean up the resources created in this sample.
328
+
329
+ Synchronous sample:
330
+
331
+ ``` csharp
332
+ client .Threads .DeleteThread (threadId : thread .Id );
333
+ client .Administration .DeleteAgent (agentId : agent .Id );
334
+ ```
335
+
336
+ Asynchronous sample:
337
+
338
+ ``` csharp
339
+ await client .Threads .DeleteThreadAsync (threadId : thread .Id );
340
+ await client .Administration .DeleteAgentAsync (agentId : agent .Id );
341
+ ```
342
+
343
+
266
344
::: zone-end
267
345
268
346
:::zone pivot="javascript"
@@ -470,4 +548,4 @@ curl $AZURE_AI_AGENTS_ENDPOINT/threads/thread_abc123/messages?api-version=2024-1
470
548
- H " Authorization: Bearer $AZURE_AI_AGENTS_TOKEN"
471
549
` ` `
472
550
473
- :::zone-end
551
+ :::zone-end
0 commit comments