Függvényhívási módok

Amikor az AI-modell egy függvénylistát tartalmazó parancssort kap, választhat egyet vagy többet a kérés végrehajtásához. Ha a modell kiválaszt egy függvényt, azt a Szemantikus Kernelnek kell meghívnia.

A Szemantikus Kernelben az alrendszert hívó függvény kétféle módon hívja meg a függvényeket: automatikus és manuális.

A meghívási módtól függően a Szemantic Kernel vagy teljes körű függvényhívást végez, vagy a hívónak a függvényhívási folyamat felett ad vezérlést.

Automatikus függvényhívás

Az automatikus függvényhívás a Szemantikus Kernel függvényhívási alrendszer alapértelmezett módja. Amikor az AI-modell kiválaszt egy vagy több függvényt, a Szemantikus Kernel automatikusan meghívja a kiválasztott függvényeket. A függvényhívások eredményeit a rendszer hozzáadja a csevegési előzményekhez, és a következő kérésekben automatikusan elküldi a modellnek. A modell ezután indokokat ad a csevegési előzményekről, szükség esetén további függvényeket választ, vagy létrehozza a végső választ. Ez a megközelítés teljesen automatizált, és nem igényel manuális beavatkozást a hívótól.

Tip

Az automatikus függvényhívás eltér az automatikus függvényválasztás viselkedésétől. Az előbbi azt határozza meg, hogy a függvényeket automatikusan meghívja-e Szemantikus kernel, míg az utóbbi határozza meg, hogy az AI-modell automatikusan választ-e függvényeket.

Ez a példa bemutatja, hogyan használható az automatikus függvényhívás a Szemantikus Kernelben. Az AI-modell dönti el, hogy mely függvényeket hívja meg a parancssor befejezéséhez, a Szemantikus Kernel pedig elvégzi a többit, és automatikusan meghívja őket.

using Microsoft.SemanticKernel;

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<WeatherForecastUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

// By default, functions are set to be automatically invoked.  
// If you want to explicitly enable this behavior, you can do so with the following code:  
// PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: true) };  
PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }; 

await kernel.InvokePromptAsync("Given the current time of day and weather, what is the likely color of the sky in Boston?", new(settings));
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
from semantic_kernel.functions.kernel_arguments import KernelArguments
from semantic_kernel.kernel import Kernel

kernel = Kernel()
kernel.add_service(OpenAIChatCompletion())

# Assuming that WeatherPlugin and DateTimePlugin are already implemented
kernel.add_plugin(WeatherPlugin(), "WeatherPlugin")
kernel.add_plugin(DateTimePlugin(), "DateTimePlugin")

query = "What is the weather in Seattle today?"
arguments = KernelArguments(
    settings=PromptExecutionSettings(
        # By default, functions are set to be automatically invoked.
        # If you want to explicitly enable this behavior, you can do so with the following code:
        # function_choice_behavior=FunctionChoiceBehavior.Auto(auto_invoke=True),
        function_choice_behavior=FunctionChoiceBehavior.Auto(),
    )
)

response = await kernel.invoke_prompt(query, arguments=arguments)

Tip

Hamarosan további frissítések érkeznek a Java SDK-ba.

Egyes AI-modellek támogatják a párhuzamos függvényhívást, ahol a modell több függvényt is kiválaszt a meghíváshoz. Ez akkor lehet hasznos, ha a kiválasztott függvények meghívása hosszú időt vesz igénybe. Az AI például dönthet úgy, hogy egyszerre kéri le a legfrissebb híreket és az aktuális időt, ahelyett, hogy minden egyes függvényhez külön kérés-válasz ciklust hajtana végre.

A Szemantikus Kernel kétféleképpen hívhatja meg ezeket a függvényeket:

  • Egymás után: A függvények egymás után lesznek meghívva. Ez az alapértelmezett viselkedés.
  • Egyidejűleg: A függvények egyidejűleg lesznek meghívva. Ez úgy engedélyezhető, hogy a tulajdonságot az FunctionChoiceBehaviorOptions.AllowConcurrentInvocation alábbi példában látható értékre trueállítja.
using Microsoft.SemanticKernel;

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<NewsUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

// Enable concurrent invocation of functions to get the latest news and the current time.
FunctionChoiceBehaviorOptions options = new() { AllowConcurrentInvocation = true };

PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(options: options) }; 

