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

function,calling,semantic,kernel · 浏览次数 : 0

小编点评

**Function Calling 在 Semantic Kernel 中的应用** 在上一章中我们介绍了 OpenAI 的 function calling 的执行原理,在这一章我们将探讨 function calling 在 Semantic Kernel 的应用。 **ToolCallBehavior 属性** ToolCallBehavior 属性用于设置如何处理工具调用的行为。默认情况下,ToolCallBehavior 属性设置为 ToolCallBehavior.None,这表示模型不会向模型提供内核的插件函数信息,也不会自动处理函数调用请求。 如果我们设置 ToolCallBehavior 属性为 ToolCallBehavior.AutoInvokeKernelFunctions,模型将向模型提供内核的插件函数信息,并会自动处理任何函数调用请求。 **OpenAIPromptExecutionSettings 类** OpenAIPromptExecutionSettings 类用于设置 OpenAI 的函数调用参数。该类包含以下属性: * **Temperature**:控制模型训练的温度。 * **ToolCallBehavior**:设置如何处理工具调用的行为。 * **Other**:包含其他设置参数的字典。 **使用 Semantic Kernel 的函数 calling** 1. 创建一个 OpenAIPromptExecutionSettings 对象,设置 ToolCallBehavior 属性为 ToolCallBehavior.EnableKernelFunctions。 2. 创建一个 ChatHistory 对象,添加系统消息和用户消息。 3. 获取 LLM 的实例并获取其频道服务。 4. 在频道服务中使用 chat.GetChatMessageContentAsync() 获取聊天内容,并添加聊天内容到 ChatHistory 中。 5. 在循环中,调用 channel.GetChatMessageContentAsync() 获取函数调用结果,并将其添加到聊天历史中。 6. 打印聊天历史。 **结论** 在 Semantic Kernel 中的函数 calling 可以灵活地控制工具调用的行为,从手动调用到自动调用。通过设置 OpenAIPromptExecutionSettings 中的 ToolCallBehavior 属性,我们可以优化工具调用体验。

正文

引言

上一章我们熟悉了 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 中的运用,为您的项目和应用带来更多可能性和创新。

示例代码
本文源代码

与深入探讨Function Calling:在Semantic Kernel中的应用实践相似的内容:

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

引言 上一章我们熟悉了 OpenAI 的 function calling 的执行原理,这一章节我们讲解一下 function calling 在 Semantic Kernel 的应用。 在OpenAIPromptExecutionSettings跟 LLM 交互过程中,ToolCallBehav

深入探讨Function Calling:实现外部函数调用的工作原理

引言 Function Calling 是一个允许大型语言模型(如 GPT)在生成文本的过程中调用外部函数或服务的功能。 Function Calling允许我们以 JSON 格式向 LLM 模型描述函数,并使用模型的固有推理能力来决定在生成响应之前是否调用该函数。模型本身不执行函数,而是生成包含函

深入学习Semantic Kernel:创建和配置prompts functions

引言 上一章我们熟悉了一下 Semantic Kernel 的理论知识,Kernel 创建以及简单的Sample熟悉了一下 SK 的基本使用。在Semantic Kernel中的 kernel functions由两部分组成第一部分是prompts functions(提示函数),第二部分Nativ

Service Mesh技术详解

深入探讨Service Mesh的基本概念和核心技术,涵盖了服务发现、负载均衡、断路器与熔断机制,以及数据平面与控制平面的详细工作原理和实现方法。 关注作者,复旦博士,分享云服务领域全维度开发技术。拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,复旦机器人智能实验室成员,国家级大学生赛事

< Python全景系列-5 > 解锁Python并发编程:多线程和多进程的神秘面纱揭晓

深入探讨Python中的并发编程,特别关注多线程和多进程的应用。我们将先从基本概念开始,然后通过详细举例探讨每一种机制,最后分享一些实战经验以及一种优雅的编程技巧。

深入探讨Java面试中内存泄漏:如何识别、预防和解决

引言 在编写和维护Java应用程序时,内存泄漏是一个重要的问题,可能导致性能下降和不稳定性。本文将介绍内存泄漏的概念,为什么它在Java应用程序中如此重要,并明确本文的目标,即识别、预防和解决内存泄漏问题。 内存泄漏的概念 内存泄漏是指应用程序中分配的内存(通常是堆内存)在不再需要时未能正确释放。这

用户空间协议栈设计和netmap综合指南

深入探讨用户空间协议栈设计和netmap技术,以提高网络效率。我们将详细介绍用户空间协议栈的工作原理、优点和挑战,并提供一系列优化策略。

深入探讨安全验证:OAuth2.0、Cookie与Session、JWT令牌、SSO与开放授权平台设计

这篇文章讨论了认证和授权的概念,并探讨了设计权限认证框架的原则。它还比较了Cookie和Session的区别,并探讨了处理分布式部署时的Session保存问题。此外,文章还介绍了CSRF攻击及其防范方法,以及OAuth2.0、JWT令牌和SSO的概念。最后,文章提出了设计开放授权平台时需要考虑的因素。

深入探讨进程间通信的重要性:理解不同的通信机制(上)

本文旨在探讨进程间通信的重要性,并介绍了不同的通信机制,如管道、消息队列、共享内存、信号量、信号和套接字。通过理解这些通信机制的特点和应用场景,可以更好地实现进程间的高效数据共享。同时,本文还强调了同步和互斥机制的重要性,以确保数据的一致性和正确性。最后,还介绍了套接字作为一种跨网络和同一主机上进程间通信的通信机制,为读者提供了更全面的了解。通过阅读本文,读者将能够深入理解进程间通信的概念和不同机制,为实现有效的数据共享提供指导。

深入探讨进程间通信的重要性:理解不同的通信机制(下)

本文旨在探讨进程间通信的重要性,并介绍了不同的通信机制,如管道、消息队列、共享内存、信号量、信号和套接字。通过理解这些通信机制的特点和应用场景,可以更好地实现进程间的高效数据共享。同时,本文还强调了同步和互斥机制的重要性,以确保数据的一致性和正确性。最后,还介绍了套接字作为一种跨网络和同一主机上进程间通信的通信机制,为读者提供了更全面的了解。通过阅读本文,读者将能够深入理解进程间通信的概念和不同机制,为实现有效的数据共享提供指导。