Planner とは

複数のプラグインを作成したら、AI エージェントがそれらを一緒に使用してユーザーのニーズを解決する方法が必要になります。 ここで計画が立ちます。

セマンティック カーネルは早い段階で、プロンプトを使用して呼び出す関数を選択するよう AI に要求するプランナーの概念を導入しました。 ただし、セマンティック カーネルが導入されたので、OpenAI では、モデルが関数を呼び出すか、関数呼び出しを "呼び出す" ためのネイティブな方法 導入されました。 Gemini、Claude、Mistral などの他の AI モデルでは、その後、コア機能として関数呼び出しが採用され、モデル間でサポートされる機能となっています。

このような進歩により、セマンティック カーネルは、タスクを計画および実行するための主要な方法として関数呼び出しを使用するように進化しました。

重要

関数呼び出しは、0613 以降の OpenAI モデルでのみ使用できます。 古いモデル (0314 など) を使用している場合、この機能はエラーを返します。 この機能を利用するには、最新の OpenAI モデルを使用することをお勧めします。

関数呼び出しによって "プラン" はどのように作成されますか?

最も単純な関数呼び出しは、AI が適切なパラメーターを使用して関数を呼び出すための方法にすぎません。 たとえば、ユーザーが電球をオンにしたいとします。 AI が適切なプラグインを持っていると仮定すると、関数を呼び出してライトをオンにすることができます。

ロール メッセージ
🔵User ライト #1 をオンにしてください
🔴アシスタント (関数呼び出し) Lights.change_state(1, { "isOn": true })
🟢ツール { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴アシスタント ランプがオンになりました

しかし、ユーザーがライトの ID を知らない場合はどうでしょうか。 または、ユーザーがすべてのライトをオンにしたい場合はどうなりますか? ここで計画が立ちます。 現在の LLM モデルは、ユーザーのニーズを解決するために関数を繰り返し呼び出す機能を備えています。 これは、AI が関数を呼び出し、結果を確認し、次に何を行うかを決定できるフィードバック ループを作成することによって実現されます。

たとえば、ユーザーは、電球を "切り替える" よう AI に求める場合があります。 AI では、まず電球の状態を確認してから、電源をオンまたはオフにするかどうかを決定する必要があります。

ロール メッセージ
🔵User すべてのライトを切り替えてください
🔴アシスタント (関数呼び出し) 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" }
🔴アシスタント ライトが切り替えられた

Note

この例では、並列関数呼び出しも確認しました。 ここで、AI は複数の関数を同時に呼び出すことができます。 これは、AI がより迅速に複雑なタスクを解決するのに役立つ強力な機能です。 1106年に OpenAI モデルに追加されました。

自動計画ループ

セマンティック カーネルを使用しない関数呼び出しのサポートは比較的複雑です。 次の処理を実行するループを記述する必要があります。

  1. 各関数の JSON スキーマを作成する
  2. 以前のチャット履歴と関数スキーマを LLM に提供する
  3. LLM の応答を解析して、メッセージで応答するか、関数を呼び出すかを判断します
  4. LLM が関数を呼び出す場合は、LLM の応答から関数名とパラメーターを解析する必要があります
  5. 適切なパラメーターを使用して関数を呼び出す
  6. LLM が次に何をすべきかを判断できるように、関数の結果を返します。
  7. LLM がタスクを完了したと判断するか、ユーザーの支援が必要になるまで、手順 2 から 6 を繰り返します。

セマンティック カーネルでは、このループを自動化することで関数呼び出しを簡単に使用できます。 これにより、ユーザーのニーズを解決するために必要なプラグインの構築に集中できます。

Note

パフォーマンスと信頼性の高い AI エージェントを構築するには、関数呼び出しループのしくみを理解することが不可欠です。 ループのしくみの詳細については、 関数呼び出し 記事を参照してください。

自動関数呼び出しの使用

セマンティック カーネルで自動関数呼び出しを使用するには、次の操作を行う必要があります。

  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 プランナーは、セマンティック カーネルで引き続き使用できます。 ただし、より強力で使いやすいため、ほとんどのタスクに関数呼び出しを使用することをお勧めします。 Stepwise と Handlebars の両方のプランナーは、セマンティック カーネルの将来のリリースで非推奨となる予定です。

Stepwise Planner を自動関数呼び出しに する方法について説明

注意事項

新しい AI エージェントを構築する場合は、Stepwise または Handlebars プランナー使用することをお勧めします。 代わりに、より強力で使いやすい関数呼び出しを使用してください。

次のステップ

セマンティック カーネルでのプランナーの動作を理解したので、AI エージェントがユーザーに代わってタスクを最適に計画および実行できるように、AI エージェントに与える影響について詳しく学習できます。