Dados estruturados: extrair, classificar, normalizar
Objetivos deste capítulo
- Extrair informações precisas de texto livre com um esquema estrito
- Classificar em lote com uma taxonomia fechada e definições por categoria
- Normalizar os valores e encaminhar os casos duvidosos para uma revisão humana
O filão escondido no texto livre
Depois da feira profissional de Lyon, a Sofia traz um espólio incómodo: 80 emails de potenciais clientes, notas de conversas tiradas à pressa, e o ficheiro das 200 avaliações de clientes do trimestre que dorme desde o capítulo 4. Toda esta matéria contém dados preciosos — quem pede uma demonstração, que restaurante, que tamanho de equipa, que nível de urgência — mas fechados em texto livre, ilegível para uma folha de cálculo. Voltar a digitá-los à mão? Dois dias. Mandá-los extrair por um prompt bem concebido? Uma hora, verificação incluída.
É o ofício deste capítulo: transformar texto livre em dados estruturados fiáveis. O capítulo 4 pôs o tijolo de base — o JSON estrito com esquema. Vamos agora industrializá-lo: extração multi-campos, classificação com taxonomia fechada, normalização dos valores, tratamento em lote, e sobretudo o encaminhamento dos casos duvidosos — porque a diferença entre um gadget de demonstração e uma ferramenta de produção joga-se inteiramente nos casos que não cabem nas caixas.
A extração: um esquema, regras por campo
A extração consiste em localizar num texto informações precisas e arrumá-las em campos definidos. A qualidade depende de três elementos que já conheces separadamente: um esquema exato (capítulo 4), uma regra de não-invenção (capítulo 6), e — a novidade — regras por campo: para cada campo, o que se extrai, em que forma, e o que pôr quando a informação está ausente.
Extrais dados de contacto de emails de potenciais clientes, para a equipa comercial de um editor de software de horários para restaurantes.
Para cada email entre delimitadores, devolve APENAS um objeto JSON:
{
"nome": "nome próprio e apelido, ou null se ausente",
"estabelecimento": "nome do restaurante ou grupo, ou null",
"tamanho_equipa": "número inteiro de empregados, ou null se não mencionado",
"pedido": "demo" | "precos" | "questao" | "outro",
"urgencia": "alta" | "normal",
"citacao_chave": "a frase do email que justifica o campo pedido"
}
Regras:
- NUNCA inventes um valor: informação ausente = null.
- tamanho_equipa: apenas se um número estiver escrito; «uma grande equipa» = null.
- urgencia = alta apenas se um prazo explícito for mencionado.
- citacao_chave: cópia exata do texto, sem reformulação.
--- EMAIL ---
{{email}}
--- FIM ---O campo citacao_chave é o truque mais rentável deste prompt: ao exigir a frase exata que justifica a classificação, tornas cada linha auditável em dois segundos — a citação cola ou não cola — e reduzes a invenção, porque o modelo tem de ancorar a resposta no texto. É o mesmo princípio do raciocínio verificável do capítulo 3, transposto para os dados. Quanto às regras por campo, decidem de antemão as ambiguidades que de outro modo descobririas em produção: o que fazer de «uma grande equipa», o que merece urgência «alta».
A classificação: uma taxonomia fechada e definida
Classificar é arrumar cada elemento numa categoria de uma lista fechada. O erro clássico é dar os nomes das categorias sem as definir: «classifica estas avaliações em: serviço, produto, preço, outro». O modelo tem então a sua própria ideia da fronteira entre «serviço» e «produto» — e ela muda de uma avaliação para outra. Uma taxonomia profissional define cada categoria, dá um exemplo, e precisa as regras de desempate.
Classifica cada avaliação de cliente numa ÚNICA categoria desta lista fechada:
- "funcionalidade": a avaliação incide sobre o que o software faz ou não faz. Ex.: «impossível exportar o horário em PDF».
- "ergonomia": a avaliação incide sobre a facilidade de utilização. Ex.: «levei 3 dias a encontrar onde mudar um horário».
- "suporte": a avaliação incide sobre a ajuda recebida da equipa. Ex.: «resposta em 10 minutos, problema resolvido».
- "preco": a avaliação incide sobre o custo ou a relação qualidade-preço.
- "outro": nada do que precede se aplica claramente.
Regras de desempate:
- Se a avaliação tocar várias categorias, escolhe a da frase mais desenvolvida e anota as outras em "categorias_secundarias".
- Em caso de dúvida real, usa "outro" com "confianca": "baixa" — nunca forces uma categoria.
Formato por avaliação: { "id": N, "categoria": "...", "categorias_secundarias": [...], "confianca": "alta|baixa", "citacao_chave": "..." }Três mecanismos a reter. As definições com exemplos estabilizam as fronteiras — é few-shot (capítulo 2) aplicado às categorias. A regra de desempate trata o caso multi-temas, inevitável em avaliações reais. E o campo confianca dá ao modelo uma saída honrosa quando hesita: sem ele, força uma categoria com aplomb, e as tuas estatísticas mentem em silêncio. Um «outro, confiança baixa» é um dado honesto; um «preço» adivinhado é um dado tóxico.
Normalizar: o dado limpo à primeira
Extrair não chega: é preciso que os valores sejam comparáveis. Se uma extração devolve «15», «quinze empregados» e «~15 pess.», a tua folha de cálculo afoga-se em variantes e cada ordenação fica errada. A normalização prescreve-se no prompt, campo a campo: datas no formato AAAA-MM-DD, montantes em número sem símbolo, telefones em dígitos seguidos, nomes de estabelecimento na capitalização de origem mas sem aspas. Cada formato precisado de antemão é uma hora de limpeza poupada depois.
Uma armadilha específica merece o aviso: as conversões silenciosas. Pede «o número de empregados» e o modelo poderia converter «uma dezena» em 10 — uma invenção disfarçada de normalização. A regra «apenas se um número estiver escrito» do prompt de extração existe para isso. O princípio geral: a normalização muda a forma de um valor presente, nunca cria um valor ausente. A fronteira entre os dois deve estar escrita preto no branco nas tuas regras por campo.
Antes/depois: a passagem de normalização na prática
A normalização pode integrar-se nas regras por campo logo na extração — é o ideal — mas funciona também como passagem separada, muito útil quando herdas dados já extraídos mas sujos: uma exportação de formulário, uma velha folha de cálculo preenchida à mão, o ficheiro de contactos da feira digitado por três pessoas diferentes. O prompt de normalização é então uma etapa de cadeia (capítulo 7) de pleno direito:
Normalizas fichas de potenciais clientes digitadas manualmente, sem alterar o fundo.
Para cada linha entre delimitadores, devolve a versão normalizada:
- data_contacto: formato AAAA-MM-DD. «terça-feira passada» ou data ambígua = null.
- telefone: apenas dígitos, sem espaços nem pontos. Número incompleto = null.
- estabelecimento: capitalização de origem, sem aspas nem «Restaurante» redundante como prefixo.
- tamanho_equipa: número inteiro apenas se um número figurar na ficha, senão null.
- cidade: nome completo, primeira letra em maiúscula, sem código postal.
Regras absolutas:
- Mudas a FORMA dos valores presentes, NUNCA crias um valor ausente.
- Acrescenta um campo "alertas" que lista tudo o que te pareceu ambíguo na linha.
- Conserva o identificador de linha tal e qual.
--- LINHAS ---
{{linhas ID ; data ; telefone ; estabelecimento ; tamanho ; cidade}}
--- FIM ---O campo alertas desempenha aqui o papel que confianca desempenhava na classificação: uma saída honrosa para a dúvida. «06.12.34» é um telefone truncado? «La Brasserie» e «Brasserie» são o mesmo estabelecimento? O modelo assinala em vez de decidir em silêncio, e a Sofia arbitra os alertas em bloco no fim — alguns minutos, contra horas a reler cada linha. Um dado normalizado sem pista de auditoria é um dado que acabamos por reverificar inteiramente no dia da primeira dúvida.
Tratar em lote sem perder o fio
Resta a questão de escala: 200 avaliações não se tratam num único prompt gigante. Para lá de um certo volume, a qualidade degrada-se a meio da lista — a atenção do modelo é melhor nas extremidades, como visto no capítulo 4 — e uma única saída malformada pode arruinar o lote inteiro. A prática robusta: pacotes de 10 a 20 elementos, cada um com um identificador explícito, e uma verificação por pacote antes de passar ao seguinte.
Os identificadores são o detalhe que salva: numera as tuas entradas («AVAL-001», «AVAL-002») e exige o identificador em cada objeto de saída. Podes então verificar mecanicamente que nenhuma entrada foi saltada nem duplicada — o modelo salta por vezes um elemento em pleno meio de um lote sem o assinalar. Conta as entradas, conta as saídas, compara os identificadores: três verificações de dez segundos que apanham as perdas silenciosas.
flowchart LR
T["Texto bruto: avaliações, emails, notas"] --> L["Lotes de 10 a 20 com identificadores"]
L --> X["Extração e classificação segundo o esquema"]
X --> C{"Confiança alta e JSON válido?"}
C -->|"Sim"| D["Folha de cálculo ou painel de controlo"]
C -->|"Não"| H["Fila de revisão humana"]
H -->|"Casos decididos"| DA rede de segurança: encaminhar o duvidoso, verificar por amostragem
O diagrama acima contém a decisão de arquitetura mais importante do capítulo: os casos de confiança baixa não vão para a folha de cálculo, vão para uma fila de revisão humana. Das 200 avaliações da Sofia, 14 saíram em confiança baixa; ela decidiu-as à mão em dez minutos. As outras 186 eram fiáveis — verificou-o por amostragem: 15 avaliações tiradas ao acaso, citação comparada com o texto de origem, zero erros. Amostragem limpa, lote aceite. É o mesmo espírito do conjunto de testes que sistematizaremos no capítulo 9.
Se a amostragem revelar erros, não corrijas as linhas uma a uma: procura o padrão. Três erros em avaliações irónicas? Acrescenta uma regra ou um exemplo few-shot de ironia ao prompt e relança o lote. Corrigir a saída repara uma vez; corrigir o prompt repara todas as vezes seguintes — é a lição dos templates do capítulo 5, aplicada aos dados. E guarda a versão corrigida do prompt na tua biblioteca, com os seus casos de teste.
No fim, o pipeline da Sofia cabe numa frase: lotes identificados, um esquema com regras por campo, citações para auditar, um campo confiança para encaminhar, uma amostragem para validar. Cinco mecanismos simples — e o ficheiro de 200 avaliações que dormia há dois meses tornou-se, numa manhã, um painel de controlo que a direção consulta todas as semanas.
Contexto
No regresso da feira de Lyon, a equipa comercial espera a lista qualificada dos potenciais clientes: quem quer uma demonstração, que tamanho de estabelecimento, que urgência. A Sofia tem 80 emails a granel. Quer construir o pipeline de extração completo — esquema, regras por campo, lotes identificados, encaminhamento dos casos duvidosos — e entregar uma tabela fiável antes de sexta-feira, com a prova por amostragem de que os dados estão certos.
Instruções
- Escolhe um filão de texto livre do teu quotidiano (emails, avaliações, notas, tickets) e lista os 5-6 campos que teriam valor numa folha de cálculo.
- Escreve o esquema JSON com uma regra por campo: forma esperada, normalização, e valor em caso de ausência (null, nunca invenção).
- Acrescenta um campo citacao_chave e um campo confianca com a sua regra de uso: em caso de dúvida, confiança baixa em vez de categoria forçada.
- Numera 15-20 entradas reais, trata-as num lote, depois verifica mecanicamente: tantas saídas como entradas, identificadores todos presentes, JSON válido.
- Faz uma amostragem de 5 linhas: compara cada citação com o texto de origem. Se houver erros, procura o padrão e corrige o prompt, não as linhas.
- Trata à mão a fila das confianças baixas, depois entrega a tabela final — e arruma o prompt validado na tua biblioteca com os seus casos de teste.
Em resumo
- A extração fiável = esquema exato + regras por campo (forma, normalização, valor se ausente) + proibição de inventar.
- O campo citacao_chave ancora cada dado no texto de origem: auditável em dois segundos, invenção reduzida.
- Uma taxonomia profissional define cada categoria com um exemplo e regras de desempate — não apenas nomes.
- O campo confianca dá uma saída honrosa à dúvida: «outro, confiança baixa» vale mais do que uma categoria forçada que falseia as estatísticas.
- A normalização muda a forma de um valor presente, nunca cria um valor ausente.
- Trata por lotes de 10-20 com identificadores, e verifica mecanicamente: contagem das saídas, identificadores, validade do JSON.
- Encaminha os casos duvidosos para uma revisão humana e valida os lotes por amostragem; se houver erros, corrige o prompt (o padrão), não as linhas.
Quiz — verifica a tua compreensão
1. Para que serve o campo citacao_chave num prompt de extração?
2. Porquê definir cada categoria de uma taxonomia com um exemplo?
3. O que fazer de um elemento que o modelo hesita em classificar?
4. Qual é o limite da normalização?
5. Porquê tratar 200 avaliações em lotes de 10-20 em vez de um prompt gigante?
6. A amostragem revela 3 erros em avaliações irónicas. O que fazes?