Conteúdo da trilha
7 minNarração em inglês, legenda em portuguêsPodcast (RSS)
Capítulos
  1. 0:00Abertura
  2. 1:08O diagnóstico
  3. 2:05Por que acontece
  4. 2:59Quanto custa
  5. 3:51Um desafio
  6. 4:43O tratamento
  7. 5:48Quando ignorar
  8. 6:55Fechamento
Transcrição

Abertura

Agora que você sabe medir, a gente começa a consertar. Primeiro, um smell que quase todo time que constrói com modelos tem, e quase ninguém percebe até o fechamento do mês.

Uma empresa extrai dados de contratos de fornecedores em duas etapas. A primeira lê o contrato e lista os dados principais. A segunda pega esse texto e preenche o cadastro no ERP da empresa.

E entre as duas etapas, tem isto. Uma expressão regular que procura a palavra Total, dois pontos e um número.

Funcionou por três meses. Aí um dia, o modelo começou a escrever valor total do contrato, em vez de só total. A expressão regular não achou nada. O total ficou vazio. E cento e quarenta contratos entraram no sistema sem valor, antes de alguém perceber.

Nada quebrou. Nenhuma exceção, nenhum alerta. O dado só estava vazio. Nesta aula, você vai aprender a reconhecer esse smell, por que ele é tão tentador, e a refatoração que elimina essa classe inteira de erros.

O diagnóstico

O formato é este. A primeira etapa produz um texto feito para uma pessoa ler.

E esse texto é a única interface entre as duas etapas.

O código, ou às vezes o próximo modelo, tenta adivinhar onde está cada dado.

Quando o palpite acerta, tudo funciona.

Quando o modelo muda o jeito de escrever, o dado some, sem alarme.

Como identificar? Uma etapa devolve prosa, e a próxima usa uma expressão regular, um split, ou procura a linha que começa com.

O código tolera vários nomes para o mesmo campo. Total, valor total, total geral.

A segunda etapa é outra chamada ao modelo, cujo único trabalho é entender o formato da primeira.

Mudar uma palavra num prompt quebra um parser em outro arquivo.

E campos que faltam viram vazio em silêncio, em vez de gerar um erro.

Por que acontece

Normalmente começa com um protótipo numa janela de chat. Alguém testou o prompt, gostou da resposta em texto e colou no código. No chat, texto é o produto. Num pipeline, texto é um fio desencapado.

Texto parece flexível. Você não precisa decidir nomes, tipos ou o que é obrigatório antes de começar. Um schema obriga você a decidir.

E funciona, por um tempo. Os modelos costumam repetir o formato, até o dia em que não repetem. O modelo mudou, o prompt mudou, ou só a entrada mudou. Um contrato que diz montante em vez de total.

E aqui está a armadilha de quem está começando. Pedir JSON no prompt, responda só com JSON, e achar que resolveu. Isso continua sendo texto. O modelo pode embrulhar em formatação, acrescentar uma vírgula ou esquecer uma chave.

Quanto custa

O pior custo é dado ruim em silêncio. Nada quebra. Cento e quarenta contratos sem total não geram exceção nenhuma. O financeiro só vê o buraco no fechamento do mês.

Depois, acoplamento escondido. O prompt da primeira etapa vira parte do contrato da segunda, e ninguém sabe disso. O parser mora em outro arquivo, outro repositório, talvez outro time.

Depois, medo. Qualquer ajuste de prompt ou troca de modelo vira risco. O time para de melhorar o extrator, porque a expressão regular do financeiro vai quebrar.

E tokens desperdiçados. Prosa feita para um parser gasta saída com palavras que ninguém lê. O valor total do contrato, impostos inclusos, é. Dezenas de tokens que um campo só não precisa.

Um desafio

Uma pergunta para você. O time pediu JSON no prompt, com as chaves total e data, e o código faz o parse. Uma vez por semana, a execução quebra por uma vírgula a mais, ou uma marcação de formatação em volta do objeto. Qual próximo passo elimina essa classe inteira de erro?

