Simple Science

La science de pointe expliquée simplement

# Informatique# Génie logiciel# Intelligence artificielle

Automatiser l'amélioration des logiciels avec des LLM

Une nouvelle méthode utilise des LLM pour automatiser la correction de bugs et l'ajout de fonctionnalités.

― 21 min lire


LLMs dans la réparationLLMs dans la réparationde logicielsles mises à jour des programmes.la correction des bugs et améliorentDe nouvelles méthodes LLM automatisent
Table des matières

Ces dernières années, les chercheurs ont fait de grands progrès dans l'amélioration du développement de logiciels. Beaucoup de nouveaux outils et méthodes ont été créés pour aider les programmeurs avec des tâches comme résumer des problèmes, reproduire des bugs, trouver des défauts et réparer des programmes. Ces techniques automatisées aident à réduire la quantité de travail que les développeurs doivent faire. L'émergence d'outils avancés appelés Modèles de Langage de Grande Taille (LLMs) a changé la donne. Ces modèles peuvent servir d'assistants de programmation, permettant aux développeurs d'écrire du code sans beaucoup d'intervention humaine.

Cependant, l'ingénierie logicielle ne se résume pas seulement à écrire du code. Cela implique aussi de maintenir et de mettre à jour les logiciels, comme corriger des bugs et ajouter de nouvelles fonctionnalités. Cet article parle d'une méthode automatisée pour résoudre des problèmes sur GitHub, ce qui peut aider à améliorer les programmes de manière autonome. Notre approche utilise des LLMs combinés avec des techniques avancées de recherche de code, aboutissant à des modifications ou des correctifs pour le programme.

Contrairement à d'autres approches qui se concentrent uniquement sur la technologie LLM, notre objectif est l'ingénierie logicielle. Nous représentons les programmes avec un arbre de syntaxe abstraite (AST) plutôt que de les voir comme de simples collections de fichiers. Cela nous permet de mieux comprendre le problème en question et nous permet d'approfondir la structure du code.

Notre méthode utilise le format des classes et des méthodes pour améliorer la compréhension des problèmes sous-jacents par le modèle et pour récupérer le contexte de manière efficace. S'il existe une suite de tests disponible, nous pouvons également utiliser la localisation des défauts basée sur le spectre. Cette technique aide à identifier où se trouvent les bugs en analysant quels tests réussissent ou échouent. Nous avons étudié un ensemble de données appelé SWE-bench-lite, qui contient 300 problèmes GitHub réels nécessitant des corrections de bugs ou des ajouts de fonctionnalités. Nos expériences ont montré que notre approche était capable de résoudre 22-23 % de ces problèmes plus efficacement que les efforts récents de la communauté AI. Fait remarquable, nous avons réussi à résoudre 67 problèmes GitHub en moins de 12 minutes chacun, tandis que les développeurs prenaient généralement plus de 2,77 jours en moyenne pour corriger des problèmes similaires. Sur un ensemble de données plus large avec 2 294 problèmes, nous avons constaté que notre méthode a réussi à résoudre environ 16 % des problèmes, surpassant d'autres systèmes AI récents en termes d'efficacité et d'efficacité.

Au-delà de la programmation automatique

L'idée d'automatiser les tâches de développement logiciel a longtemps fasciné les ingénieurs logiciels et les chercheurs. Un défi majeur est d'interpréter correctement les exigences vagues en langage naturel qui apparaissent souvent lors de la programmation. Bien qu'il y ait eu quelques avancées dans des domaines connexes, comme la génération automatique de tests et la réparation automatique de programmes, l'émergence d'outils comme GitHub Copilot a suscité un nouvel intérêt pour la programmation automatique.

Cela soulève des questions importantes, comme de savoir si le code généré automatiquement peut être fiable lorsqu'il est intégré dans des projets existants. Sinon, quelles étapes peuvent être prises pour améliorer cette technologie ? Une possibilité est de créer des systèmes capables de réparer automatiquement le code généré, ce qui le rendrait plus fiable. Cela met en évidence la nécessité d'automatiser les tâches de réparation de programmes pour réaliser l'objectif global de l'ingénierie logicielle autonome.

