Suivi du projet · Text-to-SQL français

Du jeu de données
au modèle entraîné.

Le point d’avancement unique du projet : données finales, comportement des modèles bruts, puis résultats des entraînements LoRA.

01 · Données

Jeux finaux et séparation

206 bases distinctes au total — 146 en train, 20 en validation et 40 en test, sans aucun recouvrement entre les splits.

Les longueurs et volumes des fichiers finaux sont détaillés ci-dessous.

Pour découvrir en détail la préparation des données et le pipeline associé, cliquez ici.

Fichier Cas Moyenne
(tokens)
P95
(tokens)
P99
(tokens)
Max.
(tokens)
> 1 024
(%)
> 1 536
(%)
> 2 048
(%)
Taille

Séquence complèteMême exemple train · 176 tokens · à prédire


          

Exemple complet tokeniséTokenizer officiel Qwen · ␠ espace · ↵ retour ligne


          

Longueurs en tokens Qwen 3.5 de la séquence complète : system + user + préambule assistant + SQL cible + <|im_end|>. P95 et P99 utilisent le rang le plus proche.

02 · Point de départ

Tests des modèles bruts

Résultats figés sur les 2 147 requêtes du jeu de test, avant fine-tuning. Les meilleurs résultats Qwen sont indiqués en vert ; GPT-5.6 Luna est présenté comme repère externe.

  • Execution accuracy : part des requêtes dont le résultat renvoyé par SQLite est exactement le même que celui de la requête de référence. C’est la mesure principale de la justesse fonctionnelle.
  • Exact match : part des requêtes dont le texte SQL, après normalisation, est identique à la référence. Une requête différente mais équivalente peut donc réussir l’exécution sans compter ici.
  • SQL exécutable : part des requêtes que SQLite peut lancer sur la base concernée sans produire d’erreur. Cela vérifie notamment que les tables, colonnes et types employés sont cohérents avec le schéma.
  • SQL valide : part des sorties dont la syntaxe peut être analysée comme du SQL. Cette métrique ne garantit ni que les noms du schéma existent, ni que la réponse à la question est correcte.
  • Erreurs d’exécution : requêtes syntaxiquement valides, mais rejetées au moment de l’exécution — par exemple à cause d’une table ou d’une colonne inexistante.
  • SQL invalides : sorties qui ne peuvent pas être analysées comme une requête SQL, souvent en raison d’une syntaxe incomplète, d’un format parasite ou d’une réponse en langage naturel.
  • Timeouts : exécutions interrompues parce qu’elles dépassent la durée autorisée, généralement à cause d’une requête trop coûteuse.

Vert : meilleure valeur Qwen de la colonne. Rouge : moins bonne valeur Qwen. GPT‑5.6 Luna est exclu de ces repères.

03 · Expériences de fine-tuning

Adaptations LoRA comparées

Chaque expérience entraîne un adaptateur LoRA sur les 8 651 exemples de train, puis évalue tous ses checkpoints par exécution SQLite sur les 1 034 exemples de validation. Le checkpoint retenu est choisi exclusivement sur cette validation, avant toute évaluation finale sur test.

Paramètres du fine-tuning : LoRA (r=16, α=32, dropout 0,05) · 3 époques · learning rate 1e-4 · batch par GPU 2, accumulation de gradients 32, batch effectif 64 · séquences de 3 072 tokens maximum · AdamW avec scheduler cosinus · bfloat16, avec des paramètres de base restaurés en FP32 (36 pour le 2B, 48 pour le 4B)
Modèle · checkpoint Loss validation Execution accuracy · validation Execution accuracy · test
Qwen 3.5 2B · Fine-tuned · Epoch 1 0,2813 65,09 % —
Qwen 3.5 2B · Fine-tuned · Epoch 2 0,3013 63,93 % —
Qwen 3.5 2B · Fine-tuned · Epoch 3 0,3046 66,25 % 67,44 %
Qwen 3.5 4B · Fine-tuned · Epoch 1 0,2573 73,02 % —
Qwen 3.5 4B · Fine-tuned · Epoch 2 0,2742 74,66 % 73,17 %
Qwen 3.5 4B · Fine-tuned · Epoch 3 0,2846 73,69 % —