Usar a saída estruturada da API, com um schema, e validar os campos no código. O formato deixa de ser um pedido ao modelo e vira uma garantia da API.

Tentar de novo até o parse funcionar esconde a instabilidade. E no dia em que a variação for um texto onde devia haver um número, o parse funciona, e o dado ruim entra. Colocar três exemplos de JSON válido baixa a taxa, mas nunca zera. Você ainda dependeria do modelo obedecer uma instrução de formato.

O tratamento

O tratamento é uma refatoração chamada replace free text with structured output. O contrato entre as etapas fica explícito.

O CNPJ do fornecedor, a chave de acesso da nota, que pode faltar, o total, com tipo de dinheiro, e a lista de vencimentos.

A API garante a forma. O código lê o campo total, não uma frase. Valor total do contrato simplesmente não tem mais como existir. E um campo obrigatório que falta vira erro na hora. O documento vai para revisão humana, em vez de entrar no sistema como zero.

E muitas vezes tem um bônus. Se a segunda etapa só existia para transformar o texto em campos, ela pode sumir. A primeira chamada já devolve os campos.

Mas schema não substitui eval. Uma forma correta ainda pode trazer o CNPJ de uma empresa que não é a emissora. O eval mede se o valor está certo. O schema garante que o valor chegou como valor.

Quando ignorar

Quando dá para ignorar? Quando o destino é uma pessoa. Uma resposta de chat ou um e-mail para um cliente deve ser texto. O smell é texto entre máquinas.

Quando o texto é o produto. Uma etapa escreve o rascunho de um artigo, e outra revisa. Elas trocam texto de forma legítima. Estruture o que o código usa de fato, como a lista de problemas encontrados, ou se foi aprovado. Não o artigo em si.

E um protótipo descartável tudo bem. No dia em que o parser for para o sistema de verdade, o schema vai junto.

Um último caso, para afiar o olho. Um classificador de tickets responde com uma palavra só, cobrança, pedido ou outro, e o código compara o texto. Às vezes volta Cobrança com maiúscula e ponto final, e o ticket cai na fila errada. Isso é esse smell? É. Mesmo uma palavra é texto livre, se o seu código depende da forma exata dela. Um schema com uma lista fechada de valores resolve, com um campo só.

Fechamento

Então, a ideia para levar. Texto é para pessoas. Quando uma etapa entrega dado para o código, ou para outra etapa, o contrato precisa ser um schema, não uma frase. Senão o seu sistema funciona até o dia em que o modelo achar um jeito mais bonito de dizer total.

Na próxima aula, a gente faz a refatoração em si, passo a passo, com eval antes e depois: replace free text with structured output. Até lá.

SmellAcopladores

Passagem em Texto Livre

Free-Text Handoff

Passagem em Texto Livre (Free-Text Handoff) é um smell de IA, ou seja, um sinal de problema em sistemas com LLM, do grupo Acopladores. Uma etapa entrega texto solto para a próxima, que precisa adivinhar o formato.

Elemento
23/37
Nível
Iniciante
Leitura
4 min
Atualizado
Nesta página 7
  1. 01Como reconhecer
  2. 02Por que acontece
  3. 03Quanto custa ignorar
  4. 04Tratamento
  5. 05O que você ganha
  6. 06Quando ignorar
  7. 07É esse smell?
  8. ··Perguntas rápidas

Como reconhecer

Uma chain extrai dados de contratos de fornecedor e de DANFEs (a representação em PDF da NF-e brasileira). O primeiro passo lê o PDF e “lista os dados principais”. O segundo passo recebe esse texto e preenche o cadastro no ERP. O código entre os dois (anonimizado):

summary = llm("Liste os dados principais do contrato.", pdf_text)

