Udostępnij za pośrednictwem


Planowanie

Gdy masz wiele wtyczek, potrzebujesz sposobu, aby agent sztucznej inteligencji używał ich razem, aby rozwiązać potrzeby użytkownika. W tym momencie wkracza planowanie.

Na początku Semantic Kernel wprowadziło koncepcję planistów, które używały monitów, aby zażądać od AI wyboru funkcji do wywołania. Ponieważ wprowadzono jądro semantyczne, OpenAI wprowadziło jednak natywny sposób, aby model mógł wywołać funkcję: wywoływanie funkcji. Inne modele sztucznej inteligencji, takie jak Gemini, Claude i Mistral, przyjęły od tego czasu wywoływanie funkcji jako podstawową zdolność, co czyni ją funkcją obsługiwaną przez wiele modeli.

Ze względu na te postępy semantyczne jądro ewoluowało, aby używać wywoływania funkcji jako podstawowego sposobu planowania i wykonywania zadań.

Ważne

Wywoływanie funkcji jest dostępne tylko w modelach OpenAI, które są 0613 lub nowsze. Jeśli używasz starszego modelu (np. 0314), ta funkcja zwróci błąd. Zalecamy korzystanie z tej funkcji przy użyciu najnowszych modeli OpenAI.

Jak wywoływanie funkcji tworzy "plan"?

W najprostszej formie wywołanie funkcji to sposób, w jaki sztuczna inteligencja może uruchomić funkcję z odpowiednimi parametrami. Załóżmy na przykład, że użytkownik chce włączyć żarówkę. Zakładając, że sztuczna inteligencja ma właściwą wtyczkę, może wywołać funkcję , aby włączyć światło.

