Engenharia

Seu eval set é um museu. Ele deveria ser um ralo.

Um test set fixo apodrece no momento em que você começa a passar nele. O conserto é um flywheel: toda conversa real que deu errado vira um novo teste, então você nunca consegue dar overfit num problema que já resolveu.

ASR

Apollo Space Research

Apollo Space

· 12 min de leitura

Um time escreve duzentos casos de teste para seu agent, roda, ganha um dashboard verde, e lança. Três semanas depois um cliente pergunta ao agent algo que nenhum dos duzentos cobria, o agent atrapalha tudo, e o dashboard continua verde. Ele esteve verde o tempo todo. Ele vai continuar verde enquanto o produto lentamente para de funcionar, porque o test set parou de aprender no dia em que foi escrito.

Esse é o jeito silencioso como toda suíte de eval morre. Não num build vermelho, num verde que não significa mais nada.

O conserto não é um test set maior. É um test set que cresce a partir do trabalho. Toda conversa que deu errado deveria deixar para trás um teste, para que o eval nunca consiga dar overfit num problema que você já resolveu. Este post é sobre como construir um eval que drena falhas reais para fora da produção e transforma cada uma numa pergunta permanente que você nunca mais consegue errar.

O eval ingênuo é um museu, e museus não se movem

O jeito óbvio de avaliar um agent é o jeito que você avaliaria um estudante: escreva a prova uma vez, corrija contra ela para sempre. Você se senta no começo do projeto, imagina as coisas que os usuários vão perguntar, escreve algumas centenas de casos, e a partir daí uma rodada que passa significa “o agent faz o que imaginamos”.

Funciona lindamente por exatamente o tempo em que sua imaginação bateu com a realidade. Ou seja, por uma semana.

Aqui está a falha, e ela é estrutural, não preguiçosa. Os casos que você escreveu são os casos que você já entendia. Você não consegue escrever um teste para uma falha que ainda não imaginou, se você a tivesse imaginado, você a teria tratado, e não haveria nada a testar. Então um eval set fixo mede uma coisa precisamente: sua previsão no dia em que o escreveu. Ele não diz nada sobre o input que aparece na próxima terça, a formulação que ninguém do time jamais usaria, a borda do produto onde os usuários reais vivem. O set é um museu. Os itens em exposição são as falhas que você viu chegando. As que te machucam são as que entraram depois de fechar.

E piora, porque você otimiza contra ele. Todo conserto que você faz é mirado no test set, então o set fica mais fácil de passar a cada sprint. A verdura sobe enquanto a coisa que a verdura deveria prever, ele funciona para uma pessoa real, se afasta por baixo. Você não está mais medindo qualidade. Você está medindo quão bem decorou sua própria prova.

O gargalo nunca desaparece. Ele só se move de “conseguimos passar no teste” para “o teste ainda é sobre alguma coisa”.

O flywheel: uma falha vira um teste, automaticamente

Então paramos de tratar o eval set como uma coisa que você escreve e começamos a tratá-lo como uma coisa que se preenche sozinha.

A versão ingênua diz: um teste é algo que um engenheiro escreve. A nossa versão diz: um teste é algo que uma conversa ruim deposita. Quando uma interação real dá errado, o agent escolhe a ferramenta errada, esquece o que foi dito a ele um minuto atrás, responde uma pergunta na língua do usuário com uma ação na língua errada, alega que fez algo que não fez, essa conversa não é só logada e esquecida. Ela é cunhada num flow: um caso nomeado e reproduzível que reproduz exatamente o que deu errado, estacionado permanentemente no corpus.

O mecanismo é simples de enunciar e esse é o ponto. Uma falha real entra. Capturamos a forma dela, o input, o contexto, qual era a resposta certa, o que o agent fez em vez disso. Transformamos essa forma num caso que roda contra o runtime real do agent, não um mock. A partir daí, aquela falha exata é uma pergunta que o agent tem que responder corretamente para sempre. Conserte uma vez, e o teste fica de guarda para que você nunca mais consiga silenciosamente quebrá-la.

Toda conversa que deu errado deveria deixar para trás um teste, para que o eval nunca consiga dar overfit num problema que você já resolveu.

