|
| 1 | +--- |
| 2 | +title: Migrating to the new Function Calling capabilities |
| 3 | +description: Describes the steps for SK caller code to migrate from the current function calling capabilities, represented by the `ToolCallBehavior` class, to the new one represented by the `FunctionChoiceBehavior` class. |
| 4 | +zone_pivot_groups: programming-languages |
| 5 | +author: SergeyMenshykh |
| 6 | +ms.topic: conceptual |
| 7 | +ms.author: semenshi |
| 8 | +ms.service: semantic-kernel |
| 9 | +--- |
| 10 | +::: zone pivot="programming-language-csharp" |
| 11 | +# Function Calling Migration Guide |
| 12 | +Semantic Kernel is gradually transitioning from the current function calling capabilities, represented by the `ToolCallBehavior` class, to the new enhanced capabilities, represented by the `FunctionChoiceBehavior` class. |
| 13 | +The new capability is service-agnostic and is not tied to any specific AI service, unlike the current model. Therefore, it resides in Semantic Kernel abstractions and will be used by all AI connectors working with function-calling capable AI models. |
| 14 | + |
| 15 | + |
| 16 | +This guide is intended to help you to migrate your code to the new function calling capabilities. |
| 17 | + |
| 18 | +## Migrate ToolCallBehavior.AutoInvokeKernelFunctions behavior |
| 19 | +The `ToolCallBehavior.AutoInvokeKernelFunctions` behavior is equivalent to the `FunctionChoiceBehavior.Auto` behavior in the new model. |
| 20 | +```csharp |
| 21 | +// Before |
| 22 | +var executionSettings = new OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions }; |
| 23 | + |
| 24 | +// After |
| 25 | +var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }; |
| 26 | +``` |
| 27 | + |
| 28 | +## Migrate ToolCallBehavior.EnableKernelFunctions behavior |
| 29 | +The `ToolCallBehavior.EnableKernelFunctions` behavior is equivalent to the `FunctionChoiceBehavior.Auto` behavior with disabled auto invocation. |
| 30 | +```csharp |
| 31 | +// Before |
| 32 | +var executionSettings = new OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions }; |
| 33 | + |
| 34 | +// After |
| 35 | +var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false) }; |
| 36 | +``` |
| 37 | + |
| 38 | +## Migrate ToolCallBehavior.EnableFunctions behavior |
| 39 | +The `ToolCallBehavior.EnableFunctions` behavior is equivalent to the `FunctionChoiceBehavior.Auto` behavior that configured with list of functions with disabled auto invocation. |
| 40 | +```csharp |
| 41 | +var function = kernel.CreateFunctionFromMethod(() => DayOfWeek.Friday, "GetDayOfWeek", "Returns the current day of the week."); |
| 42 | + |
| 43 | +// Before |
| 44 | +var executionSettings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.EnableFunctions(functions: [function.Metadata.ToOpenAIFunction()]) }; |
| 45 | + |
| 46 | +// After |
| 47 | +var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(functions: [function], autoInvoke: false) }; |
| 48 | +``` |
| 49 | + |
| 50 | +## Migrate ToolCallBehavior.RequireFunction behavior |
| 51 | +The `ToolCallBehavior.RequireFunction` behavior is equivalent to the `FunctionChoiceBehavior.Required` behavior that configured with list of functions with disabled auto invocation. |
| 52 | +```csharp |
| 53 | +var function = kernel.CreateFunctionFromMethod(() => DayOfWeek.Friday, "GetDayOfWeek", "Returns the current day of the week."); |
| 54 | + |
| 55 | +// Before |
| 56 | +var executionSettings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.RequireFunction(functions: [function.Metadata.ToOpenAIFunction()]) }; |
| 57 | + |
| 58 | +// After |
| 59 | +var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Required(functions: [function], autoInvoke: false) }; |
| 60 | +``` |
| 61 | + |
| 62 | +## Replace the usage of connector-specific function call classes |
| 63 | +Function calling functionality in Semantic Kernel allows developers to access a list of functions chosen by the AI model in two ways: |
| 64 | +- Using connector-specific function call classes like `ChatToolCall` or `ChatCompletionsFunctionToolCall`, available via the `ToolCalls` property of the OpenAI-specific `OpenAIChatMessageContent` item in chat history. |
| 65 | +- Using connector-agnostic function call classes like `FunctionCallContent`, available via the `Items` property of the connector-agnostic `ChatMessageContent` item in chat history. |
| 66 | + |
| 67 | +Both ways are supported at the moment by the current and new models. However, we strongly recommend using the connector-agnostic approach to access function calls, as it is more flexible and allows your code to work with any AI connector that supports the new function-calling model. |
| 68 | +Moreover, considering that the current model will be deprecated soon, now is a good time to migrate your code to the new model to avoid breaking changes in the future. |
| 69 | + |
| 70 | +So, if you use [Manual Function Invocation](../concepts/ai-services/chat-completion/function-calling/function-invocation.md#manual-function-invocation) with the connector-specific function call classes like in this code snippet: |
| 71 | +```csharp |
| 72 | +using System.Text.Json; |
| 73 | +using Microsoft.SemanticKernel; |
| 74 | +using Microsoft.SemanticKernel.ChatCompletion; |
| 75 | +using Microsoft.SemanticKernel.Connectors.OpenAI; |
| 76 | +using OpenAI.Chat; |
| 77 | + |
| 78 | +var chatHistory = new ChatHistory(); |
| 79 | + |
| 80 | +var settings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions }; |
| 81 | + |
| 82 | +var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel); |
| 83 | + |
| 84 | +// Current way of accessing function calls using connector specific classes. |
| 85 | +var toolCalls = ((OpenAIChatMessageContent)result).ToolCalls.OfType<ChatToolCall>().ToList(); |
| 86 | + |
| 87 | +while (toolCalls.Count > 0) |
| 88 | +{ |
| 89 | + // Adding function call from AI model to chat history |
| 90 | + chatHistory.Add(result); |
| 91 | + |
| 92 | + // Iterating over the requested function calls and invoking them |
| 93 | + foreach (var toolCall in toolCalls) |
| 94 | + { |
| 95 | + string content = kernel.Plugins.TryGetFunctionAndArguments(toolCall, out KernelFunction? function, out KernelArguments? arguments) ? |
| 96 | + JsonSerializer.Serialize((await function.InvokeAsync(kernel, arguments)).GetValue<object>()) : |
| 97 | + "Unable to find function. Please try again!"; |
| 98 | + |
| 99 | + // Adding the result of the function call to the chat history |
| 100 | + chatHistory.Add(new ChatMessageContent( |
| 101 | + AuthorRole.Tool, |
| 102 | + content, |
| 103 | + metadata: new Dictionary<string, object?>(1) { { OpenAIChatMessageContent.ToolIdProperty, toolCall.Id } })); |
| 104 | + } |
| 105 | + |
| 106 | + // Sending the functions invocation results back to the AI model to get the final response |
| 107 | + result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel); |
| 108 | + toolCalls = ((OpenAIChatMessageContent)result).ToolCalls.OfType<ChatToolCall>().ToList(); |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +You can refactor it to use the connector-agnostic classes: |
| 113 | +```csharp |
| 114 | +using Microsoft.SemanticKernel; |
| 115 | +using Microsoft.SemanticKernel.ChatCompletion; |
| 116 | + |
| 117 | +var chatHistory = new ChatHistory(); |
| 118 | + |
| 119 | +var settings = new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false) }; |
| 120 | + |
| 121 | +var messageContent = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel); |
| 122 | + |
| 123 | +// New way of accessing function calls using connector agnostic function calling model classes. |
| 124 | +var functionCalls = FunctionCallContent.GetFunctionCalls(messageContent).ToArray(); |
| 125 | + |
| 126 | +while (functionCalls.Length != 0) |
| 127 | +{ |
| 128 | + // Adding function call from AI model to chat history |
| 129 | + chatHistory.Add(messageContent); |
| 130 | + |
| 131 | + // Iterating over the requested function calls and invoking them |
| 132 | + foreach (var functionCall in functionCalls) |
| 133 | + { |
| 134 | + var result = await functionCall.InvokeAsync(kernel); |
| 135 | + |
| 136 | + chatHistory.Add(result.ToChatMessage()); |
| 137 | + } |
| 138 | + |
| 139 | + // Sending the functions invocation results to the AI model to get the final response |
| 140 | + messageContent = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel); |
| 141 | + functionCalls = FunctionCallContent.GetFunctionCalls(messageContent).ToArray(); |
| 142 | +} |
| 143 | +``` |
| 144 | + |
| 145 | +The code snippets above demonstrate how to migrate your code that uses the OpenAI AI connector. |
| 146 | +A similar migration process can be applied to the Gemini and Mistral AI connectors when they are updated to support the new function calling model. |
| 147 | + |
| 148 | +## Next steps |
| 149 | +Now after you have migrated your code to the new function calling model, you can proceed to learn how to configure various aspects of the model that might better correspond to your specific scenarios by referring to the [function choice behaviors article](../concepts/ai-services/chat-completion/function-calling/function-choice-behaviors.md) |
| 150 | + |
| 151 | +> [!div class="nextstepaction"] |
| 152 | +> [Function Choice Behaviors](../concepts/ai-services/chat-completion/function-calling/function-choice-behaviors.md) |
| 153 | +
|
| 154 | + |
| 155 | +::: zone-end |
| 156 | +::: zone pivot="programming-language-python" |
| 157 | +## Coming soon |
| 158 | +More info coming soon. |
| 159 | +::: zone-end |
| 160 | +::: zone pivot="programming-language-java" |
| 161 | +## Coming soon |
| 162 | +More info coming soon. |
| 163 | +::: zone-end |
0 commit comments