antonio leandro

ia generativa

Evaluating Large Language Models Trained on Code

paper · Mark Chen, Jerry Tworek, Heewoo Jun, Qiming Yuan, et al. ·

a tese

medir código por teste unitário em vez de semelhança com a referência muda o placar: o codex-12b resolve 28,8% dos problemas na primeira tentativa e 70,2% quando pode tentar cem vezes

o que fica

  1. BLEU não serve para medir código: no experimento do paper, as distribuições de BLEU das soluções corretas e das incorretas se sobrepõem, então subir a nota não significa subir o acerto.
  2. Amostrar muda o regime do problema: o mesmo Codex-12B que resolve 28,8% dos problemas com uma amostra resolve 70,2% quando basta que uma das cem passe nos testes.
  3. A temperatura ótima depende de quantas amostras você vai gerar — 0,2 para uma só, 0,8 para cem — porque com muitas amostras a diversidade vale mais que a precisão de cada uma.
  4. Estimar pass@k como 1-(1-p)^k a partir do pass@1 empírico subestima o valor real de forma sistemática; o paper usa um estimador combinatório sem viés sobre n amostras.
  5. Quando não há testes para filtrar, ranquear as amostras pela log-probabilidade média é melhor que escolher ao acaso, e ranquear pela soma das log-probabilidades é pior que ao acaso.
  6. Prompt com bugs sutis faz o modelo escrever código pior do que ele é capaz de escrever, e essa lacuna aumenta com o tamanho do modelo — o paper chama isso de desalinhamento, não de incompetência.

o problema

Em 2021 já dava para pedir um programa a um modelo de linguagem e receber algo parecido com código. O que não dava era dizer se aquilo prestava. A prática da área era comparar a saída com uma solução de referência, por match exato ou por BLEU. Isso funciona mal para código por um motivo estrutural: o conjunto de programas funcionalmente equivalentes a uma referência é enorme e não tem nada a ver com proximidade textual. Uma solução correta escrita de outro jeito é punida; uma solução errada que copia a cara do gabarito é premiada. O paper mede isso e mostra o resultado: para as amostras do Codex-12B, as densidades de BLEU de soluções corretas e incorretas se sobrepõem a ponto de não serem separáveis.

O segundo problema é de dado. Um modelo treinado em boa parte do GitHub já viu as soluções dos benchmarks públicos — o paper cita mais de dez repositórios com soluções de problemas do Codeforces, que compõem parte do APPS. Qualquer avaliação montada a partir de problemas existentes mede memorização junto com capacidade, sem separar as duas.

a ideia

Trocar semelhança por execução. Um programa está certo se passa nos testes, ponto. É assim que desenvolvedor julga código na vida real, e é o critério que test-driven development leva ao extremo.

Aceita isso, o resto se reorganiza. Se a correção é binária e verificável, gerar código deixa de ser “produzir a resposta” e vira “buscar no espaço de respostas”: você amostra várias vezes e pergunta se alguma passa. Essa é a segunda metade do paper — e a métrica pass@k existe para dar nome a essa distinção entre acertar de primeira e acertar em k tentativas.

como funciona

O benchmark é o HumanEval: 164 problemas escritos à mão, cada um com assinatura, docstring, corpo e uma média de 7,7 testes. Escritos à mão de propósito, para não estarem no treino.

O modelo é GPT com até 12B de parâmetros, ajustado sobre 159 GB de Python público coletado do GitHub em maio de 2020 (179 GB antes dos filtros de arquivo gerado automaticamente e linha muito longa), por 100 bilhões de tokens. Duas escolhas práticas: o tokenizer do GPT-3 ganha tokens extras para sequências de whitespace de tamanhos diferentes, o que reduz em cerca de 30% os tokens para representar código; e partir de um modelo de linguagem pré-treinado não melhorou o resultado final, só a velocidade de convergência.

Para o pass@k, geram-se n amostras (n = 200 no paper), conta-se quantas passam e aplica-se um estimador sem viés. A tentação é estimar como 1-(1-p̂)^k sobre o pass@1 empírico; isso subestima de forma consistente, e a diferença não some nem com n maior que 5k. A amostragem usa nucleus com top-p 0,95 e para em sequências como \ndef ou \nclass, senão o modelo continua escrevendo funções.

Vem então o Codex-S: um segundo fine-tuning supervisionado, só em funções isoladas corretas, montadas de duas fontes — cerca de 10.000 problemas de sites de competição e entrevista, e cerca de 40.000 funções capturadas com sys.setprofile durante os testes de integração de projetos com CI. Problemas ambíguos ou não determinísticos são descartados gerando 100 amostras com o Codex-12B e jogando fora os que ninguém resolve. O Codex-S ganha em média 6,5 pontos percentuais no pass@1 e 15,1 no pass@100.

Como em produção não existe suíte de testes esperando, o paper testa heurísticas de escolha. Ranquear por log-probabilidade média resolve 44,5% dos problemas contra 77,5% do oráculo que conhece os testes. Ranquear pela soma das log-probabilidades é pior que sortear.

o que isso custou

Os autores são explícitos sobre a eficiência: o treino consome centenas de milhões de linhas de código, mais do que um desenvolvedor lê numa carreira inteira, e um bom aluno de um curso introdutório resolveria mais problemas que o Codex-12B.

O limite mais informativo é o da composição. Com docstrings sintéticas montadas encadeando 13 operações elementares de string, a taxa de acerto cai por um fator de 2 a 3 a cada componente adicionado. Um humano que implementa uma cadeia de dois passos implementa uma de dez. O modelo, não. Junto vem a falha de binding: dado “some 3 a y, subtraia 4 de x e de w, retorne o produto dos quatro”, o Codex-12B esquece o w e retorna a coisa errada.

E há o desalinhamento, que o paper separa de incompetência: com bugs sutis no prompt, o modelo produz código pior do que sabe produzir, a instrução explícita de escrever código correto ajuda pouco, e a lacuna cresce com o tamanho do modelo. Os autores listam ainda geração de código inseguro, viés herdado do treino e o risco de excesso de confiança de quem usa.

onde isso aparece hoje

O HumanEval virou a régua padrão para modelos de código, e pass@k virou vocabulário corrente. A prática de gerar muitas amostras e filtrar por execução é o ancestral direto do que hoje se chama sampling com verificador. Uma versão de produção distinta dos modelos descritos aqui alimenta o GitHub Copilot. E a seção sobre desalinhamento aponta para RLHF como caminho de correção — o mesmo caminho que os modelos de instrução seguiram depois.

lido na íntegra por pipeline de llm, revisado por antonio leandro antes de publicar ·