Skip to content

Commit dd2bd35

Browse files
authored
Support toolcall (Azure#49293)
* auto function call * Fix reference issues * update proj * Resolved comments
1 parent f7bfc79 commit dd2bd35

17 files changed

+1192
-167
lines changed

eng/Packages.Data.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
<PackageReference Update="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3"/>
107107

108108
<!-- Azure SDK packages -->
109-
<PackageReference Update="Azure.AI.Inference" Version="1.0.0-beta.2" />
109+
<PackageReference Update="Azure.AI.Inference" Version="1.0.0-beta.4" />
110110
<PackageReference Update="Azure.AI.OpenAI" Version="2.0.0" />
111111
<PackageReference Update="Azure.AI.Projects" Version="1.0.0-beta.2" />
112112
<PackageReference Update="Azure.Communication.Identity" Version="1.3.1" />

sdk/ai/Azure.AI.Projects/README.md

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ Use the AI Projects client library to:
2929
- [Code interpreter attachment](#create-message-with-code-interpreter-attachment)
3030
- [Create Agent with Bing Grounding](#create-agent-with-bing-grounding)
3131
- [Azure AI Search](#create-agent-with-azure-ai-search)
32-
- [Function call](#function-call)
32+
- [Function call Executed Manually](#function-call-executed-manually)
33+
- [Function call Executed Automatically](#function-call-executed-automatically)
3334
- [Azure function Call](#azure-function-call)
3435
- [OpenAPI](#create-agent-with-openapi)
3536
- [Troubleshooting](#troubleshooting)
@@ -425,7 +426,7 @@ foreach (ThreadMessage threadMessage in messages)
425426
}
426427
```
427428

428-
#### Function call
429+
#### Function call executed manually
429430

430431
Tools that reference caller-defined capabilities as functions can be provided to an agent to allow it to
431432
dynamically resolve and disambiguate during a run.
@@ -647,6 +648,63 @@ do
647648
while (toolOutputs.Count > 0);
648649
```
649650

651+
#### Function call executed automatically
652+
653+
In addition to the manual function calls, SDK supports automatic function calling. After creating functions and`FunctionToolDefinition` according to the last section, here is the steps:
654+
655+
When you create an agent, you can specify the function call by tools argument similar to the example of manual function calls:
656+
```C# Snippet:StreamingWithAutoFunctionCall_CreateAgent
657+
Agent agent = client.CreateAgent(
658+
model: modelDeploymentName,
659+
name: "SDK Test Agent - Functions",
660+
instructions: "You are a weather bot. Use the provided functions to help answer questions. "
661+
+ "Customize your responses to the user's preferences as much as possible and use friendly "
662+
+ "nicknames for cities whenever possible.",
663+
tools: [getCityNicknameTool, getCurrentWeatherAtLocationTool, getUserFavoriteCityTool]
664+
);
665+
```
666+
667+
We create a thread and message similar to the example of manual function tool calls:
668+
```C# Snippet:StreamingWithAutoFunctionCall_CreateThreadMessage
669+
AgentThread thread = client.CreateThread();
670+
671+
ThreadMessage message = client.CreateMessage(
672+
thread.Id,
673+
MessageRole.User,
674+
"What's the weather like in my favorite city?");
675+
```
676+
677+
Setup `AutoFunctionCallOptions`:
678+
```C# Snippet:StreamingWithAutoFunctionCall_EnableAutoFunctionCalls
679+
List<ToolOutput> toolOutputs = new();
680+
Dictionary<string, Delegate> toolDelegates = new();
681+
toolDelegates.Add(nameof(GetWeatherAtLocation), GetWeatherAtLocation);
682+
toolDelegates.Add(nameof(GetCityNickname), GetCityNickname);
683+
toolDelegates.Add(nameof(GetUserFavoriteCity), GetUserFavoriteCity);
684+
AutoFunctionCallOptions autoFunctionCallOptions = new(toolDelegates, 10);
685+
```
686+
687+
With autoFunctionCallOptions as parameter for `CreateRunStreamingAsync`, the agent will then call the function automatically when it is needed:
688+
```C# Snippet:StreamingWithAutoFunctionCallAsync
689+
await foreach (StreamingUpdate streamingUpdate in client.CreateRunStreamingAsync(thread.Id, agent.Id, autoFunctionCallOptions: autoFunctionCallOptions))
690+
{
691+
if (streamingUpdate.UpdateKind == StreamingUpdateReason.RunCreated)
692+
{
693+
Console.WriteLine("--- Run started! ---");
694+
}
695+
else if (streamingUpdate is MessageContentUpdate contentUpdate)
696+
{
697+
Console.Write(contentUpdate.Text);
698+
}
699+
else if (streamingUpdate.UpdateKind == StreamingUpdateReason.RunCompleted)
700+
{
701+
Console.WriteLine();
702+
Console.WriteLine("--- Run completed! ---");
703+
}
704+
}
705+
```
706+
To allow the agent cast the parameters to the function call, you must use the supported argument types. They are `string`, `int`, `ushort`, `float`, `uint`, `decimal`, `double`, `long`, and `bool`. Other tpes such as array, dictionary, or classes are not supported.
707+
650708
#### Azure function call
651709

652710
We can use Azure Function from inside the agent. In the example below we are calling function "foo", which responds "Bar". In this example we create `AzureFunctionToolDefinition` object, with the function name, description, input and output queues, followed by function parameters. See below for the instructions on function deployment.

sdk/ai/Azure.AI.Projects/api/Azure.AI.Projects.net8.0.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ public AgentsClient(System.Uri endpoint, string subscriptionId, string resourceG
207207
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.AI.Projects.ThreadRun>> CreateRunAsync(Azure.AI.Projects.AgentThread thread, Azure.AI.Projects.Agent agent, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
208208
public virtual System.Threading.Tasks.Task<Azure.Response> CreateRunAsync(string threadId, Azure.Core.RequestContent content, System.Collections.Generic.IEnumerable<Azure.AI.Projects.RunAdditionalFieldList> include = null, Azure.RequestContext context = null) { throw null; }
209209
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.AI.Projects.ThreadRun>> CreateRunAsync(string threadId, string assistantId, string overrideModelName = null, string overrideInstructions = null, string additionalInstructions = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ThreadMessageOptions> additionalMessages = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolDefinition> overrideTools = null, bool? stream = default(bool?), float? temperature = default(float?), float? topP = default(float?), int? maxPromptTokens = default(int?), int? maxCompletionTokens = default(int?), Azure.AI.Projects.TruncationObject truncationStrategy = null, System.BinaryData toolChoice = null, System.BinaryData responseFormat = null, bool? parallelToolCalls = default(bool?), System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.RunAdditionalFieldList> include = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
210-
public virtual System.ClientModel.CollectionResult<Azure.AI.Projects.StreamingUpdate> CreateRunStreaming(string threadId, string assistantId, string overrideModelName = null, string overrideInstructions = null, string additionalInstructions = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ThreadMessageOptions> additionalMessages = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolDefinition> overrideTools = null, float? temperature = default(float?), float? topP = default(float?), int? maxPromptTokens = default(int?), int? maxCompletionTokens = default(int?), Azure.AI.Projects.TruncationObject truncationStrategy = null, System.BinaryData toolChoice = null, System.BinaryData responseFormat = null, bool? parallelToolCalls = default(bool?), System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
211-
public virtual System.ClientModel.AsyncCollectionResult<Azure.AI.Projects.StreamingUpdate> CreateRunStreamingAsync(string threadId, string assistantId, string overrideModelName = null, string overrideInstructions = null, string additionalInstructions = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ThreadMessageOptions> additionalMessages = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolDefinition> overrideTools = null, float? temperature = default(float?), float? topP = default(float?), int? maxPromptTokens = default(int?), int? maxCompletionTokens = default(int?), Azure.AI.Projects.TruncationObject truncationStrategy = null, System.BinaryData toolChoice = null, System.BinaryData responseFormat = null, bool? parallelToolCalls = default(bool?), System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
210+
public virtual System.ClientModel.CollectionResult<Azure.AI.Projects.StreamingUpdate> CreateRunStreaming(string threadId, string assistantId, string overrideModelName = null, string overrideInstructions = null, string additionalInstructions = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ThreadMessageOptions> additionalMessages = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolDefinition> overrideTools = null, float? temperature = default(float?), float? topP = default(float?), int? maxPromptTokens = default(int?), int? maxCompletionTokens = default(int?), Azure.AI.Projects.TruncationObject truncationStrategy = null, System.BinaryData toolChoice = null, System.BinaryData responseFormat = null, bool? parallelToolCalls = default(bool?), System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken), Azure.AI.Projects.AutoFunctionCallOptions autoFunctionCallOptions = null) { throw null; }
211+
public virtual System.ClientModel.AsyncCollectionResult<Azure.AI.Projects.StreamingUpdate> CreateRunStreamingAsync(string threadId, string assistantId, string overrideModelName = null, string overrideInstructions = null, string additionalInstructions = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ThreadMessageOptions> additionalMessages = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolDefinition> overrideTools = null, float? temperature = default(float?), float? topP = default(float?), int? maxPromptTokens = default(int?), int? maxCompletionTokens = default(int?), Azure.AI.Projects.TruncationObject truncationStrategy = null, System.BinaryData toolChoice = null, System.BinaryData responseFormat = null, bool? parallelToolCalls = default(bool?), System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken), Azure.AI.Projects.AutoFunctionCallOptions autoFunctionCallOptions = null) { throw null; }
212212
public virtual Azure.Response CreateThread(Azure.Core.RequestContent content, Azure.RequestContext context = null) { throw null; }
213213
public virtual Azure.Response<Azure.AI.Projects.AgentThread> CreateThread(System.Collections.Generic.IEnumerable<Azure.AI.Projects.ThreadMessageOptions> messages = null, Azure.AI.Projects.ToolResources toolResources = null, System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
214214
public virtual Azure.Response CreateThreadAndRun(Azure.Core.RequestContent content, Azure.RequestContext context = null) { throw null; }
@@ -317,8 +317,8 @@ public AgentsClient(System.Uri endpoint, string subscriptionId, string resourceG
317317
public virtual Azure.Response SubmitToolOutputsToRun(string threadId, string runId, Azure.Core.RequestContent content, Azure.RequestContext context = null) { throw null; }
318318
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.AI.Projects.ThreadRun>> SubmitToolOutputsToRunAsync(Azure.AI.Projects.ThreadRun run, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolOutput> toolOutputs, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
319319
public virtual System.Threading.Tasks.Task<Azure.Response> SubmitToolOutputsToRunAsync(string threadId, string runId, Azure.Core.RequestContent content, Azure.RequestContext context = null) { throw null; }
320-
public virtual System.ClientModel.CollectionResult<Azure.AI.Projects.StreamingUpdate> SubmitToolOutputsToStream(Azure.AI.Projects.ThreadRun run, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolOutput> toolOutputs, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
321-
public virtual System.ClientModel.AsyncCollectionResult<Azure.AI.Projects.StreamingUpdate> SubmitToolOutputsToStreamAsync(Azure.AI.Projects.ThreadRun run, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolOutput> toolOutputs, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
320+
public virtual System.ClientModel.CollectionResult<Azure.AI.Projects.StreamingUpdate> SubmitToolOutputsToStream(Azure.AI.Projects.ThreadRun run, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolOutput> toolOutputs, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken), Azure.AI.Projects.AutoFunctionCallOptions autoFunctionCallOptions = null) { throw null; }
321+
public virtual System.ClientModel.AsyncCollectionResult<Azure.AI.Projects.StreamingUpdate> SubmitToolOutputsToStreamAsync(Azure.AI.Projects.ThreadRun run, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolOutput> toolOutputs, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken), Azure.AI.Projects.AutoFunctionCallOptions autoFunctionCallOptions = null) { throw null; }
322322
public virtual Azure.Response UpdateAgent(string assistantId, Azure.Core.RequestContent content, Azure.RequestContext context = null) { throw null; }
323323
public virtual Azure.Response<Azure.AI.Projects.Agent> UpdateAgent(string assistantId, string model = null, string name = null, string description = null, string instructions = null, System.Collections.Generic.IEnumerable<Azure.AI.Projects.ToolDefinition> tools = null, Azure.AI.Projects.ToolResources toolResources = null, float? temperature = default(float?), float? topP = default(float?), System.BinaryData responseFormat = null, System.Collections.Generic.IReadOnlyDictionary<string, string> metadata = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
324324
public virtual System.Threading.Tasks.Task<Azure.Response> UpdateAgentAsync(string assistantId, Azure.Core.RequestContent content, Azure.RequestContext context = null) { throw null; }
@@ -629,6 +629,10 @@ public enum AuthenticationType
629629
Custom = 3,
630630
None = 4,
631631
}
632+
public partial class AutoFunctionCallOptions
633+
{
634+
public AutoFunctionCallOptions(System.Collections.Generic.Dictionary<string, System.Delegate> toolDelegates, int maxRetry) { }
635+
}
632636
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
633637
public readonly partial struct AzureAISearchQueryType : System.IEquatable<Azure.AI.Projects.AzureAISearchQueryType>
634638
{

0 commit comments

Comments
 (0)