函数调用迁移指南

语义内核正逐渐从由类表示 ToolCallBehavior 的当前函数调用功能转换为由类表示 FunctionChoiceBehavior 的新增强功能。 新功能与服务无关,与当前模型不同,它与任何特定的 AI 服务无关。 因此,它驻留在语义内核抽象中,并且将由所有处理支持函数调用的 AI 模型的 AI 连接器使用。

本指南旨在帮助你将代码迁移到新的函数调用功能。

迁移 ToolCallBehavior.AutoInvokeKernelFunctions 行为

ToolCallBehavior.AutoInvokeKernelFunctions 行为等效于 FunctionChoiceBehavior.Auto 新模型中的行为。

// Before
var executionSettings = new OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };

// After
var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };

迁移 ToolCallBehavior.EnableKernelFunctions 行为

ToolCallBehavior.EnableKernelFunctions 行为等效于 FunctionChoiceBehavior.Auto 禁用的自动调用的行为。

// Before
var executionSettings = new OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions };

// After
var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false) };

迁移 ToolCallBehavior.EnableFunctions 行为

ToolCallBehavior.EnableFunctions 行为等效于 FunctionChoiceBehavior.Auto 使用禁用自动调用的函数列表配置的行为。

var function = kernel.CreateFunctionFromMethod(() => DayOfWeek.Friday, "GetDayOfWeek", "Returns the current day of the week.");

// Before
var executionSettings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.EnableFunctions(functions: [function.Metadata.ToOpenAIFunction()]) };

// After
var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(functions: [function], autoInvoke: false) };

迁移 ToolCallBehavior.RequireFunction 行为

ToolCallBehavior.RequireFunction 行为等效于 FunctionChoiceBehavior.Required 使用禁用自动调用的函数列表配置的行为。

var function = kernel.CreateFunctionFromMethod(() => DayOfWeek.Friday, "GetDayOfWeek", "Returns the current day of the week.");

// Before
var executionSettings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.RequireFunction(functions: [function.Metadata.ToOpenAIFunction()]) };

// After
var executionSettings = new OpenAIPromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Required(functions: [function], autoInvoke: false) };

替换特定于连接器的函数调用类的用法

语义内核中的函数调用功能允许开发人员通过两种方式访问 AI 模型选择的函数列表:

  • 在聊天历史记录中使用特定于连接器的函数调用类(例如ChatToolCallChatCompletionsFunctionToolCall,或通过 ToolCalls OpenAI 特定OpenAIChatMessageContent项的属性提供)。
  • 使用与连接器无关的函数调用类(例如 FunctionCallContent,可通过 Items 聊天历史记录中与 ChatMessageContent 连接器无关的项目的属性获取)。

当前和新模型目前支持这两种方法。 但是,我们强烈建议使用与连接器无关的方法访问函数调用,因为它更加灵活,并允许代码处理支持新函数调用模型的任何 AI 连接器。 此外,考虑到当前模型即将弃用,现在是将代码迁移到新模型的好时机,以避免将来发生中断性变更。

因此,如果将手动函数调用与特定于连接器的函数调用类一起使用,如以下代码片段所示:

using System.Text.Json;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using OpenAI.Chat;

var chatHistory = new ChatHistory();

var settings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions };

var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel);

// Current way of accessing function calls using connector specific classes.
var toolCalls = ((OpenAIChatMessageContent)result).ToolCalls.OfType<ChatToolCall>().ToList();

while (toolCalls.Count > 0)
{
    // Adding function call from AI model to chat history
    chatHistory.Add(result);

    // Iterating over the requested function calls and invoking them
    foreach (var toolCall in toolCalls)
    {
        string content = kernel.Plugins.TryGetFunctionAndArguments(toolCall, out KernelFunction? function, out KernelArguments? arguments) ?
            JsonSerializer.Serialize((await function.InvokeAsync(kernel, arguments)).GetValue<object>()) :
            "Unable to find function. Please try again!";

        // Adding the result of the function call to the chat history
        chatHistory.Add(new ChatMessageContent(
            AuthorRole.Tool,
            content,
            metadata: new Dictionary<string, object?>(1) { { OpenAIChatMessageContent.ToolIdProperty, toolCall.Id } }));
    }

    // Sending the functions invocation results back to the AI model to get the final response
    result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel);
    toolCalls = ((OpenAIChatMessageContent)result).ToolCalls.OfType<ChatToolCall>().ToList();
}

可以重构它以使用与连接器无关的类:

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

var chatHistory = new ChatHistory();

var settings = new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false) };

var messageContent = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel);

// New way of accessing function calls using connector agnostic function calling model classes.
var functionCalls = FunctionCallContent.GetFunctionCalls(messageContent).ToArray();

while (functionCalls.Length != 0)
{
    // Adding function call from AI model to chat history
    chatHistory.Add(messageContent);

    // Iterating over the requested function calls and invoking them
    foreach (var functionCall in functionCalls)
    {
        var result = await functionCall.InvokeAsync(kernel);

        chatHistory.Add(result.ToChatMessage());
    }

    // Sending the functions invocation results to the AI model to get the final response
    messageContent = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel);
    functionCalls = FunctionCallContent.GetFunctionCalls(messageContent).ToArray();
}

上面的代码片段演示如何迁移使用 OpenAI AI 连接器的代码。 更新后即可将类似的迁移过程应用于 Gemini 和 Mistral AI 连接器,以支持新的函数调用模型。

后续步骤

现在,将代码迁移到新的函数调用模型后,可以继续了解如何通过引用函数调用行为部分来配置模型的各个方面,这些方面可能更好地与特定方案相对应。

即将推出

更多信息即将推出。

即将推出

更多信息即将推出。