Pour rappel, nous avions sur les modèles de base :

Qwen 3.5 2B : 29,48 % d’execution accuracy, et maintenant sa version fine-tunée :
67,44 %, soit un gain de +37,96 points.
Qwen 3.5 4B : 54,26 % d’execution accuracy, et maintenant sa version fine-tunée :
73,17 %, soit un gain de +18,91 points.
Meilleur score des modèles de base zero-shot : Qwen 3.5 9B avec 63,06 % d’execution accuracy.

04 · Optimisation LoRA

Explorer les paramètres du Qwen 3.5 2B

Le Qwen 3.5 2B réagit particulièrement bien au fine-tuning : son execution accuracy test passe de 29,48 % à 67,44 % (+37,96 points). Nous allons donc tester différentes configurations LoRA sur ce modèle. Pour isoler l’effet des hyperparamètres, les mêmes données et le même protocole d’évaluation sont conservés : seule la configuration LoRA varie.

04.1 · Capacité des adaptateurs

Faire varier r et α à ratio constant

Nous faisons varier le rang r et le facteur d’échelle α, tout en conservant α / r = 2. Le dropout et tous les autres paramètres d’entraînement restent inchangés.

Les pourcentages correspondent à l’execution accuracy sur les 1 034 exemples de validation :

Epoch r=8 · α=16 r=16 · α=32 r=32 · α=64
Epoch 1 63,44 % 65,09 % 66,83 %
Epoch 2 63,54 % 63,93 % 66,25 %
Epoch 3 66,44 % 66,25 % 65,18 %

Bien que le meilleur score de validation soit obtenu avec r=32 et α=64, son avantage reste limité. Il ne justifie pas nécessairement un adaptateur plus grand, donc davantage de paramètres LoRA à entraîner, lorsque les configurations plus légères produisent des résultats très proches. Nous retenons donc le plus petit couple, r=8 et α=16, pour la suite des essais.

04.2 · Taux d’apprentissage

Tester différents learning rates

Nous conservons le plus petit couple, r=8 et α=16, puis comparons plusieurs learning rates. Les données, les autres hyperparamètres et le protocole de sélection restent identiques.

Epoch Learning rate 5e-5 Learning rate 1e-4 Learning rate 2e-4
Epoch 1 60,35 % 63,44 % 64,41 %
Epoch 2 62,77 % 63,54 % 66,63 %
Epoch 3 64,41 % 66,44 % 65,96 %

05 · Data scaling

Mesurer l’effet du volume de données

Après avoir fixé une configuration LoRA compacte, nous allons maintenant mesurer l’apport de données d’entraînement supplémentaires. L’objectif est d’identifier comment l’Execution Accuracy évolue lorsque la taille du jeu de train augmente. Chaque version sera évaluée sur le même jeu de validation, avec le même protocole d’évaluation.

Configuration conservée : Qwen 3.5 2B · LoRA (r=8, α=16) · learning rate 1e-4 · 3 époques.

Le jeu d’entraînement sera découpé en quatre volumes : 25 %, 50 %, 75 % et 100 %. Les sous-ensembles seront imbriqués (25% ⊂ 50% ⊂ 75% ⊂ 100%) et construits par échantillonnage contrôlé selon les db_id et la difficulté Spider (easy, medium, hard, extra) : chaque base et chaque niveau de difficulté y contribueront proportionnellement à leur nombre d’exemples. Cela permet de conserver une diversité raisonnablement représentative des bases, schémas et requêtes à chaque niveau.

Spider ne fournit pas directement ces niveaux de difficulté dans ses fichiers train. Ils sont recalculés à partir de l’AST SQL gold avec les règles de son évaluateur officiel, qui classe chaque requête en easy, medium, hard ou extra.

Train · 25 % · 2 163 exemples
Train · 50 % · 4 326 exemples
Train · 75 % · 6 488 exemples
Train · 100 % · 8 651 exemples

Meilleure Execution Accuracy observée sur le jeu de validation pour chaque volume d’entraînement :

