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

引言

上一章我们熟悉了 OpenAIfunction calling 的执行原理,这一章节我们讲解一下 function callingSemantic 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-1106gpt-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

定义方法

static string GetWeatherForCity(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 KernelIChatCompletionService的会话服务

    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。 

最后

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

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

示例代码
本文源代码

发表评论

评论已关闭。

相关文章