À esquerda, um eval set fixo escrito uma vez: uma caixa selada de casos imaginados que fica verde enquanto falhas reais a contornam intocadas. À direita, um flywheel: uma conversa real dá errado, a falha é cunhada num flow nomeado, o corpus cresce, o agent é avaliado contra ele para sempre, e a próxima falha realimenta o ciclo.

A forma à direita é a ideia inteira. Uma conversa dá errado. A falha vira um flow. O corpus cresce em um. O agent é agora avaliado contra aquele flow a cada rodada, para sempre. E porque o loop nunca fecha, o corpus acompanha a realidade em vez de acompanhar sua memória da realidade. Você não consegue dar overfit nele, porque ele é alimentado pela exata coisa que o overfitting esconde de você: as falhas que você não viu chegando.

Esse é o movimento que vira um eval de um museu num ralo. Um museu exibe o que você escolheu coletar. Um ralo pega o que quer que de fato flua por ele. Você quer o ralo.

”Burro” é um teste faltando, não uma feature faltando

Há um tipo particular de reclamação que um eval set fixo te ensina a ignorar, e é o sinal mais valioso que você tem.

Imagine um usuário digitando o equivalente conversacional de essa coisa é burra. Ele pediu algo razoável e recebeu algo inútil. Num time de eval-fixo, essa reclamação não tem para onde ir. Ela não está nos duzentos casos. Não move o dashboard. Então ela vira uma mensagem no Slack, depois um sentimento vago de que “o agent anda meio off ultimamente”, depois um lamento numa retro com o qual todos concordam com a cabeça e ninguém consegue agir. O sinal era real. Ele só não tinha forma, então evaporou.

O instinto ingênuo é ler essa reclamação como uma feature faltando, precisamos tratar essa categoria melhor, e adicioná-la a um backlog onde ela compete com tudo o mais e perde.

A reformulação é mais afiada: não é uma feature faltando, é um teste faltando. O usuário acabou de te entregar, de graça, um input real que produziu uma falha real. Isso não é um sentimento para absorver; é um caso para cunhar. Você pega a conversa, captura o que deu errado, e a solta no corpus como uma lacuna localizada, não “o agent parece burro” mas “este flow exato, neste input exato, produziu esta resposta errada exata, e aqui está onde quebrou”.

A diferença é enorme. Um sentimento é algo sobre o qual você discute numa reunião. Uma lacuna localizada é algo que você conserta e depois guarda. Um re-diagnostica o mesmo mal-estar vago toda semana. O outro transforma uma única mensagem raivosa numa melhoria permanente que nunca consegue silenciosamente regredir. A reclamação para de ser ruído e vira o caso de teste mais honesto que você possui, porque nenhuma imaginação de engenheiro a produziu, a frustração real de um usuário real produziu.

Um caso vermelho não é um lamento. É um endereço.

Dois números, nunca um: o proxy rápido e a verdade

Aqui é onde um eval set crescente esbarra num limite duro, e vale ser honesto sobre ele em vez de passar pano.

Você quer que o loop rode rápido. Uma falha deveria virar um teste, o teste deveria rodar em segundos, você deveria conseguir distribuir dezenas deles em paralelo, fazer A/B entre tamanhos de modelo, e ter uma resposta de volta antes de perder o fio. Essa velocidade é o que faz o flywheel girar. Então você constrói um harness local: o runtime real do agent, in-process, reproduzindo flows contra o corpus, imprimindo o que ele classificou, quais ferramentas buscou, o que respondeu, e o que lembrou. Rápido, barato, repetível. O proxy rápido.

O movimento ingênuo é chamar verde no proxy rápido de “pronto”. Não é, e fingir que é recria o problema original do museu um nível acima. Um harness local ainda é um ambiente controlado. É o seu melhor palpite da realidade, rodado rápido, mas é um palpite. A coisa que de fato é verdade é se uma pessoa real, no produto realmente deployado, clicando na superfície real, recebeu um resultado que funcionou.

Então você reporta dois números e nunca os mescla. O número interno é o proxy rápido: como o agent se sai contra o corpus crescente, localmente, em segundos. O número externo é a verdade: como ele se sai quando um humano usa a coisa lançada. Verde-interno significa comportamentalmente promissor, pendente da superfície real. Verde-externo significa de fato funcionou para alguém. No momento em que você colapsa esses dois num único “funciona”, você contou a si mesmo uma mentira reconfortante, a mesma mentira que o dashboard verde do museu contou, só que mais rápido.

