paint-brush
Aprimorando mutações de melhoria genética usando grandes modelos de linguagemby@escholar
453
453

Aprimorando mutações de melhoria genética usando grandes modelos de linguagem

Este artigo explora a aplicação de grandes modelos de linguagem (LLMs) no melhoramento genético (GI) na engenharia de software por meio de avaliação experimental. Os insights revelam o impacto dos LLMs em técnicas baseadas em pesquisa, reparo de programas e geração de código, com foco no projeto JCodec. Descubra como as mutações do LLM melhoram os processos de desenvolvimento de software.
featured image - Aprimorando mutações de melhoria genética usando grandes modelos de linguagem
EScholar: Electronic Academic Papers for Scholars HackerNoon profile picture

Autores:

(1) Alexander EI Brownlee, Universidade de Stirling, Reino Unido;

(2) James Callan, University College London, Reino Unido;

(3) Karine Even-Mendoza, King's College London, Reino Unido;

(4) Alina Geiger, Universidade Johannes Gutenberg Mainz, Alemanha;

(5) Carol Hanna, University College London, Reino Unido;

(6) Justyna Petke, University College London, Reino Unido;

(7) Federica Sarro, University College London, Reino Unido;

(8) Dominik Sobania, Universidade Johannes Gutenberg Mainz, Alemanha.

Visão geral do conteúdo

  • Abstrato
  • Introdução
  • Configuração Experimental
  • Resultados
  • Conclusões e Trabalho Futuro
  • Referências

Abstrato

Grandes modelos de linguagem (LLMs) foram aplicados com sucesso a tarefas de engenharia de software, incluindo reparo de programas. No entanto, a sua aplicação em técnicas baseadas em pesquisa, como o Melhoramento Genético (GI), ainda é largamente inexplorada. Neste artigo, avaliamos o uso de LLMs como operadores de mutação para GI para melhorar o processo de busca. Expandimos o kit de ferramentas Gin Java GI para chamar a API do OpenAI para gerar edições para a ferramenta JCodec. Amostramos aleatoriamente o espaço de edições usando 5 tipos de edição diferentes. Descobrimos que o número de patches que passam em testes de unidade é até 75% maior com edições baseadas em LLM do que com edições de Inserção padrão. Além disso, observamos que os patches encontrados nos LLMs são geralmente menos diversos em comparação com as edições padrão. Executamos o GI com pesquisa local para encontrar melhorias no tempo de execução. Embora muitos patches de melhoria sejam encontrados pelo GI aprimorado com LLM, o melhor patch de melhoria foi encontrado pelo GI padrão.


Introdução

À medida que os sistemas de software se tornam maiores e mais complexos, é necessário um esforço manual significativo para mantê-los [2]. Para reduzir o esforço do desenvolvedor em tarefas de manutenção e otimização de software, paradigmas automatizados são essenciais. O Melhoramento Genético (GI) [15] aplica técnicas baseadas em pesquisa para melhorar propriedades não funcionais de software existente, como tempo de execução, bem como propriedades funcionais, como reparo de bugs. Embora a IG tenha tido sucesso na indústria [12,13], ela permanece limitada pelo conjunto de operadores de mutação que emprega na pesquisa [14].


Os Large Language Models (LLMs) têm uma ampla gama de aplicações, pois são capazes de processar consultas textuais sem treinamento adicional para a tarefa específica em questão. Os LLMs foram pré-treinados em milhões de repositórios de código abrangendo muitas linguagens de programação diferentes [5]. Seu uso para tarefas de engenharia de software teve grande sucesso [9,6], mostrando-se promissor também para reparo de programas [17,19].


Kang e Yoo [10] sugeriram que existe um potencial inexplorado no uso de LLMs para melhorar a IG. GI usa os mesmos operadores de mutação para diferentes tarefas de otimização. Esses operadores são elaborados manualmente antes do início da pesquisa e, portanto, resultam em um espaço de pesquisa limitado. Nossa hipótese é que aumentar as sugestões de patches LLM como um operador de mutação adicional enriquecerá o espaço de busca e resultará em variantes mais bem-sucedidas.


