3
3
# [ Microsoft Entra ID] ( #tab/dotnet-entra-id )
4
4
5
5
``` csharp
6
+ using Azure .AI .OpenAI ;
7
+ using Azure .Identity ;
8
+ using Newtonsoft .Json .Schema .Generation ;
9
+ using OpenAI .Chat ;
10
+ using System .ClientModel ;
11
+
12
+ // Create the clients
13
+ string endpoint = GetEnvironmentVariable (" AZURE_OPENAI_ENDPOINT" );
14
+
15
+ AzureOpenAIClient openAIClient = new (
16
+ new Uri (endpoint ),
17
+ new DefaultAzureCredential ());
18
+
19
+ var client = openAIClient .GetChatClient (" gpt-4o" );
20
+
21
+ // Create a chat with initial prompts
22
+ var chat = new List <ChatMessage >()
23
+ {
24
+ new SystemChatMessage (" Extract the event information and projected weather." ),
25
+ new UserChatMessage (" Alice and Bob are going to a science fair in Seattle on June 1st, 2025." )
26
+ };
27
+
28
+ // Get the schema of the class for the structured response
29
+ JSchemaGenerator generator = new JSchemaGenerator ();
30
+ var jsonSchema = generator .Generate (typeof (CalendarEvent )).ToString ();
31
+
32
+ // Get a completion with structured output
33
+ var chatUpdates = client .CompleteChatStreamingAsync (
34
+ chat ,
35
+ new ChatCompletionOptions ()
36
+ {
37
+ ResponseFormat = ChatResponseFormat .CreateJsonSchemaFormat (
38
+ " calenderEvent" ,
39
+ BinaryData .FromString (jsonSchema ))
40
+ });
41
+
42
+ // Write the structured response
43
+ await foreach (var chatUpdate in chatUpdates )
44
+ {
45
+ foreach (var contentPart in chatUpdate .ContentUpdate )
46
+ {
47
+ Console .Write (contentPart .Text );
48
+ }
49
+ }
50
+
51
+ // The class for the structured response
52
+ public class CalendarEvent ()
53
+ {
54
+ public string Name { get ; set ; }
55
+ public string Date { get ; set ; }
56
+ public List <string > Participants { get ; set ; }
57
+ }
6
58
7
59
```
8
60
9
61
# [ Key-based auth] ( #tab/dotnet-keys )
10
62
11
63
``` csharp
64
+ using Azure .AI .OpenAI ;
65
+ using Newtonsoft .Json .Schema .Generation ;
66
+ using OpenAI .Chat ;
67
+ using System .ClientModel ;
12
68
13
- ```
69
+ // Create the clients
70
+ string endpoint = GetEnvironmentVariable (" AZURE_OPENAI_ENDPOINT" );
71
+ string key = GetEnvironmentVariable (" AZURE_OPENAI_API_KEY" );
14
72
15
- ---
73
+ AzureOpenAIClient openAIClient = new (
74
+ new Uri (endpoint ),
75
+ new ApiKeyCredential (key ));
16
76
17
- ## Function calling with structured outputs
77
+ var client = openAIClient . GetChatClient ( " gpt-4o " );
18
78
19
- Structured Outputs for function calling can be enabled with a single parameter, by supplying ` strict: true ` .
79
+ // Create a chat with initial prompts
80
+ var chat = new List <ChatMessage >()
81
+ {
82
+ new SystemChatMessage (" Extract the event information and projected weather." ),
83
+ new UserChatMessage (" Alice and Bob are going to a science fair in Seattle on June 1st, 2025." )
84
+ };
20
85
21
- > [ !NOTE]
22
- > Structured outputs are not supported with parallel function calls. When using structured outputs set ` parallel_tool_calls ` to ` false ` .
86
+ // Get the schema of the class for the structured response
87
+ JSchemaGenerator generator = new JSchemaGenerator ();
88
+ var jsonSchema = generator .Generate (typeof (CalendarEvent )).ToString ();
23
89
24
- # [ Microsoft Entra ID] ( #tab/dotnet-entra-id )
90
+ // Get a completion with structured output
91
+ var chatUpdates = client .CompleteChatStreamingAsync (
92
+ chat ,
93
+ new ChatCompletionOptions ()
94
+ {
95
+ ResponseFormat = ChatResponseFormat .CreateJsonSchemaFormat (
96
+ " calenderEvent" ,
97
+ BinaryData .FromString (jsonSchema ))
98
+ });
25
99
26
- ``` csharp
100
+ // Write the structured response
101
+ await foreach (var chatUpdate in chatUpdates )
102
+ {
103
+ foreach (var contentPart in chatUpdate .ContentUpdate )
104
+ {
105
+ Console .Write (contentPart .Text );
106
+ }
107
+ }
108
+
109
+ // The class for the structured response
110
+ public class CalendarEvent ()
111
+ {
112
+ public string Name { get ; set ; }
113
+ public string Date { get ; set ; }
114
+ public List <string > Participants { get ; set ; }
115
+ }
27
116
28
117
```
29
118
30
- # [ Key-based auth] ( #tab/dotnet-keys )
119
+ ---
120
+
121
+ ## Function calling with structured outputs
122
+
123
+ Structured Outputs for function calling can be enabled with a single parameter, by supplying ` strict: true ` .
124
+
125
+ # [ Microsoft Entra ID] ( #tab/dotnet-entra-id )
31
126
32
127
``` csharp
33
128
using Azure .AI .OpenAI ;
34
- using Azure .Identity ;
35
- using Newtonsoft .Json .Schema ;
36
129
using Newtonsoft .Json .Schema .Generation ;
37
- using OpenAI .Assistants ;
38
130
using OpenAI .Chat ;
39
- using OpenAI .Files ;
40
- using System ;
41
131
using System .ClientModel ;
42
- using System .Text ;
43
- using System .Text .Json ;
44
132
133
+ // Create the clients
134
+ string endpoint = GetEnvironmentVariable (" AZURE_OPENAI_ENDPOINT" );
135
+
136
+ AzureOpenAIClient openAIClient = new (
137
+ new Uri (endpoint ),
138
+ new DefaultAzureCredential ());
139
+
140
+ var chatClient = openAIClient .GetChatClient (" gpt-4o" );
141
+
142
+ // Local function to be used by the assistant tooling
45
143
string GetTemperature (string location , string date )
46
144
{
47
- // Call the weather API here.
145
+ // Placeholder for Weather API
48
146
if (location == " Seattle" && date == " 2025-06-01" )
49
147
{
50
- return " 45 " ;
148
+ return " 75 " ;
51
149
}
52
150
53
151
return " 50" ;
54
152
}
55
153
154
+ // Create a tool to get the temperature
56
155
ChatTool GetTemperatureTool = ChatTool .CreateFunctionTool (
57
156
functionName : nameof (GetTemperature ),
58
157
functionSchemaIsStrict : true ,
@@ -76,28 +175,20 @@ ChatTool GetTemperatureTool = ChatTool.CreateFunctionTool(
76
175
""" u8 .ToArray ())
77
176
);
78
177
79
- AzureOpenAIClient openAIClient = new (new Uri (" " ), new ApiKeyCredential (" " ));
80
-
178
+ // Create a chat with prompts
81
179
var chat = new List <ChatMessage >()
82
180
{
83
181
new SystemChatMessage (" Extract the event information and projected weather." ),
84
182
new UserChatMessage (" Alice and Bob are going to a science fair in Seattle on June 1st, 2025." )
85
183
};
86
184
185
+ // Create a JSON schema for the CalendarEvent structured response
87
186
JSchemaGenerator generator = new JSchemaGenerator ();
88
187
var schema = generator .Generate (typeof (CalendarEvent ));
89
188
string jsonSchema = schema .ToString ();
90
189
91
- var json = Encoding .UTF8 .GetBytes (schema .ToString ());
92
-
93
- var client = openAIClient .GetChatClient (" gpt-4o" );
94
-
95
- bool requiresAction ;
96
-
97
- do
98
- {
99
- requiresAction = false ;
100
- var completion = client .CompleteChat (
190
+ // Get a chat completion from the AI model
191
+ var completion = chatClient .CompleteChat (
101
192
chat ,
102
193
new ChatCompletionOptions ()
103
194
{
107
198
Tools = { GetTemperatureTool }
108
199
});
109
200
110
- switch (completion .Value .FinishReason )
111
- {
112
- case ChatFinishReason .Stop :
113
- {
114
- // Add the assistant message to the conversation history.
115
- chat .Add (new AssistantChatMessage (completion ));
116
- Console .WriteLine (completion .Value .Content [0 ].Text );
117
- break ;
118
- }
119
-
120
- case ChatFinishReason .ToolCalls :
121
- {
122
- // First, add the assistant message with tool calls to the conversation history.
123
- chat .Add (new AssistantChatMessage (completion ));
124
-
125
- // Then, add a new tool message for each tool call that is resolved.
126
- foreach (ChatToolCall toolCall in completion .Value .ToolCalls )
127
- {
128
- switch (toolCall .FunctionName )
129
- {
130
- case nameof (GetTemperature ):
131
- {
132
- using JsonDocument argumentsJson = JsonDocument .Parse (toolCall .FunctionArguments );
133
- bool hasLocation = argumentsJson .RootElement .TryGetProperty (" location" , out JsonElement location );
134
- bool hasDate = argumentsJson .RootElement .TryGetProperty (" date" , out JsonElement date );
135
-
136
- if (! hasLocation || ! hasDate )
137
- {
138
- throw new ArgumentNullException (nameof (location ), " The location and date arguments are required." );
139
- }
140
-
141
- string toolResult = GetTemperature (location .GetString (), date .GetString ());
142
- chat .Add (new ToolChatMessage (toolCall .Id , toolResult ));
143
- break ;
144
- }
145
-
146
- default :
147
- {
148
- // Handle other unexpected calls.
149
- throw new NotImplementedException ();
150
- }
151
- }
152
- }
201
+ Console .WriteLine (completion .Value .ToolCalls [0 ].FunctionName );
202
+
203
+ // Structured response class
204
+ public class CalendarEvent ()
205
+ {
206
+ public string Name { get ; set ; }
207
+ public string Date { get ; set ; }
208
+ public string Temperature { get ; set ; }
209
+ public List <string > Participants { get ; set ; }
210
+ }
211
+ ```
153
212
154
- requiresAction = true ;
155
- break ;
156
- }
213
+ # [ Key-based auth] ( #tab/dotnet-keys )
214
+
215
+ ``` csharp
216
+ using Azure .AI .OpenAI ;
217
+ using Newtonsoft .Json .Schema .Generation ;
218
+ using OpenAI .Chat ;
219
+ using System .ClientModel ;
157
220
158
- case ChatFinishReason .Length :
159
- throw new NotImplementedException (" Incomplete model output due to MaxTokens parameter or token limit exceeded." );
221
+ // Create the clients
222
+ string endpoint = GetEnvironmentVariable (" AZURE_OPENAI_ENDPOINT" );
223
+ string key = GetEnvironmentVariable (" AZURE_OPENAI_API_KEY" );
160
224
161
- case ChatFinishReason .ContentFilter :
162
- throw new NotImplementedException (" Omitted content due to a content filter flag." );
225
+ AzureOpenAIClient openAIClient = new (
226
+ new Uri (endpoint ),
227
+ new ApiKeyCredential (key ));
163
228
164
- case ChatFinishReason .FunctionCall :
165
- throw new NotImplementedException (" Deprecated in favor of tool calls." );
229
+ var chatClient = openAIClient .GetChatClient (" gpt-4o" );
166
230
167
- default :
168
- throw new NotImplementedException (completion .Value .FinishReason .ToString ());
231
+ // Local function to be used by the assistant tooling
232
+ string GetTemperature (string location , string date )
233
+ {
234
+ // Placeholder for Weather API
235
+ if (location == " Seattle" && date == " 2025-06-01" )
236
+ {
237
+ return " 75" ;
169
238
}
170
239
171
- } while (requiresAction );
240
+ return " 50" ;
241
+ }
242
+
243
+ // Create a tool to get the temperature
244
+ ChatTool GetTemperatureTool = ChatTool .CreateFunctionTool (
245
+ functionName : nameof (GetTemperature ),
246
+ functionSchemaIsStrict : true ,
247
+ functionDescription : " Get the projected temperature by date and location." ,
248
+ functionParameters : BinaryData .FromBytes ("""
249
+ {
250
+ "type": "object",
251
+ "properties": {
252
+ "location": {
253
+ "type": "string",
254
+ "description": "The location of the weather."
255
+ },
256
+ "date": {
257
+ "type": "string",
258
+ "description": "The date of the projected weather."
259
+ }
260
+ },
261
+ "required": ["location", "date"],
262
+ "additionalProperties": false
263
+ }
264
+ """ u8 .ToArray ())
265
+ );
266
+
267
+ // Create a chat with prompts
268
+ var chat = new List <ChatMessage >()
269
+ {
270
+ new SystemChatMessage (" Extract the event information and projected weather." ),
271
+ new UserChatMessage (" Alice and Bob are going to a science fair in Seattle on June 1st, 2025." )
272
+ };
273
+
274
+ // Create a JSON schema for the CalendarEvent structured response
275
+ JSchemaGenerator generator = new JSchemaGenerator ();
276
+ var schema = generator .Generate (typeof (CalendarEvent ));
277
+ string jsonSchema = schema .ToString ();
278
+
279
+ // Get a chat completion from the AI model
280
+ var completion = chatClient .CompleteChat (
281
+ chat ,
282
+ new ChatCompletionOptions ()
283
+ {
284
+ ResponseFormat = ChatResponseFormat .CreateJsonSchemaFormat (
285
+ " calenderEvent" ,
286
+ BinaryData .FromString (jsonSchema )),
287
+ Tools = { GetTemperatureTool }
288
+ });
172
289
290
+ Console .WriteLine (completion .Value .ToolCalls [0 ].FunctionName );
173
291
292
+ // Structured response class
174
293
public class CalendarEvent ()
175
294
{
176
295
public string Name { get ; set ; }
0 commit comments