Duas leituras da mesma mudança de agent. O loop interno rápido reproduz o corpus crescente localmente em segundos e reporta uma taxa de aprovação interna, um proxy rápido. O loop externo lento roda a superfície real deployada que um humano pode tocar e reporta uma taxa de aprovação externa, a verdade. A seta flui num sentido só: verde-interno só ganha o direito de checar o externo; ele nunca o substitui.

Os dois números importam, e importam de modo diferente. O número interno é como você se move rápido sem voar às cegas, ele pega a regressão em segundos, na sua máquina, antes de ela chegar a uma pessoa. O número externo é como você fica honesto, é o único que tem permissão de dizer “isso é real”. Mantê-los separados é a disciplina que impede um loop rápido de silenciosamente virar de volta um museu que só roda mais vezes.

O corpus é o ativo, não o agent

Dê um passo atrás e note o que você está de fato construindo quando roda o loop desse jeito.

Todo time acha que o agent é a coisa valiosa, os prompts, as ferramentas, a orquestração. Eles não são nada. Mas são substituíveis. O modelo por baixo vai mudar. O prompt vai ser reescrito. A camada de ferramentas vai ser trocada. Nada disso é o moat.

O moat é o corpus. Toda falha que seu produto já bateu, cunhada num caso, reproduzível contra qualquer agent que venha a seguir. Esse set é um registro estruturado de todo jeito que seu produto específico, no seu domínio específico, foi errado por pessoas reais. Um novo modelo chega, você o roda contra o corpus e descobre, numa tarde, se ele é de fato melhor no seu trabalho ou só melhor no benchmark de alguém. Você reconstrói o agent do zero, o corpus te diz instantaneamente quais das falhas antigas voltaram. O agent é o candidato. O corpus é a entrevista, e é uma entrevista que fica mais difícil e mais honesta a cada semana, porque é alimentada pela única fonte que não pode ser burlada: o que de fato deu errado.

Esse é o ativo que compõe. Imagine dois times lançando o mesmo agent no dia um. Um escreve um test set fixo e o congela. O outro drena toda falha para um corpus crescente. Seis meses depois, digamos mil conversas reais, o set do primeiro time ainda mede a imaginação do dia um. O set do segundo time mede mil jeitos reais como o produto encontrou o mundo. Eles não são mais a mesma empresa, e a diferença não é o modelo. É que um deles continuou aprendendo de estar errado.

A virada: o custo de uma reclamação que não vai a lugar nenhum

Tire o harness, o corpus e os dois números, e o que sobra é mais antigo que tudo isso.

Toda empresa já tem a matéria-prima do flywheel. Ela chega todo dia, de graça, na forma de usuários te dizendo exatamente onde o produto os decepcionou. A pergunta nunca foi se você tem o sinal. Você está se afogando nele. A pergunta é se alguma coisa o captura, se uma mensagem frustrada vira um teste permanente, ou vira um sentimento que some até sexta.

Uma reclamação que não vai a lugar nenhum é a coisa mais cara numa empresa de software, porque você pagou o preço cheio, a confiança de um usuário, e não recebeu nada de volta. Nenhum conserto que se sustenta, nenhum teste que guarda, nenhuma lição que o sistema não consiga esquecer. Você absorveu o dano e descartou os dados. O flywheel é, por baixo de toda a maquinaria, só a decisão de parar de fazer isso: tratar todo momento em que o produto decepcionou alguém como um presente que você se recusa a desperdiçar.

Essa é a parte que não é sobre evals de jeito nenhum. É sobre se sua empresa fica mais inteligente de estar errada, ou só fica cansada disso. Os times que vencem a próxima década não serão os com os agents mais espertos. Serão aqueles cujos erros só conseguem acontecer uma vez.


É isso que estamos construindo na Apollo Space, não um test set que você escreve e congela, mas um que se preenche sozinho a partir de toda conversa que não saiu do jeito que deveria, para que o sistema seja sempre avaliado pelo que de fato deu errado. Se você já viu um dashboard verde te tranquilizar enquanto o produto silenciosamente parava de funcionar, você já sabe por que seu eval set deveria ser um ralo, não um museu.

A Apollo cuida da operação repetitiva da sua empresa pro seu time não precisar.

Entre na lista de espera: acesso antecipado, preço de usuário fundador e um lugar na primeira fila enquanto a gente constrói.

Entrar na lista de espera