Preparação para entrevista
RefatoraçãoCompondo prompts

Extrair Template Versionado

Extract Versioned Template

Extrair Template Versionado (Extract Versioned Template) é uma refatoração de IA para sistemas com LLM, do grupo Compondo prompts. Juntar pedaços de prompt espalhados em um template com nome, versão e variáveis.

Elemento
05/35
Nível
Iniciante
Leitura
5 min
Atualizado
Nesta página 8
  1. 01Problema
  2. 02Solução
  3. 03Antes e depois
  4. 04Por que funciona
  5. 05Passo a passo seguro
  6. 06Riscos
  7. 07Desafio
  8. 08Teste seu entendimento
  9. ··Perguntas rápidas

Problema

O prompt está espalhado em pedaços pelo código, sem versão, ou ajustado a um modelo de um jeito que ninguém consegue mudar com segurança. São os smells Prompt Espalhado, Prompt Sem Versão e Prompt Preso ao Modelo.

Imagine o SDR da Empresa. A primeira mensagem para um lead nasce em quatro arquivos: a persona em persona.py, o tom em tone.py, a campanha do trimestre em campaigns/q3.py e um if no writer.py que esconde o preço se o lead for enterprise. Ninguém no time consegue colar o prompt inteiro num chat e dizer “é isto que o modelo vê”.

Uma segunda-feira a taxa de resposta cai. Você abre o trace e vê só a chamada ao modelo. Sem nome, sem versão, sem o texto renderizado. Qual dos quatro arquivos mudou? A campanha de Q3 ainda está no ar em outubro? O if de preço disparou para o lead errado? Sem um artefato, você está adivinhando.

O padrão de destino desta refatoração é o Registro de Templates.

Solução

Junte os pedaços num template único, com nome, versão imutável e variáveis declaradas. O código carrega o template por nome e versão, preenche as variáveis e registra a versão em cada execução.

Antes e depois

-# persona.py, tone.py, campaigns/q3.py, writer.py
-prompt = BASE + tone(lead.segment) + CAMPAIGN + f"Lead: {lead.name}. " \
-         + ("Não mencione preço. " if lead.is_enterprise else "")
+# prompts/sdr_first_message/v14.yaml
+# name: sdr_first_message
+# version: 14
+# model: claude-sonnet-4-5
+# variables: [lead_name, company, tone, pricing_policy, campaign]
+# template: |
+#   Você é Júlia, consultora da Empresa.
+#   Tom: {{ tone }}.
+#   Campanha ativa: {{ campaign }}.
+#   Política de preço para este lead: {{ pricing_policy }}.
+#   Lead: {{ lead_name }}, {{ company }}.
+
+tpl = prompts.get("sdr_first_message", version=14)
+prompt = tpl.render(
+    lead_name=lead.name, company=lead.company, tone=tone_for(lead.segment),
+    pricing_policy=pricing_policy_for(lead), campaign=active_campaign())
+trace.set("prompt.name", tpl.name)
+trace.set("prompt.version", tpl.version)

Antes: o prompt existe só em tempo de execução.

flowchart LR
  A["persona.py"]:::tool --> J["1. Concatenação"]:::tool
  B["tone.py"]:::tool --> J
  C["campaign.py"]:::tool --> J
  J --> M(["2. Prompt sem nome nem versão"]):::llm

Depois: um template versionado, preenchido por variáveis declaradas.

flowchart LR
  R[("1. Registro: sdr_first_message v14")]:::store --> T["2. Renderizar com variáveis"]:::tool
  V(["Dados do lead"]):::io --> T
  T --> M(["3. Modelo"]):::llm
  M --> L[("4. Trace com nome e versão")]:::store
  1. O template inteiro está num lugar, com nome e versão.
  2. O código só fornece os valores das variáveis declaradas. Tom e política de preço são calculados em Python, não no YAML.
  3. O modelo recebe um prompt que pode ser lido e reproduzido.
  4. Cada execução registra qual versão usou.

Exemplo trabalhado

Pegue um lead realista: Marina, da Indústria Norte, segmento indústria, contrato enterprise. No antes, o writer.py concatena quatro strings e o if lead.is_enterprise acrescenta “Não mencione preço”. O texto final só existe naquele instante.

No depois, tone_for("industria") devolve "formal", pricing_policy_for(lead) devolve "Não mencione preço nem faixa." e active_campaign() devolve o texto da campanha vigente. O template v14 recebe cinco valores e produz um prompt reproduzível. O span fica assim:

prompt.name=sdr_first_message  prompt.version=14
lead_name=Marina  company=Indústria Norte  tone=formal

Uma semana depois a taxa de resposta cai de novo. Você filtra o trace por prompt.version=14, pega o prompt renderizado e compara com um caso que funcionava. Se o texto for idêntico, o problema não é o prompt: é o lead, o modelo ou o canal. Se diferir, você sabe exatamente o que mudou.

Checagem +20 XP de primeiraUma mensagem de SDR saiu com tom informal para um lead enterprise. O trace da chamada não tem prompt.name nem prompt.version. Qual é o primeiro diagnóstico?

Por que funciona

Um template versionado transforma o prompt num artefato: dá para ler inteiro, revisar num pull request, comparar duas versões e voltar atrás. As variáveis declaradas deixam explícito o que muda de um pedido para outro; o resto é fixo e testável.

A versão no trace fecha o ciclo. Uma resposta ruim aponta para o texto exato que a gerou, e o eval pode comparar a versão nova com a anterior antes da troca. Migrar de modelo vira criar uma versão nova do template para o modelo novo e comparar as duas, em vez de reescrever if model == ... espalhados.