Rola Komunikat
🔵 użytkownika Włącz światło #1
🔴 Asystent (wywołanie funkcji) Lights.change_state(1, { "isOn": true })
🟢 narzędzia { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴 Asystent Lampa jest teraz włączona

Ale co zrobić, jeśli użytkownik nie zna identyfikatora światła? A co zrobić, jeśli użytkownik chce włączyć wszystkie światła? Na tym etapie kluczową rolę odgrywa planowanie. Dzisiejsze modele LLM są w stanie iteracyjnie wywoływać funkcje, aby rozwiązać potrzeby użytkownika. Osiąga się to poprzez utworzenie pętli sprzężenia zwrotnego, w której sztuczna inteligencja może wywołać funkcję, sprawdzić wynik, a następnie zdecydować, co zrobić dalej.

Na przykład użytkownik może poprosić sztuczną inteligencję o przełączenie żarówki. Przed podjęciem decyzji o włączeniu lub wyłączeniu sztucznej inteligencji należy najpierw sprawdzić stan żarówki.

Rola Komunikat
🔵 użytkownika Przełącz wszystkie światła
🔴 Asystent (wywołanie funkcji) Lights.get_lights()
🟢 narzędzia { "lights": [ { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }, { "id": 2, "name": "Ceiling Light", "isOn": false, "brightness": 0, "hex": "FFFFFF" } ] }
🔴 Asystent (wywołanie funkcji) Lights.change_state(1, { "isOn": false }) Lights.change_state(2, { "isOn": true })
🟢 narzędzia { "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 0, "hex": "FFFFFF" }
🟢 narzędzia { "id": 2, "name": "Ceiling Light", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴 Asystent Światła zostały zmienione

Uwaga / Notatka

W tym przykładzie przedstawiono również wywołanie funkcji równoległych. W tym miejscu sztuczna inteligencja może jednocześnie wywoływać wiele funkcji. Jest to zaawansowana funkcja, która może pomóc sztucznej inteligencji szybciej rozwiązywać złożone zadania. Dodano go do modeli OpenAI w wersji 1106.

Pętla automatycznego planowania

Obsługa wywoływania funkcji bez jądra semantycznego jest stosunkowo złożona. Należy napisać pętlę, która będzie wykonywać następujące czynności:

  1. Tworzenie schematów JSON dla każdej funkcji
  2. Dostarcz LLM wcześniejszą historię czatu i schematy funkcji
  3. Przeanalizuj odpowiedź LLM, aby określić, czy chce odpowiedzieć za pomocą wiadomości lub wywołać funkcję
  4. Jeśli model LLM chce wywołać funkcję, należy przeanalizować nazwę i parametry funkcji z odpowiedzi LLM.
  5. Wywoływanie funkcji przy użyciu odpowiednich parametrów
  6. Zwróć wyniki funkcji, aby LLM mógł zadecydować, co zrobić dalej.
  7. Powtórz kroki od 2 do 6, dopóki LLM nie zdecyduje, że zadanie zostało ukończone lub potrzebuje pomocy od użytkownika.

W semantycznym jądrze ułatwiamy korzystanie z wywoływania funkcji, automatyzując tę pętlę. Dzięki temu można skupić się na tworzeniu wtyczek potrzebnych do rozwiązania potrzeb użytkownika.

Uwaga / Notatka

Zrozumienie, jak działa pętla wywoływania funkcji, jest niezbędne do tworzenia wydajnych i niezawodnych agentów sztucznej inteligencji. Szczegółowe informacje na temat działania pętli można znaleźć w artykule dotyczącym wywoływania funkcji .

Używanie automatycznego wywoływania funkcji

Aby użyć automatycznego wywoływania funkcji w jądrze semantycznym, należy wykonać następujące czynności:

  1. Rejestrowanie wtyczki za pomocą jądra
  2. Tworzenie obiektu ustawień wykonywania, który informuje sztuczną inteligencję o automatycznym wywoływaniu funkcji
  3. Wywołaj usługę uzupełniania czatu z historią czatu i jądrem

Wskazówka

Poniższy przykładowy kod używa LightsPlugin, który jest zdefiniowany tutaj.

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.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.chat_completion_client_base import ChatCompletionClientBase
from semantic_kernel.connectors.ai.open_ai import (
    AzureChatCompletion,
    AzureChatPromptExecutionSettings,
)
from semantic_kernel.contents import ChatHistory
from semantic_kernel.functions import kernel_function

async def main():
    # 1. Create the kernel with the Lights plugin
    kernel = Kernel()
    kernel.add_service(AzureChatCompletion())
    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_choice_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_content(
            chat_history=history,
            settings=execution_settings,
            kernel=kernel,
        )

        # 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());

Gdy używasz automatycznego uruchamiania funkcji, wszystkie kroki w pętli automatycznego planowania są obsługiwane automatycznie i dodawane do obiektu ChatHistory. Po zakończeniu pętli wywoływania funkcji można sprawdzić obiekt ChatHistory, aby zobaczyć wszystkie wykonane wywołania funkcji i wyniki dostarczone przez Semantyczne Jądro.

Co się stało z planistami Stepwise i Handlebars?

Planiści Stepwise i Handlebars zostali wycofani i usunięci z pakietu Semantic Kernel. Te planery nie są już obsługiwane w Pythonie, .NET lub Javie.

Zalecamy używanie wywoływania funkcji, które jest zarówno bardziej zaawansowane, jak i łatwiejsze w użyciu w większości scenariuszy.

Aby zaktualizować istniejące rozwiązania, postępuj zgodnie z naszym Przewodnikiem po migracji krokowej Planisty.

Wskazówka

W przypadku nowych agentów sztucznej inteligencji należy używać wywoływania funkcji zamiast przestarzałych narzędzi planowania. Zapewnia lepszą elastyczność, wbudowaną obsługę narzędzi i prostsze środowisko programistyczne.

Dalsze kroki

Teraz, gdy już wiesz, jak planiści pracują w semantycznym jądrze, możesz dowiedzieć się więcej o tym, jak wpływać na agenta sztucznej inteligencji, aby w najlepszy sposób planował i wykonywał zadania w imieniu użytkowników.