Neste artigo, conduzimos vários experimentos para explorar se o uso de LLMs como operador de mutação em GI pode melhorar a eficiência e eficácia da busca. Nossos resultados mostram que os patches gerados pelo LLM têm taxas de compilação de 51,32% e 53,54% para busca aleatória e busca local, respectivamente (com a categoria de prompt Médio). Anteriormente, foi demonstrado que LLMs (usando um modelo LLM como está) produziam código que compilava aproximadamente 40% do tempo [16,18]. Descobrimos que edições baseadas em LLM amostradas aleatoriamente compilaram e passaram em testes de unidade com mais frequência em comparação com edições GI padrão. Observamos que o número de patches que passam em testes de unidade é até 75% maior para edições baseadas em LLM do que para edições de GI Insert. No entanto, observamos que os patches encontrados nos LLMs são menos diversos. Para pesquisa local, a melhor melhoria é alcançada usando edições padrão de GI Statement, seguidas por edições baseadas em LLM. Estas descobertas demonstram o potencial dos LLMs como operadores de mutação e destacam a necessidade de mais pesquisas nesta área.


Configuração Experimental

Para analisar o uso de LLMs como operador de mutação em GI, utilizamos o modelo GPT 3.5 Turbo da OpenAI e a caixa de ferramentas GI Gin [3]. Experimentamos dois tipos de busca implementados no Gin: busca aleatória e busca local. As solicitações ao LLM utilizando a API OpenAI foram via biblioteca Langchain4J, com temperatura de 0,7. O projeto alvo de melhoria em nossos experimentos foi o popular projeto JCodec [7] que é escrito em Java. Os métodos 'quentes' a serem alvo das edições foram identificados usando a ferramenta profiler do Gin, repetindo o perfil 20 vezes e realizando a união do conjunto resultante.


Para os experimentos de amostragem aleatória, configuramos as execuções com edições em nível de instrução (copiar/excluir/substituir/trocar de [14] e inserir quebra/continuar/retornar de [4]) e edições LLM, gerando 1000 de cada tipo aleatoriamente . Um tempo limite de 10.000 milissegundos foi usado para cada teste de unidade para capturar loops infinitos introduzidos pelas edições; exceder o tempo limite conta como uma falha no teste. Para busca local, os experimentos foram montados de forma semelhante. Houve 10 execuções repetidas (uma para cada um dos 10 principais métodos), mas as execuções foram limitadas a 100 avaliações, resultando em 1.000 avaliações no total, correspondendo à pesquisa aleatória. Na prática, foram 99 edições por execução, já que a primeira foi usada para cronometrar o código original sem patch.


Experimentamos três prompts diferentes para enviar solicitações ao LLM para ambos os tipos de pesquisa: um prompt simples, um prompt médio e um prompt detalhado. Com todos os três prompts, nossa implementação solicita cinco variações diferentes do código em questão. O prompt simples solicita apenas o código sem qualquer informação adicional. O prompt médio fornece mais informações sobre o código fornecido e os requisitos, conforme mostrado na Figura 1. Especificamente, fornecemos ao LLM a linguagem de programação utilizada, o projeto ao qual o código pertence, bem como instruções de formatação. O prompt detalhado estende o prompt médio com um exemplo de mudança útil. Este exemplo foi retirado dos resultados obtidos por Brownlee et al. [4]. O patch é uma instância bem-sucedida da edição de inserção aplicada ao projeto jCodec (ou seja, uma edição que compilou, passou nos testes de unidade e ofereceu uma aceleração em relação ao código original). Usamos o mesmo exemplo para todas as solicitações de prompt detalhadas usadas em nossos experimentos; isso ocorre porque os LLMs são capazes de raciocínio indutivo onde o usuário apresenta informações específicas, e o LLM pode usar essa entrada para gerar declarações mais gerais, melhoradas ainda mais no GPT-4 [8].



Figura 1. O prompt médio para solicitações LLM, com quebras de linha adicionadas para facilitar a leitura.



