Wat is een Planner?
Zodra u meerdere invoegtoepassingen hebt, hebt u een manier nodig voor uw AI-agent om deze samen te gebruiken om de behoeften van een gebruiker op te lossen. Dit is waar de planning binnenkomt.
Vroeg in de Semantische Kernel werd het concept van planners geïntroduceerd waarin prompts werden gebruikt om de AI aan te vragen om te kiezen welke functies moeten worden aangeroepen. Sinds Semantic Kernel is geïntroduceerd, heeft OpenAI echter een systeemeigen manier geïntroduceerd voor het model om een functie aan te roepen of aan te roepen: functieoproepen. Andere AI-modellen, zoals Gemini, Claude en Mistral, hebben sindsdien functie aanroepen als kernmogelijkheid aangenomen, waardoor het een functie die door meerdere modellen wordt ondersteund.
Vanwege deze ontwikkelingen is Semantische kernel ontwikkeld om functie-aanroepen te gebruiken als de primaire manier om taken te plannen en uit te voeren.
Belangrijk
Functie aanroepen is alleen beschikbaar in OpenAI-modellen die 0613 of hoger zijn. Als u een ouder model gebruikt (bijvoorbeeld 0314), retourneert deze functionaliteit een fout. U wordt aangeraden de nieuwste OpenAI-modellen te gebruiken om te profiteren van deze functie.
Hoe maakt functie-aanroepen een 'plan'?
Het eenvoudigst is het aanroepen van functies slechts een manier voor een AI om een functie aan te roepen met de juiste parameters. Neem bijvoorbeeld een gebruiker die een gloeilamp wil inschakelen. Ervan uitgaande dat de AI de juiste invoegtoepassing heeft, kan deze de functie aanroepen om het licht in te schakelen.
Role | Bericht |
---|---|
🔵Gebruiker | Schakel het licht in #1 |
🔴Assistent (functieoproep) | Lights.change_state(1, { "isOn": true }) |
🟢Tool | { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" } |
🔴Assistent | De lamp is nu ingeschakeld |
Maar wat als de gebruiker de id van het licht niet weet? Of wat als de gebruiker alle lichten wil inschakelen? Dit is waar de planning binnenkomt. De LLM-modellen van vandaag kunnen iteratief functies aanroepen om de behoeften van een gebruiker op te lossen. Dit wordt bereikt door een feedbacklus te maken waarin de AI een functie kan aanroepen, het resultaat kan controleren en vervolgens bepaalt wat u vervolgens moet doen.
Een gebruiker kan bijvoorbeeld de AI vragen om een gloeilamp te "in- of uitschakelen". De AI moet eerst de status van de gloeilamp controleren voordat wordt bepaald of deze moet worden ingeschakeld of uitgeschakeld.
Role | Bericht |
---|---|
🔵Gebruiker | Schakel alle lichten in |
🔴Assistent (functieoproep) | Lights.get_lights() |
🟢Tool | { "lights": [ { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }, { "id": 2, "name": "Ceiling Light", "isOn": false, "brightness": 0, "hex": "FFFFFF" } ] } |
🔴Assistent (functieoproep) | Lights.change_state(1, { "isOn": false }) Lights.change_state(2, { "isOn": true }) |
🟢Tool | { "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 0, "hex": "FFFFFF" } |
🟢Tool | { "id": 2, "name": "Ceiling Light", "isOn": true, "brightness": 100, "hex": "FF0000" } |
🔴Assistent | De lichten zijn in-/uitgeschakeld |
Notitie
In dit voorbeeld hebt u ook parallelle functie aanroepen gezien. Hier kan de AI meerdere functies tegelijk aanroepen. Dit is een krachtige functie waarmee de AI complexe taken sneller kan oplossen. Het werd toegevoegd aan de OpenAI-modellen in 1106.
De automatische planningslus
Ondersteunende functie aanroepen zonder Semantische kernel is relatief complex. U moet een lus schrijven die het volgende zou bereiken:
- JSON-schema's maken voor elk van uw functies
- Geef de LLM op met de vorige chatgeschiedenis en functieschema's
- Parseert het antwoord van de LLM om te bepalen of deze een bericht wil beantwoorden of een functie wil aanroepen
- Als de LLM een functie wil aanroepen, moet u de functienaam en parameters parseren uit het antwoord van de LLM
- De functie aanroepen met de juiste parameters
- De resultaten van de functie retourneren, zodat de LLM kan bepalen wat er moet worden uitgevoerd
- Herhaal stap 2-6 totdat de LLM besluit dat deze de taak heeft voltooid of hulp nodig heeft van de gebruiker
In Semantic Kernel maken we het eenvoudig om functie-aanroepen te gebruiken door deze lus voor u te automatiseren. Hierdoor kunt u zich richten op het bouwen van de invoegtoepassingen die nodig zijn om de behoeften van uw gebruiker op te lossen.
Notitie
Begrijpen hoe de functie-aanroeplus werkt, is essentieel voor het bouwen van krachtige en betrouwbare AI-agents. Zie het artikel over het aanroepen van functies voor een uitgebreid overzicht van de werking van de lus.
Automatisch aanroepen van functies gebruiken
Als u automatische functie-aanroepen in Semantische kernel wilt gebruiken, moet u het volgende doen:
- De invoegtoepassing registreren bij de kernel
- Een object voor uitvoeringsinstellingen maken waarmee de AI automatisch functies moet aanroepen
- Roep de chatvoltooiingsservice aan met de chatgeschiedenis en de kernel
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());
Wanneer u automatische functie-aanroepen gebruikt, worden alle stappen in de automatische planningslus voor u verwerkt en toegevoegd aan het ChatHistory
object. Nadat de functieaanroeplus is voltooid, kunt u het ChatHistory
object inspecteren om alle functieaanroepen te zien die zijn gemaakt en de resultaten die worden geleverd door Semantic Kernel.
Hoe zit het met de planners voor het aanroepen van stapsgewijze functies en handlebars?
De planners voor stapsgewijze en stuurgrepen zijn nog steeds beschikbaar in Semantische kernel. We raden u echter aan om functie-aanroepen te gebruiken voor de meeste taken omdat deze krachtiger en eenvoudiger te gebruiken is. Zowel de stepwise- als handlebars planners worden afgeschaft in een toekomstige release van Semantic Kernel.
Informatie over het migreren van stapsgewijze planner naar automatisch aanroepen van functies.
Let op
Als u een nieuwe AI-agent bouwt, wordt u aangeraden de planners voor stapsgewijze instructies of handgrepen niet te gebruiken. Gebruik in plaats daarvan functie aanroepen omdat het krachtiger en eenvoudiger te gebruiken is.
Volgende stappen
Nu u begrijpt hoe planners werken in Semantic Kernel, kunt u meer informatie krijgen over hoe invloed heeft op uw AI-agent, zodat ze het beste taken plannen en uitvoeren namens uw gebruikers.