await kernel.InvokePromptAsync("Good morning! What is the current time and latest news headlines?", new(settings));

Előfordulhat, hogy egy modell több függvényt is kiválaszt a meghíváshoz. Ezt gyakran párhuzamos függvényhívásnak is nevezik. Ha az AI-modell több függvényt választ ki, Szemantikus kernel egyidejűleg meghívja őket.

Tip

Az OpenAI vagy Azure OpenAI-összekötővel letilthatja a párhuzamos függvényhívást az alábbi lépésekkel:

from semantic_kernel.connectors.ai.open_ai import OpenAIChatPromptExecutionSettings
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior

settings = OpenAIChatPromptExecutionSettings(
    function_choice_behavior=FunctionChoiceBehavior.Auto(),
    parallel_tool_calls=False
)

Kézi függvényhívás

Azokban az esetekben, amikor a hívó nagyobb mértékben szeretné szabályozni a függvényhívási folyamatot, a manuális függvényhívás használható.

Ha a manuális függvényhívás engedélyezve van, a Szemantikus Kernel nem hívja meg automatikusan az AI-modell által kiválasztott függvényeket. Ehelyett a kiválasztott függvények listáját adja vissza a hívónak, akik ezután eldönthetik, hogy mely függvényeket kell meghívni, egymás után vagy párhuzamosan meghívni őket, kezelni a kivételeket stb. A függvényhívási eredményeket hozzá kell adni a csevegési előzményekhez, és vissza kell adni a modellnek, ami indokolni fogja őket, és eldönti, hogy további függvényeket választ, vagy végleges választ hoz létre.

Az alábbi példa bemutatja, hogyan használható a manuális függvényhívás.

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<WeatherForecastUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

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

// Manual function invocation needs to be enabled explicitly by setting autoInvoke to false.
PromptExecutionSettings settings = new() { FunctionChoiceBehavior = Microsoft.SemanticKernel.FunctionChoiceBehavior.Auto(autoInvoke: false) };

ChatHistory chatHistory = [];
chatHistory.AddUserMessage("Given the current time of day and weather, what is the likely color of the sky in Boston?");

while (true)
{
    ChatMessageContent result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, kernel);

    // Check if the AI model has generated a response.
    if (result.Content is not null)
    {
        Console.Write(result.Content);
        // Sample output: "Considering the current weather conditions in Boston with a tornado watch in effect resulting in potential severe thunderstorms,
        // the sky color is likely unusual such as green, yellow, or dark gray. Please stay safe and follow instructions from local authorities."
        break;
    }

    // Adding AI model response containing chosen functions to chat history as it's required by the models to preserve the context.
    chatHistory.Add(result); 

    // Check if the AI model has chosen any function for invocation.
    IEnumerable<FunctionCallContent> functionCalls = FunctionCallContent.GetFunctionCalls(result);
    if (!functionCalls.Any())
    {
        break;
    }

    // Sequentially iterating over each chosen function, invoke it, and add the result to the chat history.
    foreach (FunctionCallContent functionCall in functionCalls)
    {
        try
        {
            // Invoking the function
            FunctionResultContent resultContent = await functionCall.InvokeAsync(kernel);

            // Adding the function result to the chat history
            chatHistory.Add(resultContent.ToChatMessage());
        }
        catch (Exception ex)
        {
            // Adding function exception to the chat history.
            chatHistory.Add(new FunctionResultContent(functionCall, ex).ToChatMessage());
            // or
            //chatHistory.Add(new FunctionResultContent(functionCall, "Error details that the AI model can reason about.").ToChatMessage());
        }
    }
}

Megjegyzés

A FunctionCallContent és a FunctionResultContent osztályok az AI-modellfüggvény-hívások és a Szemantikus Kernel függvényhívási eredmények megjelenítésére szolgálnak. Ezek a kiválasztott függvényekkel kapcsolatos információkat tartalmaznak, például a függvényazonosítót, a nevet és az argumentumokat, valamint a függvényhívási eredményeket, például a függvényhívás azonosítóját és az eredményt.

Az alábbi példa bemutatja, hogyan használható a manuális függvényhívás a streamelt csevegés befejező API-jával. Figyelje meg, hogy az FunctionCallContentBuilder osztály függvényhívásokat hoz létre a streamelési tartalomból. Az API streamelési jellege miatt a függvényhívások is streamelhetők. Ez azt jelenti, hogy a hívónak a függvényhívásokat a streamelési tartalomból kell létrehoznia, mielőtt meghívja őket.

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