Há um ganho de cache também. Provedores como Anthropic e OpenAI cacheiam o prefixo estável do prompt. Se a persona, o tom-base e as regras ficam no começo do template, e só lead_name, campaign e a data mudam no fim, o cache acerta. Concatenação espalhada mistura o que muda com o que não muda, e o cache perde o prefixo.

Um erro comum: levar o if do Python para o YAML. {{ "formal" if segment == "industria" else "próximo" }} recria o Prompt Espalhado, agora escondido no template. Calcule tone em código e passe o resultado.

Passo a passo seguro

  1. Meça. Rode o eval com o prompt atual. Guarde também alguns prompts montados de verdade, para comparar byte a byte depois.
  2. Reúna os pedaços e escreva o prompt completo para cada combinação relevante (indústria enterprise, startup com preço visível, e assim por diante).
  3. Identifique o que realmente varia e transforme em variáveis declaradas. Condições complexas viram variáveis calculadas em código (pricing_policy, tone), não lógica no template.
  4. Crie o template com nome, versão e lista de variáveis, num lugar com histórico. Um arquivo no repositório basta. Ferramentas como LangSmith e Langfuse também versionam prompts, se o time já as usa.
  5. Troque a montagem por carregar e renderizar o template, falhando se faltar variável. Não use um default silencioso: variável faltando é bug, não “texto vazio”.
  6. Confira que o prompt renderizado é igual ao montado antes, para as combinações de teste. Espaço e quebra de linha contam.
  7. Registre nome e versão em cada span. Se puder, registre também o hash do texto renderizado.
  8. Meça de novo com o eval. A partir daqui, toda mudança é uma versão nova: v15, não um edit em cima da v14.

Como versionar de verdade

Versão imutável quer dizer: o arquivo v14.yaml nunca é editado depois de publicado. Um ajuste de uma palavra vira v15.yaml. Produção aponta para um número, não para latest.

Quando o modelo muda, você não reaproveita a v14 “na esperança”. Cria v15 com o texto ajustado ao modelo novo, roda o eval nas duas e só então promove. Isso é o tratamento do Prompt Preso ao Modelo: o texto e o modelo andam juntos, mas de forma explícita.

Checagem +20 XP de primeiraO time colocou no YAML Tom: {{ 'formal' if segment == 'industria' else 'próximo' }}. O prompt agora vive num arquivo só. A refatoração está completa?

Riscos

  • Lógica demais no template. Ifs e loops dentro do template recriam o problema. Calcule em código e passe como variável.
  • Diferença invisível. Espaços e quebras de linha mudam a renderização. Compare os prompts antes e depois byte a byte nos casos de teste.
  • Versão “latest” em produção. Carregar sempre a mais nova tira o controle. Fixe a versão em produção e promova versões novas depois do eval.
  • Variável que cresce sem limite. Se campaign puder receber um PDF inteiro, o template vira um saco sem fundo. Declare tipo e tamanho máximo no registro, e recuse valores fora.

Desafio

Quais partes destes trechos viram variáveis do template, e quais ficam fixas?

prompt = "Você responde dúvidas de RH da Empresa. "
prompt += f"O funcionário se chama {emp.name} e trabalha em {emp.state}. "
if emp.state == "SP":
    prompt += "Considere o feriado municipal de 25 de janeiro. "
prompt += "Seja breve. Hoje é " + date.today().isoformat() + "."
Ver solução

Fixo: a função, “seja breve”. Variáveis: employee_name, local_holidays (uma lista calculada em código a partir do estado) e today. A data deve ir no fim do prompt, ou na mensagem do usuário, para não quebrar o cache de prompt.

O if emp.state == "SP" não vai para o YAML. Em código, algo como holidays_for(emp.state) devolve "25 de janeiro (São Paulo)" ou uma lista vazia. O template só interpola.

name: hr_assistant
version: 3
variables: [employee_name, local_holidays, today]
template: |
  Você responde dúvidas de RH da Empresa. Seja breve.
  Funcionário: {{ employee_name }}.
  Feriados locais a considerar: {{ local_holidays }}.
  Data de hoje: {{ today }}.

Teste seu entendimento

Checagem +20 XP de primeiraProdução carrega prompts.get('sdr_first_message', version='latest'). Um pull request publica v15, o eval ainda não rodou, e as mensagens de SDR mudam na hora. Qual é o erro?

Checagem +20 XP de primeiraVocês vão trocar o modelo do SDR de Sonnet para um modelo menor. O template v14 foi afinado no Sonnet. Qual é o próximo passo mais seguro?

Checagem +20 XP de primeiraO renderizador encontra campaign no template, mas o código não passou esse valor. O que o código deve fazer?

Checagem +20 XP de primeiraO time quer colocar a data de hoje no começo do system prompt, logo após a persona, para o modelo 'saber que dia é'. O prefixo da persona é cacheado pelo provedor. O que acontece?

Perguntas rápidas

O que é Extrair Template Versionado?

Extrair Template Versionado (Extract Versioned Template) é uma refatoração de IA para sistemas com LLM, do grupo Compondo prompts. Juntar pedaços de prompt espalhados em um template com nome, versão e variáveis.

Que problema Extrair Template Versionado resolve?

Trata Prompt Preso ao Modelo, Prompt Espalhado e Prompt Sem Versão.

Aonde Extrair Template Versionado leva?

Ao padrão de projeto Registro de Templates.

Para ir além

Relações

Padrões de destino 1
Buscar