Avaliações

Você muda um prompt, testa uma vez, a resposta parece melhor e você publica, depois uma semana depois os usuários encontram os casos que silenciosamente ficaram piores. Uma avaliação (abreviada de evaluation) é a solução: um teste repetível de se seu recurso de IA funciona, um conjunto de entradas emparelhadas com o que uma boa saída parece, classificado da mesma forma sempre para que você possa dizer se uma mudança realmente ajudou. Um modelo é uma caixa preta probabilística que responde a mesma pergunta de forma diferente a cada execução, então medir é a única maneira de saber, e essa disciplina é muito do que separa uma demonstração de um produto.
Por que a inspeção visual falha
Verificar as respostas de sua IA manualmente parece bem no início. Você executa um prompt, lê a resposta e parece bom, então você segue em frente. O problema é que três coisas silenciosamente trabalham contra você, e você já conhece todas elas.
Aqui estão as três:
- A saída varia. O mesmo prompt pode dar respostas diferentes em cada execução, então um resultado bom não promete que o próximo também será bom.
- Mudanças causam regressões. Uma edição de prompt que corrige um caso geralmente quebra outro que você não estava vendo.
- Não escala. Você pode ler cinco respostas. Você não pode ler quinhentas toda vez que muda uma linha.
Nada disso significa que você fez algo errado. Significa que a inspeção visual é a ferramenta errada para um trabalho desse tamanho, e há uma forma mais tranquila de fazer isso.
Construir um conjunto de avaliação
Um conjunto de avaliação é uma lista de casos de teste. Cada caso tem uma entrada e o que uma boa saída parece para isso. Comece pequeno. Dez a vinte casos que cubram suas situações comuns mais alguns casos extremos complicados são muito mais úteis que nenhum, e você pode crescer o conjunto conforme encontra novas falhas no mundo real.
eval_set = [
{"input": "A comida estava fria e atrasada.", "expected": "NEGATIVO"},
{"input": "Melhor refeição da minha vida!", "expected": "POSITIVO"},
{"input": "Foi ok, nada de especial.", "expected": "NEUTRO"},
# ...adicione casos reais e casos extremos conforme descobrir
]Quando um usuário relata uma resposta ruim, adicione-a ao conjunto com a saída que deveria ter dado. Seu conjunto de avaliação se torna uma memória crescente de todo erro que você nunca quer cometer novamente, da mesma forma que um bug que você corrige se torna um teste que você mantém.
Como classificar
Tarefas diferentes precisam de classificações diferentes, então o primeiro passo é combinar a verificação com o tipo de resposta que você espera.
- Correspondência exata funciona quando há uma resposta certa: um rótulo de classificação, um campo extraído, um sim ou não. Você compara a saída ao valor esperado diretamente.
- Classificação baseada em critérios funciona quando não há uma única resposta certa, como um resumo ou uma resposta. Você verifica se a saída atende condições: O resumo menciona o fato chave? Tem menos de 50 palavras? O tom é educado?
- Modelo-como-juiz usa uma segunda chamada de modelo para classificar a saída contra seus critérios. Escala para questões de qualidade difusa que uma verificação simples não consegue capturar, mas o juiz é em si um modelo, então pode estar errado, e você verifica contra julgamento humano de vez em quando.
# classificação de correspondência exata sobre o conjunto de avaliação
def run_evals(eval_set, classify):
passed = 0
for test in eval_set:
output = classify(test["input"])
if output == test["expected"]:
passed += 1
else:
print(f'FAIL: "{test["input"]}" -> got {output}, wanted {test["expected"]}')
print(f"{passed}/{len(eval_set)} passed")Correspondência exata é o lugar mais amigável para começar, e se encaixa perfeitamente no trabalho de classificação e extração dos capítulos anteriores. A ideia de modelo-como-juiz funciona porque notar se uma resposta atende um padrão é geralmente uma predição mais fácil do que produzir a resposta foi, da mesma forma que revisar um ensaio é mais fácil que escrever um. Mas o juiz é outro preditor com os mesmos defeitos, então trate suas pontuações como uma estimativa útil, dê-lhe um rubrica claro, e verifique suas notas contra as suas em uma amostra de vez em quando.
Execute-os em toda mudança
Um conjunto de avaliação é útil apenas se você realmente o executar. Trate seus prompts como código: antes de enviar uma mudança para um prompt, modelo ou sua recuperação, execute as avaliações e compare a pontuação com o que era antes. Se o número desceu, você causou uma regressão, mesmo que seu único teste manual aconteça parecer bom.
Isto é o que transforma engenharia de prompt de adivinhação em algo que você pode iterar com confiança. Mude algo, meça, guarde o que marca mais alto, e descarte o que marca mais baixo. É o mesmo loop que torna o software ordinário confiável, agora aplicado às partes difusas de um recurso de IA.
Se a pontuação caiu, você causou uma regressão. Um teste manual sortudo não anula o conjunto, então deixe o número ser o desempate sempre.
Na prática
A função run_evals da seção anterior é um arnês de avaliação completo, se pequeno. Você o aponta para seu classificador e seu conjunto de avaliação, e ele diz quantos casos passam e mostra exatamente quais falham:
run_evals(eval_set, classify_review)
# FAIL: "Foi ok, nada de especial." -> got POSITIVO, wanted NEUTRO
# 2/3 passedEssa única linha falhando vale mais que uma dúzia de testes manuais bem-sucedidos, porque aponta uma fraqueza real que você agora pode corrigir e re-medir. O capítulo final, Segurança e limites, cobre os riscos para desenhar contra antes de colocar tudo isso na frente dos usuários reais.
run_evals já ganha seu lugar: oferece uma pontuação e os casos exatos que quebraram. Corrija um, execute novamente, veja o número se mover. A seguir, Segurança e limites cobre o que guardar contra antes dos usuários reais chegarem. 
