当前位置: 欣欣网 > 码农

深入探讨Function Calling:在Semantic Kernel中的应用实践

2024-05-31码农

引言

上一章我们熟悉了 OpenAI function calling 的执行原理,这一章节我们讲解一下 function calling Semantic Kernel 的应用。

OpenAIPromptExecutionSettings 跟 LLM 交互过程中, ToolCallBehavior 的属性之前我们的章节有介绍过

  • ToolCallBehavior :属性用于获取或设置如何处理工具调用的行为。

    // Enable auto function calling
    OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
    {
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
    };

    1. EnableKernelFunctions :会向模型提供内核的插件函数信息,但不会自动处理函数调用请求。模型需要显式发起函数调用请求,并系统会传播这些请求给适当的处理程序来执行。

     OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions };
    var chatHistory = new ChatHistory();
     ChatMessageContent result = await chat.GetChatMessageContentAsync(chatHistory, settings, kernel);
    //手动调用
     IEnumerable<FunctionCallContent> functionCalls = FunctionCallContent.GetFunctionCalls(result);

    EnableKernelFunctions :需要通过 FunctionCallContent 手动调用

    2. AutoInvokeKernelFunctions :除了向模型提供内核的插件函数信息外,还会尝试自动处理任何函数调用请求。模型发起函数调用请求后,系统会自动执行相应的操作,并将结果返回给模型,而无需模型显式处理函数调用的过程。

  • 模型推荐

    建议使用 OpenAI 的最新模型(如 gpt-3.5-turbo-1106 gpt-4-1106-preview )以获得最佳的工具调用体验。 OpenAI 的最新模型通常具有更好的性能和更高的准确性,因此使用这些模型可以提高工具调用的效果。

    我这里是公司提供的 Azure OpenAI 的服务,我自己通过 yarp 代理了一层做了相关服务的认证

    {
    "InternalAzureOpenAI": {
    "Endpoint""https://localhost:7079",
    "ModelId""gpt-35-turbo-1106",
    "ApiKey""***"
    }
    }

    实战

    接下来我们会问一下大模型当前北京的天气情况

    定义 Prompts

    var template = "我想知道现在北京的天气状况?";

    定义 kernel

    var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion(config.ModelId, endpoint: config.Endpoint, apiKey: config.ApiKey)
    .Build();

    注册 kernel function 到 plugins

    定义方法

    staticstringGetWeatherForCity(string cityName)
    {
    return$"{cityName} 25°,天气晴朗。";
    }

    为 Kernel 提供插件

     kernel.ImportPluginFromFunctions("WeatherPlugin"new[]
     {
    kernel.CreateFunctionFromMethod(GetWeatherForCity, "GetWeatherForCity""获取指定城市的天气")
     });

    手动调用 function calling

    根据上面的描述 手动处理 function calling 的关键实际上是 ToolCallBehavior.EnableKernelFunctions 参数。

    OpenAIPromptExecutionSettings settings = new OpenAIPromptExecutionSettings()
    {
    Temperature = 0,
    ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions
    };

    需要用到 Semantic Kernel IChatCompletionService 的会话服务

    var chatHistory = new ChatHistory();
    chatHistory.AddSystemMessage("You are a useful assistant.");
    chatHistory.AddUserMessage(template);
    Console.WriteLine($"User: {template}");
    var chat = kernel.GetRequiredService<IChatCompletionService>();
    while (true)
    {
    ChatMessageContent result = await chat.GetChatMessageContentAsync(chatHistory, settings, kernel);
    if (result.Content is not null)
    {
    Console.Write(result.Content);
    }
    IEnumerable<FunctionCallContent> functionCalls = FunctionCallContent.GetFunctionCalls(result);
    if (!functionCalls.Any())
    {
    break;
    }
    chatHistory.Add(result); // Adding LLM response containing function calls(requests) to chat history as it's required by LLMs.
    foreach (var functionCall in functionCalls)
    {
    try
    {
    FunctionResultContent resultContent = await functionCall.InvokeAsync(kernel); // Executing each function.
    chatHistory.Add(resultContent.ToChatMessage());
    }
    catch (Exception ex)
    {
    chatHistory.Add(new FunctionResultContent(functionCall, ex).ToChatMessage());
    }
    }
    Console.WriteLine();
    }



    输出

    =====>手动function calling
    User: 我想知道现在北京的天气状况?
    Assistant:现在北京的天气是晴朗,气温为25°C。

    自动调用 function calling

    和手动的区别就是上面描述的 OpenAIPromptExecutionSettings 配置的 ToolCallBehavior 属性值不同

    OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new OpenAIPromptExecutionSettings()
    {
    Temperature = 0,
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
    };

    自动 function calling 从本质上来讲是隐藏了跟大模型多次交互的逻辑,有 Semantic Kernel 框架自动帮我们调用

    核心代码

    var chatHistory = new ChatHistory();
    chatHistory.AddSystemMessage("You are a useful assistant.");
    chatHistory.AddUserMessage(template);
    Console.WriteLine($"User: {template}");
    var chatService = kernel.GetRequiredService<IChatCompletionService>();
    var result = await chatService.GetChatMessageContentAsync(chatHistory, openAIPromptExecutionSettings, kernel);
    Console.Write("Assistant:" + result.ToString());

    输出

    =====>自动function calling
    User: 我想知道现在北京的天气状况?
    Assistant:北京现在的天气状况是晴朗,气温为25°C。

    最后

    在本章中,我们探讨了在 OpenAI function calling Semantic Kernel 中的应用。通过对 ToolCallBehavior 属性的设置,我们可以灵活地控制工具调用的行为,从手动调用到自动调用,为用户提供了更加便捷和高效的体验。

    建议在实践中使用 OpenAI 的最新模型(如 gpt-3.5-turbo-1106 gpt-4-1106-preview )以获得最佳的工具调用效果。同时,通过合理配置 OpenAIPromptExecutionSettings 中的参数,可以更好地适配不同的场景和需求。希望本章内容能够帮助您更深入地理解 function calling Semantic Kernel 中的运用,为您的项目和应用带来更多可能性和创新。

    示例代码 本文源代码 [1]

    参考资料

    [1]

    本文源代码: https://github.com/Dong-Ruipeng/SK-WorkBook