Compartilhar via


Engenharia de solicitação no .NET

Neste artigo, você vai explorará os conceitos essenciais de engenharia de prompt. Muitos modelos de IA são baseados em prompts, o que significa que respondem ao texto de entrada do usuário (um prompt) com uma resposta gerada por algoritmos preditivos (um preenchimento). Modelos mais recentes também costumam ser compatíveis com preenchimentos em formato de chat com mensagens baseadas em funções (sistema, usuário, assistente) e um histórico de chat para preservar as conversas.

Trabalhe com prompts

Considere este exemplo de geração de texto em que a solicitação é a entrada do usuário e o preenchimento é a saída do modelo:

Solicitação: "O presidente que teve um mandato curto foi"

Preenchimento: "Pedro Lascurain".

O preenchimento parece correto, mas o que dizer se o seu aplicativo se destina a ajudar os estudantes de história dos EUA? O mandato de 45 minutos de Pedro Lascurain foi o mandato mais curto de que já se teve notícia, mas ele foi presidente do México. Os estudantes de história dos EUA provavelmente estão procurando por "William Henry Harrison". Claramente, o aplicativo pode ser mais útil para seus usuários pretendidos se você forneceu contexto a ele.

A engenharia de prompt adiciona contexto ao prompt fornecendo instruções, exemplos e pistas para ajudar o modelo a produzir preenchimentos melhores.

Os modelos GPT compatíveis com geração de texto não requerem nenhum formato específico, mas você deve organizar seus prompts de modo que fique claro o que é uma instrução e o que é um exemplo. Os modelos GPT compatíveis com aplicativos baseados em chat usam três funções para organizar preenchimentos: uma função de sistema que controla o chat, uma função de usuário para representar a entrada do usuário e uma função de assistente para responder aos usuários. Você divide seus prompts em mensagens para cada função:

  • Mensagens do sistema dão instruções sobre o assistente ao modelo. Uma solicitação pode ter apenas uma mensagem do sistema e deve ser a primeira mensagem.
  • As mensagens do usuário incluem prompts do usuário e mostram exemplos e prompts históricos, ou contêm instruções para o assistente. Um exemplo de preenchimento de chat deve ter pelo menos uma mensagem de usuário.
  • As mensagens do assistente mostram exemplos ou históricos de preenchimentos e devem conter uma resposta à mensagem anterior do usuário. Mensagens de assistente não são necessárias, mas se você incluir uma, elas deverão ser emparelhadas com uma mensagem de usuário para formar um exemplo.

Use instruções para aprimorar o preenchimento

Uma instrução é um texto que informa ao modelo como responder. Uma instrução pode ser uma diretiva ou um imperativo:

  • Diretivas dizem ao modelo como se comportar, mas não são comandos simples. Pense na preparação do personagem para um ator de improviso: "Você está ajudando os alunos a aprender sobre a história dos EUA, então fale sobre os EUA, a menos que perguntem especificamente sobre outros países"
  • Imperativos são comandos claros para o modelo seguir. "Traduzir para tagalo:"

Diretivas são mais abertas e flexíveis do que imperativos:

  • Você pode combinar várias diretivas em uma instrução.
  • As instruções geralmente funcionam melhor quando você as usa com exemplos. No entanto, como os imperativos são comandos claros, os modelos não precisam de exemplos para entendê-los (embora você possa usar um exemplo para mostrar ao modelo como formatar respostas). Como uma diretiva não informa ao modelo exatamente o que fazer, cada exemplo pode ajudar o modelo a funcionar melhor.
  • Normalmente, é melhor dividir uma instrução difícil em uma série de etapas, o que você pode fazer com uma sequência de diretivas. Você também deve informar o modelo para gerar o resultado de cada etapa, para poder fazer ajustes granulares facilmente. Embora você possa dividir a instrução em etapas por conta própria, é mais fácil apenas dizer ao modelo para fazê-lo e gerar o resultado de cada etapa. Essa abordagem é chamada solicitação de cadeia de pensamento.

Contexto de adição de conteúdo principal e de apoio

Você pode fornecer conteúdo para adicionar mais contexto às instruções.

Conteúdo principal é o texto que você deseja que o modelo processe com uma instrução. Seja qual for a ação que a instrução implicar, o modelo a executará no conteúdo principal para produzir um preenchimento.

Conteúdo de suporte é um texto que você faz referência em uma instrução, mas que não é o alvo da instrução. O modelo usa o conteúdo de suporte para concluir a instrução, o que significa que o suporte ao conteúdo também aparece em preenchimentos, normalmente como algum tipo de estrutura (como em rótulos de coluna ou títulos).

Use rótulos com seu conteúdo instrucional para ajudar o modelo a descobrir como usá-lo com a instrução. Não se preocupe muito com a precisão. Os rótulos não precisam corresponder exatamente às instruções porque o modelo lidará com coisas como capitalização e formato de palavra.

