Ingeniería de solicitudes en .NET

En este artículo, explorará los ingeniería de indicaciones. Muchos modelos de IA se basan en indicaciones, lo que significa que responden al texto de entrada del usuario (una indicación) con una respuesta generada por algoritmos predictivos (una finalización). Los modelos más recientes también suelen admitir finalizaciones en forma de chat, con mensajes basados en roles (sistema, usuario, asistente) e historial de chat para conservar las conversaciones.

Trabajando con indicaciones

Considere este ejemplo de generación de texto donde solicitud es la entrada del usuario y finalización es la salida del modelo:

Solicitud: "El presidente que ejerció el mandato más corto fue "

Finalización: "Pedro Lascurain".

La finalización parece correcta, pero ¿qué ocurre si la aplicación debe ayudar a estudiantes de historia de los Estados Unidos? El mandato de 45 minutos de Pedro Lascurain es el más corto de cualquier presidente, pero fue presidente de México. Es probable que los estudiantes de historia de los Estados Unidos busquen "William Henry Harrison". Está claro que la aplicación podría ser más útil para sus usuarios previstos si le diera algo de contexto.

La ingeniería de indicaciones agrega contexto a la indicación, al proporcionar instrucciones, ejemplos e pistas para ayudar al modelo a producir mejores finalizaciones.

Por lo general, los modelos que admiten la generación de texto no requieren ningún formato específico, pero debe organizar las indicaciones para que quede claro qué parte es una instrucción y qué parte es un ejemplo. Los modelos que admiten aplicaciones basadas en chat usan tres roles para organizar las finalizaciones: un rol del sistema que controla el chat, un rol de usuario para representar la entrada del usuario y un rol de asistente para responder a los usuarios. Divida las indicaciones en mensajes para cada rol:

  • Los mensajes del sistema proporcionan las instrucciones del modelo sobre el asistente. Una solicitud solo puede tener un mensaje del sistema y debe ser el primer mensaje.
  • Los mensajes de usuario incluyen indicaciones del usuario y muestran ejemplos, indicaciones históricas o contienen instrucciones para el asistente. Una finalización de chat de ejemplo debe tener al menos un mensaje de usuario.
  • Los mensajes del asistente muestran finalizaciones históricas o de ejemplo y deben contener una respuesta al mensaje de usuario anterior. Los mensajes del asistente no son necesarios, pero si incluye uno, debe emparejarse con un mensaje de usuario para formar un ejemplo.

Uso de instrucciones para mejorar la finalización

Una instrucción es el texto que indica al modelo cómo responder. Una instrucción puede ser una directiva o un imperativo:

  • Las directivas indican al modelo cómo comportarse, pero no son comandos sencillos; piense en la preparación de personajes para un actor de improvisación: "Está ayudando a los alumnos a aprender sobre la historia de EE. UU., así que hable sobre los Estados Unidos, a menos que pregunten específicamente sobre otros países".
  • Los imperativos son comandos inequívocas que el modelo debe seguir. "Traducir al tagalo:"

Las directivas son más abiertas y flexibles que los imperativos:

  • Puede combinar varias directivas en una instrucción.
  • Las instrucciones suelen funcionar mejor cuando se usan con ejemplos. Sin embargo, dado que los imperativos son comandos inequívocos, los modelos no necesitan ejemplos para comprenderlos (aunque puede usar un ejemplo para mostrar el modelo cómo dar formato a las respuestas). Dado que una directiva no indica exactamente qué hacer al modelo, cada ejemplo puede ayudar al modelo a funcionar mejor.
  • Normalmente, es mejor dividir una instrucción difícil en una serie de pasos, lo que puede hacer con una secuencia de directivas. También debe indicar al modelo que produzca el resultado de cada paso, de modo que pueda realizar fácilmente ajustes pormenorizados. Aunque puede desglosar la instrucción en pasos usted mismo, es más fácil indicarle al modelo que lo haga y generar el resultado de cada paso. Este enfoque se denomina solicitudes de la cadena de pensamiento.

