Conexão · Interrompida

Algo não carregou

Parte desta página não chegou até você. Recarregue para tentar novamente — se persistir, verifique sua conexão.

Pular para o conteúdo principal
Research11 min de leitura

Pré-registrando o Experimento #1: Quão Frágeis São os Prompts de Extração de JSON em Produção?

O primeiro experimento concreto da linha de pesquisa de precisão — comprometido em público antes da coleta dos dados. Cinco classes de perturbação, quinze variantes, quatro métricas, quatro hipóteses falsificáveis e um repositório companion executável com testes.

Todos os Posts
2/4

Na semana passada eu publiquei AI Prompts: How Good and How Bad They Are — o tiro de abertura de uma linha de pesquisa sobre tirar modelos de linguagem do "melhor esforço" para algo especificável e mensurável. Aquele post listou cinco perguntas de pesquisa. Este post começa a responder a primeira, e faz isso de um modo específico que quero defender antes de executar uma única chamada de API:

Isto é um pré-registro. Hipóteses, métricas, tamanhos de amostra, regras de parada — tudo comprometido antes que os dados sejam coletados. O código companion já está aberto. Se os resultados contradisserem as hipóteses, isso será publicado exatamente da mesma forma que as confirmações seriam.

Estou fazendo isso deliberadamente. O post anterior argumentou que a cultura de benchmarks encobre a fragilidade reportando um único número por modelo por tarefa. O contramovimento honesto é me amarrar à metodologia antes de saber a resposta. Pré-registro foi como o restante da ciência empírica aprendeu a parar de se enganar, e não vejo razão para a engenharia de prompts ser exceção.

Este post não contém resultados. Os resultados vêm em seguida, em um field report separado. Se você quer acompanhar — ou discutir o design — agora é a hora.

O que este experimento vai e o que não vai medir

Das cinco perguntas no post anterior, esta é a Q1: quão frágeis, na prática, são os prompts que de fato vão para produção? A menor versão honesta dessa pergunta é uma tarefa de extração estruturada — chamada única, schema fixo, pontuável objetivamente. Escolhi por três razões.

Primeiro, extração é onde as equipes em produção estão de fato perdendo confiabilidade neste momento. Um estudo do ExtractBench de 2026 descobriu que modelos de fronteira caem para 0% de output válido em um schema de relatório financeiro de 369 campos — a falha não é exótica, aparece em escala modesta. O trabalho cross-model do PromptPort levanta o ponto mais incômodo: um prompt que retorna JSON limpo em um modelo retorna saída com cercas, embrulhada em prosa ou malformada em outro, e parsers estritos rejeitam extrações que de outra forma estariam corretas. A dor econômica é real.

Segundo, outputs estruturados são exatamente onde a área afirma já ter vencido. O post anterior celebrou a decodificação restrita — XGrammar a <40µs por token, backend padrão para vLLM/SGLang/TensorRT-LLM desde março de 2026, XGrammar-2 em maio — como uma vitória genuína no nível sintático. Se mesmo essa superfície é frágil quando você para de olhar uma única variante, a área tem um problema mais profundo do que admite.

Terceiro, é barato pontuar honestamente. Sem LLM-as-judge, sem desvio de rubrica. Validade de schema é binária. Acurácia de campo é match exato contra ground truth. F1 em arrays aninhados é cálculo de livro-texto. Toda a stack de medição roda offline contra fixtures comprometidas no repo.

O que este experimento não vai fazer:

  • Não vai testar múltiplos modelos. Um modelo de fronteira, um conjunto de variantes. Contraste multi-modelo é o Experimento #2, onde a pergunta vira "fragilidade é uma propriedade do modelo ou uma propriedade universal".
  • Não vai medir RAG, fluxos agênticos ou geração aberta. Esses têm seus próprios experimentos na fila.
  • Não vai tentar otimizar o prompt. O objetivo é caracterizar a variância sob perturbações que preservam a semântica, não encontrar o vencedor.
  • Não vai medir tradeoffs de custo ou latência. Essa é a pergunta Q5 do post anterior e tem o seu próprio tratamento.

O escopo é intencionalmente estreito. Um resultado pequeno e honesto é mais útil do que um amplo e ambíguo.

A tarefa

Extração de itens de linha de fatura, em chamada única, a partir de um parágrafo de texto comercial em inglês para um schema JSON fixo. ~12 campos, dois arrays aninhados, complexidade média — mais próximo de um schema real de produção do que de um schema brinquedo, mas pequeno o suficiente para controlar.

O corpus é gerado proceduralmente, com seed, e comprometido no repositório. Duzentos documentos de input, sem PII, projetados para cobrir os tipos de variação de formatação (símbolos de moeda, formatos de data, convenções de quebra de linha, preenchimento polido) que equipes em produção encontram em campo. A ground truth é produzida pelo gerador no momento de build do corpus, não pelo modelo.

