Skip to content

Commit 617f23a

Browse files
committed
Update dotnet sample code
1 parent dbcf8c7 commit 617f23a

File tree

1 file changed

+145
-89
lines changed

1 file changed

+145
-89
lines changed

articles/ai-services/openai/includes/assistants-csharp.md

Lines changed: 145 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ author: aapowell
77
ms.author: aapowell
88
ms.service: azure-ai-openai
99
ms.topic: include
10-
ms.date: 03/05/2024
10+
ms.date: 9/27/2024
1111
---
1212

1313
[Reference documentation](/dotnet/api/overview/azure/ai.openai.assistants-readme?context=/azure/ai-services/openai/context/context) | [Source code](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/openai/Azure.AI.OpenAI/src) | [Package (NuGet)](https://www.nuget.org/packages/Azure.AI.OpenAI/)
@@ -24,124 +24,180 @@ ms.date: 03/05/2024
2424

2525
### Create a new .NET Core application
2626

27-
In a console window (such as cmd, PowerShell, or Bash), use the `dotnet new` command to create a new console app with the name `azure-openai-quickstart`. This command creates a simple "Hello World" project with a single C# source file: *Program.cs*.
27+
1. In a console window (such as cmd, PowerShell, or Bash), use the `dotnet new` command to create a new console app with the name `azure-openai-quickstart`. This command creates a simple "Hello World" project with a single C# source file: *Program.cs*.
28+
29+
```dotnetcli
30+
dotnet new console -n azure-openai-assistants-quickstart
31+
```
2832
29-
```dotnetcli
30-
dotnet new console -n azure-openai-assistants-quickstart
31-
```
32-
33-
Change your directory to the newly created app folder. You can build the application with:
33+
2. Change your directory to the newly created app folder. You can build the application with:
3434
35-
```dotnetcli
36-
dotnet build
37-
```
35+
```dotnetcli
36+
dotnet build
37+
```
3838
39-
The build output should contain no warnings or errors.
39+
The build output should contain no warnings or errors.
40+
41+
```output
42+
...
43+
Build succeeded.
44+
0 Warning(s)
45+
0 Error(s)
46+
...
47+
```
4048
41-
```output
42-
...
43-
Build succeeded.
44-
0 Warning(s)
45-
0 Error(s)
46-
...
47-
```
49+
3. Install the OpenAI .NET client library with:
4850
49-
Install the OpenAI .NET client library with:
50-
51-
```console
52-
dotnet add package Azure.AI.OpenAI.Assistants --prerelease
53-
```
51+
```console
52+
dotnet add package Azure.AI.OpenAI.Assistants --prerelease
53+
```
5454
5555
[!INCLUDE [get-key-endpoint](get-key-endpoint.md)]
5656
5757
[!INCLUDE [environment-variables](environment-variables.md)]
5858
59-
## Create an assistant
60-
61-
In our code we are going to specify the following values:
62-
63-
| **Name** | **Description** |
64-
|:---|:---|
65-
| **Assistant name** | Your deployment name that is associated with a specific model. |
66-
| **Instructions** | Instructions are similar to system messages this is where you give the model guidance about how it should behave and any context it should reference when generating a response. You can describe the assistant's personality, tell it what it should and shouldn't answer, and tell it how to format responses. You can also provide examples of the steps it should take when answering responses. |
67-
| **Model** | This is where you set which model deployment name to use with your assistant. The retrieval tool requires `gpt-35-turbo (1106)` or `gpt-4 (1106-preview)` model. **Set this value to your deployment name, not the model name unless it is the same.** |
68-
| **Code interpreter** | Code interpreter provides access to a sandboxed Python environment that can be used to allow the model to test and execute code. |
69-
70-
### Tools
71-
72-
An individual assistant can access up to 128 tools including `code interpreter`, as well as any custom tools you create via [functions](../how-to/assistant-functions.md).
59+
### Create the assistant
7360
7461
Create and run an assistant with the following:
7562
7663
```csharp
7764
using Azure;
7865
using Azure.AI.OpenAI.Assistants;
7966
80-
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new ArgumentNullException("AZURE_OPENAI_ENDPOINT");
81-
string key = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? throw new ArgumentNullException("AZURE_OPENAI_API_KEY");
82-
AssistantsClient client = new AssistantsClient(new Uri(endpoint), new AzureKeyCredential(key));
83-
84-
// Create an assistant
85-
Assistant assistant = await client.CreateAssistantAsync(
86-
new AssistantCreationOptions("gpt-4-1106-preview") // Replace this with the name of your model deployment
67+
// Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning.
68+
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
69+
string key = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");
70+
71+
var openAIClient = new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(key));
72+
73+
// Use for passwordless auth
74+
//var openAIClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential());
75+
76+
FileClient fileClient = openAIClient.GetFileClient();
77+
AssistantClient assistantClient = openAIClient.GetAssistantClient();
78+
79+
// First, let's contrive a document we'll use retrieval with and upload it.
80+
using Stream document = BinaryData.FromString("""
81+
{
82+
"description": "This document contains the sale history data for Contoso products.",
83+
"sales": [
84+
{
85+
"month": "January",
86+
"by_product": {
87+
"113043": 15,
88+
"113045": 12,
89+
"113049": 2
90+
}
91+
},
92+
{
93+
"month": "February",
94+
"by_product": {
95+
"113045": 22
96+
}
97+
},
98+
{
99+
"month": "March",
100+
"by_product": {
101+
"113045": 16,
102+
"113055": 5
103+
}
104+
}
105+
]
106+
}
107+
""").ToStream();
108+
109+
OpenAIFileInfo salesFile = await fileClient.UploadFileAsync(
110+
document,
111+
"monthly_sales.json",
112+
FileUploadPurpose.Assistants);
113+
114+
// Now, we'll create a client intended to help with that data
115+
AssistantCreationOptions assistantOptions = new()
116+
{
117+
Name = "Example: Contoso sales RAG",
118+
Instructions =
119+
"You are an assistant that looks up sales data and helps visualize the information based"
120+
+ " on user queries. When asked to generate a graph, chart, or other visualization, use"
121+
+ " the code interpreter tool to do so.",
122+
Tools =
123+
{
124+
new FileSearchToolDefinition(),
125+
new CodeInterpreterToolDefinition(),
126+
},
127+
ToolResources = new()
87128
{
88-
Name = "Math Tutor",
89-
Instructions = "You are a personal math tutor. Write and run code to answer math questions.",
90-
Tools = { new CodeInterpreterToolDefinition() }
91-
});
92-
93-
// Create a thread
94-
AssistantThread thread = await client.CreateThreadAsync();
95-
96-
// Add a user question to the thread
97-
ThreadMessage message = await client.CreateMessageAsync(
98-
thread.Id,
99-
MessageRole.User,
100-
"I need to solve the equation `3x + 11 = 14`. Can you help me?");
101-
102-
// Run the thread
103-
ThreadRun run = await client.CreateRunAsync(
104-
thread.Id,
105-
new CreateRunOptions(assistant.Id)
106-
);
107-
108-
// Wait for the assistant to respond
129+
FileSearch = new()
130+
{
131+
NewVectorStores =
132+
{
133+
new VectorStoreCreationHelper([salesFile.Id]),
134+
}
135+
}
136+
},
137+
};
138+
139+
Assistant assistant = await assistantClient.CreateAssistantAsync(deploymentName, assistantOptions);
140+
141+
// Now we'll create a thread with a user query about the data already associated with the assistant, then run it
142+
ThreadCreationOptions threadOptions = new()
143+
{
144+
InitialMessages = { "How well did product 113045 sell in February? Graph its trend over time." }
145+
};
146+
147+
ThreadRun threadRun = await assistantClient.CreateThreadAndRunAsync(assistant.Id, threadOptions);
148+
149+
// Check back to see when the run is done
109150
do
110151
{
111-
await Task.Delay(TimeSpan.FromMilliseconds(500));
112-
run = await client.GetRunAsync(thread.Id, run.Id);
113-
}
114-
while (run.Status == RunStatus.Queued
115-
|| run.Status == RunStatus.InProgress);
152+
Thread.Sleep(TimeSpan.FromSeconds(1));
153+
threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id);
154+
} while (!threadRun.Status.IsTerminal);
116155
117-
// Get the messages
118-
PageableList<ThreadMessage> messagesPage = await client.GetMessagesAsync(thread.Id);
119-
IReadOnlyList<ThreadMessage> messages = messagesPage.Data;
156+
// Finally, we'll print out the full history for the thread that includes the augmented generation
157+
AsyncCollectionResult<ThreadMessage> messages
158+
= assistantClient.GetMessagesAsync(threadRun.ThreadId, new MessageCollectionOptions() { Order = MessageCollectionOrder.Ascending });
120159
121-
// Note: messages iterate from newest to oldest, with the messages[0] being the most recent
122-
foreach (ThreadMessage threadMessage in messages.Reverse())
160+
await foreach (ThreadMessage message in messages)
123161
{
124-
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
125-
foreach (MessageContent contentItem in threadMessage.ContentItems)
162+
Console.Write($"[{message.Role.ToString().ToUpper()}]: ");
163+
foreach (MessageContent contentItem in message.Content)
126164
{
127-
if (contentItem is MessageTextContent textItem)
165+
if (!string.IsNullOrEmpty(contentItem.Text))
166+
{
167+
Console.WriteLine($"{contentItem.Text}");
168+
169+
if (contentItem.TextAnnotations.Count > 0)
170+
{
171+
Console.WriteLine();
172+
}
173+
174+
// Include annotations, if any.
175+
foreach (TextAnnotation annotation in contentItem.TextAnnotations)
176+
{
177+
if (!string.IsNullOrEmpty(annotation.InputFileId))
178+
{
179+
Console.WriteLine($"* File citation, file ID: {annotation.InputFileId}");
180+
}
181+
if (!string.IsNullOrEmpty(annotation.OutputFileId))
182+
{
183+
Console.WriteLine($"* File output, new file ID: {annotation.OutputFileId}");
184+
}
185+
}
186+
}
187+
if (!string.IsNullOrEmpty(contentItem.ImageFileId))
128188
{
129-
Console.Write(textItem.Text);
189+
OpenAIFileInfo imageInfo = await fileClient.GetFileAsync(contentItem.ImageFileId);
190+
BinaryData imageBytes = await fileClient.DownloadFileAsync(contentItem.ImageFileId);
191+
using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png");
192+
imageBytes.ToStream().CopyTo(stream);
193+
194+
Console.WriteLine($"<image: {imageInfo.Filename}.png>");
130195
}
131-
Console.WriteLine();
132196
}
197+
Console.WriteLine();
133198
}
134199
```
135200

136-
This will print an output as follows:
137-
138-
```
139-
2024-03-05 03:38:17 - user: I need to solve the equation `3x + 11 = 14`. Can you help me?
140-
2024-03-05 03:38:25 - assistant: The solution to the equation \(3x + 11 = 14\) is \(x = 1\).
141-
```
142-
143-
New messages can be created on the thread before re-running, which will see the assistant use the past messages as context within the thread.
144-
145201
## Clean up resources
146202

147203
If you want to clean up and remove an Azure OpenAI resource, you can delete the resource or resource group. Deleting the resource group also deletes any other resources associated with it.

0 commit comments

Comments
 (0)