Adición de contexto principal y auxiliar de contenido

Puede proporcionar contenido para agregar más contexto a las instrucciones.

El contenido principal es el texto que desea que el modelo procese con una instrucción. Independientemente de la acción que implique la instrucción, el modelo lo realizará en el contenido principal para generar una finalización.

El contenido auxiliar es el texto al que se hace referencia en una instrucción, pero que no es el destino de la instrucción. El modelo usa el contenido auxiliar para completar la instrucción, lo que significa que dicho contenido también aparece en finalizaciones, normalmente como algún tipo de estructura (por ejemplo, en encabezados o etiquetas de columna).

Use etiquetas con el contenido informativo para ayudar al modelo a averiguar cómo usarlo con la instrucción. No se preocupe demasiado por la precisión: las etiquetas no tienen que coincidir exactamente con las instrucciones porque el modelo controlará aspectos como el formato de palabras y la mayúsculas.

Supongamos que usa la instrucción "Resumir los logros presidenciales de EE. UU." para generar una lista. El modelo puede organizarlo y ordenarlo de cualquier manera. ¿Pero qué ocurre si desea que la lista agrupe los logros de un conjunto específico de categorías? Use contenido auxiliar para agregar esa información a la instrucción.

Ajuste la instrucción para que el modelo se agrupe por categoría y anexe contenido auxiliar que especifique esas categorías:

prompt = """
Instructions: Summarize US Presidential accomplishments, grouped by category.
Categories: Domestic Policy, US Economy, Foreign Affairs, Space Exploration.
Accomplishments: 'George Washington
- First president of the United States.
- First president to have been a military veteran.
- First president to be elected to a second term in office.
- Received votes from every presidential elector in an election.
- Filled the entire body of the United States federal judges; including the Supreme Court.
- First president to be declared an honorary citizen of a foreign country, and an honorary citizen of France.
John Adams ...' ///Text truncated
""";

Uso de ejemplos para guiar el modelo

Un ejemplo es texto que muestra al modelo cómo responder proporcionando la entrada de usuario de ejemplo y la salida del modelo. El modelo usa ejemplos para deducir qué incluir en las finalizaciones. Los ejemplos pueden aparecer antes o después de las instrucciones de una solicitud diseñada, pero los dos no deben intercalarse.

Un ejemplo comienza con una indicación y, de manera opcional, puede incluir una finalización. Una finalización en un ejemplo no tiene que incluir la respuesta textual; podría contener una palabra con formato, la primera viñeta de una lista desordenada o algo similar a indicar cómo debe iniciarse cada finalización.

Los ejemplos se clasifican como aprendizaje "zero shot" o aprendizaje "few shot" en función de si contienen finalizaciones textuales.

  • Entre los ejemplos de aprendizaje "zero shot" se incluye una solicitud sin finalización textual. Este enfoque prueba las respuestas de un modelo sin proporcionar una salida de datos de ejemplo. Las indicaciones "zero shot" pueden tener finalizaciones que incluyan pistas, como indicar que el modelo debe generar una lista ordenada incluyendo "1." como finalización.
  • Algunos ejemplos de aprendizaje "few shot" incluyen varios pares de solicitudes con finalizaciones textuales. El aprendizaje "few shot" puede cambiar el comportamiento del modelo agregando a su conocimiento existente.

Descripción de las pistas

Una indicación es el texto que transmite la estructura deseada o el formato de salida. Al igual que una instrucción, el modelo no procesa una indicación como si fuera una entrada de usuario. Como ejemplo, una indicación muestra el modelo lo que desea en lugar de decirle qué hacer. Puede agregar tantas indicaciones como desee, por lo que puede iterar para obtener el resultado que quiera. Las indicaciones se usan con una instrucción o un ejemplo y deben estar al final de la solicitud.

