Skip to content
This page has been auto-translated and may contain errors.View in English

Avaliações

docs.scrimba.com

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.

JunoPor que a inspeção visual falha Ler respostas manualmente falha por três razões, todas enraizadas em como o modelo funciona: a saída varia de execução para execução, as edições silenciosamente quebram casos que você não estava vendo, e você não consegue acompanhar manualmente uma vez que há centenas de respostas. Não é um problema de disciplina, é a ferramenta errada para o tamanho do trabalho. A boa notícia é que a solução é amigável, e está chegando a seguir.

Ler uma resposta manualmente diz quase nada, e a razão está em como o modelo funciona. Como a saída é não-determinística (o mesmo prompt pode dar respostas diferentes em cada execução), uma única resposta é uma amostra de tamanho um. Não pode dizer o taxa de aprovação, a proporção de casos que saem certos, porque você precisa de muitas execuções nos mesmos casos para estimar com que frequência realmente funciona.

Regressões se escondem por uma razão relacionada. Corrija um caso manualmente e você não tem registro dos outros, então a próxima edição pode quebrar algo que você parou de assistir. A única maneira de ver isso é um conjunto fixo de casos classificado da mesma forma sempre, para que uma queda apareça como um número em vez de uma surpresa em produção.

Há um problema humano além da matemática. A revisão manual varia entre pessoas e entre humores: a mesma resposta lê como adequada na segunda-feira e fraca na sexta-feira. Então o movimento é converter "parece bom" em uma taxa de aprovação medida sobre um conjunto fixo de casos. Converta uma sensação em um número sobre os mesmos casos.

JunoPor que a inspeção visual falha Uma resposta é uma amostra de tamanho um, então diz que o modelo funcionou uma vez, não com que frequência funciona. Para ver uma taxa de aprovação real você executa muitos casos; para pegar regressões você corrige esse conjunto de casos e classifica da mesma forma sempre. A revisão manual também varia com o revisor, então o trabalho é substituir "parece bom" por um número medido.

A verificação pontual não falha porque você é descuidado. Falha porque tem viés de seleção embutido: você vê os casos que espera funcionar, então o comportamento que nunca verifica é aquele que regride na frente dos usuários. A métrica que você não rastreia é exatamente aquela que se move.

Sem uma pontuação de base, toda mudança de qualidade é uma história que você conta a si mesmo. Você não consegue atribuir uma mudança a uma edição específica, e você não consegue fazer bisecção de um conjunto de mudanças para encontrar qual diminuiu a taxa de aprovação (a proporção de seus casos que saem corretos), porque você nunca mediu o antes. "Parece melhor" sobrevive porque nada o contradiz.

Iteração baseada em sensações também overfita. Você continua digitando os mesmos exemplos, afina até que pareçam certos, e silenciosamente treina seu prompt para esse pequeno conjunto privado enquanto o tráfego real flutua para outro lugar. A revisão manual não consegue ver essa mudança de distribuição, porque as novas entradas são aquelas que você não está digitando. Um conjunto de avaliação versionado com uma pontuação rastreada é a única maneira de dizer que uma mudança ajudou em vez de parecer melhor, e é a diferença entre iterar e adivinhar.

JunoPor que a inspeção visual falha Já enviei em sensações e depois assisti o único caminho que nunca verifiquei pontualmente iluminar os logs de erro, é o viés de seleção fazendo seu trabalho. Sem base significativa não há atribuição e nenhuma bisecção: você não consegue provar qual edição moveu o número se nunca teve um número. Mantenha um conjunto versionado e uma pontuação rastreada, ou você está overfitando para os cinco exemplos que continua digitando enquanto o tráfego real sai para um lugar que você não consegue ver.

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.

python
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.

JunoConstruir um conjunto de avaliação Um conjunto de avaliação é uma lista de casos de teste: uma entrada e o que uma boa resposta parece. Comece com dez a vinte que cubram suas situações cotidianas e algumas complicadas. Toda vez que um usuário encontra uma resposta ruim, adicione-a com a resposta que deveria ter dado, e seu conjunto silenciosamente se lembra de todo erro que nunca quer repetir.

Um conjunto de avaliação é sua coleção de casos de teste, cada um uma entrada emparelhada com a saída que você aceitaria como bom. O número que importa não é tamanho, é cobertura. Um conjunto de vinte casos bem escolhidos bate cinquenta descartáveis sempre.

