Geração automática de mensagens para commits

Ei! Meu nome é Alexandra Eliseeva, sou aluna do Centro de Ciência da Computação . Como parte da minha prática no semestre de outono de 2020, participei do projeto BERT for Source Code liderado por Timofey Bryksin e Yaroslav Sokolov da JetBrains Research . Pesquisei como resolver o problema de geração automática de mensagens de commit usando o modelo de linguagem BERT. O que aconteceu, e o que ainda precisa ser trabalhado, vou contar para vocês neste post.







Sobre o projeto



Existem muitos problemas interessantes no campo do processamento de linguagens de programação, cuja solução automática pode ser útil para criar ferramentas convenientes para desenvolvedores.



O código-fonte dos programas difere de muitas maneiras dos textos em linguagem natural, mas também pode ser considerado uma sequência de tokens e métodos semelhantes podem ser usados. Por exemplo, no campo do processamento de linguagem natural, o modelo de linguagem BERT é usado ativamente. O processo de treinamento envolve dois estágios: pré-treinamento em um grande conjunto de dados não rotulados e treinamento adicional para tarefas específicas em conjuntos de dados rotulados menores. Esta abordagem permite que muitas tarefas sejam resolvidas com muito boa qualidade.



Trabalhos recentes ( 1 , 2, 3 ) mostrou que se você treinar o modelo BERT em um grande conjunto de dados de código de programa, então ele lida bem com várias tarefas nesta área (entre elas, por exemplo, localização e eliminação de variáveis ​​usadas incorretamente e geração de comentários para métodos) .



O projeto visa investigar o uso do BERT para outras tarefas de código-fonte. Em particular, nos concentramos na tarefa de gerar mensagens de confirmação automaticamente.



Sobre a tarefa



Por que escolhemos esta tarefa?



Em primeiro lugar, os sistemas de controle de versão são usados ​​no desenvolvimento de muitos projetos, portanto, uma ferramenta para resolver este problema automaticamente pode ser relevante para uma ampla gama de desenvolvedores.



Em segundo lugar, formulamos a hipótese de que o uso de BERT para essa tarefa poderia levar a bons resultados. Isto acontece por diversas razões:



  • em trabalhos existentes ( 4 , 5 , 6 ), os dados são coletados de fontes abertas e requerem filtragem séria, portanto, há poucos exemplos de treinamento. É aqui que a capacidade do BERT de treinar em pequenos conjuntos de dados pode ser útil;

  • O resultado do estado da arte na hora de trabalhar no projeto estava no modelo de arquitetura do Transformer, que foi pré-ensinado de forma bastante específica em um pequeno conjunto de dados ( 6 ). Foi interessante para nós compará-lo com o modelo baseado em BERT, que é pré-treinado de uma forma diferente, mas com muito mais dados.



Durante o semestre, tive que fazer o seguinte:



  • estudar a área temática;
  • encontre um conjunto de dados e selecione uma representação dos dados de entrada;
  • desenvolver um pipeline para treinamento e avaliação de qualidade;
  • faça experiências.


Dados



Existem vários conjuntos de dados abertos para esta tarefa, escolhi o mais filtrado ( 5 ).



O conjunto de dados foi coletado dos 1000 principais repositórios abertos do GitHub na linguagem Java. Após a filtragem, dos milhões de exemplos originais, restam cerca de 30 mil.



Os próprios exemplos são pares da saída do comando git diff e da mensagem curta correspondente em inglês. É mais ou menos assim:







As alterações e mensagens no conjunto de dados são curtas - não mais que 100 e 30 tokens, respectivamente.



Na maior parte do trabalho existente investigando o problema de geração automática de mensagens para commits, uma sequência de tokens do git diff é alimentada para os modelos.



Há outra ideia: selecionar explicitamente duas sequências, antes e depois das alterações, e alinhá-las usando o algoritmo clássico para o cálculo da distância editorial. Assim, os tokens alterados estão sempre nas mesmas posições.



Idealmente, gostaríamos de experimentar várias abordagens e entender como elas afetam a qualidade da solução deste problema. No estágio inicial, usei um bastante simples: duas sequências foram alimentadas para a entrada do modelo, antes e depois das alterações, mas sem nenhum alinhamento.



BERT para tarefas sequência a sequência



Os dados de entrada e saída para a tarefa de geração automática de mensagens para commits são sequências, cujo comprimento pode ser diferente.



Para resolver tais problemas, uma arquitetura de codificador-decodificador é geralmente usada, que consiste em dois componentes:



  • o modelo do codificador constrói uma representação vetorial com base na sequência de entrada,
  • o modelo-decodificador gera uma sequência de saída com base na representação vetorial.