IKernelBuilder builder = Kernel.CreateBuilder(); 
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<WeatherForecastUtils>();
builder.Plugins.AddFromType<DateTimeUtils>(); 

Kernel kernel = builder.Build();

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

// Manual function invocation needs to be enabled explicitly by setting autoInvoke to false.
PromptExecutionSettings settings = new() { FunctionChoiceBehavior = Microsoft.SemanticKernel.FunctionChoiceBehavior.Auto(autoInvoke: false) };

ChatHistory chatHistory = [];
chatHistory.AddUserMessage("Given the current time of day and weather, what is the likely color of the sky in Boston?");

while (true)
{
    AuthorRole? authorRole = null;
    FunctionCallContentBuilder fccBuilder = new ();

    // Start or continue streaming chat based on the chat history
    await foreach (StreamingChatMessageContent streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync(chatHistory, settings, kernel))
    {
        // Check if the AI model has generated a response.
        if (streamingContent.Content is not null)
        {
            Console.Write(streamingContent.Content);
            // Sample streamed output: "The color of the sky in Boston is likely to be gray due to the rainy weather."
        }
        authorRole ??= streamingContent.Role;

        // Collect function calls details from the streaming content
        fccBuilder.Append(streamingContent);
    }

    // Build the function calls from the streaming content and quit the chat loop if no function calls are found
    IReadOnlyList<FunctionCallContent> functionCalls = fccBuilder.Build();
    if (!functionCalls.Any())
    {
        break;
    }

    // Creating and adding chat message content to preserve the original function calls in the chat history.
    // The function calls are added to the chat message a few lines below.
    ChatMessageContent fcContent = new ChatMessageContent(role: authorRole ?? default, content: null);
    chatHistory.Add(fcContent);

    // Iterating over the requested function calls and invoking them.
    // The code can easily be modified to invoke functions concurrently if needed.
    foreach (FunctionCallContent functionCall in functionCalls)
    {
        // Adding the original function call to the chat message content
        fcContent.Items.Add(functionCall);

        // Invoking the function
        FunctionResultContent functionResult = await functionCall.InvokeAsync(kernel);

        // Adding the function result to the chat history
        chatHistory.Add(functionResult.ToChatMessage());
    }
}
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
from semantic_kernel.contents.chat_history import ChatHistory
from semantic_kernel.contents.function_call_content import FunctionCallContent
from semantic_kernel.contents.function_result_content import FunctionResultContent
from semantic_kernel.kernel import Kernel

kernel = Kernel()
chat_completion_service = OpenAIChatCompletion()

# Assuming that WeatherPlugin is already implemented
kernel.add_plugin(WeatherPlugin(), "WeatherPlugin")

settings = PromptExecutionSettings(
    function_choice_behavior=FunctionChoiceBehavior.Auto(auto_invoke=False),
)

chat_history = ChatHistory()
chat_history.add_user_message("What is the weather in Seattle on 10th of September 2024 at 11:29 AM?")

response = await chat_completion_service.get_chat_message_content(chat_history, settings, kernel=kernel)
function_call_content = response.items[0]
assert isinstance(function_call_content, FunctionCallContent)

# Need to add the response to the chat history to preserve the context
chat_history.add_message(response)

function = kernel.get_function(function_call_content.plugin_name, function_call_content.function_name)
function_result = await function(kernel, function_call_content.to_kernel_arguments())

function_result_content = FunctionResultContent.from_function_call_content_and_result(
    function_call_content, function_result
)

# Adding the function result to the chat history
chat_history.add_message(function_result_content.to_chat_message_content())

# Invoke the model again with the function result
response = await chat_completion_service.get_chat_message_content(chat_history, settings, kernel=kernel)
print(response)
# The weather in Seattle on September 10th, 2024, is expected to be [weather condition].

Megjegyzés

A FunctionCallContent és a FunctionResultContent osztályok az AI-modellfüggvény-hívások és a Szemantikus Kernel függvényhívási eredmények megjelenítésére szolgálnak. Ezek a kiválasztott függvényekkel kapcsolatos információkat tartalmaznak, például a függvényazonosítót, a nevet és az argumentumokat, valamint a függvényhívási eredményeket, például a függvényhívás azonosítóját és az eredményt.

Tip

Hamarosan további frissítések érkeznek a Java SDK-ba.