Objetivo cobrir três coisas: o caminho comum que seus usuários realmente seguem, os limites de decisão onde dois rótulos ficam próximos (os casos ambíguos bem na linha), e os modos de falha conhecidos que você já viu dar errado. Entradas selecionadas amigáveis fazem suas pontuações parecerem boas e dizem nada, então mantenha o conjunto representativo do tráfego real.

Todo bug que um usuário relata se torna um caso permanente no conjunto. Isso o transforma em uma suite de regressão: um bug corrigido permanece corrigido porque o caso que o expôs agora executa toda vez. Quando suas saídas esperadas são estruturadas em vez de texto livre, como um rótulo ou um campo JSON, você pode classificar com comparação de correspondência exata, que é limpa e inequívoca, veja saída estruturada.

Mantenha uma fatia separada retida que você nunca afina contra. Se você ajustar o prompt até passar nos casos exatos que está assistindo, você está se classificando nas respostas que já estudou, e a pontuação deixa de significar nada.

JunoConstruir um conjunto de avaliação Cobertura bate tamanho bruto: acerte o caminho comum, os limites ambíguos entre rótulos, e as falhas que você já viu. Transforme todo bug relatado em um caso permanente para que o conjunto funcione como uma suite de regressão. Mantenha uma fatia retida que você nunca afina contra, ou você está se classificando nas respostas que estudou.

Trate o conjunto de avaliação como um ativo que você versiona bem ao lado do prompt, porque os dois se movem juntos e uma mudança de prompt pode silenciosamente deslocar o que conta como uma boa resposta. A qualidade de rótulo do conjunto é o limite em sua métrica: um valor "esperado" errado limita sua pontuação e silenciosamente o ensina a lição errada, então cuidar dos rótulos cuidadosamente importa tanto quanto coletar casos.

Guarde-se contra vazamento de teste. Se você afina até passar no conjunto exato que relata, o número é teatro. Mantenha uma fatia que você não vê ao iterar, e rode-a ao longo do tempo para que não vaze lentamente em seu loop de afinação mesmo assim.

Observe o equilíbrio de classe. Um conjunto que é noventa por cento positivos inequívocos relata um número lisonjeiro enquanto esconde todo fracasso nos dez por cento que realmente importam, então amostre para que os casos difíceis e raros carreguem peso real. Puxe casos dos logs de produção em vez de imaginação, já que o tráfego real expõe formulações que você nunca inventaria em sua mesa.

Aceite que o conjunto apodrece. Conforme o produto muda, casos antigos deixam de refletir o que os usuários enviam e novos modos de falha aparecem que o conjunto nunca viu. Curá-lo é um trabalho contínuo, não uma construção única.

JunoConstruir um conjunto de avaliação O conjunto é um ativo que você versiona ao lado do prompt, e sua qualidade de rótulo é o teto rígido em sua métrica, um valor esperado ruim limita a pontuação inteira. Mantenha uma fatia e rode-a, ou seu número relatado é teatro. Observe o equilíbrio de classe, amostre casos reais de logs, e assuma que o conjunto apodrece conforme o produto se move, então curá-lo nunca realmente termina.

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.
python
# 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.

JunoComo classificar Escolha a verificação que se encaixa na resposta: correspondência exata quando há uma resposta certa, critérios quando há várias boas, e um segundo modelo como juiz para qualidade difusa. Correspondência exata é o início mais gentil, e se alinha bem com a classificação e extração que você já praticou. Mas o juiz é um modelo também, então espreite suas notas você mesmo de vez em quando.

Combine o classificador com a tarefa, então alcance o mais barato que ainda capture o que você se importa. Um classificador é o código ou chamada de modelo que decide se uma saída passou, e a escolha errada ou perde falhas reais ou marca respostas que foram boas.

Correspondência exata é para rótulos e campos extraídos: você compara a saída ao valor esperado e o resultado é determinístico, então você pode confiar nela. Emparelha naturalmente com saída estruturada, já que um modelo retornando um esquema fixo oferece algo limpo para comparar em vez de prosa de forma livre.

Critérios programáticos cobrem o meio do caminho barato: verifique o comprimento, confirme que uma string obrigatória está presente, valide se o JSON analisa, execute uma regex. Estes executam em milissegundos sem chamada de modelo, então use-os para tudo semi-estruturado antes de gastar dinheiro em um juiz.