Considérant combien de temps les programmeurs passent souvent à trouver et corriger manuellement les bugs, nous avons visé à enquêter sur l'amélioration automatique des programmes. Plus précisément, nous avons identifié la correction de bugs et l'ajout de fonctionnalités comme les deux principaux axes d'intervention pour maintenir les logiciels existants. Pour ce faire, nous avons développé une approche qui combine les LLMs avec des connaissances contextuelles obtenues à partir de dépôts de code.

Notre méthode peut être décrite comme suit : face à un problème GitHub réel, le LLM commence par traiter la description en langage naturel qui l'accompagne, en cherchant des mots-clés qui représentent des fichiers, des classes, des méthodes ou des extraits de code pertinents. Une fois ces mots-clés identifiés, nous employons une stratégie structurée pour que l'agent LLM recueille le contexte du code en invoquant plusieurs API de recherche de code pertinentes en même temps. Ces API fonctionnent localement sur la base d'une analyse AST, leur permettant de récupérer des informations importantes comme les signatures de classe et les détails d'implémentation des méthodes.

En tirant progressivement le contexte du code avec chaque recherche, le LLM affine sa compréhension du problème. Il vérifie s'il y a suffisamment de contexte projet avant de procéder à l'identification des emplacements où les bugs pourraient exister. Un deuxième agent LLM construit ensuite les correctifs nécessaires en fonction des zones problématiques et du contexte collecté jusqu'à ce point.

De plus, le modèle peut tirer parti de techniques de débogage comme la localisation des défauts basée sur le spectre lorsqu'une suite de tests est disponible. Cette analyse attribue des scores aux différentes méthodes dans le programme, indiquant leur probabilité de contenir des bugs. Le LLM peut concentrer sa recherche sur des méthodes spécifiques en fonction de ces informations.

Nous avons inspecté l'ensemble de données SWE-bench-lite, contenant 300 problèmes GitHub liés à des corrections de bugs et des demandes de fonctionnalités. Nos résultats expérimentaux ont montré que nous avons atteint un taux de réussite de 15,95 % dans la résolution des problèmes au sein du plus grand ensemble de données SWE-bench, ainsi qu'un taux de réussite de 22,33 % au sein du sous-ensemble SWE-bench-lite. Dans l'ensemble, nos résultats indiquent que notre approche contribue de manière significative à l'automatisation des tâches de réparation de programmes.

Littérature pertinente

La réparation automatique de programmes (APR) a attiré une attention considérable ces dernières années. Différentes techniques visent à générer des correctifs pour les logiciels défectueux afin qu'ils passent une suite de tests donnée. Cela inclut des méthodes basées sur la recherche, des méthodes basées sur la sémantique, et des méthodes basées sur des motifs ou l'apprentissage. Les approches basées sur la recherche impliquent généralement la génération de correctifs par des opérateurs de mutation de code prédéfinis, tandis que les techniques basées sur la sémantique formulent des contraintes de réparation basées sur les spécifications de la suite de tests. Les méthodes basées sur l'apprentissage exploitent de grands dépôts de code pour entraîner des modèles qui prédisent les jetons de code les plus appropriés pour les correctifs.

Des études récentes démontrent l'utilisation de LLMs pour la réparation automatique de programmes. Cette méthode suppose souvent que les déclarations de programme défectueuses sont connues et se concentre uniquement sur la génération de correctifs pour celles-ci. Cependant, identifier les emplacements des bugs dans des projets matures est un défi complexe et essentiel.

Bien que les techniques APR soient utilisées avec succès dans l'industrie pour la correction de bugs spécifiques à un domaine, elles ont encore des difficultés avec des problèmes logiciels réels. Beaucoup de ces techniques nécessitent des suites de tests de haute qualité, qui ne peuvent pas être trouvées dans tous les cas. De plus, elles n'exploitent pas les informations précieuses provenant des descriptions de problèmes en langage naturel. Pour relever ces défis et faire des progrès vers une ingénierie logicielle autonome, nous nous sommes concentrés sur la résolution de problèmes GitHub tirés de jeux de données réels.

Nous comprenons notre approche comme un point de référence qui évalue les capacités des Grands Modèles de Langage à gérer efficacement les tâches d'ingénierie logicielle quotidiennes. Chaque tâche dans notre ensemble de données sélectionné implique un problème GitHub associé à sa demande de tirage correspondante, qui comprend des insights de développeurs humains sur la façon de résoudre un problème donné.