Train Exemples Meilleur checkpoint Execution Accuracy · validation Gain vs. niveau précédent
25 % 2 163 Epoch 3 58,41 % —
50 % 4 326 Epoch 3 62,86 % +4,45 points
75 % 6 488 Epoch 3 64,80 % +1,94 points
100 % 8 651 Epoch 3 66,44 % +1,64 points

06 · Qualité et diversité

Ajouter des données d’entraînement, oui mais lesquelles ?

Le data scaling montre qu’augmenter le volume améliore les résultats, mais que chaque lot supplémentaire apporte un gain plus faible que le précédent. La prochaine étape n’est donc pas seulement d’ajouter des exemples : il faut choisir ceux qui complètent le mieux ce que le modèle sait déjà faire.

Commençons d’abord par regarder où notre modèle fait le plus d’erreurs.

Le run entraîné sur 100 % des données est évalué sur les 1 034 exemples de validation. Les niveaux de difficulté sont calculés avec les règles de l’évaluateur officiel Spider.

Easy248 exemples · 209 corrects · 39 erreurs
Exemple

« Donnez le nombre de vols. »

SELECT count(*) FROM FLIGHTS
Medium446 exemples · 302 corrects · 144 erreurs
Exemple

« Combien pèse le chien le plus jeune ? »

SELECT weight FROM pets ORDER BY pet_age LIMIT 1
Hard174 exemples · 101 corrects · 73 erreurs
Exemple

« Quelle année a compté le plus de matchs ? »

SELECT YEAR FROM matches GROUP BY YEAR ORDER BY count(*) DESC LIMIT 1
Extra166 exemples · 75 corrects · 91 erreurs
Exemple

« Combien de chiens n’ont suivi aucun traitement ? »

SELECT count(*) FROM Dogs WHERE dog_id NOT IN (SELECT dog_id FROM Treatments)

Nous allons maintenant tenter quatre expériences (A, B, C et D), en faisant varier la nature des données ajoutées et le type de bases concernées :

Données ajoutées Bases existantes Nouvelles bases
Cas tous niveaux A B
Cas difficiles (hard, extra) C D

L’objectif est de mesurer si l’ajout de nouvelles données améliore les performances, selon qu’elles proviennent de bases déjà présentes dans le jeu d’entraînement ou de nouvelles bases, et selon leur niveau de difficulté.
On vise 5k exemples en plus pour chaque expérience.

06.1 · Préparation des nouvelles données

Générer et contrôler les nouveaux datasets A à D

Objectif des nouveaux datasets

Objectif commun : 5 000 nouvelles paires d'exemples par dataset (question en français - requête SQL attendue).

Comment

Pipeline de création des 100 bases fictives

Pipeline de création des nouvelles données d’entraînement

Résultat obtenu

06.2 · Résultats des entraînements

Quel ajout de données améliore réellement la validation ?

Les quatre expériences ajoutent 5 000 exemples synthétiques au train Spider initial (8 651 exemples), avec la même configuration Qwen 3.5 2B, LoRA r=8 · α=16, learning rate 1e-4 et 3 époques. Le tableau retient le meilleur checkpoint de chaque expérience sur les 1 034 exemples du jeu de validation.

Train Nombre d’exemples Meilleur checkpoint Execution Accuracy · validation Gain vs. baseline
Train set Spider initial uniquement 8 651 Epoch 3 66,44 % —
Dataset A + Train set Spider initialBases existantes
Tous niveaux
13 651 Epoch 3 67,70 % +1,26 points
Dataset B + Train set Spider initialNouvelles bases
Tous niveaux
13 651 Epoch 3 66,63 % +0,19 point
Dataset C + Train set Spider initialBases existantes
Données difficiles
13 651 Epoch 2 66,92 % +0,48 point
Dataset D + Train set Spider initialNouvelles bases
Données difficiles
13 651 Epoch 3 65,86 % −0,58 point

06.3 · Analyse par difficulté

Les résultats changent-ils selon la difficulté Spider ?

Execution Accuracy sur les 1 034 exemples de validation, ventilée selon la difficulté Spider. Le nombre entre parenthèses correspond aux requêtes correctes sur le total de la catégorie.