Modelo-como-juiz é para qualidade aberta, onde um resumo ou uma resposta tem muitas formas boas e nenhum alvo exato. Precisa de um rubrica escrito para que o juiz aplique um padrão consistente, mais uma verificação de calibração onde você compara suas notas com suas próprias em uma amostra. Lembre-se que um classificador é código que você também tem que confiar: um classificador instável lhe entrega uma pontuação confiante errada.

JunoComo classificar Use o classificador mais barato que ainda pegue o que importa: correspondência exata para rótulos e campos, verificações programáticas para comprimento ou JSON válido ou uma string obrigatória, e um juiz modelo só para qualidade aberta. Correspondência exata funciona bem com saída estruturada porque um esquema fixo oferece algo limpo para comparar. Seja qual for o que você escolher, o classificador é código que você confia também, então um instável lhe entrega uma pontuação confiante errada.

Modelo-como-juiz é o classificador que quebra das formas mais interessantes, então planeje seus vieses antes de depender dele. Um juiz favorece respostas mais longas, escolhe a primeira opção ao comparar um par, e recompensa texto que lê como seu próprio estilo, e suas pontuações absolutas são mal calibradas, então um 8 de uma execução não é um 8 da próxima.

Trate o juiz como um modelo que você está avaliando por conta própria. Fixe e versione o modelo juiz, porque ele flutua quando atualiza e suas pontuações se movem com ele. Dê-lhe um rubrica apertado com alguns exemplos de âncora, então meça concordância juiz-versus-humano em uma amostra rotulada para saber até que ponto confiar nele.

Onde você conseguir, peça uma comparação em pares ("A ou B é melhor?") em vez de uma pontuação 1-a-10 absoluta; julgamentos relativos são geralmente mais confiáveis que pedir a um modelo para acertar um número calibrado. Fixe o juiz, rubrica apertado, verifique contra humanos.

Cuidado com a circularidade e a conta. A mesma família de modelo classificando sua própria saída compartilha seus pontos cegos, então uma falha que o gerador cometeu é uma falha que o juiz provavelmente vai perder, e julgar todo caso em escala é uma segunda conta de modelo em cima da primeira.

JunoComo classificar O juiz tem opiniões que você não pediu: gosta de respostas longas, a primeira opção, e prosa que soa como ele mesmo, e suas pontuações absolutas vagam entre execuções. Fixe e versione-o, dê-lhe um rubrica apertado com âncoras, e rastreie com que frequência concorda com um humano, porque você está classificando o classificador agora. Dependa de comparações em pares sobre um solitário 1-a-10, e esteja ciente que um modelo julgando sua própria família compartilha seus pontos cegos e dobra a conta.

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.

JunoExecute-os em toda mudança Um conjunto de avaliação só ajuda se você o executar, então faça um hábito: antes de qualquer mudança enviar, execute as avaliações e verifique a pontuação contra a última vez. Se desceu, isso é uma regressão para corrigir, não um acaso para deixar de lado. Mude, meça, guarde o que marca mais alto, e você está iterando em vez de adivinhar.

Conecte a execução da avaliação em seu loop de desenvolvimento para que gate mudanças da forma que uma suite de teste gatea uma mesclagem. Uma mudança para um prompt, um modelo, ou sua recuperação (o passo que puxa documentos de suporte) não envia até que você tenha executado o conjunto e comparado a pontuação com a execução anterior. O número, não seu instinto depois de um teste manual, decide se a mudança é uma melhoria.

Mude uma variável por vez. Se você editar o prompt e trocar o modelo na mesma passagem, um movimento na pontuação tem duas possíveis causas e você não consegue atribuir a nenhuma. Isole a mudança, execute o conjunto, leia o resultado, então siga para a próxima.

Leia o diff por caso, não apenas a pontuação agregada (o número único calculado em média em todo caso). Um total estável pode esconder um caso que foi corrigido e um que quebrou ao mesmo tempo, que soma zero enquanto seu comportamento silenciosamente mudou. Olhar para quais casos viraram diz o que sua mudança realmente fez.

Rastreie a pontuação ao longo do tempo para que a melhoria seja visível e as regressões se destaquem. Um histórico registrado transforma "isso parece melhor" em uma linha que você pode apontar, e torna uma queda repentina rápida de rastrear de volta para a mudança que a causou.

JunoExecute-os em toda mudança Gate mudanças na pontuação da forma que você gatea uma mesclagem em testes: nenhuma execução, nenhum envio. Mude uma variável por passagem para que um movimento de pontuação tenha uma causa, e leia o diff por caso, já que um total plano pode esconder um caso corrigido e um quebrado. Registre a pontuação ao longo do tempo para que vitórias sejam visíveis e regressões se destaquem.