# passo 2: tirar o total do texto
match = re.search(r"Total:\s*R\$\s*([\d\.,]+)", summary)
total = parse_brl(match.group(1)) if match else None

Funcionou por três meses. Um dia, o modelo começou a escrever “Valor total do contrato: R$ 48.200,00” em vez de “Total: R$ 48.200,00”. O regex não achou nada, total virou None, e 140 contratos entraram no ERP sem valor antes de alguém notar.

O mesmo padrão aparece na NF-e: o modelo descreve “CNPJ do emitente 12.345.678/0001-90” e o código procura a linha CNPJ:. A chave de acesso de 44 dígitos some no meio de um parágrafo. O financeiro só vê o furo no fechamento.

Sinais de Passagem em Texto Livre:

  • Um passo devolve prosa ou markdown, e o passo seguinte usa regex, split ou “procure a linha que começa com”.
  • O código tem vários formatos tolerados para o mesmo campo (“Total”, “Valor total”, “Total geral”).
  • O segundo passo é outra chamada de modelo que recebe o texto do primeiro e “entende” o formato.
  • Mudar uma palavra do prompt quebra um parser em outro arquivo.
  • Campos ausentes viram None em silêncio, em vez de erro.
flowchart LR
  A(["1. Passo A escreve texto"]):::llm --> T["2. Texto livre"]:::tool
  T --> P["3. Regex adivinha o formato"]:::tool
  P --> B(["4. Passo B"]):::llm
  P -->|"formato mudou"| X(["5. Campo vazio, sem erro"]):::io
  1. O primeiro passo produz texto pensado para uma pessoa ler.
  2. Esse texto é a única interface entre os passos.
  3. O código ou o modelo seguinte tenta adivinhar onde está cada dado.
  4. Quando a adivinhação acerta, tudo funciona.
  5. Quando o modelo muda o jeito de escrever, o dado some sem nenhum alarme.
Checagem +20 XP de primeiraO parser procura Total: e o modelo passou a escrever Valor total do contrato:. Cento e quarenta registros entram no ERP sem valor. Qual falha de desenho veio primeiro?

Por que acontece

  • O protótipo foi feito no chat. A pessoa testou o prompt na interface, gostou da resposta em texto e colou no código. No chat, texto é o produto. No pipeline, texto é um fio desencapado.
  • Texto parece flexível. Não precisa definir schema antes de começar. Você vê o PDF, pede “os dados principais” e segue. Schema pede decidir nomes, tipos e o que é obrigatório.
  • Funciona por um tempo. Modelos repetem o formato com frequência, até o dia em que não repetem: mudou o modelo, o prompt, a versão da API ou só a entrada (um contrato que fala “montante” em vez de “total”).
  • Saída estruturada parecia complicada. Quando o sistema começou, talvez o recurso não existisse ou ninguém conhecesse. Hoje as APIs dos provedores aceitam schema. Continuar com regex é inércia, não restrição técnica.

A armadilha de quem está começando: pedir JSON no prompt (“responda só com JSON”) e achar que resolveu. Isso ainda é texto. O modelo pode envolver o JSON em markdown, acrescentar uma vírgula, omitir uma chave. json.loads quebra, ou pior, passa e o campo vem com o tipo errado.

Quanto custa ignorar

  • Dados errados em silêncio. O pior tipo de falha: nada quebra, o dado só fica vazio ou errado no sistema de destino. Cento e quarenta contratos sem total não disparam exceção.
  • Acoplamento escondido. O prompt do passo A vira parte do contrato do passo B, mas ninguém sabe disso até quebrar. O parser mora em outro arquivo, outro repositório, outro time.
  • Medo de mudar. Qualquer ajuste no prompt, troca de modelo ou atualização de versão vira risco. O time deixa de melhorar o extrator porque “o regex do financeiro quebra”.
  • Tokens gastos à toa. Prosa para ser lida por um parser gasta saída com palavras que ninguém vai ler. “O valor total do contrato, já incluídos os impostos, é de” são dezenas de tokens que um campo total não precisa.

