4. Projetando Prompts Reutilizáveis com Templates
No Capítulo 3, construímos uma CLI de chat com streaming funcional onde os prompts estavam incorporados diretamente em nosso código Python. Isso funciona para protótipos rápidos, mas à medida que suas aplicações de IA crescem, prompts codificados diretamente se tornam um pesadelo de manutenção. Imagine atualizar a mesma lógica de prompt em vários arquivos, ou tentar fazer testes A/B de diferentes variações de prompt sem reimplantar código.
Este capítulo ensina como projetar prompts reutilizáveis e sustentáveis usando o sistema de templates do LangChain. Você aprenderá a separar a lógica de prompt do código da aplicação, aproveitar mensagens baseadas em papéis para melhor controle do LLM, externalizar prompts para arquivos YAML para colaboração em equipe e validar templates antes da execução para detectar erros cedo.
O Que Este Capítulo Cobre (e O Que Não Cobre):
Neste capítulo, trabalharemos com templates e prompts manualmente—você renderizará explicitamente templates para mensagens, depois enviará essas mensagens ao LLM usando llm.invoke(). Esta abordagem prática ajuda você a entender exatamente o que os templates fazem e como funcionam.
No Capítulo 6, você aprenderá LCEL (LangChain Expression Language), que permite compor templates e LLMs em pipelines usando o operador |. Por enquanto, estamos focando nos fundamentos de templates sem essa camada de orquestração.
Ao final deste capítulo, você terá um sistema robusto de gerenciamento de prompts que escala de chatbots simples a fluxos de trabalho complexos multi-agente.
4.1) Separação de Responsabilidades: Desacoplando Código de Prompts
Por Que Separar Prompts do Código?
Quando você codifica prompts diretamente na lógica da sua aplicação, você cria acoplamento forte que leva a vários problemas:
Carga de Manutenção: Alterar um prompt requer modificar código Python, executar testes e reimplantar. Mudanças de prompt tipicamente acontecem muito mais frequentemente do que mudanças de código, tornando este ciclo de modificação-teste-reimplantação altamente ineficiente para o que deveriam ser simples edições de texto.
Desafios de Controle de Versão: Quando código e prompts estão misturados, o controle de versão se torna difícil. Conflitos de merge são mais prováveis, e cada conflito requer resolução manual e refatoração.
Fricção de Colaboração: Membros não técnicos da equipe (gerentes de produto, especialistas de domínio) não podem editar diretamente prompts que vivem em arquivos .py e devem depender de assistência de desenvolvedores. Esta dependência torna os ciclos de melhoria de prompt significativamente mais lentos.
Complexidade de Testes: Testar diferentes variações de prompt significa copiar código, modificar strings e gerenciar múltiplos branches—tornando experimentos lentos e propensos a erros.
Pense em prompts como consultas SQL em aplicações tradicionais. Você não codificaria strings SQL por todo seu código Python—você usaria um ORM ou pelo menos centralizaria consultas. Prompts merecem a mesma disciplina arquitetural.
Sistema de Templates do LangChain
O LangChain fornece as classes PromptTemplate e ChatPromptTemplate para separar a estrutura fixa do seu prompt dos dados que mudam. Escreva seu prompt uma vez com {placeholders}, depois conecte valores diferentes cada vez—sem mais reconstrução de prompts com f-strings ou concatenação.
Sintaxe e Uso de Templates
Sintaxe de Placeholder
Templates usam {nome_variavel} como placeholders. Em tempo de execução, você fornece um dicionário com chaves correspondentes:
from langchain_core.prompts import PromptTemplate
# Define template com placeholders
template = PromptTemplate.from_template(
"Traduza {content} de {source_lang} para {target_lang}"
)
# Preenche placeholders com dicionário
result = template.invoke({
"content": "Hello world",
"source_lang": "Inglês",
"target_lang": "Coreano"
})
print(result.text)Saída:
Traduza Hello world de Inglês para CoreanoRegras Principais:
- Nomes de placeholder devem corresponder exatamente às chaves do dicionário
- Todos os placeholders devem ser fornecidos (chaves ausentes geram
KeyError) - Chaves extras do dicionário são ignoradas
- Use
invoke()para renderizar o template com seus valores
PromptTemplate vs ChatPromptTemplate
PromptTemplate: Retorna uma string simples (envolvida em StringPromptValue)
- Para completação de texto simples ou modelos legados
- Saída: String única como
"Resumir: {content}"
ChatPromptTemplate: Retorna mensagens estruturadas com papéis (envolvidas em ChatPromptValue)
- Para modelos de chat modernos (GPT-4, Claude, Gemini)
- Saída: Mensagens separadas por papel (system/user/assistant)
- Escolha preferida: Melhor para manter instruções de sistema separadas da entrada do usuário
Quando usar qual?
- Padrão para
ChatPromptTemplatepara modelos de chat—é mais claro e sustentável - Use
PromptTemplateapenas para completações simples ou quando separação de papéis não for necessária
# PromptTemplate - saída de string única
from langchain_core.prompts import PromptTemplate
template1 = PromptTemplate.from_template("Resumir: {content}")
result1 = template1.invoke({"content": "LangChain é um framework..."})
print(result1)Saída:
text='Resumir: LangChain é um framework...'# ChatPromptTemplate - mensagens baseadas em papéis
from langchain_core.prompts import ChatPromptTemplate
template2 = ChatPromptTemplate.from_messages([
("system", "Você é um assistente prestativo"),
("user", "{question}")
])
result2 = template2.invoke({"question": "O que é LangChain?"})
print(result2)Saída:
messages=[SystemMessage(content='Você é um assistente prestativo'), HumanMessage(content='O que é LangChain?')]O template é definido uma vez. Você pode reutilizá-lo com valores diferentes sem modificar a definição do template. Tanto PromptTemplate.invoke() quanto ChatPromptTemplate.invoke() retornam valores de prompt prontos para serem enviados diretamente a um LLM.
De Formatação de String para Templates
Vamos refatorar um prompt codificado para usar templates. Aqui está a versão "antes" do Capítulo 3:
# Abordagem codificada (estilo Capítulo 3)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
user_input = "Explique computação quântica"
# Lógica de prompt misturada com código
prompt = f"Você é um assistente prestativo. Responda esta pergunta: {user_input}"
response = llm.invoke(prompt)
print(response.content)Agora com templates—usando a abordagem passo a passo que praticaremos ao longo deste capítulo:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Template definido separadamente
template = ChatPromptTemplate.from_messages([
("system", "Você é um assistente prestativo."),
("user", "{user_input}")
])
# Lógica da aplicação - execução passo a passo
llm = ChatOpenAI(model="gpt-4o-mini")
user_input = "Explique computação quântica"
# Passo 1: Renderizar template para mensagens
messages = template.invoke({"user_input": user_input})
# Passo 2: Enviar mensagens ao LLM
response = llm.invoke(messages)
print(response.content)O Que Mudou?
- Definição de Template: A estrutura do prompt é definida uma vez em
template, separada da lógica de execução. - Sintaxe de Placeholder:
{user_input}é um placeholder que é preenchido em tempo de execução. - Execução Passo a Passo: Renderizamos explicitamente o template (
template.invoke()), depois enviamos o resultado ao LLM (llm.invoke()). Este processo de dois passos ajuda você a entender o que os templates realmente fazem. - Reutilização: O mesmo
templatepode ser usado para qualquer pergunta do usuário sem modificação. - Estrutura de Mensagem:
template.invoke()retorna umChatPromptValueformatado adequadamente que o LLM espera.
Por Que a Abordagem Passo a Passo?
Ao longo deste capítulo, você verá este padrão repetidamente:
messages = template.invoke(inputs) # Passo 1: Renderizar template
response = llm.invoke(messages) # Passo 2: Enviar ao LLMEstamos usando esta abordagem de dois passos intencionalmente para aprendizado—ela mostra exatamente o que os templates fazem: transformar dados de entrada em mensagens estruturadas. No Capítulo 6, você aprenderá o padrão de produção do mundo real: combinar estes passos com pipelines LCEL (template | llm). Mas entender cada passo separadamente primeiro constrói uma base sólida.
Validação de Template
Templates detectam erros cedo. Se você referenciar um placeholder que não existe, o LangChain gera um erro antes de fazer uma chamada de API:
template = PromptTemplate.from_template("Resumir: {text}")
# Isso falhará - chave 'text' ausente
try:
template.invoke({"content": "Algum texto"}) # Nome de chave errado
except KeyError as e:
print(f"Erro de template: {e}")Saída:
Erro de template: "Input to PromptTemplate is missing variables {'text'}. Expected: ['text'] Received: ['content']Esta validação acontece no momento da renderização do template, não durante a execução do LLM—economizando tanto tempo quanto custos de API.
4.2) Templates de Prompt Conscientes de Papel (System, User, Assistant)
Compreendendo Papéis de Mensagem
LLMs modernos (GPT-4, GPT-5, Claude, Gemini) entendem estrutura conversacional através de papéis de mensagem. Cada mensagem tem um papel específico que diz ao modelo como interpretá-la.
Os Três Papéis Principais:
System: Define como a IA deve se comportar
- Propósito: Define a personalidade, expertise e regras operacionais da IA
- Exemplo: "Você é um especialista em Python que escreve exemplos de código concisos"
- Quando se aplica: Definido uma vez no início, influencia todas as respostas
- Pense nisso como: O manual de instruções da IA
User: Representa entrada humana
- Propósito: Faz perguntas ou solicitações
- Exemplo: "Como eu leio um arquivo em Python?"
- Quando se aplica: Toda vez que um humano envia uma mensagem
- Pense nisso como: As perguntas que você faz
Assistant: Representa as respostas anteriores da IA
- Propósito: Fornece histórico de conversa
- Exemplo: "Você pode usar a função open() para ler arquivos"
- Quando se aplica: Quando você precisa de conversas multi-turno
- Pense nisso como: A memória da IA de respostas anteriores
Mensagens de Sistema: O Mecanismo de Controle
A mensagem de sistema diz à IA quem ela é e como deve operar—antes de qualquer interação do usuário.
O Que Você Pode Controlar:
- Expertise: "Você é um desenvolvedor Python sênior"
- Formato de Saída: "Sempre responda em formato JSON"
- Regras Comportamentais: "Se não tiver certeza, diga 'Não sei'"
- Estilo de Resposta: "Seja conciso e técnico"
Por Que Isso Importa:
Sem mensagem de sistema → respostas genéricas e verbosas
Com mensagem de sistema → comportamento consistente e personalizado
Mensagens de Sistema em Ação
Vamos ver o impacto real das mensagens de sistema comparando a mesma pergunta com e sem uma. Preste atenção em como a resposta muda dramaticamente—não apenas em comprimento, mas em tom, complexidade e abordagem de ensino.
Sem Mensagem de Sistema:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
template = ChatPromptTemplate.from_messages([
("user", "O que é Python?")
])
llm = ChatOpenAI(model="gpt-4o-mini")
messages = template.invoke({})
response = llm.invoke(messages)
print(response.content)Saída:
Python é uma linguagem de programação de alto nível e interpretada, conhecida por sua legibilidade e simplicidade.
Foi criada por Guido van Rossum e lançada pela primeira vez em 1991.
Python enfatiza a legibilidade do código, permitindo que programadores expressem conceitos em menos linhas de código comparado a linguagens como C++ ou Java.
Características principais do Python incluem:
...Com Mensagem de Sistema:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Controla persona e estilo de saída com mensagem System
template = ChatPromptTemplate.from_messages([
("system", """Você é um instrutor sênior de Python com 15 anos de experiência em ensino.
Seus alunos são iniciantes completos que nunca programaram antes.
Estilo de ensino:
- Use analogias simples do dia a dia
- Evite jargão técnico
- Mostre exemplos práticos da vida diária
- Seja encorajador e paciente"""),
("user", "O que é Python?")
])
llm = ChatOpenAI(model="gpt-4o-mini")
messages = template.invoke({})
response = llm.invoke(messages)
print(response.content)Saída:
Ótima pergunta! Pense em Python como uma ferramenta muito útil na sua caixa de ferramentas.
Assim como um martelo ou uma chave de fenda ajuda você a construir ou consertar coisas em casa, Python ajuda você a criar software ou automatizar tarefas em um computador.
Imagine que você quisesse fazer um bolo.
Você precisa de uma receita para seguir, certo? Nesta analogia, Python é como essa receita.
Ele diz ao computador quais passos seguir para alcançar um objetivo, seja fazer cálculos, organizar arquivos ou até executar um jogo.
...A Diferença:
Sem Mensagem de Sistema:
- A IA usa seu comportamento padrão: educada, informativa, mas genérica
- Respostas são enciclopédicas e formais—otimizadas para públicos amplos
- Sem persona consistente: cada resposta pode variar em tom e estilo
- Sem restrições: a IA decide por conta própria quão detalhada ou técnica ser
Com Mensagem de Sistema:
- A IA segue suas instruções específicas: persona, estilo e regras que você definiu
- Respostas são consistentes e previsíveis—cada resposta corresponde aos seus requisitos
- Persona clara mantida: age como o papel que você atribuiu (professor, especialista, assistente)
- Restrições explícitas aplicadas: formato de saída, nível de linguagem e limites comportamentais que você definiu
Insight Chave: Sem uma mensagem de sistema, você obtém o modo padrão da IA. Com uma mensagem de sistema, você obtém sua IA—personalizada para as necessidades da sua aplicação. A mensagem de sistema transforma a IA de uma ferramenta de propósito geral em um assistente especializado que se comporta exatamente como você quer, todas as vezes.
Papéis User e Assistant: Construindo Conversas
Pergunta Única (Apenas User):
template = ChatPromptTemplate.from_messages([
("system", "Você é um especialista em Python."),
("user", "{question}")
])
llm = ChatOpenAI(model="gpt-4o-mini")
messages = template.invoke({"question": "Como eu leio um CSV?"})
response = llm.invoke(messages)Funciona bem para perguntas independentes.
Multi-Turno com Contexto (User + Assistant):
Sem histórico:
template = ChatPromptTemplate.from_messages([
("system", "Você é um especialista em Python."),
("user", "Como isso funciona?") # "isso" = ???
])A IA não sabe a que "isso" se refere.
Com histórico:
template = ChatPromptTemplate.from_messages([
("system", "Você é um especialista em Python."),
("user", "O que é a biblioteca pandas?"),
("assistant", "Pandas é uma biblioteca de análise de dados."),
("user", "Como isso funciona?") # Agora "isso" = pandas
])O histórico da conversa (pergunta anterior do usuário + resposta do assistente) fornece contexto. A IA agora entende que "isso" significa pandas.
Exemplo: Construindo uma Conversa com Histórico
Agora vamos construir um exemplo que lembra trocas anteriores. Esta função mantém o histórico da conversa e o passa para a IA com cada nova pergunta:
llm = ChatOpenAI(model="gpt-4o-mini")
def chat_with_history(user_input: str, history: list):
messages = [("system", "Você é um especialista em Python.")]
# Adiciona histórico
for msg in history:
messages.append((msg["role"], msg["content"]))
# Adiciona entrada atual
messages.append(("user", user_input))
# Usa formato mustache para evitar erros quando o conteúdo contém {chaves}
template = ChatPromptTemplate.from_messages(messages, template_format="mustache")
formatted = template.format()
response = llm.invoke(formatted)
return response.content
# Uso
history = []
# Turno 1
resp1 = chat_with_history("O que é um dicionário Python?", history)
print(resp1)
history.append({"role": "user", "content": "O que é um dicionário Python?"})
history.append({"role": "assistant", "content": resp1})
# Turno 2 - usa contexto
resp2 = chat_with_history("Mostre um exemplo.", history)
print(resp2)Regras de Ordem de Mensagens
LLMs esperam uma estrutura de conversa específica: System → User → Assistant → User → Assistant → ...
Por Que Esta Ordem?
Este padrão espelha conversas naturais humano-IA:
-
System vem primeiro (opcional): Porque define regras comportamentais que se aplicam à conversa inteira, deve ser definido antes de qualquer interação começar. Assim como você orienta alguém antes de começar a trabalhar, não no meio de uma tarefa.
-
User então Assistant alternam: Em conversas reais, humanos falam (User), IA responde (Assistant), humanos fazem follow-up (User), IA responde novamente (Assistant). Este padrão de alternância é como a IA foi treinada, então ela espera esta estrutura.
-
Deve terminar com User: A IA gera uma resposta à última mensagem User. Se a conversa termina com Assistant, não há nada para a IA responder.
Exemplos Válidos:
# System + User único
[("system", "..."), ("user", "...")]
# System + conversa
[("system", "..."), ("user", "..."), ("assistant", "..."), ("user", "...")]Padrões Problemáticos:
# Assistant antes de User - IA fica confusa sobre contexto
[("system", "..."), ("assistant", "..."), ("user", "...")]
# A IA vê uma resposta sem uma pergunta. Pode alucinar qual pergunta
# estava sendo respondida, levando a respostas irrelevantes ou confusas.# Duas mensagens User seguidas - resposta da IA ausente
[("system", "..."), ("user", "..."), ("user", "...")]
# A IA não sabe a qual mensagem User responder, ou pode mesclá-las
# de forma estranha. Perde o fluxo conversacional.# Termina com Assistant - nada para responder
[("system", "..."), ("user", "..."), ("assistant", "...")]
# A conversa está completa. A IA não tem nada para gerar já que não há
# pergunta User pendente. Provavelmente produzirá um erro ou resposta vazia.Ponto Chave: Estes padrões nem sempre causam erros graves, mas confundem a IA porque quebram a lógica conversacional na qual ela foi treinada. A IA pode gerar respostas, mas elas serão não confiáveis ou sem sentido. Sempre siga o padrão esperado para comportamento previsível.
Além do Histórico Simples: Padrões de Produção (Preview)
Nota Importante: O padrão de histórico de conversa que você acabou de aprender é uma ótima base, mas sistemas de produção usam abordagens mais sofisticadas.
O Problema com Histórico Bruto:
Simplesmente passar todo o histórico de conversa para a IA tem limitações:
- Desperdício de tokens: Cada mensagem (mesmo as antigas) conta para seu limite de tokens e custos
- Perda de foco: A IA pode se distrair com conversas anteriores irrelevantes
- Sem tarefa explícita: A IA infere o que fazer do histórico, em vez de receber instruções claras
Uma Abordagem Melhor:
Sistemas de produção separam contexto de instruções:
Abordagem de histórico simples (o que acabamos de aprender):
messages = [
("system", "Você é um especialista em Python."),
("user", "O que é um dicionário?"),
("assistant", "Um dicionário é uma estrutura de dados chave-valor."),
("user", "Mostre um exemplo.")
]Abordagem de produção (vindo em capítulos posteriores):
messages = [
("system", "Você é um especialista em Python."),
("user", """Contexto: O usuário perguntou anteriormente sobre dicionários Python e aprendeu que são estruturas chave-valor.
Tarefa: Forneça um exemplo de código demonstrando o uso de dicionário.""")
]A Diferença:
- Histórico bruto: IA vê a conversa completa e descobre o que fazer
- Padrão de produção: IA recebe contexto resumido + instrução explícita
Benefícios da separação:
- Menos tokens (menor custo, respostas mais rápidas)
- Comportamento mais confiável (instruções claras)
- Melhor controle (você decide qual contexto importa)
Onde você aprenderá isso:
- Capítulo 8: Gerenciando estado de conversa e memória
- Capítulo 11: Recuperação Contextual (combinando RAG com memória de conversa)
- Capítulo 16: Roteamento dinâmico baseado em contexto de conversa
Por enquanto, entender histórico bruto é essencial—é a base para estes padrões avançados. Mas tenha em mente: o que você acabou de aprender é uma ferramenta de ensino, não a solução final.
4.3) Externalizando Prompts: Gerenciando Arquivos de Template (.yaml)
Por Que Externalizar Prompts?
À medida que sua aplicação de IA cresce, gerenciar prompts em código Python se torna difícil. Externalizar prompts para arquivos YAML fornece:
Colaboração Não Técnica: Gerentes de produto, especialistas de domínio e engenheiros de prompt podem editar arquivos YAML sem tocar em código Python ou entender conceitos de programação.
Clareza de Controle de Versão: Rastreie mudanças de prompt separadamente de mudanças de código. Não mais commits mistos onde ajustes de prompt e atualizações de lógica aparecem juntos.
Prompts Específicos de Ambiente: Prompts diferentes para desenvolvimento, staging e produção sem mudanças de código.
Testes A/B: Teste variações de prompt carregando arquivos diferentes—sem mudanças de código necessárias.
Pense em arquivos de prompt YAML como arquivos de configuração em aplicações tradicionais—eles definem comportamento sem exigir mudanças de código ou reimplantação.
O Que é YAML?
YAML é um formato de dados legível por humanos comumente usado para arquivos de configuração. Se você nunca viu YAML antes, pense nele como uma alternativa mais limpa ao JSON—ele usa indentação em vez de colchetes e é mais fácil de ler e editar.
Estrutura de Prompt YAML
O LangChain define uma estrutura de arquivo YAML padrão para prompts. Vamos ver exemplos:
Exemplo 1: Prompt sem variáveis
Quando um prompt não precisa de valores em tempo de execução, defina input_variables como uma lista vazia:
# prompts/system_prompt.yaml
_type: prompt
input_variables: []
template: |
Você é um assistente prestativo.
Por favor, responda em um tom amigável e encorajador.O símbolo | permite que você escreva texto multi-linha, e quebras de linha são preservadas.
Exemplo 2: Prompt com variáveis
Quando um prompt precisa de valores em tempo de execução, liste-os em input_variables:
# prompts/user_prompt.yaml
_type: prompt
input_variables:
- user_input
template: |
Pergunta do usuário: {user_input}
Por favor, forneça uma resposta clara.Em tempo de execução, o placeholder {user_input} é substituído pelo valor real.
Componentes principais:
_type: prompt: Identifica isso como um template de promptinput_variables: Lista todos os placeholders usados no template (lista vazia[]se nenhum)template: O texto real do prompt com{placeholders}
Carregando e Usando Prompts YAML
Carregamento Básico:
Agora vamos carregar os arquivos YAML que criamos e usá-los com um LLM:
from langchain_core.prompts import load_prompt, ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Carrega prompts de arquivos YAML
system_prompt_template = load_prompt("prompts/system_prompt.yaml")
user_prompt_template = load_prompt("prompts/user_prompt.yaml")
# Combina prompts carregados em um template de chat
chat_template = ChatPromptTemplate.from_messages([
("system", system_prompt_template.template),
("user", user_prompt_template.template)
])
llm = ChatOpenAI(model="gpt-4o-mini")
# Passo 1: Renderizar template com valores em tempo de execução
messages = chat_template.invoke({"user_input": "O que é LangChain?"})
# Passo 2: Enviar ao LLM
response = llm.invoke(messages)
print(response.content)Verificando Templates Carregados:
Antes de usar um template, verifique se ele foi carregado corretamente:
from langchain_core.prompts import load_prompt
# Carrega o template
user_prompt_template = load_prompt("prompts/user_prompt.yaml")
# Verifica quais variáveis ele espera
print("Variáveis de entrada:", user_prompt_template.input_variables)
# Vê o texto do template
print("Template:", user_prompt_template.template)Saída:
Variáveis de entrada: ['user_input']
Template: Pergunta do usuário: {user_input}
Por favor, forneça uma resposta clara.Erros Comuns em YAML
Erro 1: Indentação inconsistente
YAML requer indentação consistente (tipicamente 2 espaços). Cada nível deve usar a mesma quantidade de espaçamento:
Errado:
_type: prompt
input_variables:
- user_input # Errado: itens de lista devem ser indentados
- question # Errado: níveis de indentação misturadosCorreto:
_type: prompt
input_variables:
- user_input # Correto: ambos os itens no mesmo nível de indentação
- questionErro 2: Incompatibilidade de placeholder
Placeholders em template devem corresponder a input_variables:
Errado:
input_variables:
- user_input
template: "Pergunta: {question}" # 'question' não está em input_variables!Correto:
input_variables:
- user_input
template: "Pergunta: {user_input}"O LangChain gerará um erro se os placeholders não corresponderem às variáveis declaradas.
4.4) Visualizando e Validando Templates antes da Execução
Por Que Visualizar Templates?
Engenharia de prompt é iterativa. Você ajusta a redação, ajusta a estrutura, adiciona exemplos—e cada iteração custa tokens de API e tempo. Visualizar templates antes da execução permite que você:
Economize Tempo e Dinheiro: Detecte erros antes de fazer chamadas de API caras.
Verifique Correção: Garanta que variáveis sejam preenchidas corretamente e a formatação seja como esperado.
Depure Eficientemente: Veja o prompt exato enviado ao LLM, com todas as variáveis preenchidas e formatação aplicada.
Pense na visualização de template como depuração com print—você inspeciona o estado intermediário antes da execução para verificar correção.
Visualização Básica de Template
Inspecionando Estrutura de Template:
Antes de usar um template com um LLM, inspecione sua estrutura e visualize como ele renderiza com dados de exemplo:
from langchain_core.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages([
("system", "Você é um {role}."),
("user", "{user_input}")
])
# Visualiza estrutura do template
print("Variáveis de entrada:", template.input_variables)
print("Contagem de mensagens:", len(template.messages))
# Visualiza com dados de exemplo
prompt_value = template.invoke({
"role": "especialista em programação Python",
"user_input": "O que é Python?"
})
print("\nVisualização:")
for msg in prompt_value.to_messages():
print(f"{msg.type}: {msg.content}")Saída:
Variáveis de entrada: ['role', 'user_input']
Contagem de mensagens: 2
Visualização:
system: Você é um especialista em programação Python.
human: O que é Python?Isso mostra exatamente o que será enviado ao LLM, permitindo que você verifique o prompt antes da execução.
Validando Templates: Detectando Variáveis Ausentes
O erro de template mais comum é variáveis obrigatórias ausentes. Aqui está uma função de validação reutilizável que detecta variáveis ausentes:
from langchain_core.prompts import ChatPromptTemplate
def preview_template(template: ChatPromptTemplate, inputs: dict):
"""Visualiza template com entradas fornecidas, detectando erros."""
try:
prompt_value = template.invoke(inputs)
print("VISUALIZAÇÃO DE TEMPLATE")
print("=" * 60)
for i, msg in enumerate(prompt_value.to_messages(), 1):
print(f"Mensagem {i} ({msg.type.upper()}):")
print(msg.content)
print("-" * 60)
except KeyError as e:
print(f"ERRO: {e}")
print(f"Variáveis obrigatórias: {template.input_variables}")
# Uso
template = ChatPromptTemplate.from_messages([
("system", "Você é um {role}."),
("user", "{user_input}")
])
# Entradas válidas
preview_template(template, {
"role": "especialista em programação Python",
"user_input": "O que é Python?"
})
# Variável ausente
preview_template(template, {
"user_input": "O que é Python?" # Faltando 'role'
})Saída:
VISUALIZAÇÃO DE TEMPLATE
============================================================
Mensagem 1 (SYSTEM):
Você é um especialista em programação Python.
------------------------------------------------------------
Mensagem 2 (HUMAN):
O que é Python?
------------------------------------------------------------
ERRO: "Input to ChatPromptTemplate is missing variables {'role'}.
Expected: ['role', 'user_input'] Received: ['user_input']
...
Variáveis obrigatórias: ['role', 'user_input']Fluxo de Validação:
Aqui está o processo típico de validação de template:
Este processo iterativo ajuda a detectar erros antes de chamadas LLM caras.
Checklist Pré-Execução
Antes de enviar templates para produção:
- Todas as
input_variablesestão declaradas em YAML/template - Dados de exemplo renderizam sem erros
- Prompts multi-linha exibem corretamente
- Placeholders correspondem exatamente aos nomes de variáveis
- Teste com casos extremos (strings vazias, texto longo)
Resumo do Capítulo:
Você aprendeu a projetar prompts sustentáveis e reutilizáveis usando o sistema de templates do LangChain:
- Separação de Responsabilidades: Desacople prompts do código para manutenção e iteração mais fáceis
- Templates Conscientes de Papel: Use mensagens system, user e assistant para interações LLM estruturadas com hierarquia de instruções adequada
- Prompts Externalizados: Gerencie prompts em arquivos YAML para colaboração não técnica e controle de versão
- Visualização e Validação: Detecte erros cedo e verifique templates antes da execução
Próximos Passos:
No Capítulo 5, você verá como templates permitem tomada de decisão autônoma em exemplos de agentes de visualização. Depois, no Capítulo 6, você aprenderá LCEL (LangChain Expression Language) para compor estes templates em pipelines poderosos usando o operador |.