Skip to content

Commit 29902c8

Browse files
authored
Merge pull request #653 from MicrosoftDocs/main
10/4/2024 AM Publish
2 parents 470c81c + a6f5c47 commit 29902c8

File tree

8 files changed

+476
-126
lines changed

8 files changed

+476
-126
lines changed

articles/ai-services/openai/gpt-v-quickstart.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ Get started using GPT-4 Turbo with images with the Azure OpenAI Service.
4545

4646
::: zone-end
4747

48+
::: zone pivot="programming-language-dotnet"
49+
50+
[!INCLUDE [.NET quickstart](includes/gpt-v-dotnet.md)]
51+
52+
::: zone-end
53+
4854
## Next steps
4955

5056
* Learn more about these APIs in the [GPT-4 Turbo with Vision how-to guide](./gpt-v-quickstart.md)

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

Lines changed: 175 additions & 82 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,123 +24,216 @@ 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`](/dotnet/core/tools/dotnet-new) command to create a new console app with the name `azure-openai-quickstart`:
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 into the directory of the newly created app folder and build the app with the [`dotnet build`](/dotnet/core/tools/dotnet-build) command:
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](https://www.nuget.org/packages/Azure.AI.OpenAI/) with the [dotnet add package](/dotnet/core/tools/dotnet-add-package) command:
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 --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
59+
### Passwordless authentication is recommended
60+
61+
Passwordless authentication is more secure than key-based alternatives and is the recommended approach for connecting to Azure services. If you choose Passwordless authentication, you'll need to complete the following:
6062
61-
In our code we are going to specify the following values:
63+
1. Add the [`Azure.Identity`](https://www.nuget.org/packages/Azure.Identity) package.
6264
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. |
65+
```dotnetcli
66+
dotnet add package Azure.Identity
67+
```
6968
70-
### Tools
69+
1. Assign the `Cognitive Services User` role to your user account. This can be done in the Azure portal on your OpenAI resource under **Access control (IAM)** > **Add role assignment**.
70+
1. Sign-in to Azure using Visual Studio or the Azure CLI via `az login`.
7171
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).
72+
### Create the assistant
7373
74-
Create and run an assistant with the following:
74+
Update the `Program.cs` file with the following code to create an assistant:
7575
7676
```csharp
7777
using Azure;
7878
using Azure.AI.OpenAI.Assistants;
7979
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
80+
// Assistants is a beta API and subject to change
81+
// Acknowledge its experimental status by suppressing the matching warning.
82+
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
83+
string key = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");
84+
85+
var openAIClient = new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(key));
86+
87+
// Use for passwordless auth
88+
//var openAIClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential());
89+
90+
FileClient fileClient = openAIClient.GetFileClient();
91+
AssistantClient assistantClient = openAIClient.GetAssistantClient();
92+
93+
// First, let's contrive a document we'll use retrieval with and upload it.
94+
using Stream document = BinaryData.FromString("""
95+
{
96+
"description": "This document contains the sale history data for Contoso products.",
97+
"sales": [
98+
{
99+
"month": "January",
100+
"by_product": {
101+
"113043": 15,
102+
"113045": 12,
103+
"113049": 2
104+
}
105+
},
106+
{
107+
"month": "February",
108+
"by_product": {
109+
"113045": 22
110+
}
111+
},
112+
{
113+
"month": "March",
114+
"by_product": {
115+
"113045": 16,
116+
"113055": 5
117+
}
118+
}
119+
]
120+
}
121+
""").ToStream();
122+
123+
OpenAIFileInfo salesFile = await fileClient.UploadFileAsync(
124+
document,
125+
"monthly_sales.json",
126+
FileUploadPurpose.Assistants);
127+
128+
// Now, we'll create a client intended to help with that data
129+
AssistantCreationOptions assistantOptions = new()
130+
{
131+
Name = "Example: Contoso sales RAG",
132+
Instructions =
133+
"You are an assistant that looks up sales data and helps visualize the information based"
134+
+ " on user queries. When asked to generate a graph, chart, or other visualization, use"
135+
+ " the code interpreter tool to do so.",
136+
Tools =
137+
{
138+
new FileSearchToolDefinition(),
139+
new CodeInterpreterToolDefinition(),
140+
},
141+
ToolResources = new()
87142
{
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
143+
FileSearch = new()
144+
{
145+
NewVectorStores =
146+
{
147+
new VectorStoreCreationHelper([salesFile.Id]),
148+
}
149+
}
150+
},
151+
};
152+
153+
Assistant assistant = await assistantClient.CreateAssistantAsync(deploymentName, assistantOptions);
154+
155+
// Create and run a thread with a user query about the data already associated with the assistant
156+
ThreadCreationOptions threadOptions = new()
157+
{
158+
InitialMessages = { "How well did product 113045 sell in February? Graph its trend over time." }
159+
};
160+
161+
ThreadRun threadRun = await assistantClient.CreateThreadAndRunAsync(assistant.Id, threadOptions);
162+
163+
// Check back to see when the run is done
109164
do
110165
{
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);
166+
Thread.Sleep(TimeSpan.FromSeconds(1));
167+
threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id);
168+
} while (!threadRun.Status.IsTerminal);
116169
117-
// Get the messages
118-
PageableList<ThreadMessage> messagesPage = await client.GetMessagesAsync(thread.Id);
119-
IReadOnlyList<ThreadMessage> messages = messagesPage.Data;
170+
// Finally, we'll print out the full history for the thread that includes the augmented generation
171+
AsyncCollectionResult<ThreadMessage> messages
172+
= assistantClient.GetMessagesAsync(
173+
threadRun.ThreadId,
174+
new MessageCollectionOptions() { Order = MessageCollectionOrder.Ascending });
120175
121-
// Note: messages iterate from newest to oldest, with the messages[0] being the most recent
122-
foreach (ThreadMessage threadMessage in messages.Reverse())
176+
await foreach (ThreadMessage message in messages)
123177
{
124-
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
125-
foreach (MessageContent contentItem in threadMessage.ContentItems)
178+
Console.Write($"[{message.Role.ToString().ToUpper()}]: ");
179+
foreach (MessageContent contentItem in message.Content)
126180
{
127-
if (contentItem is MessageTextContent textItem)
181+
if (!string.IsNullOrEmpty(contentItem.Text))
128182
{
129-
Console.Write(textItem.Text);
183+
Console.WriteLine($"{contentItem.Text}");
184+
185+
if (contentItem.TextAnnotations.Count > 0)
186+
{
187+
Console.WriteLine();
188+
}
189+
190+
// Include annotations, if any.
191+
foreach (TextAnnotation annotation in contentItem.TextAnnotations)
192+
{
193+
if (!string.IsNullOrEmpty(annotation.InputFileId))
194+
{
195+
Console.WriteLine($"* File citation, file ID: {annotation.InputFileId}");
196+
}
197+
if (!string.IsNullOrEmpty(annotation.OutputFileId))
198+
{
199+
Console.WriteLine($"* File output, new file ID: {annotation.OutputFileId}");
200+
}
201+
}
202+
}
203+
if (!string.IsNullOrEmpty(contentItem.ImageFileId))
204+
{
205+
OpenAIFileInfo imageInfo = await fileClient.GetFileAsync(contentItem.ImageFileId);
206+
BinaryData imageBytes = await fileClient.DownloadFileAsync(contentItem.ImageFileId);
207+
using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png");
208+
imageBytes.ToStream().CopyTo(stream);
209+
210+
Console.WriteLine($"<image: {imageInfo.Filename}.png>");
130211
}
131-
Console.WriteLine();
132212
}
213+
Console.WriteLine();
133214
}
134215
```
135216

136-
This will print an output as follows:
217+
Run the app using the [`dotnet run`](/dotnet/core/tools/dotnet-run) command:
137218

219+
```csharp
220+
dotnet run
138221
```
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-
```
142222

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.
223+
The console output should resemble the following:
224+
225+
```text
226+
[USER]: How well did product 113045 sell in February? Graph its trend over time.
227+
228+
[ASSISTANT]: Product 113045 sold 22 units in February. Let's visualize its sales trend over the given months (January through March).
229+
230+
I'll create a graph to depict this trend.
231+
232+
[ASSISTANT]: <image: 553380b7-fdb6-49cf-9df6-e8e6700d69f4.png>
233+
The graph above visualizes the sales trend for product 113045 from January to March. As seen, the sales peaked in February with 22 units sold, and fluctuated over the period from January (12 units) to March (16 units).
234+
235+
If you need further analysis or more details, feel free to ask!
236+
```
144237

145238
## Clean up resources
146239

0 commit comments

Comments
 (0)