Você construiu uma ferramenta interna que permite a uma equipe executar 28 testes unitários em uma funcionalidade baseada em LLM sem nunca chamar a API do modelo. Você fez isso envolvendo o modelo em uma interface que permite o uso de fakes e adicionando três camadas de avaliação: determinística, heurística e baseada em LLM.
Asserções padrão quebram no momento em que um LLM gera prosa. O mesmo prompt pode gerar uma frase diferente em cada execução, então assertEqual(output, expected) sinaliza uma falha mesmo quando o modelo se comportou corretamente. A maioria dos grupos de engenharia ou lança a funcionalidade sem verificação ou tenta testar o próprio modelo, tratando um alvo em constante mudança como se fosse uma biblioteca estática.
Por que o problema importa
Os LLMs agora estão inseridos em fluxos de trabalho voltados para o cliente — prospecção por e-mail, respostas de suporte, geração de conteúdo. Um único fato alucinado ou um identificador vazado pode danificar a reputação da marca, expor dados privados ou causar violações de conformidade. Sem uma estratégia de teste confiável, as equipes perdem tempo perseguindo falhas intermitentes ou lançam bugs que só aparecem em produção.
A abordagem: reduzir a responsabilidade do modelo
O primeiro passo foi limitar o que o LLM realmente faz. No sistema do autor, o modelo apenas redige mensagens de prospecção. Toda a lógica de roteamento, gerenciamento de estado e verificações de segurança permanecem no código comum. Ao confinar o modelo a uma saída única e bem definida, o sistema ao redor permanece determinístico e testável.
Para tornar isso possível, o LLM fica atrás de uma interface de provedor, permitindo que uma versão simulada (fake) seja usada nos testes. Em produção, a implementação chama a API externa; no conjunto de testes, um fake leve retorna uma resposta pré-definida. Como o restante do código interage apenas com a interface, todo o fluxo de trabalho pode ser exercitado por testes unitários que nunca tocam a rede. O resultado é um núcleo previsível que os 28 testes verificam.
Um mecanismo de avaliação honesto
Mesmo com um escopo reduzido, a saída do modelo permanece não determinística. O autor, portanto, construiu um mecanismo de avaliação de três camadas, cada uma lidando com uma classe diferente de risco.
Camada 1 – Verificações determinísticas Regras simples de expressões regulares capturam erros concretos, como um ID de edifício incorreto ou tokens proibidos. Essas verificações são rápidas e fornecem um resultado binário de passar/falhar.
Camada 2 – Verificações heurísticas Scripts procuram por números ou datas alucinados, sinalizando fabricações factuais óbvias. Eles perdem alegações falsas que carecem de pistas numéricas, e o autor reconhece abertamente essa limitação.
Camada 3 – Juiz LLM Um modelo secundário avalia o tom e o profissionalismo. Como esta etapa depende de outro sistema probabilístico, ela é usada apenas para aspectos subjetivos onde regras determinísticas seriam impossíveis.
A chave para o mecanismo é o conjunto de dados usado para a avaliação. O autor codificou padrões de falha conhecidos — armadilhas específicas e conhecimento de domínio — para que o mecanismo teste exatamente os erros que apareceram na prática. Não é uma "solução mágica para tudo", mas uma rede de segurança direcionada.
O que isso significa para as equipes
- Mantenha o trabalho do LLM pequeno. Menos responsabilidades tornam o isolamento e o teste mais fáceis.
- Coloque roteamento, estado e segurança no código. A lógica tradicional permanece determinística e totalmente testável.
- Exponha o modelo através de uma interface simulável. Testes unitários rodam sem chamadas externas, mantendo a suíte rápida e confiável.
- Use camadas de avaliação. Comece com regras determinísticas, adicione heurísticas para alucinações conhecidas e reserve juízes LLM para verificações de qualidade subjetivas.
- Declare os limites. Nenhuma camada garante perfeição; o mecanismo só captura o que você o programa explicitamente para detectar.
Contraponto: você ainda não pode testar o modelo em si com testes unitários
O autor admite que um modelo é um alvo móvel. Mesmo a camada de juiz LLM herda o mesmo não determinismo que tenta avaliar. Consequentemente, o sistema nunca pode garantir que cada alucinação ou violação de política será capturada antes do lançamento. A abordagem reduz o risco, não o elimina, e depende da capacidade da equipe de manter os dados de avaliação atualizados conforme novos modos de falha surgem.
Lição principal
Você não pode escrever um teste unitário clássico que faça uma asserção sobre a saída exata de um LLM, mas pode construir um sistema onde a influência do modelo é limitada, sua interface é substituível e sua saída é filtrada por verificações em camadas e transparentes. Essa combinação transforma um componente que, de outra forma, seria instável em uma parte previsível de uma aplicação maior e testável.
