Udostępnij za pośrednictwem


Co to jest Planista?

Gdy masz wiele wtyczek, potrzebujesz sposobu, aby agent sztucznej inteligencji używał ich razem, aby rozwiązać potrzeby użytkownika. Jest to miejsce, w którym przychodzi planowanie.

Na początku semantyczne jądro wprowadziło koncepcję planistów, które używały monitów o zażądanie użycia sztucznej inteligencji w celu wybrania funkcji do wywołania. Ponieważ wprowadzono jądro semantyczne, openAI wprowadziło jednak natywny sposób wywoływania lub wywoływania funkcji przez model: wywoływanie funkcji. Inne modele sztucznej inteligencji, takie jak Gemini, Claude i Mistral, od tego czasu przyjmują funkcję wywołującą jako podstawową funkcję, dzięki czemu jest to funkcja obsługiwana 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 funkcja wywołująca tworzy "plan"?

Najprostsze wywołanie funkcji to tylko sposób wywoływania przez sztuczną inteligencję na wywołanie funkcji 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żytkownik Włącz światło #1
🔴Asystent (wywołanie funkcji) Lights.change_state(1, { "isOn": true })
🟢Tool (Narzędzie dostępu do centrum danych) { "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? Jest to miejsce, w którym przychodzi planowanie. Dzisiejsze modele LLM są w stanie iteracyjnie wywoływać funkcje, aby rozwiązać potrzeby użytkownika. Jest to realizowane przez utworzenie pętli opinii, 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żytkownik Przełącz wszystkie światła
🔴Asystent (wywołanie funkcji) Lights.get_lights()
🟢Tool (Narzędzie dostępu do centrum danych) { "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 })
🟢Tool (Narzędzie dostępu do centrum danych) { "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 0, "hex": "FFFFFF" }
🟢Tool (Narzędzie dostępu do centrum danych) { "id": 2, "name": "Ceiling Light", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴Asystent Światła zostały przełączone

Uwaga

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. Podaj moduł LLM z poprzednią historią czatu i schematami funkcji
  3. Przeanalizuj odpowiedź LLM, aby określić, czy chce odpowiedzieć za pomocą wiadomości lub wywołać funkcję
  4. Jeśli usługa 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 funkcja LLM mogła określić, co należy zrobić dalej
  7. Powtórz kroki od 2 do 6, dopóki menedżer 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

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

W przypadku korzystania z automatycznego wywoływania funkcji wszystkie kroki w pętli automatycznego planowania są obsługiwane i dodawane do ChatHistory obiektu. Po zakończeniu pętli wywoływania funkcji można sprawdzić ChatHistory obiekt, aby wyświetlić wszystkie wykonane wywołania funkcji i wyniki dostarczone przez jądro semantyczne.

Co z funkcją wywołującą planistki stepwise i handlebars?

Planiści pasków krokowych i obsługi są nadal dostępne w semantycznym jądrze. Zalecamy jednak używanie funkcji wywołującej większość zadań, ponieważ jest ona bardziej zaawansowana i łatwiejsza w użyciu. Planiści Stepwise i Handlebars zostaną wycofani w przyszłej wersji semantycznego jądra.

Dowiedz się, jak migrować planistę krokową do automatycznego wywoływania funkcji.

Uwaga

Jeśli tworzysz nowego agenta sztucznej inteligencji, zalecamy, aby nie używać planistów krokowych ani pasków obsługi. Zamiast tego należy używać funkcji wywołującej, ponieważ jest ona bardziej zaawansowana i łatwiejsza w użyciu.

Następne kroki

Teraz, gdy już wiesz, jak planiści pracują w semantycznym jądrze, możesz dowiedzieć się więcej o wpływie agenta sztucznej inteligencji na najlepszy plan i wykonywanie zadań w imieniu użytkowników.