Comment les grands modèles de langage peuvent-ils écrire COBOL ? L'opportunité de générer du COBOL pour les LLM est énorme, d'après Gabriel Gordon-Hall de Bloop.
Gabriel Gordon-Hall, chercheur et rédacteur à Bloop, évalue les grands modèles de langage (LLM) sur COBOL. Il présente COBOLEval, le premier benchmark d'évaluation des LLM pour les complétions de code en COBOL. Il répond notamment à la question sur "Comment les LLM peuvent-ils écrire COBOL ?".
Les LLM sont en train de changer rapidement la façon dont on écrit les logiciels. Plus d'un million de développeurs paient maintenant pour GitHub Copilot et les récentes percées dans le raisonnement LLM ont rapproché le rêve d'un ingénieur logiciel entièrement IA de la réalité. Mais s'il n'est pas difficile de trouver une démo d'un LLM codant un site web ou un clone de Flappy Bird, on ne sait pas grand-chose de leur capacité à écrire du code dans des langages plus anciens comme le COBOL.
L'opportunité pour la génération LLM COBOL est énorme. Bien que le langage ait été publié pour la première fois en 1959, il continue à alimenter des systèmes critiques - 95 % des transactions des distributeurs automatiques de billets aux États-Unis sont traitées en COBOL. Mais il n'est pas enseigné dans les cours d'informatique ou dans les camps d'entraînement, et les ingénieurs qui l'écrivent professionnellement partent régulièrement à la retraite. Si les LLM pouvaient comprendre et écrire le COBOL, ils pourraient aider à maintenir les 800 milliards de lignes encore en production aujourd'hui.
Dans quelle mesure les LLM peuvent-ils écrire COBOL ? Pour autant qu'on le sait, personne n'a essayé de répondre publiquement à cette question. Jusqu'à présent...
Présentation de COBOLEval
Aujourd'hui, Bloop publie COBOLEval, le premier benchmark d'évaluation des LLM pour les complétions de code en COBOL. Il se compose de 146 problèmes de codage difficiles qui ont été convertis en COBOL à partir du benchmark de génération HumanEval Python largement utilisé. Chaque problème est associé à une moyenne de 6 cas de test. Une solution générée par LLM doit tous les réussir pour être correcte. Bloop puble également un harnais de test que vous pouvez utiliser pour évaluer vos propres modèles, ainsi que mAInframer-1 - une série de modèles open-source basés sur CodeLlama qu'ils ont affinés spécifiquement pour écrire du COBOL - qui surpassent GPT-4.
De HumanEval à COBOLEval
Les fonctions
Convertir HumanEval en COBOL n'est pas aussi simple qu'il n'y paraît. Chaque problème HumanEval se compose d'une invite, d'une signature de fonction Python typée et d'une docstring, qui est transmise directement à un LLM, qui implémente ensuite le corps de la fonction.
Mais cela pose immédiatement un problème. COBOL est un langage de programmation procédural ; il n'a pas de fonctions.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 from typing import List def has_close_elements(numbers: List[float], threshold: float) -> bool: """ Check if in given list of numbers, are any two numbers closer to each other than given threshold. >>> has_close_elements([1.0, 2.0, 3.0], 0.5) False >>> has_close_elements([1.0, 2.8, 3.0, 4.0, 5.0, 2.0], 0.3) True """
Il possède cependant des sous-programmes. Nous transformons donc chaque problème en un programme COBOL dans lequel les arguments et les variables de retour sont définis dans la SECTION DE LIEN afin qu'ils puissent être transmis et lus à partir d'un programme appelant.C'est le format des invites COBOLEval qui sont transmises au LLM.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 IDENTIFICATION DIVISION. PROGRAM-ID. HAS-CLOSE-ELEMENTS. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. DATA DIVISION. LINKAGE SECTION. 01 LINKED-ITEMS. 05 L-NUMBERS OCCURS 100 TIMES INDEXED BY NI COMP-2. 05 L-THRESHOLD COMP-2. 05 RESULT PIC 9. * Check if in given list of numbers, are any two numbers closer to each other than * given threshold. * >>> has_close_elements([1.0, 2.0, 3.0], 0.5) * False * >>> has_close_elements([1.0, 2.8, 3.0, 4.0, 5.0, 2.0], 0.3) * True * * Complete the WORKING-STORAGE SECTION and the PROCEDURE DIVISION * Store the result in the RESULT variable and mark the end of your program with END PROGRAM WORKING-STORAGE SECTION.
Les types
Le système de types de COBOL est radicalement différent de celui des langages de programmation modernes. Les variables sont déclarées avec des clauses PICTURE (PIC en abrégé) qui précisent le nombre de caractères qu'elles occupent en mémoire. Par exemple, PIC X(100) est une chaîne de 100 caractères, tandis que PIC S9(10) est un entier signé de 10 chiffres.
Contrairement à Python, COBOL n'a pas de chaînes, d'entiers ou de tableaux de longueur variable, nous fixons donc ces longueurs à des limites supérieures (aucun problème COBOLEval n'accepte ou ne renvoie un tableau d'une longueur supérieure à 100). Nous obtenons ainsi notre correspondance entre les types Python et COBOL.Notez que certains types Python, comme Any ou Dict, ne peuvent pas être facilement représentés en COBOL. Ils ont ignoré les problèmes HumanEval qui les acceptent ou les renvoient. Heureusement, ils ne sont pas nombreux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 Int => PIC S9(10) Float => COMP-2 Str => PIC X(100) List[Int] => OCCURS 100 TIMES INDEXED BY I PIC S9(10)
Section sur le stockage de travail
Les programmeurs COBOL chevronnés auront repéré un bogue dans le programme d'invite ci-dessus. La SECTION DE LIEN et la SECTION DE STOCKAGE DE TRAVAIL sont inversées. Si on essaits de le compiler, on obtient une erreur.
Pourquoi sont-elles dans le mauvais ordre ? Le problème est que - contrairement aux langages modernes (vous avez l'habitude de l'entendre maintenant) - COBOL n'a pas de variables locales. Toutes les variables - même les variables temporaires - utilisées dans la logique du programme doivent être déclarées à l'avance dans la SECTION DE TRAVAIL.
Il est clair que le LLM doit générer la SECTION DE TRAVAIL afin de pouvoir déclarer les variables qu'il utilisera dans sa solution. Mais en même temps, il doit connaître les variables qui ont déjà été déclarées dans la SECTION DE LIAISON. La structure stricte de COBOL empêche un LLM de générer des solutions dans un ordre précis de gauche à droite.
Si on veut remplir la troisième ligne de cette fonction PythonNous proposons deux approches possibles. (La première est illustrée ci-dessus) Nous intervertissons l'ordre des sections dans l'invite et demandons au modèle de générer la SECTION DU STOCKAGE DE TRAVAIL et la DIVISION DE LA PROCÉDURE l'une après l'autre. Nous réinsérons ensuite la SECTION DE TRAVAIL implémentée dans le programme à la position correcte. Cette approche est simple, mais exige que le LLM généralise au-delà de ses données d'apprentissage (il n'aura pas vu beaucoup de programmes où les sections ne sont pas dans l'ordre).
L'autre approche consiste à utiliser une technique appelée remplissage. Ici, nous décomposons le programme en préfixe, milieu et suffixe (délimités par les jetons spéciaux <PRE>, <MID> et <SUF>) et générons une complétion dans l'ordre suivant : préfixe, suffixe, milieu. Cela nous permet de compléter du code au milieu d'un programme.
l'invite de remplissage ressemblerait à ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 def factorial(n): if n > 1: return n * factorial(n - 1) elif n ==1: return 1
Pour en revenir au COBOL, on peut générer à la fois la SECTION DE STOCKAGE et la DIVISION DE PROCÉDURE en demandant au LLM de procéder comme suit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 <PRE>def factorial(n): if n > 1: <SUF> elif n ==1: return 1 <MID> return n * factorial(n - 1)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 <PRE> IDENTIFICATION DIVISION. PROGRAM-ID. SUM-OF-CUBES. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. DATA DIVISION. <SUF> LINKAGE SECTION. 01 LINKED-ITEMS. 05 L-MAX-STEP PIC S9(10). 05 RESULT PIC S9(10). * * Given an integer number, return the sum of all the integers below it. * * Example: * * sum_of_cubes(3) == 1**3 + 2**3 == 9 * sum_of_cubes(5) == 100 * * Store the result in the RESULT variable and mark the end of your program with END PROGRAM PROCEDURE DIVISION USING LINKED-ITEMS. PERFORM VARYING STEP FROM 0 BY 1 UNTIL STEP IS EQUAL TO L-MAX-STEP COMPUTE CUBE = STEP ** 3 ADD CUBE TO CUBE-SUM END-PERFORM . MOVE CUBE-SUM TO RESULT. DISPLAY 'THE SUM OF THE CUBES IS ' RESULT. GOBACK. END PROGRAM SUM-OF-CUBES. <MID> WORKING-STORAGE SECTION. 01 STEP PIC S9(10). 01 CUBE PIC 9(7). 01 CUBE-SUM PIC 9(7) VALUE 0.La mise en place de l'ensembleNous avons supprimé la SECTION DE TRAVAIL du programme, de sorte que le LLM génère d'abord la logique de la solution dans la DIVISION DE PROCÉDURE et le jeton spécial <MID>, puis déclare les variables qu'il a utilisées en générant la SECTION DE TRAVAIL.
Notez que cela fonctionne mieux avec les modèles qui ont été formés pour supporter le remplissage (par exemple, CodeLlama).
Chaque problème HumanEval est accompagné d'un ensemble de cas de test.
On génère un programme d'appel COBOLEval pour chaque cas de test. Le programme d'appel définit les données et les transmet à la solution générée par LLM. Il écrit ensuite la variable RESULT dans un fichier.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 def check(candidate): assert candidate([1.0, 2.0, 3.9, 4.0, 5.0, 2.2], 0.3) == True assert candidate([1.0, 2.0, 3.9, 4.0, 5.0, 2.2], 0.05) == False assert candidate([1.0, 2.0, 5.9, 4.0, 5.0], 0.95) == True assert candidate([1.0, 2.0, 5.9, 4.0, 5.0], 0.8) == False assert candidate([1.0, 2.0, 3.0, 4.0, 5.0, 2.0], 0.1) == True assert candidate([1.1, 2.2, 3.1, 4.1, 5.1], 1.0) == True assert candidate([1.1, 2.2, 3.1, 4.1, 5.1], 0.5) == False
Les résultats de la solution sont comparés aux valeurs réelles et un score est calculé. La version de COBOLEval comprend un harnais d'évaluation qui automatise entièrement ce processus. Note : COBOLEval utilise le compilateur open-source GnuCOBOL.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 IDENTIFICATION DIVISION. PROGRAM-ID. CAR-RACE-COLLISION-CALL. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT OUTPUT-FILE ASSIGN TO "CAR-RACE-COLLISION.TXT" ORGANIZATION IS LINE SEQUENTIAL STATUS IS OUTPUT-FILE-STATUS. DATA DIVISION. FILE SECTION. FD OUTPUT-FILE. 01 OUTPUT-RECORD PIC S9(10) SIGN LEADING. WORKING-STORAGE SECTION. 01 OUTPUT-FILE-STATUS PIC X(02). 01 LINKED-ITEMS. 05 L-N PIC S9(10). 05 RESULT PIC S9(10). PROCEDURE DIVISION. MOVE 10 TO L-N CALL "CAR-RACE-COLLISION" USING LINKED-ITEMS OPEN OUTPUT OUTPUT-FILE IF OUTPUT-FILE-STATUS NOT = "00" DISPLAY "ERROR OPENING OUTPUT FILE" STOP RUN END-IF MOVE RESULT TO OUTPUT-RECORD WRITE OUTPUT-RECORD IF OUTPUT-FILE-STATUS NOT = "00" DISPLAY "ERROR WRITING TO OUTPUT FILE" STOP RUN END-IF CLOSE OUTPUT-FILE
Quelle est leur qualité ?
On dispose maintenant d'un point de référence, alors à quel point les LLM les plus avancés peuvent-ils écrire du COBOL ? Bloop a calculé les scores "pass@1" (avec température = 0) pour quelques modèles largement utilisés.
GPT-4 - le modèle le plus performant - génère une solution correcte pour 8,90 % des problèmes. Comparez ce chiffre à celui de HumanEval, qui résout 67 % des problèmes. CodeLlama, l'un des meilleurs modèles de codage open-source, est encore moins performant, la variante 34b n'obtenant que 2 %. COBOLEval est difficile.
En regardant les cas d'échec, on peut voir que les LLMs de pointe luttent pour générer du COBOL qui se compile. Seulement 47,94% des solutions générées par GPT-4 se compilent avec GnuCOBOL.
Ici, GPT-4 a essayé d'utiliser la fonction MOD sans la faire précéder du mot-clé FUNCTION.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 PERFORM VARYING I FROM Y BY -1 UNTIL I < X IF I MOD 2 = 0 THEN MOVE I TO MAX-EVEN EXIT PERFORM END-IF END-PERFORM
mAInframer-1
Bloop publie également mAInframer-1, une série de modèles affinée pour écrire en COBOL.
Les trois modèles mAInframer surpassent considérablement les modèles CodeLlama, tandis que le modèle 34b obtient une meilleure note de passage@1 que GPT-4 !
Quelles sont les prochaines étapes ?
Il y a clairement beaucoup de marge pour améliorer le COBOL généré par LLM. Bloop espère que la communauté pourra utiliser COBOLEval pour suivre les performances des derniers modèles et construire des LLM qui aideront à maintenir l'approvisionnement mondial en code COBOL critique.
À propos de bloop
Bloop a été fondé en 2021 en tant que laboratoire de recherche se concentrant exclusivement sur l'IA appliquée aux langages de programmation. Ils ont des dizaines d'années d'expérience individuelle dans l'entraînement de modèles d'apprentissage automatique et la construction de compilateurs. Leurs investisseurs incluent Y-Combinator, Khosla Ventures, Sands Capital et LocalGlobe.
Pour commencer à utiliser COBOLEval : https://github.com/BloopAI/cobolEval
Pour télécharger la série de modèles affinée mAInframer-1 : https://huggingface.co/bloopai
Source : "Evaluating LLMs on COBOL" (Gabriel Gordon-Hall)
Et vous ?
Pensez-vous que COBOLEval est crédible ou pertinent ?
Pensez-vous que les IA vont pouvoir programmer efficacement ou cela n'arrivera jamais ?
Pensez-vous que les IA vont rendre les développeurs plus productifs sans menacer leurs emplois, ou que au contraire les IA vont finir par remplacer les développeurs ?
Voir aussi :
IBM annonce Watsonx, un outil d'IA générative qui traduirait le code COBOL en Java. Une fausse bonne idée ?
À plus de 60 ans, le langage COBOL est encore utilisé par des États américains. Les laissant face à un manque de programmeurs et des coûts de développement énormes
L'utilisation de l'assistant d'IA GitHub Copilot pour la programmation entraîne une baisse de la qualité globale du code et une quantité importante de code redondant, selon une étude
Partager