Exemple motivant

Pour illustrer comment notre approche fonctionne, faisons un tour à travers un exemple spécifique. Nous prenons un système de suivi des problèmes, comme celui utilisé par Django, où une nouvelle demande de fonctionnalité a été soumise. La demande visait à ajouter une fonctionnalité à une classe spécifique appelée ModelChoiceField. La description du problème expliquait que la classe devait "montrer la valeur du choix invalide lors de la levée d'une erreur de validation."

Avec cette information, notre outil fonctionne en deux étapes : Récupération de contexte et génération de correctifs.

Dans la première étape, notre agent LLM collecte le contexte de code pertinent à partir de la base de code Django. Il commence par identifier des noms clés dans la description du problème, comme ModelChoiceField. Après avoir localisé les classes et méthodes possibles, l'agent invoque des API de recherche spécifiques pour rassembler des informations détaillées à leur sujet - comme leurs définitions et implémentations.

Avec le contexte collecté, l'agent passe à la deuxième étape : génération de correctifs. Il utilise les informations des étapes précédentes pour écrire un correctif qui incorpore la fonctionnalité requise.

Bien que le correctif final puisse différer du correctif du développeur en termes de style d'écriture, il doit parvenir à atteindre le même objectif et à passer les cas de test associés.

Cadre d'amélioration des programmes AI

Notre approche est conçue pour fonctionner dans le contexte du développement logiciel réel. Les utilisateurs signalent des problèmes liés à des bugs dans des dépôts de logiciels, et notre système analyse de manière autonome ces problèmes, récupère le contexte de code pertinent et génère des correctifs. Ces correctifs peuvent ensuite être vérifiés par des développeurs humains. Si nous pouvons automatiser un pourcentage significatif des problèmes que les développeurs gèrent actuellement, nous pouvons réduire le travail manuel et améliorer l'efficacité globale.

Le flux de travail global comprend plusieurs étapes. Tout d'abord, nous acceptons un rapport de problème contenant son titre et sa description en entrée, ainsi que le code de base du projet logiciel correspondant. À partir de l'énoncé en langage naturel, nous analysons les exigences pour mener à bien deux tâches principales. La première est la récupération de contexte, où nous utilisons un agent LLM pour parcourir une base de code potentiellement grande afin de trouver des extraits pertinents. Pour cela, nous avons développé une série d'API de récupération de contexte qui facilitent le processus.

Ces API permettent au modèle de recueillir des informations pertinentes sur le projet, telles que les signatures de classe et les implémentations de méthode. L'agent de récupération de contexte guide la recherche et détermine quelles API utiliser à chaque étape en fonction du contexte disponible.

Pour s'assurer que la recherche semble contrôlée et efficace, nous avons conçu une stratégie stratifiée pour invoquer les API de récupération. Cette approche permet à l'agent LLM de prendre des décisions en fonction de ce qui a déjà été récolté, raffinant ses méthodes de recherche au fur et à mesure.

Après avoir rassemblé suffisamment de contexte, nous passons à la génération de correctifs. Ici, un autre agent LLM extrait des extraits de code précis et crée un correctif pour traiter le problème initial. Si le correctif généré rencontre des problèmes, l'agent peut réessayer de créer un correctif valide tout en respectant un format prédéfini.

Nous soulignons que notre flux de travail ne nécessite pas de suites de tests pour fonctionner mais peut en bénéficier considérablement lorsqu'elles sont disponibles. Lorsque des tests existent, ils peuvent fournir des retours d'exécution précieux pour influencer la recherche de code pertinent et valider les correctifs générés.

APIs de récupération de contexte

L'étape de récupération de contexte repose sur une série d'APIs que les agents LLM utilisent pour rassembler des extraits pertinents de la base de code. Souvent, les utilisateurs fournissent des indices dans leurs descriptions de problèmes, qui peuvent être des noms de méthodes, classes, fichiers, ou même des extraits de code courts. Bien que ces indices ne soient pas toujours directement indicatifs des emplacements de modification, ils peuvent tout de même révéler un contexte important pour le problème en question.

