¿Qué es un Planificador?
Una vez que tenga varios complementos, necesita una manera de que el agente de IA los use juntos para resolver la necesidad de un usuario. Aquí es donde entra en acción la planificación.
Al principio, el kernel semántico introdujo el concepto de planificadores que usaban avisos para solicitar la inteligencia artificial para elegir las funciones que se van a invocar. Sin embargo, como se introdujo el kernel semántico, OpenAI introdujo una manera nativa para que el modelo invoque o "llame" a una función: llamada a función. Otros modelos de inteligencia artificial como Gemini, Claude y Mistral han adoptado la llamada a funciones como una funcionalidad básica, lo que lo convierte en una característica admitida entre modelos.
Debido a estos avances, el kernel semántico ha evolucionado para usar la llamada a funciones como la forma principal de planear y ejecutar tareas.
Importante
La llamada a funciones solo está disponible en los modelos openAI que son 0613 o versiones posteriores. Si usa un modelo anterior (por ejemplo, 0314), esta funcionalidad devolverá un error. Se recomienda usar los modelos openAI más recientes para aprovechar esta característica.
¿Cómo crea una función que llama a un "plan"?
En su forma más sencilla, la llamada a funciones es simplemente una manera de que una inteligencia artificial invoque una función con los parámetros correctos. Por ejemplo, un usuario quiere activar una bombilla. Suponiendo que la inteligencia artificial tiene el complemento adecuado, puede llamar a la función para encender la luz.
Role | Mensaje |
---|---|
🔵User | Active la luz n.º 1. |
🔴Asistente (llamada de función) | Lights.change_state(1, { "isOn": true }) |
🟢Herramienta | { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" } |
🔴Asistente | La lámpara está ahora activada |
Pero, ¿qué ocurre si el usuario no conoce el identificador de la luz? ¿O qué ocurre si el usuario quiere encender todas las luces? Aquí es donde entra en acción la planificación. Los modelos LLM de hoy en día son capaces de llamar a funciones iterativamente para resolver la necesidad de un usuario. Esto se logra mediante la creación de un bucle de comentarios en el que la inteligencia artificial puede llamar a una función, comprobar el resultado y, a continuación, decidir qué hacer a continuación.
Por ejemplo, un usuario puede pedir a la inteligencia artificial que "alterne" una bombilla. La inteligencia artificial primero tendría que comprobar el estado de la bombilla antes de decidir si se activará o desactivará.
Role | Mensaje |
---|---|
🔵User | Por favor, alterna todas las luces |
🔴Asistente (llamada de función) | Lights.get_lights() |
🟢Herramienta | { "lights": [ { "id": 1, "name": "Table Lamp", "isOn": true, "brightness": 100, "hex": "FF0000" }, { "id": 2, "name": "Ceiling Light", "isOn": false, "brightness": 0, "hex": "FFFFFF" } ] } |
🔴Asistente (llamada de función) | Lights.change_state(1, { "isOn": false }) Lights.change_state(2, { "isOn": true }) |
🟢Herramienta | { "id": 1, "name": "Table Lamp", "isOn": false, "brightness": 0, "hex": "FFFFFF" } |
🟢Herramienta | { "id": 2, "name": "Ceiling Light", "isOn": true, "brightness": 100, "hex": "FF0000" } |
🔴Asistente | Las luces se han activado |
Nota:
En este ejemplo, también ha visto llamadas a funciones paralelas. Aquí es donde la inteligencia artificial puede llamar a varias funciones al mismo tiempo. Se trata de una característica eficaz que puede ayudar a la inteligencia artificial a resolver tareas complejas con mayor rapidez. Se agregó a los modelos openAI en 1106.
Bucle de planeación automática
Admitir llamadas a funciones sin kernel semántico es relativamente compleja. Tendría que escribir un bucle que lograra lo siguiente:
- Creación de esquemas JSON para cada una de las funciones
- Proporcionar el LLM con los esquemas de función y historial de chat anteriores
- Analizar la respuesta de LLM para determinar si quiere responder con un mensaje o llamar a una función
- Si LLM quiere llamar a una función, tendría que analizar el nombre de la función y los parámetros de la respuesta de LLM.
- Invocación de la función con los parámetros correctos
- Devuelve los resultados de la función para que LLM pueda determinar lo que debe hacer a continuación.
- Repita los pasos del 2 al 6 hasta que LLM decida que ha completado la tarea o necesita ayuda del usuario.
En kernel semántico, facilitamos el uso de llamadas a funciones mediante la automatización de este bucle automáticamente. Esto le permite centrarse en la creación de los complementos necesarios para resolver las necesidades del usuario.
Nota:
Comprender cómo funciona el bucle de llamada de funciones es esencial para crear agentes de inteligencia artificial confiables y eficaces. Para obtener información detallada sobre cómo funciona el bucle, consulte el artículo llamada a funciones.
Uso de llamadas automáticas a funciones
Para usar llamadas automáticas a funciones en kernel semántico, debe hacer lo siguiente:
- Registro del complemento con el kernel
- Creación de un objeto de configuración de ejecución que indica a la inteligencia artificial que llame automáticamente a funciones
- Invocación del servicio de finalización de chat con el historial de chat y el 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());
Cuando se usa la llamada automática a funciones, todos los pasos del bucle de planeación automática se controlan automáticamente y se agregan al ChatHistory
objeto . Una vez completado el bucle de llamada de función, puede inspeccionar el ChatHistory
objeto para ver todas las llamadas de función realizadas y los resultados proporcionados por kernel semántico.
¿Qué ocurre con las funciones que llaman paso a paso y los planificadores de handlebars?
Los planificadores Stepwise y Handlebars siguen estando disponibles en kernel semántico. Sin embargo, se recomienda usar la llamada de función para la mayoría de las tareas, ya que es más eficaz y fácil de usar. Los planificadores Stepwise y Handlebars quedarán en desuso en una versión futura del kernel semántico.
Obtenga información sobre cómo migrar Stepwise Planner a Auto Function Calling.
Precaución
Si va a crear un nuevo agente de IA, se recomienda no usar los planificadores Stepwise o Handlebars. En su lugar, use la llamada de función, ya que es más eficaz y fácil de usar.
Pasos siguientes
Ahora que comprende cómo funcionan los planificadores en kernel semántico, puede obtener más información sobre cómo influyen el agente de IA para que planeen y ejecuten las tareas en nombre de los usuarios.