Modelo único: Claude Sonnet 4.6. Temperatura 0. Schema idêntico. Esqueleto de system prompt idêntico em todas as condições. A única coisa que varia é a perturbação.

A taxonomia de perturbações

Cinco classes de perturbação. A instrução completa em inglês varia; o schema e a definição da tarefa não. Cada classe tem três variantes, totalizando quinze prompts.

P1 — Lexical. Trocas de sinônimos nas instruções. "Extract the line items" vira "pull out the line items" vira "identify the line items". Mesma semântica, forma de superfície diferente. Essa é a classe que a maioria das pessoas assume ser a fonte dominante de fragilidade, e os dados do BrittleBench sugerem que estão erradas quanto a isso.

P2 — Estrutural. A ordem dos blocos de instrução. Schema antes das regras vs. regras antes do schema vs. schema e regras intercalados. O conteúdo é idêntico; a sequência muda.

P3 — Formatação. Cabeçalhos Markdown vs. rótulos em prosa simples vs. seções com tags XML. ### Schema vs. Schema: vs. <schema>...</schema>. As instruções lêem-se da mesma forma para um humano; a tokenização não.

P4 — Quantidade de exemplos. Zero-shot, one-shot, three-shot — com os mesmos exemplos canônicos, tirados do mesmo gerador. Este é um teste controlado da contribuição marginal do in-context learning, mantendo o conteúdo dos exemplos constante.

P5 — Voz e polidez. Polido vs. imperativo seco vs. declarativo neutro. "Please carefully extract..." vs. "Extract..." vs. "The task is to extract..." Este está aqui principalmente porque toda equipe que já vi fez A/B testing acidental disso sem medir.

As métricas

Quatro variáveis dependentes, computadas por célula (variante-de-prompt, input).

  1. Taxa de validade de schema. A saída faz parse contra o schema JSON? Binário, por chamada.
  2. Acurácia em nível de campo. Match exato por campo contra a ground truth, com média sobre os 200 inputs.
  3. F1 de conjunto de valores. Para os dois arrays aninhados — onde a ordem dos itens pode legitimamente variar — calcular precisão e recall sobre o conjunto de valores.
  4. Concordância run-a-run (α de Krippendorff). Cada célula (variante, input) é repetida cinco vezes. α é computado sobre as cinco repetições, tratando as saídas como nominais. A α mediana entre células é o score de estabilidade por variante.

A combinação importa. (1) e (2) medem se o modelo acerta. (3) trata do caso "resposta certa, ordem diferente" que pune pontuação ingênua. (4) — a que a maioria das equipes em produção pula — mede se o modelo concorda com ele mesmo, execução a execução, em temperatura zero. O post anterior argumentou que mesmo em T=0, batching e otimizações de inferência produzem outputs diferentes entre execuções. (4) é onde eu descubro quanto isso importa para esta tarefa.

As hipóteses

Quatro afirmações falsificáveis, cada uma com um tamanho de efeito que aceitarei como limiar para "real".

H1 — Fragilidade existe em escala de produção. Ao longo das quinze variantes de perturbação, a acurácia média em nível de campo varia em pelo menos 5 pontos percentuais entre a melhor e a pior variante nos mesmos 200 inputs. O limiar de tamanho de efeito é conservador — o BrittleBench reporta até 12 — e é definido deliberadamente baixo para tornar a hipótese difícil de confirmar por acidente.

H2 — Formato domina o lexical. A classe P3 (formatação) contribui mais para a variância de acurácia do que a classe P1 (lexical). Se for verdade, a implicação prática é inequívoca: mudar seus cabeçalhos markdown para tags XML importa mais do que escolher o verbo perfeito. A maior parte do conselho de prompt-tuning de 2025 tinha isso ao contrário.

H3 — Instabilidade entre execuções é significativa em T=0. A α de Krippendorff mediana entre células é abaixo de 0,90. Se α é alto, "não-determinismo é uma feature, não um bug" está exagerado para esta classe de tarefa e a preocupação da área é mal colocada. Se α é baixo, a implicação é mais aguda: sistemas em produção que vão ao ar após uma boa resposta cometeram um erro de categoria.

H4 — Decodificação restrita não fecha a lacuna semântica. Reexecutar a variante de pior desempenho de H1 com decodificação estrita imposta pelo schema (JSON-mode ou equivalente). A diferença para a variante de melhor desempenho não deve fechar por mais da metade. Isso testa a afirmação do post anterior de que decodificação restrita resolve sintaxe mas não semântica — e é a ponte natural para o Experimento #2.

