Dela via


Vad är en planerare?

När du har flera plugin-program behöver du ett sätt för AI-agenten att använda dem tillsammans för att lösa en användares behov. Det är här planeringen kommer in.

Tidigt introducerade Semantic Kernel begreppet planerare som använde uppmaningar för att begära att AI:n skulle välja vilka funktioner som ska anropas. Eftersom semantisk kernel introducerades introducerade OpenAI dock ett internt sätt för modellen att anropa eller "anropa" en funktion: funktionsanrop. Andra AI-modeller som Gemini, Claude och Mistral har sedan dess antagit funktionsanrop som en kärnfunktion, vilket gör det till en funktion som stöds av flera modeller.

På grund av dessa framsteg har Semantic Kernel utvecklats till att använda funktionsanrop som det primära sättet att planera och köra uppgifter.

Viktigt!

Funktionsanrop är endast tillgängligt i OpenAI-modeller som är 0613 eller senare. Om du använder en äldre modell (t.ex. 0314) returnerar den här funktionen ett fel. Vi rekommenderar att du använder de senaste OpenAI-modellerna för att dra nytta av den här funktionen.

Hur skapar funktionsanrop en "plan"?

Som enklast är funktionsanrop bara ett sätt för en AI att anropa en funktion med rätt parametrar. Ta till exempel en användare vill slå på en glödlampa. Förutsatt att AI:n har rätt plugin-program kan den anropa funktionen för att tända ljuset.

Roll Meddelande
🔵Användare Tänd lampan #1
🔴Assistent (funktionsanrop) Lights.change_state(1, { "isOn": true })
🟢Verktyg { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴Assistent Lampan är nu på

Men vad händer om användaren inte känner till ljusets ID? Eller vad händer om användaren vill aktivera alla lampor? Det är här planeringen kommer in. Dagens LLM-modeller kan iterativt anropa funktioner för att lösa en användares behov. Detta uppnås genom att skapa en feedbackloop där AI:n kan anropa en funktion, kontrollera resultatet och sedan bestämma vad som ska göras härnäst.

En användare kan till exempel be AI:n att "växla" en glödlampa. AI:n måste först kontrollera glödlampans tillstånd innan du bestämmer dig för om den ska slås på eller stängas av.

Roll Meddelande
🔵Användare Växla alla lampor
🔴Assistent (funktionsanrop) Lights.get_lights()
🟢Verktyg { "lights": [ { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }, { "id": 2, "name": "Ceiling Light", "isOn": false, "brightness": 0, "hex": "FFFFFF" } ] }
🔴Assistent (funktionsanrop) Lights.change_state(1, { "isOn": false }) Lights.change_state(2, { "isOn": true })
🟢Verktyg { "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 0, "hex": "FFFFFF" }
🟢Verktyg { "id": 2, "name": "Ceiling Light", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴Assistent Lamporna har växlats

Kommentar

I det här exemplet såg du även parallella funktionsanrop. Det är här AI:n kan anropa flera funktioner samtidigt. Det här är en kraftfull funktion som kan hjälpa AI att lösa komplexa uppgifter snabbare. Den lades till i OpenAI-modellerna 1106.

Den automatiska planeringsloopen

Stöd för funktionsanrop utan semantisk kernel är relativt komplext. Du skulle behöva skriva en loop som skulle göra följande:

  1. Skapa JSON-scheman för var och en av dina funktioner
  2. Ange LLM med tidigare chatthistorik och funktionsscheman
  3. Parsa LLM-svaret för att avgöra om den vill svara med ett meddelande eller anropa en funktion
  4. Om LLM vill anropa en funktion måste du parsa funktionsnamnet och parametrarna från LLM:s svar
  5. Anropa funktionen med rätt parametrar
  6. Returnera resultatet av funktionen så att LLM kan avgöra vad den ska göra härnäst
  7. Upprepa steg 2–6 tills LLM beslutar att den har slutfört uppgiften eller behöver hjälp från användaren

I Semantic Kernel gör vi det enkelt att använda funktionsanrop genom att automatisera den här loopen åt dig. På så sätt kan du fokusera på att skapa de plugin-program som behövs för att lösa användarens behov.

Kommentar

Det är viktigt att förstå hur funktionsanropsloopen fungerar för att skapa högpresterande och tillförlitliga AI-agenter. En djupgående titt på hur loopen fungerar finns i artikeln funktionsanrop.

Använda automatiska funktionsanrop

Om du vill använda automatiska funktionsanrop i semantisk kernel måste du göra följande:

  1. Registrera plugin-programmet med kerneln
  2. Skapa ett körningsinställningsobjekt som instruerar AI:n att automatiskt anropa funktioner
  3. Anropa tjänsten för chattens slutförande med chatthistoriken och kerneln
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());

När du använder automatiska funktionsanrop hanteras alla steg i den automatiska planeringsloopen åt dig och läggs till i ChatHistory objektet. När funktionsanropsloopen är klar kan du granska ChatHistory objektet för att se alla funktionsanrop som gjorts och resultat från Semantic Kernel.

Hur är det med planerare för funktionssamtal stegvisa och styren?

Stepwise- och Handlebars-planerare är fortfarande tillgängliga i semantisk kernel. Vi rekommenderar dock att du använder funktionsanrop för de flesta uppgifter eftersom det är kraftfullare och enklare att använda. Både Stepwise- och Handlebars-planerarna kommer att bli inaktuella i en framtida version av semantisk kernel.

Lär dig hur du migrerar Stepwise Planner till autofunktionsanrop.

Varning

Om du skapar en ny AI-agent rekommenderar vi att du inte använder stepwise- eller handlebars-planerarna. Använd i stället funktionsanrop eftersom det är kraftfullare och enklare att använda.

Nästa steg

Nu när du förstår hur planerare fungerar i Semantic Kernel kan du lära dig mer om hur du påverkar DIN AI-agent så att de bäst planerar och utför uppgifter åt dina användare.