Train Easy · 248 exemples Medium · 446 exemples Hard · 174 exemples Extra · 166 exemples Total · 1 034 exemples
Train set Spider initial uniquement 84,27 % 209 / 248 67,71 % 302 / 446 58,05 % 101 / 174 45,18 % 75 / 166 66,44 % 687 / 1 034
Dataset A + Train set Spider initialBases existantes
Tous niveaux
85,89 % 213 / 248 68,39 % 305 / 446 63,79 % 111 / 174 42,77 % 71 / 166 67,70 % 700 / 1 034
Dataset B + Train set Spider initialNouvelles bases
Tous niveaux
84,27 % 209 / 248 66,59 % 297 / 446 64,37 % 112 / 174 42,77 % 71 / 166 66,63 % 689 / 1 034
Dataset C + Train set Spider initialBases existantes
Données difficiles
84,27 % 209 / 248 68,61 % 306 / 446 59,77 % 104 / 174 43,98 % 73 / 166 66,92 % 692 / 1 034
Dataset D + Train set Spider initialNouvelles bases
Données difficiles
84,27 % 209 / 248 68,16 % 304 / 446 59,77 % 104 / 174 38,55 % 64 / 166 65,86 % 681 / 1 034

06.4 · Diagnostic

Pourquoi ces données n’ont-elles presque rien apporté ?

La cause se trouve dans notre pipeline de génération. Pour que le classifieur Spider accepte les requêtes, les prompts envoyés à GPT-5.6 Luna imposaient une seule forme de SQL par difficulté. Ces requêtes sont difficiles pour le classifieur, mais pas pour le modèle.

Difficulté Ce que demandait le prompt envoyé à GPT-5.6 Luna Ce qu’on obtenait (datasets A à D)
Easy2 399 exemples Une seule table, une seule expression dans le SELECT, au plus un filtre simple. Ni agrégat, ni jointure, ni tri, ni sous-requête. SELECT col FROM t (42,5 %) et SELECT col FROM t WHERE col = valeur (39,8 %) 10 structures, dont 2 couvrent 82 % des exemples
Medium2 978 exemples Exactement SELECT col, COUNT(*) FROM t GROUP BY col. Rien d’autre. SELECT col, COUNT(*) FROM t GROUP BY col (100 %) 1 seule structure
Hard7 362 exemples Recopier SELECT col FROM t WHERE cle IN (SELECT cle FROM t), avec la même table et la même clé dans la sous-requête. Ni alias, ni agrégat, ni jointure, ni tri. SELECT col FROM t WHERE cle IN (SELECT cle FROM …) (99,4 %, avec ses variantes NOT IN et DISTINCT) 85 % sur la même table et la même clé : le filtre ne filtre rien
Extra7 261 exemples Exactement SELECT col, COUNT(*) FROM t WHERE filtre1 AND filtre2 GROUP BY col. Ni jointure, ni sous-requête, ni tri. SELECT col, COUNT(*) FROM t WHERE filtre1 AND filtre2 GROUP BY col (99,2 %) 61 structures, qui ne diffèrent presque que par les opérateurs (=, >, !=…)
5 000 exemples Structures SQL distinctes JOIN 2 JOIN ou plus ORDER BY LIMIT GROUP BY UNION, INTERSECT, EXCEPT
Train set Spider initialÉchantillon de 5 000 exemples 1 012 43,6 % 18,6 % 20,2 % 13,0 % 21,8 % 6,4 %
Dataset A 71 1,2 % 0,3 % 0 % 0 % 53,6 % 0 %
Dataset B 45 0 % 0 % 0 % 0 % 50,0 % 0 %
Dataset C 40 0 % 0 % 0 % 0 % 50,0 % 0 %
Dataset D 44 0 % 0 % 0 % 0 % 50,0 % 0 %

Or ces opérations absentes sont justement celles que le modèle rate. Sur les 347 erreurs du baseline (comparaison stricte), 75 sont des erreurs no such column, souvent une colonne cherchée dans la mauvaise table lors d’une jointure.