As hipóteses são independentes. H1 pode falhar e H3 ainda assim se manter. H4 poderia falhar de um modo que vindique a decodificação restrita — o que seria o desfecho mais interessante dos quatro, porque atualizaria meu prior na direção de "as ferramentas existentes da área são mais fortes do que meu post anterior insinuou".

Regras de parada e o que falsificaria cada afirmação

N é fixado de antemão. 3.000 chamadas por classe de perturbação, 15.000 no total, mais um orçamento separado de ~1.000 chamadas para a varredura de decodificação restrita de H4. Não haverá "o resultado está perto, deixa eu adicionar mais amostras". Se os dados forem ambíguos no N comprometido, o writeup diz isso.

Os limiares de falsificação:

  • H1 falsificada se max - min da acurácia de campo entre todas as quinze variantes for ≤ 2pp. Nesse caso o experimento se torna um resultado nulo, a linha de pesquisa é reenquadrada e o próximo post explica por quê — isso é uma história mais interessante do que a confirmação de H1 seria.
  • H2 falsificada se a contribuição de P1 para a variância estiver dentro de ±10% da de P3.
  • H3 falsificada se a α mediana for ≥ 0,90.
  • H4 falsificada se a decodificação restrita fechar mais de 50% da lacuna de H1.

Se duas ou mais entre H1–H3 falharem em confirmar, o post que reporta os dados vai explicitamente passar pelo que o post anterior errou e em que eu estou atualizando. Eu prefiro publicar isso a maquiar um resultado fraco.

Como é o harness executável

O repositório companion é a pré-condição para que qualquer pessoa — inclusive eu — leve este pré-registro a sério. Ele contém:

  • O gerador de corpus com seed (para que os 200 inputs sejam reproduzíveis).
  • As quinze variantes de perturbação, geradas programaticamente a partir de um único template canônico (para que as variantes não sejam ajustadas artesanalmente).
  • O código de pontuação (validade de schema, acurácia de campo, F1, α de Krippendorff).
  • Um runner agnóstico ao modelo com suporte a stub, para que todo o pipeline rode ponta-a-ponta contra um modelo falso sem gastar um centavo — útil para revisão.
  • Uma suíte pytest que exercita o gerador de perturbações, o código de pontuação, o gerador de corpus e o runner contra o stub. Amigável a CI, sem chamadas de API.

Repositório: github.com/tiarebalbi/prompt-fragility-exp1. O README explica a reprodução em menos de cinco comandos.

O repositório será tagueado no momento em que o experimento for executado, para que qualquer pessoa lendo o post de resultados possa fazer git checkout do código exato que produziu os números.

Como será "publicar o resultado"

Quando o experimento rodar, o writeup vai incluir:

  • Os números brutos por célula (cada variante × cada métrica), não apenas estatísticas-resumo.
  • Os padrões de confusão — quais campos falham, em quais inputs, sob quais perturbações.
  • Decisões que tomei e sobre as quais não estou confiante (e o que eu faria diferente no Experimento #2).
  • A tabela de hipóteses, marcada como confirmada / falsificada / inconclusiva, com os tamanhos de efeito reais.

Se algo me surpreender, isso será apontado. Se uma hipótese falhar de um modo que atualize a tese mais ampla do post anterior, isso também será apontado. O ponto desta linha de pesquisa inteira não é estar certo; é tornar a suposição estrutural da área — o modelo pode cometer um erro — em algo que pode ser medido, contratado e ou mantido ou substituído. Uma hipótese confirmada avança isso. Uma falsificação surpreendente avança ainda mais.

O enquadramento maior

Pré-registro é um movimento pequeno. Ele não, por si só, leva a área até a precisão. Mas é uma das práticas de engenharia desglamouradas que o post anterior argumentou serem exatamente o que está faltando. Bancos de dados ganharam schemas versionados. Redes ganharam especificações formais. Protocolos web ganharam suítes de teste de conformidade. Prompts ganham um vibe check e um joinha.

A menor versão de "tratar prompts como artefatos de engenharia" é: comprometa-se com o que você vai medir antes de medir. É isso que este post é. O repositório companion é a segunda menor versão: torne a medição reproduzível por alguém que discorda de você.

O Experimento #2 — contraste multi-modelo no mesmo harness — já está escopado. Os Experimentos #3 e #4 — variância de RAG e estabilidade de trajetória agêntica — estão na fila. O ponto não é o experimento individual. O ponto é que agora há uma fila.

Mais por vir.

Continue lendo

Curtindo? Talvez goste disso aqui.

Nada parecido — quer tentar outro ângulo?

Isso foi útil?

Deixe uma avaliação ou uma nota rápida — me ajuda a melhorar.