Skip to content

Commit f7df8d4

Browse files
Merge pull request #6412 from aahill/aug-fixes
updating csharp code
2 parents d7152dd + 68fcad6 commit f7df8d4

File tree

1 file changed

+106
-57
lines changed

1 file changed

+106
-57
lines changed

articles/ai-foundry/agents/how-to/tools/code-interpreter-samples.md

Lines changed: 106 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -146,112 +146,161 @@ This ensures proper resource management and prevents unnecessary resource consum
146146

147147
:::zone pivot="csharp"
148148

149-
## Create a client and agent
149+
## Create a project client
150150

151-
First, set up the configuration using `appsettings.json`, create a `PersistentAgentsClient`, and then create a `PersistentAgent` with the Code Interpreter tool enabled.
151+
Create a client object, which will contain the project endpoint for connecting to your AI project and other resources.
152152

153153
```csharp
154154
using Azure;
155155
using Azure.AI.Agents.Persistent;
156156
using Azure.Identity;
157-
using Microsoft.Extensions.Configuration;
158-
using System.Diagnostics;
159157

160-
IConfigurationRoot configuration = new ConfigurationBuilder()
161-
.SetBasePath(AppContext.BaseDirectory)
162-
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
163-
.Build();
158+
var projectEndpoint = System.Environment.GetEnvironmentVariable("ProjectEndpoint");
159+
var projectEndpoint = System.Environment.GetEnvironmentVariable("ModelDeploymentName");
160+
var projectEndpoint = System.Environment.GetEnvironmentVariable("BingConnectionId");
164161

165-
var projectEndpoint = configuration["ProjectEndpoint"];
166-
var modelDeploymentName = configuration["ModelDeploymentName"];
162+
// Create the Agent Client
163+
PersistentAgentsClient agentClient = new(projectEndpoint, new DefaultAzureCredential());
164+
```
165+
166+
## Create an Agent with the Grounding with Bing search tool enabled
167167

