函数调用模式

当 AI 模型收到包含函数列表的提示时,可以选择其中一个或多个用于调用以完成提示。 模型选择函数时,需要 由语义内核调用 它。

语义内核中的函数调用子系统有两种函数调用模式: 自动手动

根据调用模式,语义内核要么执行端到端函数调用,要么为调用方提供对函数调用进程的控制。

自动函数调用

自动函数调用是语义内核函数调用子系统的默认模式。 当 AI 模型选择一个或多个函数时,语义内核会自动调用所选函数。 这些函数调用的结果将添加到聊天历史记录,并在后续请求中自动发送到模型。 然后,模型会根据聊天历史记录的原因,根据需要选择其他函数,或生成最终响应。 此方法是完全自动化的,无需调用方进行手动干预。

此示例演示如何在语义内核中使用自动函数调用。 AI 模型决定要调用哪些函数来完成提示,语义内核执行其余操作并自动调用它们。

using Microsoft.SemanticKernel;

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<WeatherForecastUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

// By default, functions are set to be automatically invoked.  
// If you want to explicitly enable this behavior, you can do so with the following code:  
// PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: true) };  
PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }; 

await kernel.InvokePromptAsync("Given the current time of day and weather, what is the likely color of the sky in Boston?", new(settings));

某些 AI 模型支持并行函数调用,其中模型选择多个函数进行调用。 在调用所选函数需要很长时间时,这非常有用。 例如,AI 可以选择同时检索最新新闻和当前时间,而不是按函数进行往返。

语义内核可以通过两种不同的方式调用这些函数:

  • 顺序:函数逐个调用。 这是默认行为。
  • 同时:同时调用函数。 可以通过将 FunctionChoiceBehaviorOptions.AllowConcurrentInvocation 属性设置为 true启用此功能,如以下示例所示。
using Microsoft.SemanticKernel;

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<NewsUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

// Enable concurrent invocation of functions to get the latest news and the current time.
FunctionChoiceBehaviorOptions options = new() { AllowConcurrentInvocation = true };

PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(options: options) }; 

await kernel.InvokePromptAsync("Good morning! What is the current time and latest news headlines?", new(settings));

手动函数调用

如果调用方希望更好地控制函数调用过程,则可以使用手动函数调用。

启用手动函数调用后,语义内核不会自动调用 AI 模型选择的函数。 相反,它会向调用方返回所选函数的列表,然后可以决定要调用哪些函数、按顺序或并行调用它们、处理异常等。 函数调用结果需要添加到聊天历史记录并返回到模型,这会导致有关这些结果的原因,并确定是选择其他函数还是生成最终响应。

下面的示例演示如何使用手动函数调用。

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

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<WeatherForecastUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

// Manual function invocation needs to be enabled explicitly by setting autoInvoke to false.
PromptExecutionSettings settings = new() { FunctionChoiceBehavior = Microsoft.SemanticKernel.FunctionChoiceBehavior.Auto(autoInvoke: false) };

ChatHistory chatHistory = [];
chatHistory.AddUserMessage("Given the current time of day and weather, what is the likely color of the sky in Boston?");

while (true)
{
    ChatMessageContent result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel);

    // Check if the AI model has generated a response.
    if (result.Content is not null)
    {
        Console.Write(result.Content);
        // Sample output: "Considering the current weather conditions in Boston with a tornado watch in effect resulting in potential severe thunderstorms,
        // the sky color is likely unusual such as green, yellow, or dark gray. Please stay safe and follow instructions from local authorities."
        break;
    }

    // Adding AI model response containing chosen functions to chat history as it's required by the models to preserve the context.
    chatHistory.Add(result); 

    // Check if the AI model has chosen any function for invocation.
    IEnumerable<FunctionCallContent> functionCalls = FunctionCallContent.GetFunctionCalls(result);
    if (!functionCalls.Any())
    {
        break;
    }

    // Sequentially iterating over each chosen function, invoke it, and add the result to the chat history.
    foreach (FunctionCallContent functionCall in functionCalls)
    {
        try
        {
            // Invoking the function
            FunctionResultContent resultContent = await functionCall.InvokeAsync(kernel);

            // Adding the function result to the chat history
            chatHistory.Add(resultContent.ToChatMessage());
        }
        catch (Exception ex)
        {
            // Adding function exception to the chat history.
            chatHistory.Add(new FunctionResultContent(functionCall, ex).ToChatMessage());
            // or
            //chatHistory.Add(new FunctionResultContent(functionCall, "Error details that the AI model can reason about.").ToChatMessage());
        }
    }
}

注意

FunctionCallContent 和 FunctionResultContent 类分别用于表示 AI 模型函数调用和语义内核函数调用结果。 它们包含有关所选函数的信息,例如函数 ID、名称和参数,以及函数调用结果,例如函数调用 ID 和结果。

即将推出

更多信息即将推出。

即将推出

更多信息即将推出。