O modelo BERT é baseado em um codificador da arquitetura do Transformer e por si só não é adequado para tal. Várias opções são possíveis para obter um modelo de sequência a sequência completo, a mais simples é usar algum tipo de decodificador com ele. Essa abordagem com um decodificador da arquitetura Transformer tem se mostrado bem, por exemplo, para a tarefa de tradução automática neural ( 7 ).



Pipeline



Para conduzir os experimentos, o código foi necessário para treinar e avaliar a qualidade de tal modelo sequência a sequência.



Para trabalhar com o modelo BERT, usei a biblioteca Transformers do HuggingFace, e para a implementação em geral, o framework PyTorch.



Como no início eu tinha pouca experiência com PyTorch, confiei amplamente nos exemplos existentes de modelos de sequência a sequência de outras arquiteturas, adaptando-me gradualmente às especificidades da minha tarefa. Infelizmente, essa abordagem resultou em muitos códigos de baixa qualidade.



Em algum momento, decidiu-se começar a refatorar, praticamente reescrevendo o pipeline. A biblioteca PyTorch Lightning ajudou a estruturar o código, o que permite coletar toda a lógica principal do modelo em um módulo e automatizá-lo de várias maneiras.



Experimentos



Durante os experimentos, queríamos entender se o uso do modelo BERT pré-treinado melhora o estado da arte dos resultados nesta área.



Dentre os modelos BERT treinados no código, apenas o CodeBERT ( 1 ) veio até nós , visto que apenas ele possuía a linguagem de programação Java nos exemplos de treinamento. Primeiro, usando CodeBERT como codificador, tentei decodificadores de diferentes arquiteturas:



  1. GRU.



    , - . GRU Transformer, , .

    - .
  2. Transformer.



    , — .



    , GPT-2 (8) — Transformer, , — distilGPT-2 (9).


Não houve tempo suficiente para novos experimentos no semestre de outono, continuei no inverno. Vimos várias outras maneiras de representar a entrada: tentamos alinhar as sequências antes e depois das alterações e também preenchemos um git diff.



Os principais resultados dos experimentos são os seguintes:











Resumindo



Em geral, a suposição sobre os benefícios do uso do CodeBERT para esta tarefa não foi confirmada; em todos os casos, o modelo do Transformer treinado do zero apresentou qualidade superior. O melhor método nesta área continua a ser o modelo CoreGen6: este também é um Transformer, mas adicionalmente pré-treinado usando a função objetivo proposta pelos autores.



Para resolver este problema, muitas outras idéias podem ser consideradas: por exemplo, tente a representação de dados com base em árvores de sintaxe abstratas, que é frequentemente usado ao trabalhar com código de programa ( 10 , 11), tente outros modelos pré-treinados ou faça algum pré-treinamento específico para o campo, se houver recursos disponíveis. No semestre da primavera, focamos na aplicação mais prática dos resultados obtidos e nos engajamos no autopreenchimento das mensagens aos commits. Vou falar sobre isso na segunda parte :)



Concluindo, quero dizer que foi muito interessante participar do projeto, mergulhei em uma nova área de estudo para mim e aprendi muito durante esse tempo. O trabalho no projeto foi muito bem organizado, pelo que muito obrigado aos meus líderes.



Obrigado pela atenção!



Fontes de



  1. Feng, Zhangyin, et al. "Codebert: um modelo pré-treinado para programação e linguagens naturais." 2020

  2. Buratti, Luca, et al. «Exploring Software Naturalness through Neural Language Models.» 2020
  3. Kanade, Aditya, et al. «Learning and Evaluating Contextual Embedding of Source Code.» 2020
  4. Jiang, Siyuan, Ameer Armaly, and Collin McMillan. «Automatically generating commit messages from diffs using neural machine translation.» 2017
  5. Liu, Zhongxin, et al. «Neural-machine-translation-based commit message generation: how far are we?.» 2018
  6. Nie, Lun Yiu, et al. «CoreGen: Contextualized Code Representation Learning for Commit Message Generation.» 2021
  7. Rothe, Sascha, Shashi Narayan, and Aliaksei Severyn. «Leveraging pre-trained checkpoints for sequence generation tasks.» 2020
  8. Radford, Alec, et al. «Language models are unsupervised multitask learners.» 2019
  9. Sanh, Victor, et al. «DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter.» 2019
  10. Yin, Pengcheng, et al. «Learning to represent edits.» 2018
  11. Kim, Seohyun, et al. «Code prediction by feeding trees to transformers.» 2021



All Articles