Skip to content

Commit b29d8fe

Browse files
authored
Add quickstart for structured output (#45979)
1 parent 13bf96c commit b29d8fe

File tree

5 files changed

+204
-1
lines changed

5 files changed

+204
-1
lines changed

docs/ai/quickstarts/evaluate-ai-response.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ To provision an Azure OpenAI service and model using the Azure portal, complete
2424

2525
## Create the test app
2626

27-
Complete the following steps to create an MSTest project that connects to your local `phi3:mini` AI model.
27+
Complete the following steps to create an MSTest project that connects to the `gpt-4o` AI model.
2828

2929
1. In a terminal window, navigate to the directory where you want to create your app, and create a new MSTest app with the `dotnet new` command:
3030

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using Azure.AI.OpenAI;
2+
using Azure.Identity;
3+
using Microsoft.Extensions.AI;
4+
using Microsoft.Extensions.Configuration;
5+
6+
// <SnippetGetChatClient>
7+
IConfigurationRoot config = new ConfigurationBuilder()
8+
.AddUserSecrets<Program>()
9+
.Build();
10+
11+
string endpoint = config["AZURE_OPENAI_ENDPOINT"];
12+
string model = config["AZURE_OPENAI_GPT_NAME"];
13+
string tenantId = config["AZURE_TENANT_ID"];
14+
15+
// Get a chat client for the Azure OpenAI endpoint.
16+
AzureOpenAIClient azureClient =
17+
new(
18+
new Uri(endpoint),
19+
new DefaultAzureCredential(new DefaultAzureCredentialOptions() { TenantId = tenantId }));
20+
IChatClient chatClient = azureClient
21+
.GetChatClient(deploymentName: model)
22+
.AsIChatClient();
23+
// </SnippetGetChatClient>
24+
25+
// <SnippetSimpleRequest>
26+
string review = "I'm happy with the product!";
27+
var response = await chatClient.GetResponseAsync<Sentiment>($"What's the sentiment of this review? {review}");
28+
Console.WriteLine($"Sentiment: {response.Result}");
29+
// </SnippetSimpleRequest>
30+
31+
// <SnippetMultipleReviews>
32+
string[] inputs = [
33+
"Best purchase ever!",
34+
"Returned it immediately.",
35+
"Hello",
36+
"It works as advertised.",
37+
"The packaging was damaged but otherwise okay."
38+
];
39+
40+
foreach (var i in inputs)
41+
{
42+
var response2 = await chatClient.GetResponseAsync<Sentiment>($"What's the sentiment of this review? {i}");
43+
Console.WriteLine($"Review: {i} | Sentiment: {response2.Result}");
44+
}
45+
// </SnippetMultipleReviews>
46+
47+
// <SnippetRecordRequest>
48+
var review3 = "This product worked okay.";
49+
var response3 = await chatClient.GetResponseAsync<SentimentRecord>($"What's the sentiment of this review? {review3}");
50+
51+
Console.WriteLine($"Response text: {response3.Result.ResponseText}");
52+
Console.WriteLine($"Sentiment: {response3.Result.ReviewSentiment}");
53+
// </SnippetRecordRequest>
54+
55+
// <SnippetInputOutputRecord>
56+
record SentimentRecord(string ResponseText, Sentiment ReviewSentiment);
57+
// </SnippetInputOutputRecord>
58+
59+
// <SnippetSentimentEnum>
60+
public enum Sentiment
61+
{
62+
Positive,
63+
Negative,
64+
Neutral
65+
}
66+
// </SnippetSentimentEnum>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<UserSecretsId>f28ec9ea-e017-46d7-9865-73550c9ec06b</UserSecretsId>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Azure.AI.OpenAI" Version="2.1.0" />
13+
<PackageReference Include="Azure.Identity" Version="1.13.2" />
14+
<PackageReference Include="Microsoft.Extensions.AI" Version="9.4.0-preview.1.25207.5" />
15+
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.4.0-preview.1.25207.5" />
16+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.4" />
17+
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.4" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
title: Quickstart - Request a response with structured output
3+
description: Learn how to create a chat app that responds with structured output, that is, output that conforms to a type that you specify.
4+
ms.date: 04/30/2025
5+
ms.topic: quickstart
6+
ms.custom: devx-track-dotnet, devx-track-dotnet-ai
7+
---
8+
9+
# Request a response with structured output
10+
11+
In this quickstart, you create a chat app that requests a response with *structured output*. A structured output response is a chat response that's of a type you specify instead of just plain text. The chat app you create in this quickstart analyzes sentiment of various product reviews, categorizing each review according to the values of a custom enumeration.
12+
13+
## Prerequisites
14+
15+
- [.NET 8 or a later version](https://dotnet.microsoft.com/download)
16+
- [Visual Studio Code](https://code.visualstudio.com/) (optional)
17+
18+
## Configure the AI service
19+
20+
To provision an Azure OpenAI service and model using the Azure portal, complete the steps in the [Create and deploy an Azure OpenAI Service resource](/azure/ai-services/openai/how-to/create-resource?pivots=web-portal) article. In the "Deploy a model" step, select the `gpt-4o` model.
21+
22+
## Create the chat app
23+
24+
Complete the following steps to create a console app that connects to the `gpt-4o` AI model.
25+
26+
1. In a terminal window, navigate to the directory where you want to create your app, and create a new console app with the `dotnet new` command:
27+
28+
```dotnetcli
29+
dotnet new console -o SOChat
30+
```
31+
32+
1. Navigate to the `SOChat` directory, and add the necessary packages to your app:
33+
34+
```dotnetcli
35+
dotnet add package Azure.AI.OpenAI
36+
dotnet add package Azure.Identity
37+
dotnet add package Microsoft.Extensions.AI --prerelease
38+
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
39+
dotnet add package Microsoft.Extensions.Configuration
40+
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
41+
```
42+
43+
1. Run the following commands to add [app secrets](/aspnet/core/security/app-secrets) for your Azure OpenAI endpoint, model name, and tenant ID:
44+
45+
```bash
46+
dotnet user-secrets init
47+
dotnet user-secrets set AZURE_OPENAI_ENDPOINT <your-azure-openai-endpoint>
48+
dotnet user-secrets set AZURE_OPENAI_GPT_NAME gpt-4o
49+
dotnet user-secrets set AZURE_TENANT_ID <your-tenant-id>
50+
```
51+
52+
> [!NOTE]
53+
> Depending on your environment, the tenant ID might not be needed. In that case, remove it from the code that instantiates the <xref:Azure.Identity.DefaultAzureCredential>.
54+
55+
1. Open the new app in your editor of choice.
56+
57+
## Add the code
58+
59+
1. Define the enumeration that describes the different sentiments.
60+
61+
:::code language="csharp" source="./snippets/structured-output/Program.cs" id="SentimentEnum":::
62+
63+
1. Create the <xref:Microsoft.Extensions.AI.IChatClient> that will communicate with the model.
64+
65+
:::code language="csharp" source="./snippets/structured-output/Program.cs" id="GetChatClient":::
66+
67+
> [!NOTE]
68+
> <xref:Azure.Identity.DefaultAzureCredential> searches for authentication credentials from your environment or local tooling. You'll need to assign the `Azure AI Developer` role to the account you used to sign in to Visual Studio or the Azure CLI. For more information, see [Authenticate to Azure AI services with .NET](../azure-ai-services-authentication.md).
69+
70+
1. Send a request to the model with a single product review, and then print the analyzed sentiment to the console. You declare the requested structured output type by passing it as the type argument to the <xref:Microsoft.Extensions.AI.ChatClientStructuredOutputExtensions.GetResponseAsync``1(Microsoft.Extensions.AI.IChatClient,System.String,Microsoft.Extensions.AI.ChatOptions,System.Nullable{System.Boolean},System.Threading.CancellationToken)?displayProperty=nameWithType> extension method.
71+
72+
:::code language="csharp" source="./snippets/structured-output/Program.cs" id="SimpleRequest":::
73+
74+
This code produces output similar to:
75+
76+
```output
77+
Sentiment: Positive
78+
```
79+
80+
1. Instead of just analyzing a single review, you can analyze a collection of reviews.
81+
82+
:::code language="csharp" source="./snippets/structured-output/Program.cs" id="MultipleReviews":::
83+
84+
This code produces output similar to:
85+
86+
```output
87+
Review: Best purchase ever! | Sentiment: Positive
88+
Review: Returned it immediately. | Sentiment: Negative
89+
Review: Hello | Sentiment: Neutral
90+
Review: It works as advertised. | Sentiment: Neutral
91+
Review: The packaging was damaged but otherwise okay. | Sentiment: Neutral
92+
```
93+
94+
1. And instead of requesting just the analyzed enumeration value, you can request the text response along with the analyzed value.
95+
96+
Define a record type to contain the text response and analyzed sentiment:
97+
98+
:::code language="csharp" source="./snippets/structured-output/Program.cs" id="InputOutputRecord":::
99+
100+
Send the request using the record type as the type argument to `GetResponseAsync<T>`:
101+
102+
:::code language="csharp" source="./snippets/structured-output/Program.cs" id="RecordRequest":::
103+
104+
This code produces output similar to:
105+
106+
```output
107+
Response text: Certainly, I have analyzed the sentiment of the review you provided.
108+
Sentiment: Neutral
109+
```
110+
111+
## See also
112+
113+
- [Structured outputs (Azure OpenAI Service)](/azure/ai-services/openai/how-to/structured-outputs)
114+
- [Using JSON schema for structured output in .NET for OpenAI models](https://devblogs.microsoft.com/semantic-kernel/using-json-schema-for-structured-output-in-net-for-openai-models)
115+
- [Introducing Structured Outputs in the API (OpenAI)](https://openai.com/index/introducing-structured-outputs-in-the-api/)

docs/ai/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ items:
1717
items:
1818
- name: Build a chat app
1919
href: quickstarts/build-chat-app.md
20+
- name: Request structured output
21+
href: quickstarts/structured-output.md
2022
- name: Build a .NET AI vector search app
2123
href: quickstarts/build-vector-search-app.md
2224
- name: Execute a local .NET function

0 commit comments

Comments
 (0)