Deux éléments rendaient aussi la lecture de 06.2 difficile :

06.5 · Nouvelle génération

Dataset A2 : générer à partir d’exemples Spider

A2 reprend les conditions du dataset A (146 bases existantes, 5 000 exemples, tous niveaux, au prorata de chaque base). Seule la méthode de génération change :

Étape Paires Détail
Génération · GPT-5.6 Luna 6 337 401 prompts de 16 paires demandées
Contrôles automatiques 6 024 Exécution SQLite, parseur Spider, doublons, résultats vides
Juge sémantique · Haiku 5.5 5 286 519 refusées, 219 incertaines
Export 5 000 Easy 1 135 · Medium 1 874 · Hard 1 202 · Extra 789

Le niveau extra représente 15,8 % de l’export contre 20,3 % dans le train Spider, car le juge le rejette plus souvent. Les contrôles de résultat vide ne s’appliquent pas aux 7 bases Spider livrées sans aucune ligne.

Les 5 000 paires de A2 retrouvent la diversité de Spider : 1 030 structures SQL distinctes contre 1 012 sur un échantillon de même taille, 41,6 % de JOIN (43,6 % dans Spider), 21,4 % d’ORDER BY (20,2 %) et 6,6 % d’opérations ensemblistes (6,4 %). Seules les requêtes à 2 JOIN ou plus restent en retrait, à 14,0 % contre 18,6 %.

06.6 · Résultats de A2

Le gain se confirme-t-il sur deux graines ?

Nous comparons A2 au train Spider seul avec deux graines aléatoires, à l’époque 3 et avec la même configuration que 06.2. Les deux graines n’ont pas tourné sur la même machine : il ne faut donc comparer les runs qu’à l’intérieur d’une même graine.

Graine Baseline · stricte A2 · stricte Gain · strict Baseline · façon Spider A2 · façon Spider Gain · façon Spider Exemples gagnés / perdus IC 95 % du gain
42 66,44 % 70,41 % +3,97 points 69,83 % 74,18 % +4,35 points +72 / −27 [+1,65 ; +6,73]
7 65,67 % 69,34 % +3,67 points 69,54 % 73,21 % +3,68 points +69 / −31 [+0,85 ; +6,16]

Exemples gagnés et perdus et IC 95 % en comparaison façon Spider. L’intervalle provient d’un bootstrap par base de validation. Le test de McNemar apparié donne p < 0,01 sur les deux paires.

Par difficulté Spider, en comparaison stricte :

Train Easy · 248 exemples Medium · 446 exemples Hard · 174 exemples Extra · 166 exemples Total · 1 034 exemples
Baseline · graine 42 84,27 % 209 / 248 67,71 % 302 / 446 58,05 % 101 / 174 45,18 % 75 / 166 66,44 % 687 / 1 034
Dataset A2 · graine 42 87,10 % 216 / 248 71,08 % 317 / 446 64,94 % 113 / 174 49,40 % 82 / 166 70,41 % 728 / 1 034
Baseline · graine 7 85,08 % 211 / 248 67,26 % 300 / 446 58,05 % 101 / 174 40,36 % 67 / 166 65,67 % 679 / 1 034
Dataset A2 · graine 7 85,89 % 213 / 248 71,97 % 321 / 446 62,07 % 108 / 174 45,18 % 75 / 166 69,34 % 717 / 1 034

Par type de requête, en comparaison façon Spider et en moyenne sur les deux graines :

Type de requête Exemples Baseline A2 Écart
1 table62680,59 %83,63 %+3,04 points
JOIN40852,94 %58,46 %+5,51 points
2 JOIN ou plus8834,09 %36,36 %+2,27 points
ORDER BY / LIMIT23771,31 %75,32 %+4,01 points
GROUP BY27764,98 %69,31 %+4,33 points
Sous-requête8351,20 %55,42 %+4,22 points
UNION, INTERSECT, EXCEPT8050,00 %55,00 %+5,00 points

Un même exemple peut compter dans plusieurs lignes. Les petites catégories restent peu précises. Erreurs no such column : 75 → 60 en graine 42, 74 → 52 en graine 7.