共用方式為


什麼是 Planner?

一旦您有多個外掛程式,您接著需要一種方式讓 AI 代理程式一起使用,以解決使用者的需求。 這是規劃的所在。

在早期,Semantic Kernel 引進了規劃工具的概念,這些規劃工具使用提示來要求 AI 選擇要叫用哪些函式。 不過,由於引進語意核心,OpenAI 引進了一種原生方式,讓模型叫用或「呼叫」函式: 函式呼叫。 自那以後,雙子座、Claude 和Mistral等其他 AI 模型已採用函式呼叫作為核心功能,使其成為跨模型支援的功能。

由於這些進步,Semantic Kernel 已進化為使用函式呼叫作為規劃和執行工作的主要方式。

重要

函式呼叫僅適用於 0613 或更新的 OpenAI 模型。 如果您使用較舊的模型(例如 0314),這項功能會傳回錯誤。 建議您使用最新的 OpenAI 模型來利用這項功能。

函式呼叫如何建立「方案」?

簡單來說,函數呼叫只是讓 AI 使用正確參數叫用函式的一種方式。 例如,使用者想要開啟燈泡。 假設 AI 有正確的外掛程式,它可以呼叫 函式來開啟光線。

角色 訊息
🔵使用者 請開啟淺色 #1
🔴小幫手(函數調用) Lights.change_state(1, { "isOn": true })
🟢工具 { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴小幫手 燈現在開啟

但是,如果使用者不知道光線的標識符,該怎麼辦? 或者,如果使用者想要開啟所有燈光,該怎麼辦? 這是規劃的所在。 現今的 LLM 模型能夠反覆呼叫函式來解決使用者的需求。 這可藉由建立意見反應迴圈來完成,讓 AI 可以呼叫函式、檢查結果,然後決定接下來該怎麼做。

例如,使用者可能會要求 AI「切換」燈泡。 AI 必須先檢查燈泡的狀態,再決定是否將燈泡開啟或關閉。

角色 訊息
🔵使用者 請切換所有燈光
🔴小幫手(函數調用) Lights.get_lights()
🟢工具 { "lights": [ { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }, { "id": 2, "name": "Ceiling Light", "isOn": false, "brightness": 0, "hex": "FFFFFF" } ] }
🔴小幫手(函數調用) Lights.change_state(1, { "isOn": false }) Lights.change_state(2, { "isOn": true })
🟢工具 { "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 0, "hex": "FFFFFF" }
🟢工具 { "id": 2, "name": "Ceiling Light", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴小幫手 已切換燈

注意

在此範例中,您也看到平行函式呼叫。 這是 AI 可以同時呼叫多個函式的位置。 這是一項功能強大的功能,可協助 AI 更快速地解決複雜的工作。 它已於 1106 年新增至 OpenAI 模型。

自動規劃迴圈

支援在沒有語意核心的情況下呼叫函式相當複雜。 您必須撰寫可完成下列作業的循環:

  1. 為每個函式建立 JSON 架構
  2. 提供 LLM 與先前的聊天記錄和函式架構
  3. 剖析 LLM 的回應,以判斷其是否要以訊息回復或呼叫函式
  4. 如果 LLM 想要呼叫函式,您必須從 LLM 的回應中剖析函式名稱和參數
  5. 使用正確的參數叫用函式
  6. 傳回函式的結果,讓 LLM 可以判斷下一步應該執行的動作
  7. 重複步驟 2-6,直到 LLM 決定已完成工作或需要用戶協助

在語意核心中,我們可讓您輕鬆地使用函式呼叫,方法是為您自動化此迴圈。 這可讓您專注於建置解決使用者需求所需的外掛程式。

注意

瞭解函式呼叫循環的運作方式對於建置高效能且可靠的 AI 代理程式而言非常重要。 如需循環運作方式的深入探討,請參閱 函式呼叫 一文。

使用自動函數呼叫

若要在 Semantic Kernel 中使用自動函數呼叫,您需要執行下列動作:

  1. 向核心註冊外掛程式
  2. 建立執行設定物件,告知 AI 自動呼叫函式
  3. 使用聊天歷程記錄和核心叫用聊天完成服務
using System.ComponentModel;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

// 1. Create the kernel with the Lights plugin
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey);
builder.Plugins.AddFromType<LightsPlugin>("Lights");
Kernel kernel = builder.Build();

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

// 2. Enable automatic function calling
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() 
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

var history = new ChatHistory();

string? userInput;
do {
    // Collect user input
    Console.Write("User > ");
    userInput = Console.ReadLine();

    // Add user input
    history.AddUserMessage(userInput);

    // 3. Get the response from the AI with automatic function calling
    var result = await chatCompletionService.GetChatMessageContentAsync(
        history,
        executionSettings: openAIPromptExecutionSettings,
        kernel: kernel);

    // Print the results
    Console.WriteLine("Assistant > " + result);

    // Add the message from the agent to the chat history
    history.AddMessage(result.Role, result.Content ?? string.Empty);
} while (userInput is not null)
import asyncio

from semantic_kernel import Kernel
from semantic_kernel.functions import kernel_function
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.chat_completion_client_base import ChatCompletionClientBase
from semantic_kernel.contents.chat_history import ChatHistory
from semantic_kernel.functions.kernel_arguments import KernelArguments

from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.azure_chat_prompt_execution_settings import (
    AzureChatPromptExecutionSettings,
)

async def main():
    # 1. Create the kernel with the Lights plugin
    kernel = Kernel()
    kernel.add_service(AzureChatCompletion(
        deployment_name="your_models_deployment_name",
        api_key="your_api_key",
        base_url="your_base_url",
    ))
    kernel.add_plugin(
        LightsPlugin(),
        plugin_name="Lights",
    )

    chat_completion : AzureChatCompletion = kernel.get_service(type=ChatCompletionClientBase)

    # 2. Enable automatic function calling
    execution_settings = AzureChatPromptExecutionSettings()
    execution_settings.function_call_behavior = FunctionChoiceBehavior.Auto()

    # Create a history of the conversation
    history = ChatHistory()

    userInput = None
    while True:
        # Collect user input
        userInput = input("User > ")

        # Terminate the loop if the user says "exit"
        if userInput == "exit":
            break

        # Add user input to the history
        history.add_user_message(userInput)

        # 3. Get the response from the AI with automatic function calling
        result = (await chat_completion.get_chat_message_contents(
            chat_history=history,
            settings=execution_settings,
            kernel=kernel,
            arguments=KernelArguments(),
        ))[0]

        # Print the results
        print("Assistant > " + str(result))

        # Add the message from the agent to the chat history
        history.add_message(result)

# Run the main function
if __name__ == "__main__":
    asyncio.run(main())

    OpenAIAsyncClient client = new OpenAIClientBuilder()
        .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
        .endpoint(CLIENT_ENDPOINT)
        .buildAsyncClient();

    // Import the LightsPlugin
    KernelPlugin lightPlugin = KernelPluginFactory.createFromObject(new LightsPlugin(),
        "LightsPlugin");

    // Create your AI service client
    ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
        .withModelId(MODEL_ID)
        .withOpenAIAsyncClient(client)
        .build();

    // Create a kernel with Azure OpenAI chat completion and plugin
    Kernel kernel = Kernel.builder()
        .withAIService(ChatCompletionService.class, chatCompletionService)
        .withPlugin(lightPlugin)
        .build();

    // Add a converter to the kernel to show it how to serialise LightModel objects into a prompt
    ContextVariableTypes
        .addGlobalConverter(
            ContextVariableTypeConverter.builder(LightModel.class)
                .toPromptString(new Gson()::toJson)
                .build());

    // Enable planning
    InvocationContext invocationContext = new InvocationContext.Builder()
        .withReturnMode(InvocationReturnMode.LAST_MESSAGE_ONLY)
        .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true))
        .build();

    // Create a history to store the conversation
    ChatHistory history = new ChatHistory();

    // Initiate a back-and-forth chat
    Scanner scanner = new Scanner(System.in);
    String userInput;
    do {
      // Collect user input
      System.out.print("User > ");

      userInput = scanner.nextLine();
      // Add user input
      history.addUserMessage(userInput);

      // Prompt AI for response to users input
      List<ChatMessageContent<?>> results = chatCompletionService
          .getChatMessageContentsAsync(history, kernel, invocationContext)
          .block();

      for (ChatMessageContent<?> result : results) {
        // Print the results
        if (result.getAuthorRole() == AuthorRole.ASSISTANT && result.getContent() != null) {
          System.out.println("Assistant > " + result);
        }
        // Add the message from the agent to the chat history
        history.addMessage(result);
      }
    } while (userInput != null && !userInput.isEmpty());

當您使用自動函數呼叫時,會自動規劃迴圈中的所有步驟都會為您處理,並新增至 ChatHistory 物件。 函式呼叫迴圈完成之後,您可以檢查 ChatHistory 物件,以查看語意核心所提供的所有函式呼叫和結果。

函式呼叫 Stepwise 和 Handlebars planners 呢?

Stepwise 和 Handlebars planners 仍可在語意核心中使用。 不過,我們建議針對大部分工作使用函式呼叫,因為它功能更強大且更容易使用。 在語意核心的未來版本中,Stepwise 和 Handlebars 規劃工具都會被取代。

瞭解如何將 Stepwise Planner 移轉至自動函數呼叫

警告

如果您要建置新的 AI 代理程式,建議您 不要 使用 Stepwise 或 Handlebars 規劃工具。 相反地,請使用函式呼叫,因為它功能更強大且更容易使用。

下一步

既然您已了解規劃工具在語意核心中的運作方式,您可以深入瞭解如何影響 AI 代理程式,讓他們能代表使用者最好地規劃和執行工作。