Faça um portão real, não um ritual. Coloque um limite de pontuação em CI para que uma mudança que caia abaixo da barra falhe a compilação em vez de depender de alguém se lembrar de olhar. E re-execute o conjunto em toda atualização de versão de modelo, porque o mesmo prompt cai diferente em novos pesos; fixe a versão do modelo que você testou contra e re-avalie antes de adotar um novo.

Mantenha duas armadilhas em mente. Primeiro, o conjunto de avaliação (sua coleção fixa de casos de teste com resultados esperados) é um proxy, não verdade fundamental, então afinar duro contra ele overfita: você sobe a pontuação enquanto o comportamento real estagna. Mantenha expandindo e rodando o conjunto para que você esteja medindo a tarefa, não memorizando o teste.

Segundo, avaliações offline não são a imagem toda. Emparelhe-as com sinais online, tráfego de produção amostrado, feedback de usuário, taxas de reclamação, e alimente falhas reais de volta ao conjunto como novos casos.

Como a saída é não-determinística, a mesma entrada pode marca diferente entre execuções. Execute amostras suficientes por caso e classifique contra uma tolerância em vez de perseguir ruído de execução única; uma oscilação de um ponto entre execuções é a medição respirando, não uma regressão. Defina a barra em um nível que sobreviva essa variância, ou você gastará sua semana investigando fantasmas. Fiz exatamente isso, mais de uma vez.

JunoExecute-os em toda mudança Coloque um limite em CI para que uma mudança ruim falhe a compilação, e re-avalie em toda atualização de versão de modelo porque novos pesos leem o mesmo prompt diferentemente. O conjunto é um proxy, então continue rodando e emparelhe com sinais online, ou você vai overfit ao seu próprio teste. E como a saída é não-determinística, classifique contra uma tolerância em vez de investigar fantasmas, que sim, fiz.

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:

python
run_evals(eval_set, classify_review)
# FAIL: "Foi ok, nada de especial." -> got POSITIVO, wanted NEUTRO
# 2/3 passed

Essa ú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.

JunoNa prática Um pequeno arnês como 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.

Um pequeno arnês de avaliação, o bit de código que executa todo caso em seu conjunto de avaliação e classifica a saída contra o que você esperava, é o loop que transforma "parece bom" em um número que você pode mover. Você executa o conjunto, recebe uma pontuação mais uma lista de falhas, corrige a falha real mais barata, executa novamente.

Cada caso falhando é uma unidade de trabalho com uma definição clara de feito: o caso passa. Esse é um alvo mais agudo que "tornar o prompt melhor", porque você pode ver exatamente quando acerta e exatamente quando regride.

Antes de tudo isso encontrar usuários reais, o próximo capítulo, Segurança e limites, cobre os riscos que você desenha contra desde o início.

JunoNa prática O arnês transforma sensações em um número que você pode mover: execute o conjunto, leia a pontuação e as falhas, corrija a falha real mais barata, re-execute. Cada falha é uma tarefa com uma definição clara de feito, que é um alvo mais agudo que "tornar melhor". Então Segurança e limites antes dos usuários reais verem.

Em produção esse pequeno arnês deixa de ser um script que você executa manualmente e se torna parte do sistema. Cresce em um portão de CI, uma verificação que bloqueia um lançamento quando a pontuação cai abaixo de uma linha que você definiu, mais um dashboard que você vê entre lançamentos para pegar a deriva lenta que uma única execução nunca mostra.

Avaliações offline, o conjunto fixo que você classifica antes de enviar, e monitoramento online, os sinais que você coleta do tráfego real depois, alimentam um ao outro: falhas de produção se tornam novos casos offline, e o conjunto offline diz se sua correção resistiu. Os times que ganham aqui não são aqueles com o prompt mais inteligente. São aqueles que mediram enquanto todos os outros examinaram.

Essa é a disciplina. O próximo capítulo, Segurança e limites, cobre os riscos para desenhar contra antes que tudo isso chegue aos usuários reais.

JunoNa prática Madureça isso e o script se torna um portão de CI mais um dashboard, com avaliações offline e monitoramento online se alimentando um ao outro. Enviei em "parece bom para mim" e paguei por isso depois, então acredite em mim: os times que ganharam mediram enquanto o resto examinou. Leia Segurança e limites antes dos usuários reais chegarem.