antonio leandro

ia generativa

SWE-bench: Can Language Models Resolve Real-World GitHub Issues?

paper · núcleo · Jimenez, Carlos E., Yang, John, Wettig, Alexander, Yao, Shunyu, Pei, Kexin, Press, Ofir, Narasimhan, Karthik · · ~104 min de leitura do original

a tese

medir modelo em issue real de github derruba o placar: sobre 2.294 tarefas com teste de verdade, o melhor sistema avaliado resolve 1,96% — e o gargalo é achar o que editar, não escrever o código

o que fica

  1. O melhor modelo avaliado resolve 1,96% das 2.294 tarefas com recuperação BM25, e 4,80% quando recebe de bandeja os arquivos que a solução real editou.
  2. Ampliar o contexto piorou o resultado: no limite de 50.000 tokens o BM25 recupera mais arquivos certos que no de 13.000, e mesmo assim o modelo resolve menos issues.
  3. Uma tarefa só entra no benchmark se existir um teste que falha antes do PR e passa depois; a nota vem de execução, não de semelhança com o diff humano.
  4. A avaliação também roda os testes que já passavam antes — resolver a issue quebrando o resto conta como fracasso.
  5. Entre os patches que aplicam e não resolvem, a maioria não faz nenhum teste fail-to-pass passar: são no-op ou regressão pura.
  6. O desempenho não muda para issues criadas depois de 2023, o que enfraquece a hipótese de que os modelos estejam apenas repetindo código memorizado.

o problema

Até 2023 o benchmark de código que valia era o HumanEval: uma docstring, uma função para escrever, alguns testes para conferir. Problema fechado, resolvido em poucas linhas, sem contexto além do enunciado. Serviu enquanto serviu, mas mede uma coisa que quase ninguém faz no trabalho: escrever uma função isolada a partir de uma especificação limpa.

O trabalho real é outro. Uma issue chega dizendo que HuberRegressor estoura com array booleano, ou que o sharey=1 não é aceito onde sharey=True é. O repositório tem, em média nas tarefas do SWE-bench, 3.010 arquivos e 438 mil linhas fora dos testes. A descrição da issue tem 195 palavras. Entre ler isso e escrever a correção existe um passo que nenhum benchmark de função isolada exercita: descobrir quais das 438 mil linhas importam. E existe um segundo passo: não quebrar o resto.

a ideia

O open source já produz de graça o par que um benchmark precisa: um enunciado em linguagem natural e um verificador executável. A issue é o enunciado. O pull request que a fechou contém os dois lados — o código que resolve e os testes que provam que resolveu. Basta separar os dois, jogar fora o código, entregar ao modelo o repositório no commit anterior mais o texto da issue, e cobrar um patch.

O corte que dá rigor ao esquema é o teste fail-to-pass: só vira tarefa o PR que trouxe pelo menos um teste que falha antes de aplicar a solução e passa depois. Isso garante que o problema é real, que a verificação é automática e que ninguém precisou escrever o gabarito à mão. Como o procedimento é mecânico, o benchmark se renova: dá para colher issues criadas depois da data de corte de treino de qualquer modelo.

como funciona

O pipeline tem três estágios. Coleta: cerca de 90 mil PRs dos 12 repositórios Python mais baixados que permitem uso da licença — django, sympy, sphinx, scikit-learn, matplotlib, astropy, xarray, pytest, pylint, requests, flask, seaborn. Filtro por atributo: fica o PR mergeado que referencia uma issue e mexe em arquivo de teste. Filtro por execução: aplica-se o test patch sozinho, roda, aplica-se a solução, roda de novo, e compara os dois logs. Sem transição fail-to-pass, a tarefa cai. Sobram 2.294.

O enunciado é o título e o corpo das issues mais os comentários anteriores ao primeiro commit do PR — o corte de data existe para não vazar a solução. A avaliação aplica o patch gerado com patch, roda a suíte e exige duas coisas: todos os testes fail-to-pass passando e todos os pass-to-pass também. Um desses passa a falhar e a tarefa está perdida.

Como nenhum repositório cabe na janela, os baselines usam BM25 para escolher arquivos, mais um cenário artificial chamado “oracle”, em que o modelo recebe exatamente os arquivos que o PR de referência editou. Os autores ainda treinam SWE-Llama, um CodeLlama-Python 7b e 13b ajustados com LoRA sobre 19 mil pares issue-PR de outros 37 repositórios, disjuntos dos de avaliação.

o que isso custou

Os números são baixos ao ponto de quase não discriminar. Claude 2 resolve 1,96% com BM25 e 4,80% com o oracle; Claude 3 Opus chega a 3,79% e 9,39% no cenário mais generoso, em que só as linhas ao redor da edição real ficam visíveis. Boa parte do fracasso nem chega à lógica: menos da metade dos patches sequer aplica, e os que aplicam são curtos — cerca de 30 linhas contra 74,5 do patch humano médio, quase sempre num arquivo só. Entre os que aplicam e não resolvem, a maioria não move um único teste.

O achado desconfortável é sobre contexto: aumentar o limite de tokens aumenta o recall do BM25 e derruba a taxa de resolução. Mais material relevante no prompt não compensa a distração.

Os autores listam os limites. É só Python, e só doze projetos. O cenário oracle é irreal, porque um engenheiro de verdade não sabe de antemão quais arquivos mexer. Issues com imagem embutida — 32% em matplotlib — são insolúveis para um modelo sem visão. E passar nos testes não é sinônimo de bom código: a análise por complexidade ciclomática mostra patches corretos que enfiam um if numa classe central em vez de criar o tipo de erro adequado. Os baselines são deliberadamente simples: um prompt, uma geração, sem rodar teste nenhum no meio.

onde isso aparece hoje

A recomendação final do artigo é a parte que envelheceu melhor: os autores dizem que não pretendem prender o campo ao formato de uma geração só e apontam agentes e uso de ferramentas como direção. É exatamente o que veio — o loop de ler, editar, rodar teste e reeditar virou a forma padrão de atacar essa tarefa, e a lógica de avaliar por execução em vez de similaridade textual é hoje o conselho corrente para quem monta evals para agentes e agentes eficazes. O subconjunto Lite, com 300 instâncias sobre 11 dos 12 repositórios, existe para quem não quer pagar 2.294 execuções por experimento.

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