Suponha que você use a instrução "Resumir realizações presidenciais dos EUA" para produzir uma lista. O modelo organizá-la e ordená-la de várias maneiras. Mas e se você quiser que a lista agrupe as realizações por um conjunto específico de categorias? Use o conteúdo de suporte para adicionar essas informações à instrução.

Ajuste a instrução para que o modelo agrupe por categoria e acrescente o conteúdo de suporte que especifica essas categorias:

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
""";

Use exemplos para orientar o modelo

Um exemplo é o texto que mostra ao modelo como responder fornecendo entrada de usuário e saída de modelo de exemplo. O modelo usa exemplos para inferir o que incluir nos preenchimentos. Exemplos podem vir antes ou depois das instruções em uma solicitação construída, mas as duas não devem ser intercaladas.

Um exemplo começa com um prompt e pode, opcionalmente, incluir um preenchimento. Um preenchimento em um exemplo não precisa incluir a resposta literal. Ele pode conter apenas uma palavra formatada, o primeiro marcador em uma lista não ordenada ou algo semelhante para indicar como cada preenchimento deve ser iniciado.

Os exemplos são classificados como Aprendizado sem nenhuma tentativa ou aprendizado de poucas tentativas com base em se contêm preenchimentos literais.

  • Exemplos de aprendizado sem nenhuma tentativa incluem uma solicitação sem preenchimento literal. Essa abordagem testa as respostas de um modelo sem lhe dar um exemplo de saída de dados. Os prompts zero-shot (sem treinamento anterior) podem ter preenchimentos que incluem pistas, como indicar que o modelo deve gerar uma lista ordenada ao incluir "1." como o preenchimento.
  • Exemplos de aprendizado com poucas tentativas incluem vários pares de solicitações com preenchimentos literais. O aprendizado com poucas tentativas pode alterar o comportamento do modelo ao adicionar ao seu conhecimento existente.

Entenda as pistas

Uma sugestão é um texto que transmite a estrutura ou o formato de saída desejado. Como uma instrução, uma sugestão não é processada pelo modelo como se fosse entrada de usuário. Como um exemplo, uma sugestão mostra ao modelo o que você deseja em vez de dizer o que fazer. Você pode adicionar quantas sugestões desejar, para poder iterar para obter o resultado desejado. As sugestões são usadas com uma instrução ou um exemplo e devem estar no final da solicitação.

Suponha que você use uma instrução para informar ao modelo para produzir uma lista de realizações presidenciais por categoria, juntamente com o conteúdo de suporte que informa ao modelo quais categorias usar. Você decide que o modelo deve produzir uma lista aninhada em maiúsculo para categorias, com as realizações de cada presidente em cada categoria listada em uma linha que começa com o respectivo nome, com presidentes listados cronologicamente. Após a instrução e o conteúdo de suporte, você pode adicionar três sugestões para mostrar ao modelo como estruturar e formatar a 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:
""";
  • POLÍTICA DOMÉSTICA mostra ao modelo que você deseja que ele inicie cada grupo com a categoria em maiúsculo.
  • – George Washington: mostra ao modelo para começar cada seção com as realizações de George Washington listadas em uma linha.
  • – John Adams: mostra ao modelo que deve listar os presidentes restantes em ordem cronológica.

Exemplo de prompt usando o .NET

O .NET fornece várias ferramentas para criar prompts e conversar com diferentes modelos de IA. Use o Kernel Semântico para se conectar a uma ampla variedade de modelos e serviços de IA e também a outros SDKs, como a biblioteca do .NET da OpenAI oficial. O Kernel Semântico inclui ferramentas para criar prompts com diferentes funções e manter o histórico de chat, além de muitos outros recursos.

Considere o seguinte exemplo de código:

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

O código anterior fornece exemplos dos seguintes conceitos:

  • Cria um serviço de histórico de chat para solicitar preenchimentos ao modelo de IA com base em funções de autor.
  • Configura a IA com uma mensagem de AuthorRole.System.
  • Aceita a entrada do usuário para permitir diferentes tipos de prompts no contexto de um AuthorRole.User.
  • Transmite o preenchimento de IA de forma assíncrona para fornecer uma experiência de chat dinâmica.

Amplie suas técnicas de engenharia de prompt

Você também pode aumentar o poder de seus prompts com técnicas de engenharia de prompt mais avançadas que são abordadas em profundidade em seus próprios artigos.

  • Os LLMs têm limites de entrada de token que restringem a quantidade de texto que você pode ajustar em uma solicitação. Use incorporações e soluções de banco de dados vetorial para reduzir o número de tokens necessários para representar um determinado trecho de texto.
  • Os LLMs não são treinados em seus dados, a menos que você os treine por conta própria, o que pode ser caro e demorado. Use a geração aumentada de recuperação (RAG) para disponibilizar seus dados para um LLM sem treiná-lo.