Supongamos que usa una instrucción para indicar al modelo que genere una lista de logros presidenciales por categoría, junto con el contenido auxiliar que indica al modelo qué categorías usar. Decide que quiere que el modelo produzca una lista anidada de categorías en mayúsculas, con los logros de cada presidente en cada categoría listados en una línea que comienza con su nombre, con los presidentes listados cronológicamente. Después de la instrucción y el contenido auxiliar, puede agregar tres indicaciones para mostrar el modelo cómo estructurar y dar formato a la lista:

prompt = """
Instructions: Summarize US Presidential accomplishments, grouped by category.
Categories: Domestic Policy, US Economy, Foreign Affairs, Space Exploration.
Accomplishments: George Washington
First president of the United States.
First president to have been a military veteran.
First president to be elected to a second term in office.
First president to receive votes from every presidential elector in an election.
First president to fill the entire body of the United States federal judges; including the Supreme Court.
First president to be declared an honorary citizen of a foreign country, and an honorary citizen of France.
John Adams ...  /// Text truncated

DOMESTIC POLICY
- George Washington: 
- John Adams:
""";
  • DOMESTIC POLICY muestra el modelo que desea que inicie cada grupo con la categoría en mayúsculas.
  • - George Washington: muestra al modelo que inicie cada sección con los logros de George Washington enumerados en una sola línea.
  • - John Adams: muestra al modelo que debe enumerar los presidentes restantes en orden cronológico.

Ejemplo de indicación mediante .NET

.NET proporciona varias herramientas para enviar indicaciones y chatear con diferentes modelos de IA. Use el kernel semántico para conectarse a una amplia variedad de modelos y servicios de IA, así como a otros SDK, como la biblioteca de .NET de OpenAI oficial. El kernel semántico incluye herramientas para crear indicaciones con distintos roles y mantener el historial de chat, así como muchas otras características.

Tenga en cuenta el siguiente código de ejemplo:

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

// Create a kernel with OpenAI chat completion
#pragma warning disable SKEXP0010
Kernel kernel = Kernel.CreateBuilder()
                    .AddOpenAIChatCompletion(
                        modelId: "phi3:mini",
                        endpoint: new Uri("http://localhost:11434"),
                        apiKey: "")
                    .Build();

var aiChatService = kernel.GetRequiredService<IChatCompletionService>();
var chatHistory = new ChatHistory();
chatHistory.Add(
    new ChatMessageContent(AuthorRole.System, "You are a helpful AI Assistant."));

while (true)
{
    // Get user prompt and add to chat history
    Console.WriteLine("Your prompt:");
    chatHistory.Add(new ChatMessageContent(AuthorRole.User, Console.ReadLine()));

    // Stream the AI response and add to chat history
    Console.WriteLine("AI Response:");
    var response = "";
    await foreach (var item in
        aiChatService.GetStreamingChatMessageContentsAsync(chatHistory))
    {
        Console.Write(item.Content);
        response += item.Content;
    }
    chatHistory.Add(new ChatMessageContent(AuthorRole.Assistant, response));
    Console.WriteLine();
}

El código anterior proporciona ejemplos de los conceptos siguientes:

  • Crea un servicio de historial de chat para pedir al modelo de IA que complete las finalizaciones en función de los roles de autor.
  • Configura la IA con un mensaje de AuthorRole.System.
  • Acepta la entrada de usuario para permitir distintos tipos de indicaciones en el contexto de un AuthorRole.User.
  • Transmite de forma asincrónica la finalización desde la IA para proporcionar una experiencia de chat dinámica.

Amplíe su conocimiento de técnicas de ingeniería de indicaciones

También puede aumentar la eficacia de sus indicaciones con técnicas de ingeniería de indicaciones más avanzadas que se tratan en profundidad en sus propios artículos.

  • Los LLM tienen límites de entrada de token que restringen la cantidad de texto que puede caber en una solicitud. Use inserciones y soluciones de base de datos vectoriales para reducir el número de tokens que necesita para representar un fragmento de texto determinado.
  • Los LLM no se entrenan en los datos a menos que los entrene usted mismo, lo que puede ser costoso y lento. Use la generación aumentada de recuperación (RAG) para que los datos estén disponibles para un LLM sin entrenarlos.