深入探討Function Calling:在Semantic Kernel中的應用實踐

董瑞鹏發表於2024-05-30

引言

上一章我們熟悉了 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 中的運用,為您的專案和應用帶來更多可能性和創新。

示例程式碼
本文原始碼

相關文章