Descobri algo embaraçoso na semana passada.
Meu pipeline de podcast com IA tem um prompt de sistema elaborado — um "guia de diálogo" — que passei dias criando. Ele diz aos apresentadores (dois comentaristas de futebol gerados por IA) exatamente como conversar entre si. Não repita a mesma abertura. Varie a estrutura entre os segmentos. Use os bordões com moderação. Nunca invente estatísticas.
O LLM leu cada palavra. Depois ignorou quase tudo.
O apresentador vietnamita disse "Trời ơi" (Ai meu Deus) 13 vezes em um único episódio. O apresentador japonês abriu cada segmento com "いやー、健一さん!" (Bom, Kenichi-san!). O apresentador inglês citou com total segurança um xG de 0,35 e 65% de posse de bola — números que não existem em lugar nenhum do meu banco de dados.
O prompt foi educadamente reconhecido. E então ignorado.
Esta é a coisa mais útil que aprendi sobre prompt engineering: os LLMs têm dois modos de leitura, e eles os tratam de forma completamente diferente.
O problema dos dois modos de leitura
Aqui está como era meu guia de diálogo original. Traduzi a versão vietnamita para o português porque a estrutura é idêntica:
DIRETRIZES DE ESTILO:
PADRÃO DE INTERAÇÃO DOS APRESENTADORES: Apresentador Emocional + Apresentador Analítico.
REGRAS ESTRITAS PARA CADA SEGMENTO:
0. NUNCA REPITA A MESMA ABERTURA. Varie qual apresentador inicia,
a qual momento da partida eles reagem primeiro.
1. INÍCIO EMOCIONAL (obrigatório): Cada segmento começa com
a reação pura do apresentador emocional.
2. REGRA DE ANCORAGEM EM DADOS (obrigatório): Toda afirmação deve citar
números específicos. Não "eles dominaram" mas "61% de posse,
3,17 de xG contra 0,65."
3. BORDÕES:
Apresentador emocional: "Você viu isso?!" "Espera espera espera..."
Apresentador analítico: "Tem uma razão mais profunda..." "Deixa eu te contar."
Parece minucioso, né? Eu realmente achei que tinha feito o trabalho.
Mas quando li os roteiros gerados, aqui está o que aconteceu:
| Regra | O que o guia dizia | O que o LLM fez |
|---|---|---|
| Regra 0 (nunca repetir) | Varie a abertura | Cada segmento abria com o bordão do apresentador emocional |
| Regra 2 (dados) | Cite números específicos | Citava números inventados com total autoridade |
| Regra 3 (bordões) | Lista de frases características | Usou cada frase de 5 a 13 vezes por episódio |
As regras estavam lá. O LLM as leu. Mas tinham a força de uma sugestão, não de uma exigência.
Foi aí que percebi: o LLM estava processando minhas regras como "contexto de estilo" — não como "restrições aplicáveis".
O padrão: Contexto vs. Comando
Pense em como você lê diferentes tipos de texto. Se eu te entrego um cardápio de restaurante, você lê como informação para agir. Se eu te entrego um artigo da Wikipédia sobre a história do macarrão, você lê como conhecimento de fundo.
Os LLMs fazem algo parecido com os prompts. Quando as regras aparecem em uma seção rotulada como "DIRETRIZES DE ESTILO" ou "PADRÃO DE INTERAÇÃO DOS APRESENTADORES" ou "REGRAS PARA SEGMENTOS", o modelo as trata como informação ambiental — contexto que colore a resposta mas não a restringe.
Quando as regras aparecem em uma seção rotulada como "MELHORIAS CRÍTICAS EXIGIDAS" ou "LIMITES ESPECÍFICOS DE FRASES", o modelo as trata como comandos aplicáveis — coisas que ele deve verificar e corrigir.
A sacada não está nas palavras "crítico" ou "exigido". Está em onde no pipeline a regra vive.
A solução: faça a etapa de revisão aplicar o que a etapa de geração ignora
Meu pipeline tem duas chamadas ao LLM:
- Etapa de geração — escreve o roteiro segmento por segmento, usando o guia de diálogo como contexto
- Etapa de revisão — lê o roteiro completo montado e o melhora
A etapa de geração era onde todas as minhas regras viviam. A etapa de revisão tinha regras anti-repetição genéricas ("não diga 'Que fascinante' duas vezes") que eram totalmente centradas no inglês e não sabiam nada sobre os bordões dos meus apresentadores ou os requisitos estruturais.
A solução foi estrutural, não lexical. Mudei a aplicação das regras para a etapa de revisão, onde o roteiro completo fica visível de uma vez.
Aqui está o que mudou:
Antes: Regras no prompt de geração (ignoradas)
DIRETRIZES DE ESTILO:
0. NUNCA REPITA A MESMA ABERTURA...
1. INÍCIO EMOCIONAL...
2. ANCORAGEM EM DADOS...
3. BORDÕES: "Você viu isso?!" ...
Depois: Regras extraídas e injetadas no prompt de revisão (aplicadas)
MELHORIAS CRÍTICAS EXIGIDAS EM TODO O ROTEIRO:
2a. APLIQUE AS REGRAS ESTRUTURAIS DAS DIRETRIZES DE ESTILO:
As DIRETRIZES DE ESTILO acima contêm exigências específicas
sobre a estrutura dos segmentos. São EXIGÊNCIAS, não sugestões.
- Se as diretrizes dizem "X de Y segmentos devem variar", MUDE
os segmentos que violam isso.
- Verifique como CADA segmento abre. Se 4+ de 5 abrem de forma idêntica,
VARIE pelo menos 2.
3b. LIMITES DE FRASES POR LOCALE (extraídos dos perfis dos apresentadores —
MÁXIMO 2 VEZES cada uma em todo o roteiro):
- "Trời ơi" / "Trời má" — máx. 4x combinadas
- "Có một lý do sâu hơn" — máx. 2x
- "Mày thấy chưa?!" — máx. 2x
...
Duas coisas aconteceram aqui:
-
As regras estruturais foram promovidas de contexto a comando — reformuladas como "APLIQUE isto" e "MUDE os segmentos que violam isto" em vez de "aqui está o padrão preferido"
-
Os bordões foram extraídos dos perfis dos apresentadores e exibidos como limites explícitos, não como uma lista de sugestões. "Bordões: aqui estão alguns" virou "Estas frases: MÁXIMO 2 VEZES cada."
Ambas as mudanças vivem no prompt de revisão, não no de geração. Essa é a decisão arquitetural chave. A etapa de geração recebe o guia de estilo como contexto — ela precisa do sabor da personalidade. A etapa de revisão recebe as regras como obrigação — ela precisa do mandato de conformidade.
O detalhe da extração (por que isso funciona em 7 idiomas)
Eu não queria manter listas de frases por idioma manualmente. Toda vez que ajustasse um perfil de apresentador, teria que atualizar o prompt de revisão também. Esse é o tipo de descompasso que mata o produto de um desenvolvedor solo.
Em vez disso, escrevi uma pequena função de extração que analisa os perfis dos apresentadores no momento da revisão. O perfil de cada locale tem uma seção de bordões com um rótulo padrão:
- Vietnamita:
Câu cửa miệng: - Japonês:
口癖: - Espanhol:
Latiguillos: - Francês:
Phrases fétiches: - Coreano:
입버릇: - Chinês:
口头禅:
A função encontra esse rótulo, extrai qualquer string entre aspas que o siga e as formata como limites aplicáveis:
@staticmethod
def _extract_catchphrase_limits(host_profiles: str) -> str:
patterns = [
(r'Câu cửa miệng:?', r'"([^"]+)"'), # Vietnamese
(r'口癖:?', r'「([^」]+)」'), # Japanese
(r'Latiguillos:?', r'"([^"]+)"'), # Spanish
# ... etc for all 7 languages
]
limits = []
for marker_pattern, quote_pattern in patterns:
match = re.search(marker_pattern, host_profiles)
if match:
phrases = re.findall(quote_pattern, host_profiles[match.end():])
for phrase in phrases:
limits.append(f' - "{phrase}" — max 2x')
return "\n".join(limits)
Agora, quando edito um perfil de apresentador e mudo seus bordões, o prompt de revisão se atualiza automaticamente. Sem descompasso. Sem idioma esquecido.
O que isso realmente corrigiu (com números)
Aqui está o que mudou entre o episódio gerado antes dessas correções e um gerado depois:
| Métrica | Antes | Depois |
|---|---|---|
| "Trời ơi" (cota: máx. 4) | 13 | Ainda não testado em vi, mas em ja: os 4 bordões dentro das cotas |
| "Có một lý do sâu hơn" (cota: máx. 2) | 5 | Dentro da cota no teste equivalente em ja |
| Estatísticas inventadas (xG, posse %, largura da formação) | 4 números inventados | Zero números inventados |
| Aberturas de segmento com padrão idêntico | 6/6 idênticas | Ainda 5/5 em ja — veja abaixo |
| Conexões Vietnã/Japão preservadas | 1/4 sobreviveu (a revisão removeu 3) | 11/11 sobreviveram |
| Contaminação cruzada de vozes dos apresentadores | Ambos usavam as frases um do outro | Separação clara |
As cotas de bordões, as regras anti-fabricação e a preservação da localização funcionaram. Os perfis dos apresentadores agora ditam as personalidades com clareza suficiente para que o LLM não confunda mais quem diz o quê.
O que ainda está quebrado
Uma regra ainda falha: a variedade estrutural. O guia de diálogo diz "pelo menos 2 de 5 segmentos devem usar entradas estruturais diferentes." Depois das correções, o episódio japonês ainda abria cada segmento de forma idêntica: "いやー、健一さん!" — cinco vezes em um episódio.
Isso não é um problema de aplicação do prompt. É um problema de arquitetura.
A etapa de geração produz cada segmento de forma independente. O segmento 3 não tem consciência de que os segmentos 1 e 2 abriram com o bordão do apresentador emocional. Cada segmento é gerado isoladamente com o mesmo guia de diálogo, então cada um chega à mesma decisão de "vamos abrir com o apresentador emocional."
A etapa de revisão deveria detectar isso — ela vê o roteiro completo de uma vez. E eu adicionei linguagem de aplicação explícita dizendo para variar as aberturas. Mas o Gemini 3.5 Flash, o modelo que roda a revisão, aparentemente acha mais difícil reestruturar aberturas de segmentos do que cortar bordões ou suavizar afirmações inventadas. A variedade de abertura exige regenerar partes do conteúdo, não apenas apertar ou remover. Isso é um trabalho mais pesado para o modelo.
Ainda estou trabalhando nisso — provavelmente um modelo de revisão mais capaz ou uma reestruturação do pipeline onde os segmentos compartilhem o estado de abertura. O ponto mais amplo: a aplicação via prompt não pode consertar problemas de arquitetura. Se a estrutura do seu pipeline torna uma regra impossível de seguir, quantidade nenhuma de "CRÍTICO" ou "OBRIGATÓRIO" nos seus prompts vai te salvar.
O framework: Três perguntas para cada regra
Depois dessa experiência, agora faço uma auditoria em cada prompt de sistema que escrevo com três perguntas:
1. Onde essa regra vive — geração ou revisão? Regras sobre personalidade e tom pertencem à geração. Regras sobre conformidade, consistência e estrutura pertencem à revisão. Se uma regra cruza as duas (como bordões — são personalidade mas precisam de limites), coloque nas duas.
2. Essa regra está formulada como contexto ou como comando? "Aqui estão os bordões" é contexto. "Máximo 2 vezes cada" é comando. Ambos são necessários para a mesma regra — a etapa de geração precisa saber QUAIS SÃO os bordões, e a etapa de revisão precisa aplicar COM QUE FREQUÊNCIA eles aparecem.
3. O pipeline consegue realmente seguir essa regra? A geração por segmento não consegue aplicar a variedade entre segmentos. Nenhum prompt vai consertar isso. Você precisa ou mover a regra para a etapa de revisão (que vê o roteiro completo) ou reestruturar o pipeline para que os segmentos compartilhem estado.
Este framework não é específico para geração de podcasts. Ele se aplica a qualquer pipeline de LLM de múltiplas etapas — geração de conteúdo, revisão de código, sumarização de documentos, qualquer coisa onde você tenha passagens separadas de geração e controle de qualidade.
Ainda estou iterando nisso, mas se você está construindo seu primeiro pipeline de LLM de múltiplas etapas: divida-o em pelo menos duas etapas. A primeira etapa gera com personalidade e liberdade — dê a ela contexto, exemplos, orientação de tom. A segunda etapa revisa com precisão e aplicação — dê a ela limites explícitos, verificações de conformidade e a autoridade para mudar as coisas.
A etapa de geração deve parecer um briefing com um colaborador criativo. A etapa de revisão deve parecer entregar uma checklist para um editor.
E quando suas regras ainda estiverem sendo ignoradas depois de fazer as duas coisas, faça primeiro a pergunta da arquitetura. É o prompt, ou é o pipeline?
Perguntas frequentes
Isso se aplica a uma configuração de prompt único (sem pipeline)?
Sim, mas de forma limitada. Em um prompt único, você está pedindo ao mesmo modelo para ser criativo e rigoroso simultaneamente — ele sempre vai favorecer a criatividade sobre o rigor quando os dois entrarem em conflito. Mesmo em um prompt único, separar suas instruções em uma seção de "contexto" e uma seção explícita de "restrições" ajuda. Mas você vai bater em um teto. Duas chamadas separadas com instruções diferentes quase sempre superam uma só.
Por que você simplesmente não colocou as regras no prompt de geração com mais força?
Eu tentei. Adicionei "OBRIGATÓRIO", "CRÍTICO", "NUNCA" e tudo em maiúsculas. A etapa de geração tem exigências demais competindo — ela está tentando ser envolvente, soar natural, ser variada, localmente autêntica e rigorosa, tudo ao mesmo tempo. Quando o modelo tem que escolher entre "soar como um torcedor vietnamita empolgado" e "dizer 'Trời ơi' só duas vezes", a personalidade sempre ganha. A etapa de revisão não tem esse conflito — seu único trabalho é aplicar.
Qual modelo você está usando para a etapa de revisão?
Gemini 3.5 Flash (por custo — a revisão roda em cada episódio em 7 idiomas). Ele lida bem com aplicação simples (cortar bordões, suavizar estatísticas inventadas). Tem dificuldade com tarefas que exigem regeneração de conteúdo, como reestruturar aberturas de segmentos. Um modelo mais forte ajudaria aí, mas ainda não justifiquei o custo.
Eu construo o DIALOGUE, uma plataforma de podcast com IA, sozinho nas minhas noites e fins de semana. O código para a extração de bordões e as mudanças no prompt de revisão é aberto — você pode ler o prompt de sistema completo e a lógica de aplicação no meu repositório podcast-engine. Escrevo sobre o que aprendo pelo caminho.
Se você já encontrou um problema parecido — regras que são lidas mas não aplicadas — eu ficaria curioso: qual era a regra e onde ela vivia no seu pipeline?
É isso de mim por enquanto.
Abraços, Chandler