Lorsque l'agent LLM invoque ces APIs, elles recherchent des classes, des méthodes et des extraits de code dans la base de code et retournent des résultats pertinents. Pour garder le contexte gérable et concentré, nous ne retournons que les informations nécessaires comme sorties. Par exemple, au lieu de récupérer des définitions de classes complètes, nous pourrions simplement fournir les signatures de classe pour éviter de submerger l'agent.

L'agent interagit avec ces APIs en leur fournissant la description du problème et la sortie attendue dans son prompt. Lorsque l'agent décide d'utiliser une API, il retourne une liste de noms d'API et les arguments correspondants. Les réponses de ces APIs sont collectées pour construire le contexte de code avec lequel l'agent LLM travaillera.

Recherche de contexte stratifiée

Notre processus de récupération de contexte n'est pas limité à un seul appel API. Par exemple, si un problème mentionne un nom de méthode, la recherche de l'implémentation de cette méthode pourrait sembler suffisante. Cependant, se concentrer sur une seule méthode pourrait conduire à un contexte incomplet. D'un autre côté, si l'agent exécute tous les appels d'API possibles à la fois, il pourrait recevoir une quantité écrasante de contexte, ce qui peut être difficile à traiter efficacement.

Au lieu de cela, nous préconisons un processus de recherche stratifié, qui permet à l'agent d'invoquer des APIs de manière itérative selon les besoins. Chaque strate commence avec le contexte actuel et s'y construit, tout en incitant l'agent LLM à sélectionner les appels d'API nécessaires. À mesure que les appels d'API retournent de nouveaux extraits de code, ces informations sont intégrées au contexte existant.

Ce processus itératif aide à affiner la compréhension du problème de manière progressive, permettant à l'agent LLM de se concentrer sur les classes et méthodes pertinentes, conduisant finalement à identifier les emplacements problématiques dans le code.

Récupération de contexte augmentée par analyse

Nous croyons que l'incorporation de techniques d'analyse de programme peut améliorer notre flux de travail. Une de ces techniques est la localisation des défauts basée sur le spectre (SBFL), qui découvre les emplacements de défauts potentiels dans le code en fonction des différences dans le flux de contrôle entre les tests réussis et échoués. Lorsqu'une suite de tests est disponible, il est utile d'utiliser le SBFL en conjonction avec notre méthode.

Au lieu de remplacer notre stratégie de récupération de contexte existante, nous utilisons le SBFL comme une étape augmentante. Avant que l'agent LLM n'entre dans la phase de récupération de contexte, nous fournissons les méthodes identifiées par le SBFL pour aider à orienter la recherche de code. Ces informations supplémentaires peuvent informer l'agent sur les emplacements de code potentiellement suspects qui pourraient correspondre à la description du problème.

En faisant des références croisées avec les résultats de l'analyse SBFL et la description actuelle du problème, l'agent LLM peut prioriser ses efforts de recherche sur des méthodes plus pertinentes. En conséquence, cette combinaison aide à rassembler un contexte plus précis pour résoudre le problème.

Génération de correctifs

Une fois le contexte suffisant rassemblé, nous entrons dans la phase de génération de correctifs. À ce stade, l'agent LLM exploite le contexte de code collecté pour rédiger un correctif traitant le problème décrit dans l'énoncé de problème. L'agent récupère des extraits de code spécifiques des emplacements défectueux identifiés et entre dans une boucle de réessai pour générer des correctifs.

Si un correctif généré ne correspond pas au format attendu ou ne peut pas être appliqué au code d'origine en raison d'erreurs de syntaxe, l'agent tentera à nouveau de créer un correctif approprié. Nous intégrons également des outils de linting pour vérifier des problèmes spécifiques, tels que des erreurs d'indentation, durant ce processus.

L'agent peut réessayer de générer un correctif jusqu'à un nombre prédéfini de tentatives. Une fois qu'il sort de la boucle de réessai, il retourne le correctif le plus prometteur qu'il a développé tout au long du processus.

Configuration de l'expérience

Pour évaluer l'efficacité de notre approche, nous l'avons mise en comparaison avec des méthodes récentes dans le but de déterminer à quel point elle résout des problèmes logiciels réels. Nous avons utilisé à la fois les ensembles de données SWE-bench et SWE-bench-lite, composés de 2 294 et 300 problèmes GitHub, respectivement.

