@@ -33,10 +33,8 @@ Azure AI Agents supports function calling, which allows you to describe the stru
33
33
Start by defining a function for your agent to call. When you create a function for an agent to call, you describe its structure of it with any required parameters in a docstring.
34
34
35
35
``` csharp
36
- // Example of a function that defines no parameters
37
36
string GetUserFavoriteCity () => " Seattle, WA" ;
38
37
FunctionToolDefinition getUserFavoriteCityTool = new (" getUserFavoriteCity" , " Gets the user's favorite city." );
39
- // Example of a function with a single required parameter
40
38
string GetCityNickname (string location ) => location switch
41
39
{
42
40
" Seattle, WA" => " The Emerald City" ,
@@ -60,6 +58,34 @@ FunctionToolDefinition getCityNicknameTool = new(
60
58
Required = new [] { " location" },
61
59
},
62
60
new JsonSerializerOptions () { PropertyNamingPolicy = JsonNamingPolicy .CamelCase }));
61
+ string GetWeatherAtLocation (string location , string temperatureUnit = " f" ) => location switch
62
+ {
63
+ " Seattle, WA" => temperatureUnit == " f" ? " 70f" : " 21c" ,
64
+ _ => throw new NotImplementedException ()
65
+ };
66
+ FunctionToolDefinition getCurrentWeatherAtLocationTool = new (
67
+ name : " getCurrentWeatherAtLocation" ,
68
+ description : " Gets the current weather at a provided location." ,
69
+ parameters : BinaryData .FromObjectAsJson (
70
+ new
71
+ {
72
+ Type = " object" ,
73
+ Properties = new
74
+ {
75
+ Location = new
76
+ {
77
+ Type = " string" ,
78
+ Description = " The city and state, e.g. San Francisco, CA" ,
79
+ },
80
+ Unit = new
81
+ {
82
+ Type = " string" ,
83
+ Enum = new [] { " c" , " f" },
84
+ },
85
+ },
86
+ Required = new [] { " location" },
87
+ },
88
+ new JsonSerializerOptions () { PropertyNamingPolicy = JsonNamingPolicy .CamelCase }));
63
89
```
64
90
65
91
< ! -- See the [C # file on GitHub ](https :// github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/samples/agents/user_functions.py) for an additional function definition examples. -->
@@ -72,15 +98,25 @@ ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall)
72
98
if (toolCall is RequiredFunctionToolCall functionToolCall )
73
99
{
74
100
if (functionToolCall .Name == getUserFavoriteCityTool .Name )
75
- {
76
- return new ToolOutput (toolCall , GetUserFavoriteCity ());
77
- }
78
- using JsonDocument argumentsJson = JsonDocument .Parse (functionToolCall .Arguments );
101
+ {
102
+ return new ToolOutput (toolCall , GetUserFavoriteCity ());
103
+ }
104
+ using JsonDocument argumentsJson = JsonDocument .Parse (functionToolCall .Arguments );
79
105
if (functionToolCall .Name == getCityNicknameTool .Name )
80
106
{
81
107
string locationArgument = argumentsJson .RootElement .GetProperty (" location" ).GetString ();
82
108
return new ToolOutput (toolCall , GetCityNickname (locationArgument ));
83
109
}
110
+ if (functionToolCall .Name == getCurrentWeatherAtLocationTool .Name )
111
+ {
112
+ string locationArgument = argumentsJson .RootElement .GetProperty (" location" ).GetString ();
113
+ if (argumentsJson .RootElement .TryGetProperty (" unit" , out JsonElement unitElement ))
114
+ {
115
+ string unitArgument = unitElement .GetString ();
116
+ return new ToolOutput (toolCall , GetWeatherAtLocation (locationArgument , unitArgument ));
117
+ }
118
+ return new ToolOutput (toolCall , GetWeatherAtLocation (locationArgument ));
119
+ }
84
120
}
85
121
return null ;
86
122
}
@@ -89,78 +125,75 @@ ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall)
89
125
## Create a client and agent
90
126
91
127
```csharp
92
- // note: parallel function calling is only supported with newer models like gpt-4-1106-preview
93
- Response <Agent > agentResponse = await client .CreateAgentAsync (
94
- model : " gpt-4-1106-preview" ,
128
+ PersistentAgent agent = await client .Administration .CreateAgentAsync (
129
+ model : modelDeploymentName ,
95
130
name : " SDK Test Agent - Functions" ,
96
- instructions : " You are a weather bot. Use the provided functions to help answer questions. "
97
- + " Customize your responses to the user's preferences as much as possible and use friendly "
98
- + " nicknames for cities whenever possible." ,
99
- tools : new List <ToolDefinition > { getUserFavoriteCityTool , getCityNicknameTool , getCurrentWeatherAtLocationTool }
100
- );
101
- Agent agent = agentResponse .Value ;
131
+ instructions : " You are a weather bot. Use the provided functions to help answer questions. "
132
+ + " Customize your responses to the user's preferences as much as possible and use friendly "
133
+ + " nicknames for cities whenever possible." ,
134
+ tools : [getUserFavoriteCityTool , getCityNicknameTool , getCurrentWeatherAtLocationTool ]);
102
135
```
103
136
104
137
## Create a thread
105
138
106
139
```csharp
107
- Response <AgentThread > threadResponse = await client .CreateThreadAsync ();
108
- AgentThread thread = threadResponse .Value ;
140
+ PersistentAgentThread thread = await client .Threads .CreateThreadAsync ();
109
141
110
- Response < ThreadMessage > messageResponse = await client .CreateMessageAsync (
142
+ await client . Messages .CreateMessageAsync (
111
143
thread .Id ,
112
144
MessageRole .User ,
113
145
" What's the weather like in my favorite city?" );
114
- ThreadMessage message = messageResponse .Value ;
115
146
```
116
147
117
148
## Create a run and check the output
118
149
119
150
```csharp
120
- Response < ThreadRun > runResponse = await client .CreateRunAsync (thread , agent );
151
+ ThreadRun run = await client .Runs . CreateRunAsync (thread . Id , agent . Id );
121
152
122
- #region Snippet:FunctionsHandlePollingWithRequiredAction
123
153
do
124
154
{
125
155
await Task .Delay (TimeSpan .FromMilliseconds (500 ));
126
- runResponse = await client .GetRunAsync (thread .Id , runResponse . Value .Id );
156
+ run = await client .Runs . GetRunAsync (thread .Id , run .Id );
127
157
128
- if (runResponse . Value .Status == RunStatus .RequiresAction
129
- && runResponse . Value .RequiredAction is SubmitToolOutputsAction submitToolOutputsAction )
158
+ if (run .Status == RunStatus .RequiresAction
159
+ && run .RequiredAction is SubmitToolOutputsAction submitToolOutputsAction )
130
160
{
131
- List <ToolOutput > toolOutputs = new () ;
161
+ List < ToolOutput > toolOutputs = [] ;
132
162
foreach (RequiredToolCall toolCall in submitToolOutputsAction .ToolCalls )
133
163
{
134
- toolOutputs .Add (GetResolvedToolOutput (toolCall ));
164
+ ToolOutput ? toolOutput = GetResolvedToolOutput (toolCall );
165
+ if (toolOutput != null )
166
+ {
167
+ toolOutputs .Add (toolOutput );
168
+ }
135
169
}
136
- runResponse = await client .SubmitToolOutputsToRunAsync (runResponse . Value , toolOutputs );
170
+ run = await client .Runs . SubmitToolOutputsToRunAsync (run , toolOutputs );
137
171
}
138
172
}
139
- while (runResponse . Value .Status == RunStatus .Queued
140
- || runResponse . Value . Status == RunStatus .InProgress );
141
- # endregion
173
+ while (run .Status == RunStatus .Queued
174
+ || run . Status == RunStatus .InProgress
175
+ || run . Status == RunStatus . RequiresAction );
142
176
143
- Response <PageableList <ThreadMessage >> afterRunMessagesResponse
144
- = await client .GetMessagesAsync (thread .Id );
145
- IReadOnlyList <ThreadMessage > messages = afterRunMessagesResponse .Value .Data ;
177
+ AsyncPageable < ThreadMessage > messages = client .Messages .GetMessagesAsync (
178
+ threadId : thread .Id ,
179
+ order : ListSortOrder .Ascending
180
+ );
146
181
147
- // Note: messages iterate from newest to oldest, with the messages[0] being the most recent
148
- foreach (ThreadMessage threadMessage in messages )
182
+ await foreach (ThreadMessage threadMessage in messages )
149
183
{
150
- Console .Write ($" {threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: " );
151
- foreach (MessageContent contentItem in threadMessage .ContentItems )
184
+ foreach (MessageContent content in threadMessage .ContentItems )
152
185
{
153
- if ( contentItem is MessageTextContent textItem )
186
+ switch ( content )
154
187
{
155
- Console .Write (textItem .Text );
188
+ case MessageTextContent textItem :
189
+ Console .WriteLine ($" [{threadMessage .Role }]: {textItem .Text }" );
190
+ break ;
156
191
}
157
- else if (contentItem is MessageImageFileContent imageFileItem )
158
- {
159
- Console .Write ($" <image from ID: {imageFileItem.FileId}" );
160
- }
161
- Console .WriteLine ();
162
192
}
163
193
}
194
+
195
+ await client .Threads .DeleteThreadAsync (threadId : thread .Id );
196
+ await client .Administration .DeleteAgentAsync (agentId : agent .Id );
164
197
```
165
198
166
199
::: zone - end
@@ -510,4 +543,4 @@ curl $AZURE_AI_AGENTS_ENDPOINT/threads/thread_abc123/messages?api-version=2024-1
510
543
- H " Authorization: Bearer $AZURE_AI_AGENTS_TOKEN"
511
544
```
512
545
513
- ::: zone-end
546
+ ::: zone - end
0 commit comments