No cenário de extração de NF-e e contratos, esse smell é o primeiro a aparecer: o modelo descreve a nota e o ERP espera campos.

Tratamento

Refatoração Escolha quando
Trocar Texto Livre por Saída Estruturada Sempre que um passo entrega dados para outro passo ou para código. O destino é o padrão Saída Estruturada.

Se o passo seguinte só existe para converter o texto em campos, ele provavelmente pode sumir: a primeira chamada já devolve os campos.

O contrato fica explícito. Exemplo de schema, no mesmo caso do total:

schema Invoice {
  vendor_tax_id: string      # CNPJ
  access_key: string | null  # chave da NF-e, 44 dígitos
  total: money
  due_dates: list[date]
}

A API garante o formato (JSON com essas chaves, tipos checados). O código do ERP lê invoice.total, não uma frase. Campo obrigatório ausente vira erro na hora, e o documento vai para revisão humana em vez de entrar zerado.

Isso não substitui eval. Um schema correto ainda pode vir com o CNPJ de quem não é o emitente. O eval mede se o valor está certo; o schema garante que o valor chegou como número.

Checagem +20 XP de primeiraO time pediu JSON no prompt ('responda com as chaves total e data') e o código faz json.loads. Uma vez por semana a execução quebra com vírgula a mais ou com um bloco markdown em volta. Qual é o próximo passo que elimina a classe de erro?

O que você ganha

  • Um contrato explícito entre os passos, com tipos e campos obrigatórios.
  • Erro na hora quando falta um campo, em vez de dado vazio no ERP.
  • Liberdade para mudar prompt e modelo sem quebrar o parser.
  • Saídas menores e mais baratas.

Quando ignorar

  • O destino é uma pessoa. Uma resposta de chat ou um email para o cliente deve ser texto. O smell é texto entre máquinas.
  • O texto é o produto. Um passo que escreve um rascunho e outro que revisa o rascunho trocam texto legitimamente. Estruture os metadados (título, tags, pontos a revisar), não o texto em si.
  • Protótipo descartável. Se o código vai ser jogado fora na semana que vem, tudo bem. No dia em que o parser for para o ERP, o schema entra junto.

É esse smell?

Checagem +20 XP de primeiraUm classificador de tickets responde com uma palavra só ('fatura', 'pedido', 'outro'), e o código compara a string. Às vezes vem 'Fatura.' com maiúscula e ponto, e o ticket cai na fila errada. É Passagem em Texto Livre?

Checagem +20 XP de primeiraUm passo gera um rascunho de artigo em markdown e o passo seguinte, outro modelo, revisa o rascunho e devolve o texto corrigido. É Passagem em Texto Livre?

Checagem +20 XP de primeiraO modelo devolve JSON pedido no prompt ('responda em JSON com as chaves total e data'), e o código faz json.loads. Uma vez por semana vem um JSON com uma vírgula a mais e a execução quebra. É Passagem em Texto Livre?

Checagem +20 XP de primeiraO passo 1 devolve um objeto Invoice validado (CNPJ, total, vencimentos). O passo 2 grava no ERP sem ler prosa. É Passagem em Texto Livre?

Perguntas rápidas

O que é Passagem em Texto Livre?

Passagem em Texto Livre (Free-Text Handoff) é um smell de IA, ou seja, um sinal de problema em sistemas com LLM, do grupo Acopladores. Uma etapa entrega texto solto para a próxima, que precisa adivinhar o formato.

Como corrigir Passagem em Texto Livre?

Com Trocar Texto Livre por Saída Estruturada. Cada refatoração traz o passo a passo seguro, com eval antes e depois.

Onde Passagem em Texto Livre aparece na prática?

Nos cenários reais Extração de NF-e e contratos.

Para ir além

Relações

Aparece nos cenários 1
Aparece nas trilhas 1
Buscar