Notre évaluation a pris en compte uniquement les descriptions en langage naturel fournies dans les problèmes GitHub originaux, ainsi que les dépôts de code défectueux correspondants. Nous avons comparé nos performances à deux systèmes établis pour évaluer l'efficacité.

Pour garantir des résultats fiables, nous avons effectué des expériences plusieurs fois et avons moyenné les résultats. Nos indicateurs d'évaluation comprenaient le pourcentage d'instances résolues, le coût moyen en temps et le coût moyen en jetons pour refléter l'efficacité et l'efficacité dans la résolution de problèmes du monde réel.

Efficacité globale

Nous avons commencé par mesurer l'efficacité globale de notre approche concernant le nombre d'instances de tâches résolues. Nous avons cherché à déterminer jusqu'où les systèmes AI actuels pouvaient résoudre automatiquement les problèmes logiciels quotidiens en utilisant uniquement les descriptions en langage naturel et les dépôts de code locaux.

Dans nos expériences, nous avons atteint un taux de réussite de 15,95 % pour résoudre des problèmes au sein de l'ensemble de données complet SWE-bench et un remarquable 22,33 % sur le sous-ensemble SWE-bench-lite, montrant l'efficacité de notre méthode. Nous avons également comparé nos résultats avec d'autres systèmes et avons constaté que notre approche surclassait les autres en termes à la fois d'efficacité et d'efficacité temporelle.

Par exemple, nous avons résolu 67 problèmes en moins de 12 minutes chacun. En revanche, les développeurs prenaient généralement en moyenne plus de 2,77 jours pour corriger des problèmes similaires. Nos résultats indiquent clairement les avantages potentiels de l'automatisation des processus de réparation logiciel.

Correctifs plausibles et corrects

La qualité des correctifs générés est une considération critique dans la réparation automatique de programmes. Un correctif plausible passe la suite de tests pertinente, tandis qu'un correctif correct est identifiable comme étant sémantiquement équivalent à la solution prévue par le développeur. Pour évaluer la qualité des correctifs, nous avons vérifié manuellement la correction des correctifs générés par notre approche.

À travers notre analyse, nous avons constaté qu'environ 65,7 % des correctifs produits par notre système étaient corrects, tandis que d'autres ne répondaient pas aux normes souhaitées. En comparaison, les systèmes de référence ont rapporté un taux de correction légèrement plus élevé. Cela indique que, bien que notre méthode montre des promesses, il y a encore de la place pour améliorer la génération de correctifs de haute qualité.

Effet du SBFL

Pour comprendre les avantages de l'utilisation de techniques d'analyse de programmes comme le SBFL, nous avons réalisé des expériences pour comparer les cas avec et sans informations SBFL lors de la phase de récupération de contexte. Nos résultats ont indiqué que l'incorporation du SBFL a conduit à des taux de réussite accrus dans la résolution des tâches.

Lorsque des informations SBFL étaient disponibles, notre approche a pu résoudre plus d'instances de tâches uniques que lorsqu'elle s'appuyait uniquement sur la validation des correctifs générés. Cela suggère que la combinaison de plusieurs techniques peut donner de meilleurs résultats et finalement conduire à une amélioration plus efficace des programmes.

Défis dans les tâches de la vie réelle

Nous avons examiné les instances de tâches qui n'ont pas été résolues avec succès et les avons classées pour découvrir les difficultés pratiques à réaliser une amélioration logicielle entièrement automatisée.

Notre classification a mis en évidence des problèmes rencontrés tant pendant les étapes de localisation des défauts que de génération de correctifs. Un nombre significatif de tâches impliquait des cas où le correctif généré modifiait les bonnes méthodes mais ne produisait pas de résultat valide. Cela indique qu'une analyse et un guidage plus fins sont nécessaires pour de futures améliorations.

D'autres catégories ont émergé où des correctifs ont été générés aux mauvais emplacements ou impliquaient des modifications de fichiers incorrects dans leur ensemble. Ces échecs proviennent souvent d'informations insuffisantes dans les descriptions de problèmes, ce qui indique qu'un certain niveau d'intervention humaine pourrait être bénéfique pour traiter ces cas complexes.

Discussion sur les améliorations