As edições do LLM são aplicadas selecionando aleatoriamente uma instrução de bloco em um método de destino 'quente'. O conteúdo deste bloco está in the prompt. The first code block in the LLM response is identified. Gin uses JavaParser (https://javaparser.org) internally to represent target source files, so we attempt to parse the LLM suggestion with JavaParser, and replace the original block with the LLM suggestion.


Resultados

O primeiro experimento compara mutações GI padrão, ou seja, edições de Inserção e Declaração, com edições LLM usando prompts detalhados de forma diferente (Simples, Médio e Detalhado) usando Amostragem Aleatória. A Tabela 1 mostra os resultados para todos os patches, bem como apenas para patches únicos. Relatamos quantos patches foram analisados com sucesso pelo JavaParser (denominados como Válidos), quantos foram compilados e quantos passaram em todos os testes de unidade (denominados como Aprovados). Excluímos patches sintaticamente equivalentes ao software original. Os melhores resultados estão em negrito .


Vemos que, embora tenham sido encontrados patches substancialmente mais válidos com as edições padrão de Insert e Statement, mais patches de passagem puderam ser encontrados usando as edições geradas pelo LLM. Em particular, para os prompts Médio e Detalhado, 292 e 230 patches passaram nos testes de unidade, respectivamente. Para as edições Insert e Statement apenas 166 e 91 passaram nos testes de unidade, respectivamente. Curiosamente, os métodos quentes com taxas de passagem de patch mais baixas/mais altas diferiram para cada operador: compreender esta variação será interessante para investigações futuras.


Também é notável que os patches LLM são menos diversos: mais de 50% mais patches exclusivos foram encontrados pelos operadores de mutação padrão do que o LLM usando Medium,



Tabela 1. Resultados do nosso experimento de amostragem aleatória. Excluímos patches sintaticamente equivalentes ao software original nesta tabela. Para todos os patches únicos, relatamos: quantos patches passaram no JavaParser, compilaram e passaram em todos os testes de unidade.




Tabela 2. Resultados da Pesquisa Local. Excluímos todos os patches vazios. Relatamos quantos patches foram compilados, passaram em todos os testes de unidade e quantos levaram a melhorias no tempo de execução. Relatamos a melhor melhoria encontrada e a melhoria mediana entre os patches de melhoria.



e prompts detalhados. Com o prompt Simple, entretanto, nem um único patch passou nos testes de unidade, já que as edições sugeridas muitas vezes não podiam ser analisadas. Assim, instruções detalhadas são necessárias para forçar o LLM a gerar resultados utilizáveis.


Investigamos mais detalhadamente as diferenças entre os prompts Médio e Detalhado para entender a redução no desempenho com o Detalhado (nos conjuntos de patches exclusivos), já que o Médio tinha um número maior de patches compilados e aprovados. Em ambos os níveis de prompt, a resposta gerada foi a mesma para 42 casos (do total de casos únicos válidos). Porém, o Detalhado tendeu a gerar respostas mais longas com média de 363 caracteres, enquanto o Médio teve em média 304 caracteres. Examinamos manualmente várias respostas de prompt detalhadas, nas quais identificamos algumas incluindo variáveis de outros arquivos, oferecendo potencialmente uma expansão significativa do conjunto de variantes de código que o GI pode explorar.


O segundo experimento expande nossa análise, comparando o desempenho das edições padrão e LLM com Pesquisa Local. A Tabela 2 mostra os resultados do experimento de Pesquisa Local. Relatamos o número de patches de compilação e passagem, bem como o número de patches onde foram encontradas melhorias no tempo de execução. Além disso, relatamos a mediana e a melhor melhoria em milissegundos (ms). Na tabela, excluímos todos os patches vazios. Como antes, os melhores resultados estão em negrito .


Novamente, vemos que mais patches que passaram nos testes de unidade podem ser encontrados com o LLM usando os prompts Médio e Detalhado. Além disso, mais melhorias poderiam ser encontradas usando o LLM com essas instruções. Especificamente, com Médio e Detalhado, encontramos 164 e 196 melhorias, respectivamente, enquanto encontramos apenas 136 com Inserir e 71 com Declaração. A melhor melhoria pode ser encontrada em 508 ms com a edição do Statement. A melhor melhoria encontrada usando LLMs (usando o prompt Médio) só foi capaz de melhorar o tempo de execução em 395 ms. Também examinamos uma série de edições nos resultados da pesquisa local para obter insights sobre as distinções entre prompts médios e detalhados devido à baixa taxa de compilação das respostas dos prompts detalhados. No exemplo, uma sequência de edições teve como objetivo incorporar uma chamada ao clipe de função. O prompt detalhado tentou incorporar a chamada quase imediatamente em algumas edições, provavelmente levando a um código inválido. Por outro lado, o prompt do Medium fez mudanças menos radicais, refinando gradativamente o código. Ele começou substituindo a expressão do operador ternário por uma instrução if-then-else e chamadas de função do sistema antes de finalmente tentar incorporar a chamada de função clip.


Conclusões e Trabalho Futuro

O melhoramento genético de software é altamente dependente dos operadores de mutação que utiliza no processo de busca. Para diversificar os operadores e enriquecer ainda mais o espaço de busca, incorporamos um Large Language Model (LLM) como operador.


Limitações . Para generalizar, trabalhos futuros devem considerar projetos além do nosso alvo, jCodec. Nossos experimentos usaram uma API que não nos dá controle sobre as respostas geradas pelo LLM ou qualquer forma de modificá-las ou otimizá-las. Embora não tenhamos observado mudanças de comportamento durante nossos experimentos, a OpenAI pode alterar o modelo a qualquer momento, portanto, trabalhos futuros devem considerar modelos locais. Experimentamos apenas três tipos de prompt para solicitações LLM e, dentro desse número limitado de prompts, encontramos uma variação nos resultados. Finalmente, a nossa implementação para analisar as respostas dos LLMs foi relativamente simplista. No entanto, isto significaria apenas que os nossos resultados relatados são pessimistas e uma melhoria ainda maior poderia ser alcançada pelo operador baseado em LLM.


Resumo . Descobrimos que, embora patches mais válidos e diversos tenham sido encontrados com edições padrão usando amostragem aleatória, mais patches que passaram nos testes de unidade foram encontrados com edições baseadas em LLM. Por exemplo, com a edição LLM usando o prompt Medium, encontramos mais de 75% mais patches passando nos testes de unidade do que com a edição Insert clássica. Em nosso experimento de pesquisa local, encontramos a melhor melhoria com a edição da declaração (508 ms). A melhor melhoria baseada no LLM foi encontrada com o prompt Médio (395 ms). Portanto, há potencial para explorar abordagens que combinem LLM e edições GI 'clássicas'.


Nossos experimentos revelaram que os prompts usados para solicitações LLM afetam muito os resultados. Assim, em trabalhos futuros, esperamos experimentar mais com engenharia imediata. Também pode ser útil misturar prompts: por exemplo, começando com médio e depois mudando para detalhado para fazer edições maiores que ultrapassem os mínimos locais. Além disso, a possibilidade de combinar edições LLM com outras, como copiar/excluir/substituir/trocar padrão ou modelos PAR [11], pode ser interessante. Finalmente, esperamos realizar experimentações mais extensas em programas de teste adicionais.


Disponibilidade de dados. O código, a infraestrutura experimental e imediata dos LLMs, os dados da avaliação e os resultados estão disponíveis como código aberto em [1]. O código também está na ramificação 'llm' de github.com/gintool/gin (commit 9fe9bdf; ramificado do master commit 2359f57 pendente de integração total com Gin).


Agradecimentos UKRI EPSRC EP/P023991/1 e ERC 741278.

Referências

  1. Artefato para melhorar mutações de melhoria genética usando grandes modelos de linguagem. Zenodo (setembro de 2023). https://doi.org/10.5281/zenodo.8304433


  2. B¨ohme, M., Soremekun, EO, Chattopadhyay, S., Ugherughe, E., Zeller, A.: Onde está o bug e como ele foi corrigido? Um experimento com praticantes. Em: Proc. Simpósio ACM sobre os Fundamentos da Engenharia de Software. págs. 117–128 (2017)


  3. Brownlee, AE, Petke, J., Alexander, B., Barr, ET, Wagner, M., White, DR: Gin: pesquisa de melhoramento genético facilitada. In: GECO. páginas 985–993 (2019)


  4. Brownlee, AE, Petke, J., Rasburn, AF: Injetando atalhos para execução mais rápida de código Java. In: IEEE CEC 2020. p. 1–8


  5. Chen, M., Tworek, J., Jun, H., Yuan, Q., Pinto, HPdO, Kaplan, J., Edwards, H., Burda, Y., Joseph, N., Brockman, G., e outros al.: Avaliando grandes modelos de linguagem treinados em código. Pré-impressão arXiv arXiv:2107.03374 (2021)


  6. Fan, A., Gokkaya, B., Harman, M., Lyubarskiy, M., Sengupta, S., Yoo, S., Zhang, JM: Grandes modelos de linguagem para engenharia de software: Pesquisa e problemas abertos (2023)

  7. Github - jcodec/jcodec: repositório principal Jcodec, https://github.com/jcodec/jcodec


  8. Han, SJ, Ransom, KJ, Perfors, A., Kemp, C.: Raciocínio indutivo em humanos e grandes modelos de linguagem. Pesquisa de Sistemas Cognitivos p. 101155 (2023)


  9. Hou, X., Liu, Y., Yang, Z., Grundy, J., Zhao, Y., Li, L., Wang, K., Luo, X., Lo, D., Wang, H.: Grandes modelos de linguagem para engenharia de software: uma revisão sistemática da literatura. arXiv:2308.10620 (2023)


  10. Kang, S., Yoo, S.: Rumo ao melhoramento genético personalizado por meio de grandes modelos de linguagem. arXiv:2304.09386 (2023)


  11. Kim, D., Nam, J., Song, J., Kim, S.: Geração automática de patches aprendida com patches escritos por humanos (2013), http://logging.apache.org/log4j/


  12. Kirbas, S., Windels, E., Mcbello, O., Kells, K., Pagano, M., Szalanski, R., Nowack, V., Winter, E., Counsell, S., Bowes, D., Hall, T., Haraldsson, S., Woodward, J.: Sobre a introdução do reparo automático de programas em Bloomberg. Software IEEE 38(4), 43–51 (2021)


  13. Marginean, A., Bader, J., Chandra, S., Harman, M., Jia, Y., Mao, K., Mols, A., Scott, A.: Sapfix: Reparo automatizado de ponta a ponta em escala. In: ICSE-SEIP. págs. 269–278 (2019)


  14. Petke, J., Alexander, B., Barr, ET, Brownlee, AE, Wagner, M., White, DR: Cenários de transformação de programas para modificação automatizada de programas usando Gin. Engenharia de Software Empírica 28(4), 1–41 (2023)


  15. Petke, J., Haraldsson, SO, Harman, M., Langdon, WB, White, DR, Woodward, JR: Melhoramento genético de software: Uma pesquisa abrangente. Transações IEEE em Computação Evolucionária 22, 415–432 (2018)


  16. Siddiq, ML, Santos, J., Tanvir, RH, Ulfat, N., Rifat, FA, Lopes, VC: Explorando a eficácia de grandes modelos de linguagem na geração de testes unitários. Pré-impressão arXiv arXiv:2305.00418 (2023)


  17. Sobania, D., Briesch, M., Hanna, C., Petke, J.: Uma análise do desempenho de correção automática de bugs do chatgpt. In: Workshop Internacional IEEE/ACM 2023 sobre Reparo Automatizado de Programas (APR). páginas 23–30. Sociedade de Computação IEEE (2023)


  18. Xia, CS, Paltenghi, M., Tian, JL, Pradel, M., Zhang, L.: Fuzzing universal por meio de grandes modelos de linguagem. Pré-impressão arXiv arXiv:2308.04748 (2023)


  19. Xia, CS, Zhang, L.: Continue a conversa: corrigindo 162 de 337 bugs por US$ 0,42 cada usando chatgpt. Pré-impressão arXiv arXiv:2304.00385 (2023)




Este artigo está disponível no arxiv sob licença CC 4.0.