168-
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
168+
To make the Grounding with Bing search tool available to your agent, use a connection to initialize the tool and attach it to the agent. You can find your connection in the **connected resources** section of your project in the [Azure AI Foundry portal](https://ai.azure.com/?cid=learnDocs).
169169

170-
PersistentAgent agent = client.Administration.CreateAgent(
170+
```csharp
171+
172+
BingGroundingToolDefinition bingGroundingTool = new(
173+
new BingGroundingSearchToolParameters(
174+
[new BingGroundingSearchConfiguration(bingConnectionId)]
175+
)
176+
);
177+
178+
// Create the Agent
179+
PersistentAgent agent = agentClient.Administration.CreateAgent(
171180
model: modelDeploymentName,
172-
name: "My Friendly Test Agent",
173-
instructions: "You politely help with math questions. Use the code interpreter tool when asked to visualize numbers.",
174-
tools: [new CodeInterpreterToolDefinition()]
181+
name: "my-agent",
182+
instructions: "Use the bing grounding tool to answer questions.",
183+
tools: [bingGroundingTool]
175184
);
176185
```
177186

178-
## Create a thread and add a message
179-
180-
Next, create a `PersistentAgentThread` for the conversation and add the initial user message.
187+
## Create a thread and run
181188

182189
```csharp
183-
PersistentAgentThread thread = client.Threads.CreateThread();
190+
PersistentAgentThread thread = agentClient.Threads.CreateThread();
184191

185-
client.Messages.CreateMessage(
192+
// Create message and run the agent
193+
PersistentThreadMessage message = agentClient.Messages.CreateMessage(
186194
thread.Id,
187195
MessageRole.User,
188-
"Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9.");
196+
"How does wikipedia explain Euler's Identity?");
197+
ThreadRun run = agentClient.Runs.CreateRun(thread, agent);
198+
189199
```
190200

191-
## Create and monitor a run
201+
## Wait for the agent to complete and print the output
192202

193-
Then, create a `ThreadRun` for the thread and agent. Poll the run's status until it completes or requires action.
203+
First, wait for the agent to complete the run by polling its status. Observe that the model uses the Grounding with Bing Search tool to provide a response to the user's question.
194204

195205
```csharp
196-
ThreadRun run = client.Runs.CreateRun(
197-
thread.Id,
198-
agent.Id,
199-
additionalInstructions: "Please address the user as Jane Doe. The user has a premium account.");
200-
206+
// Wait for the agent to finish running
201207
do
202208
{
203209
Thread.Sleep(TimeSpan.FromMilliseconds(500));
204-
run = client.Runs.GetRun(thread.Id, run.Id);
210+
run = agentClient.Runs.GetRun(thread.Id, run.Id);
205211
}
206212
while (run.Status == RunStatus.Queued
207-
|| run.Status == RunStatus.InProgress
208-
|| run.Status == RunStatus.RequiresAction);
209-
```
213+
|| run.Status == RunStatus.InProgress);
210214

211-
## Process the results and handle files
215+
// Confirm that the run completed successfully
216+
if (run.Status != RunStatus.Completed)
217+
{
218+
throw new Exception("Run did not complete successfully, error: " + run.LastError?.Message);
219+
}
220+
```
212221

213-
Once the run is finished, retrieve all messages from the thread. Iterate through the messages to display text content and handle any generated image files by saving them locally and opening them.
222+
Then, retrieve and process the messages from the completed run.
214223

215224
```csharp
216-
Pageable<PersistentThreadMessage> messages = client.Messages.GetMessages(
225+
// Retrieve all messages from the agent client
226+
Pageable<PersistentThreadMessage> messages = agentClient.Messages.GetMessages(
217227
threadId: thread.Id,
218-
order: ListSortOrder.Ascending);
228+
order: ListSortOrder.Ascending
229+
);
219230

231+
// Process messages in order
220232
foreach (PersistentThreadMessage threadMessage in messages)
221233
{
222-
foreach (MessageContent content in threadMessage.ContentItems)
234+
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
235+
foreach (MessageContent contentItem in threadMessage.ContentItems)
223236
{
224-
switch (content)
237+
if (contentItem is MessageTextContent textItem)
225238
{
226-
case MessageTextContent textItem:
227-
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
228-
break;
229-
case MessageImageFileContent imageFileContent:
230-
Console.WriteLine($"[{threadMessage.Role}]: Image content file ID = {imageFileContent.FileId}");
231-
BinaryData imageContent = client.Files.GetFileContent(imageFileContent.FileId);
232-
string tempFilePath = Path.Combine(AppContext.BaseDirectory, $"{Guid.NewGuid()}.png");
233-
File.WriteAllBytes(tempFilePath, imageContent.ToArray());
234-
client.Files.DeleteFile(imageFileContent.FileId);
235-
236-
ProcessStartInfo psi = new()
239+
string response = textItem.Text;
240+
241+
// If we have Text URL citation annotations, reformat the response to show title & URL for citations
242+
if (textItem.Annotations != null)
243+
{
244+
foreach (MessageTextAnnotation annotation in textItem.Annotations)
237245
{
238-
FileName = tempFilePath,
239-
UseShellExecute = true
240-
};
241-
Process.Start(psi);
242-
break;
246+
if (annotation is MessageTextUriCitationAnnotation urlAnnotation)
247+
{
248+
response = response.Replace(urlAnnotation.Text, $" [{urlAnnotation.UriCitation.Title}]({urlAnnotation.UriCitation.Uri})");
249+
}
250+
}
251+
}
252+
Console.Write($"Agent response: {response}");
253+
}
254+
else if (contentItem is MessageImageFileContent imageFileItem)
255+
{
256+
Console.Write($"<image from ID: {imageFileItem.FileId}");
243257
}
258+
Console.WriteLine();
244259
}
245260
}
261+
262+
```
263+
264+
## Optionally output the run steps used by the agent
265+
266+
```csharp
267+
// Retrieve the run steps used by the agent and print those to the console
268+
Console.WriteLine("Run Steps used by Agent:");
269+
Pageable<RunStep> runSteps = agentClient.Runs.GetRunSteps(run);
270+
271+
foreach (var step in runSteps)
272+
{
273+
Console.WriteLine($"Step ID: {step.Id}, Total Tokens: {step.Usage.TotalTokens}, Status: {step.Status}, Type: {step.Type}");
274+
275+
if (step.StepDetails is RunStepMessageCreationDetails messageCreationDetails)
276+
{
277+
Console.WriteLine($" Message Creation Id: {messageCreationDetails.MessageCreation.MessageId}");
278+
}
279+
else if (step.StepDetails is RunStepToolCallDetails toolCallDetails)
280+
{
281+
// We know this agent only has the Bing Grounding tool, so we can cast it directly
282+
foreach (RunStepBingGroundingToolCall toolCall in toolCallDetails.ToolCalls)
283+
{
284+
Console.WriteLine($" Tool Call Details: {toolCall.GetType()}");
285+
286+
foreach (var result in toolCall.BingGrounding)
287+
{
288+
Console.WriteLine($" {result.Key}: {result.Value}");
289+
}
290+
}
291+
}
292+
}
293+
246294
```
247295

248296
## Clean up resources
249297

250-
Finally, delete the thread and the agent to clean up the resources created in this sample.
298+
Clean up the resources from this sample.
251299

252300
```csharp
253-
client.Threads.DeleteThread(threadId: thread.Id);
254-
client.Administration.DeleteAgent(agentId: agent.Id);
301+
// Delete thread and agent
302+
agentClient.Threads.DeleteThread(threadId: thread.Id);
303+
agentClient.Administration.DeleteAgent(agentId: agent.Id);
255304
```
256305

257306
:::zone-end

0 commit comments

Comments
 (0)