En réfléchissant aux possibilités d'améliorations futures pour notre système, nous pouvons identifier plusieurs axes de croissance et d'avancement. Par exemple, une direction prometteuse consiste à créer un test de reproduction de bug basé sur les descriptions de problèmes initiales. Ce test pourrait valider la correction des correctifs générés et éventuellement déclencher un processus de régénération si nécessaire.

En outre, nous pourrions exploiter plus efficacement la sémantique de programme pour informer les processus de récupération de contexte, en utilisant des outils d'analyse statique pour identifier des méthodes supplémentaires pertinentes. En intégrant des outils de codage avancés, l'agent de récupération de contexte pourrait naviguer plus efficacement dans la base de code.

Enfin, favoriser une relation collaborative entre les agents LLM et les développeurs humains est vital pour améliorer le flux de travail global. Permettre une intervention humaine dans les processus décisionnels peut aider le système à surmonter des obstacles et à traiter des problèmes difficiles plus efficacement.

Conclusion

L'intégration des technologies LLM dans l'ingénierie logicielle présente une opportunité puissante d'améliorer la façon dont les logiciels sont développés et maintenus. En automatisant des aspects clés de l'amélioration des programmes, comme la correction des bugs et l'ajout de fonctionnalités, nous pouvons réduire considérablement le fardeau des développeurs et rationaliser les flux de travail.

Notre approche proposée se concentre sur l'exploitation de la représentation des programmes, de la recherche de code itérative et de la localisation des défauts basée sur les tests pour améliorer l'efficacité et l'efficacité de la réparation automatique des programmes. Bien que nos résultats démontrent un potentiel considérable, des améliorations supplémentaires dans la qualité des correctifs et les capacités de récupération de contexte sont nécessaires.

Alors que nous avançons dans une industrie logicielle de plus en plus dépendante des outils pilotés par l'IA, il sera important de veiller à ce que ces systèmes favorisent la confiance et la collaboration entre les développeurs humains et les agents automatisés, ouvrant la voie à un avenir plus efficace dans le développement logiciel.

Source originale

Titre: AutoCodeRover: Autonomous Program Improvement

Résumé: Researchers have made significant progress in automating the software development process in the past decades. Recent progress in Large Language Models (LLMs) has significantly impacted the development process, where developers can use LLM-based programming assistants to achieve automated coding. Nevertheless, software engineering involves the process of program improvement apart from coding, specifically to enable software maintenance (e.g. bug fixing) and software evolution (e.g. feature additions). In this paper, we propose an automated approach for solving GitHub issues to autonomously achieve program improvement. In our approach called AutoCodeRover, LLMs are combined with sophisticated code search capabilities, ultimately leading to a program modification or patch. In contrast to recent LLM agent approaches from AI researchers and practitioners, our outlook is more software engineering oriented. We work on a program representation (abstract syntax tree) as opposed to viewing a software project as a mere collection of files. Our code search exploits the program structure in the form of classes/methods to enhance LLM's understanding of the issue's root cause, and effectively retrieve a context via iterative search. The use of spectrum-based fault localization using tests, further sharpens the context, as long as a test-suite is available. Experiments on SWE-bench-lite (300 real-life GitHub issues) show increased efficacy in solving GitHub issues (19% on SWE-bench-lite), which is higher than the efficacy of the recently reported SWE-agent. In addition, AutoCodeRover achieved this efficacy with significantly lower cost (on average, $0.43 USD), compared to other baselines. We posit that our workflow enables autonomous software engineering, where, in future, auto-generated code from LLMs can be autonomously improved.

Auteurs: Yuntong Zhang, Haifeng Ruan, Zhiyu Fan, Abhik Roychoudhury

Dernière mise à jour: 2024-07-25 00:00:00

Langue: English

Source URL: https://arxiv.org/abs/2404.05427

Source PDF: https://arxiv.org/pdf/2404.05427

Licence: https://creativecommons.org/licenses/by/4.0/

Changements: Ce résumé a été créé avec l'aide de l'IA et peut contenir des inexactitudes. Pour obtenir des informations précises, veuillez vous référer aux documents sources originaux dont les liens figurent ici.

Merci à arxiv pour l'utilisation de son interopérabilité en libre accès.

Plus d'auteurs

Articles similaires