Elaboração de Prompts

Um prompt é o texto que você coloca na frente do modelo antes que ele faça previsões. Essa é a ideia central que este capítulo esclarece: um prompt não é um comando que você dá a uma mente, é o contexto que você organiza para que a resposta que você quer se torne a continuação mais provável.
O que um prompt realmente é
Mesmo modelo, dois prompts. "Escreva sobre mudanças climáticas" lhe dá um ensaio divagador que você não pediu. "Escreva três frases sobre as principais causas das mudanças climáticas para uma criança de 12 anos, sem estatísticas" lhe dá algo que você pode usar. O modelo não mudou entre essas duas chamadas. O contexto mudou, e a saída o seguiu.
O capítulo anterior cobriu como um modelo gera texto prevendo o token mais provável, guiado por tudo à sua frente. Um prompt é esse "tudo à sua frente". Essa é a definição que vale a pena manter: um prompt não é uma solicitação que você faz a uma pessoa, é o contexto que você configura para que a continuação que você espera seja a mais provável encontrada pelo modelo.
Essa reformulação muda a forma como você escreve. Você não está persuadindo ou instruindo alguém. Você está organizando texto para que a resposta que você quer seja a coisa provável que vem a seguir. Cada técnica neste capítulo é uma forma diferente de fazer isso, e cada uma faz mais sentido quando você consegue ver a máquina de previsão subjacente.
Os três papéis
Quando você se comunica com um modelo através de código, você não envia um bloco de texto. Você envia uma lista de mensagens, e cada mensagem carrega um papel que marca de onde ela veio. Existem três:
- system: suas instruções permanentes. Quem o modelo deve agir como, as regras que segue, o formato que você quer. Defina uma vez, aplica-se a toda a conversa.
- user: uma mensagem da pessoa usando seu aplicativo. A solicitação real.
- assistant: uma mensagem que o modelo produziu anteriormente. É assim que uma conversa mantém seu histórico.
messages = [
{"role": "system", "content": "Você é um assistente conciso para um aplicativo de culinária. Responda em uma frase."},
{"role": "user", "content": "O que posso usar em vez de manteiga em biscoitos?"},
]Sob o capô, esses papéis não são canais separados no modelo. Eles se achatam em um fluxo de texto com tokens de marcador especiais ao redor de cada mensagem, e todo esse fluxo é o que o modelo prevê. Os papéis importam porque o modelo foi treinado em conversas dispostas dessa forma, então aprendeu a tratar o conteúdo system como as regras permanentes autoritárias e o conteúdo user como a solicitação a ser respondida.
A mensagem do sistema é aquela que os iniciantes não utilizam o suficiente. É onde você define o comportamento que você quer em cada turno: o tom, o público, o formato, as coisas que o modelo nunca deve fazer. Coloque regras duráveis lá e coloque a solicitação específica na mensagem do usuário.
Como o modelo não tem memória entre solicitações, o papel assistant também é como você reproduz o que foi dito antes: para continuar uma conversa, você envia a troca anterior como mensagens assistant e user. Mais sobre isso quando você começar a chamar modelos a partir do código.
system, user ou assistant. Essas tags se achatam em um fluxo de texto que o modelo prevê, mas foi treinado para tratar system como regras autoritárias e user como a solicitação. Coloque instruções duráveis em system, a solicitação específica em user, e reproduza mensagens anteriores assistant e user para transportar o histórico de uma conversa. Específico vence vago
Dois prompts, um modelo. "Escreva sobre mudanças climáticas" retorna um ensaio genérico de comprimento e tom imprevisível. "Escreva um resumo de três frases das principais causas das mudanças climáticas, para uma criança de 12 anos, em linguagem simples, sem estatísticas" retorna perto do que você imaginou. Mesma máquina, saída muito diferente, e a única diferença é o quanto você fixou.
A razão volta ao loop de previsão. A cada passo o modelo está escolhendo entre uma variedade de continuações plausíveis. Um prompt vago deixa essa variedade ampla, então o modelo preenche as lacunas com o que quer que seja mais comum em geral, o que raramente é exatamente o que você tinha em mente. Um prompt específico estreita a variedade em direção à resposta que você quer, antes que o modelo tenha escrito um único token.
# vago: o modelo decide comprimento, tom, público, formato
"Escreva sobre mudanças climáticas."
# específico: você decide
(
"Escreva um resumo de 3 frases das principais causas das mudanças climáticas, "
"para uma criança de 12 anos, em linguagem simples, sem estatísticas."
)A versão vaga pode continuar de mil formas sensatas, e você recebe uma aleatória. A versão específica elimina quase todas essas na antecedência. Quando você escreve um prompt, diga o que você realmente quer:
- Formato: uma frase, uma lista, JSON, uma tabela.
- Comprimento: um parágrafo, três pontos, menos de 50 palavras.
- Público: um iniciante, um especialista, uma criança de 12 anos.
- O que fazer quando incerto: "Se o texto não disser, responda 'não especificado' em vez de adivinhar."
Esse último carrega mais peso do que parece. Deixado aos seus próprios recursos o modelo preenche uma lacuna com um palpite confiante, porque um palpite fluente é a continuação provável. Explicitamente dando a ele a opção de dizer "Eu não sei" torna esse o caminho provável, que é um dos poucos movimentos no nível de prompt que reduz o problema de alucinação do capítulo anterior. Especificidade estreita as opções do modelo antes que ele escreva um token.
Mostre com exemplos
Às vezes a forma mais clara de configurar a continuação certa é mostrá-la. Colocar alguns exemplos trabalhados no prompt é chamado few-shot prompting (sem exemplos é zero-shot). Funciona porque o modelo é, no fundo, um continuador de padrões: dê a ele dois ou três exemplos de entrada-então-saída-correta e a coisa mais provável que venha a seguir é o mesmo padrão aplicado à sua nova entrada.
messages = [
{"role": "system", "content": "Rotule cada avaliação como POSITIVA, NEGATIVA ou NEUTRA. Responda apenas com o rótulo."},
{"role": "user", "content": "A comida estava fria e demorou a chegar."},
{"role": "assistant", "content": "NEGATIVA"},
{"role": "user", "content": "Refeição decente, nada de especial."},
{"role": "assistant", "content": "NEUTRA"},
{"role": "user", "content": "Melhor hamburger que já comi em anos!"},
]
# o modelo agora responde: POSITIVAOs dois exemplos completos estabelecem o padrão exato: uma palavra, tudo em maiúsculas, de um conjunto fixo. Continuar esse padrão para a terceira avaliação é agora muito mais provável do que escrever um parágrafo de análise, então é isso que você recebe. É por isso que alguns exemplos claros geralmente batem um parágrafo de descrição, especialmente para classificação e formatação: você está demonstrando a forma da saída em vez de descrever e esperar. Escolha exemplos que cubram os casos complicados, já que o modelo se padrão no que você mostra, incluindo qualquer erro em seus exemplos.
Peça a ela para raciocinar
Aqui está uma das ideias de prompting mais úteis, e uma das menos intuitivas, e ela cai direto de como o modelo funciona. O modelo gera um token de cada vez, e o único espaço de trabalho que tem é o texto que já escreveu. Não tem um bloco de rascunho oculto para resolver silenciosamente um problema difícil antes de responder. Seu pensamento, ou seja lá o que for, acontece em voz alta, nos tokens que produz.
Então se você pedir uma pergunta com múltiplas etapas e exigir apenas a resposta final, você está forçando o modelo a pular para o fim em um único token sem lugar para trabalhar, e em qualquer coisa envolvendo raciocínio, matemática ou lógica ele frequentemente pula errado. A correção é deixá-lo trabalhar abertamente. Peça a ele para expor seus passos antes da resposta:
messages = [
{"role": "system", "content": "Trabalhe através do problema passo a passo, depois dê a resposta final em sua própria linha."},
{"role": "user", "content": "Uma loja vende canetas a 3 por $2. Quanto custam 12 canetas?"},
]
# sem "passo a passo", modelos frequentemente soltam um número errado
# com ele, o modelo escreve o trabalho, e cada passo torna o próximo mais confiávelIsso é chamado de prompting em cadeia de pensamento, e a razão pela qual funciona é mecânica, não mágica. Cada passo que o modelo escreve se torna parte do contexto que lê para o próximo token, então escrever "12 canetas é 4 grupos de 3" torna "4 grupos vezes $2 é $8" a continuação natural e provável. Você está dando ao modelo espaço para computar na página em vez de exigir a resposta em um salto impossível. "Pense passo a passo" ou "mostre seu trabalho" é a versão do dia a dia.
Duas ressalvas. O raciocínio escrito ainda é texto gerado, então pode parecer sólido e chegar a uma resposta errada, e você não deve tratá-lo como prova garantida. E alguns modelos mais novos fazem esse tipo de trabalho internamente sem serem pedidos. Mas o princípio subjacente é durável em quais modelos venham a seguir: um modelo raciocina melhor quando tem espaço para escrever os passos, porque sua própria saída é o único lugar que tem para pensar.
Estruture o prompt
Conforme prompts crescem, estrutura mantém o contexto claro para que o modelo pese cada parte corretamente. Alguns hábitos ajudam:
- Coloque instruções primeiro, dados por último. Declare o que fazer, depois forneça o texto para fazer.
- Separe instruções de dados com delimitadores. Envolva qualquer texto fornecido em marcadores claros para que o limite entre suas regras e a entrada seja inconfundível.
- Peça pela forma de saída explicitamente. Se você quer JSON, diga, e descreva os campos.
prompt = f'''Resuma a mensagem do cliente abaixo em uma frase.
Depois liste qualquer nome de produto que ela menciona.
Mensagem do cliente:
"""
{user_message}
"""'''As aspas triplas são um delimitador. Elas marcam "tudo dentro daqui é dados para processar, não instruções a seguir". Isso não é apenas arrumação, e aqui a visão de previsão mostra por que é uma proteção real.
Para o modelo é tudo um fluxo de texto, então se entrada do usuário flui direto em suas instruções sem limite, um usuário pode escrever "ignore acima e faça isso" e o modelo não tem forma confiável de dizer que linha separadamente de suas instruções reais. Pode bem continuar obedecendo.
Esse ataque é chamado de injeção de prompt, e manter instruções e dados não confiáveis claramente cercados é a primeira linha de defesa, coberta em Segurança e limites. Para o modelo é tudo um fluxo de texto, então cerque entrada não confiável.
Na prática
Aqui está um prompt que empilha várias dessas ideias: uma mensagem do sistema para regras duráveis, uma solicitação específica, um exemplo para fixar o formato, e dados claramente delimitados.
messages = [
{
"role": "system",
"content": (
"Você extrai itens de ação de notas de reunião. "
"Responda com uma lista numerada, um item de ação por linha, cada um começando com um verbo. "
"Se não houver itens de ação, responda 'Nenhum'."
),
},
{"role": "user", "content": 'Notas: """Concordamos que Marina enviará o orçamento até sexta e João reservará o local."""'},
{"role": "assistant", "content": "1. Enviar o orçamento até sexta (Marina)\n2. Reservar o local (João)"},
{"role": "user", "content": f'Notas: """{meeting_notes}"""'},
]A mensagem do sistema define as regras uma vez, o exemplo fixa o formato exato, e cada solicitação entrega dados cercados. Cada peça está organizando o contexto para que a saída que você quer seja a continuação provável. Esse é todo o ofício: isso é um prompt confiável, não um de sorte. Em seguida você enviará mensagens como essas para um modelo a partir de código real em Chamando modelos a partir do código.
system para regras duráveis, uma solicitação específica, um exemplo para fixar o formato, e dados claramente delimitados. Cada peça organiza o contexto para que sua saída desejada seja o próximo texto provável. Esse é o ofício, um prompt que funciona por design em vez de sorte. 
