TLDR : Comme pressenti dans l’article précédent, avec l’outillage adéquat, un SLM peut devenir radioamateur français ! Cette fois-ci, l’objectif n’est pas d’avoir un bon benchmark, ni d’évaluer la connaissance intrinsèque d’un SLM, mais bien d’obtenir le meilleur score dans les 2 catégories de questions : réglementation et technique. Pour cela, il suffit d’un petit RAG sur une liste de connaissances assez réduite et d’un petit coup de pouce pour la vision.

Introduction

Dans l’article précédent, j’avais cherché à faire un benchmark pour évaluer des SLMs tournant sur ma machine avec une RTX 2080 comme GPU, soit 8 Go de vRAM. L’objectif était de comprendre si leurs connaissances intrinsèques leur permettraient de devenir radioamateur. Nous avions vu qu’en technique, il y avait un potentiel certain, mais qu’un coup de pouce d’une calculatrice était nécessaire. En réglementation, il leur fallait un rappel de certaines précisions et spécificités françaises. Dans ce benchmark, ministral-3-8B et Qwen3-VL-8B s’en sortent très bien. Pour rappel, il y a besoin de modèles multimodaux car certaines questions nécessitent la compréhension de schémas.

La dernière approche testée consistait à rajouter dans le prompt système ces informations spécifiques, et à réduire le nombre d’outils disponibles pour le SLM à un seul : Python. C’était un compromis pour éviter le sur-appel de fonctions (overtooling). Avec cette configuration, la probabilité que le SLM devienne radioamateur était grande, mais pas de 100 %. De plus, un prompt qui améliorait un modèle détériorait l’autre ! J’ai donc voulu me consacrer à un modèle en particulier.

J’ai donc cherché à améliorer le prompt uniquement pour Ministral. J’ai lancé une boucle d’exploration automatique afin de trouver le prompt idéal. Malheureusement, cette boucle d’auto-amélioration n’a pas convergé. Plus il avait de connaissances, plus le modèle hésitait, moins bonnes étaient les notes. Il fallait donc ne lui injecter que l’information nécessaire à la question. C’est exactement le principe du RAG (Génération Augmentée par Récupération). C’est ce que je vais vous expliquer ci-après. Mais avant cela, il faut aussi que je vous parle de la partie vision.

Analyse d’images

Oscillogramme de 2 périodes d'un signal régulier s'étalant sur 8 divisions avec une légende indiquant 5ms/division. copyright Exam'1synoptique d'un récepteur hétérodine dont un des étages a pour label un point d'interrogation. Copyright Exam'1

Voici 2 exemples de pourquoi je me suis focalisé sur des SLMs multimodaux. L’examen comporte régulièrement des questions avec des schémas électriques simplifiés, des synoptiques d’émetteurs/récepteurs, ou encore des oscillogrammes dont il faut repérer la fréquence ou le déphasage d’un ou plusieurs signaux. Le SLM doit donc être en mesure d’interpréter ces images. Dans le benchmark précédent, je n’avais rien fait de spécifique concernant l’analyse d’images. J’avais laissé libre le SLM dans son interprétation des images. Maintenant que mon but est d’avoir le meilleur score, j’ai légèrement modifié le prompt avec ceci :

MÉTHODOLOGIE D’ANALYSE DES SCHÉMAS ET CIRCUITS :

  • Pour les schémas synoptiques : observe attentivement l’image, le sens de circulation du signal (antenne vers haut-parleur ou micro vers antenne) et les liaisons avec les oscillateurs auxiliaires avant d’identifier un bloc fonctionnel.
  • Pour les circuits électriques : vérifie toujours la nature de la source d’alimentation (courant continu DC vs alternatif AC) et les polarités des composants avant d’appliquer une formule.

Oui, c’est assez ciblé, mais cela m’a permis de grapiller encore quelques points. Malheureusement, il faut savoir que 100 % des erreurs résiduelles en technique portent sur des questions contenant des images ou des schémas. Peut-être qu’un retravail du prompt permettrait de gagner encore quelques points, mais je n’ai pas de doute non plus que les SLMs vont progresser dans le futur aussi.

RAG - Génération Augmentée par Récupération

Le but de cet article n’est pas de faire un tutoriel sur le RAG. Il faut juste savoir que c’est une manière d’injecter des informations spécifiques dans le prompt fourni au SLM. Normalement, cela se fait par création d’une base de vecteurs à partir de documents sources découpés en chunks, puis sélection de chunks par analyse de distance entre le prompt utilisateur et lesdits chunks. Ces chunks sont alors insérés avant que l’ensemble soit envoyé à l’API du SLM.

Comme je ne voulais pas avoir à installer une base de vecteurs, créer celle-ci à partir de différents documents, etc., j’ai fait un RAG du pauvre. J’ai simplement associé des mots-clefs à un chunk documentaire. Autrement dit, à chaque question, je vérifie si la question de l’examen utilise un des mots-clefs, si oui, j’injecte alors le bloc documentaire associé. Bien évidemment, chaque bloc n’est inséré qu’une seule fois. L’avantage est que cela est rapide, simple et suffisant pour ce test très spécifique. Il est évident qu’un passage en production nécessiterait un vrai RAG car si j’utilise le mot brouilleur au lieu de brouillage, ce système ne fonctionnerait pas plus.

À noter que ces informations n’ont été rajoutées que parce que sans elles, Ministral se trompait.

📌 Préfixes CEPT

{
        "id": "prefixes_uk_cept",
        "keywords": [
            "préfixe", "préfixes", "prefixe", "prefixes", "indicatif", "indicatifs", "identifiant", "pays", "cept",
            "alphabet", "phonétique", "phonetique", "épeler", "epeler", "épellation", "epellation", "oaci",
            "estonie", "hongrie", "bulgarie", "écosse", "ecosse", "corse", "dom", "tom",
            "guadeloupe", "martinique", "guyane", "réunion", "reunion", "polynésie", "polynesie", "suisse", "liechtenstein",
            "croatie", "wallis", "futuna", "taaf", "mayotte", "saint-pierre", "miquelon", "f4abc", "f4x", "f5x", "to5", "tm", "f8zz", "liste orange", "réattribution", "de plein droit", "personnel",
            "région 1", "région 2", "région 3", "region 1", "region 2", "region 3", "régions", "regions", "iaru", "fx", "/mm", "maritime", "lituanie", "lettonie", "ly", "yl",
            "es", "ha", "lz", "ea", "oh", "yl", "gm", "mm", "gw", "tk", "fg", "fm", "fy", "fr", "fo", "fw", "ft", "fh", "fp", "hb9", "hb0", "s5", "9a", "tm", "to", "tx",
            "t7", "saint-marin", "saint marin", "f4w", "f0", "f1", "f2", "f3", "f5", "f6", "f8", "f9", "f5uxy", "canadien", "canada", "classe 1", "classe 2", "classe 3", "radio-club", "radioclub"
        ],
        "text": (
            "Indicatifs UK, CEPT, DOM-TOM, Régions UIT & Alphabet : "
            "Régions UIT mondiales : Région 1 = Europe, Afrique, Moyen-Orient, ex-URSS, et les T.A.A.F. (Terres Australes et Antarctiques Françaises : Kerguelen, Crozet font partie de la Région 1 !) | Région 2 = Amériques (Guadeloupe FG, Martinique FM, Guyane FY, Saint-Pierre-et-Miquelon FP) | Région 3 = Asie et Pacifique (Polynésie FO, Nouvelle-Calédonie FK, Wallis-et-Futuna FW). "
            "Préfixes pays CEPT & Europe : G/M = Angleterre, GD/MD = Île de Man, GU/MU = Guernesey, GI/MI = Irlande du Nord, GW/MW = Pays de Galles, GM/MM = Écosse, GJ/MJ = Jersey. "
            "ON = Belgique, OM = Slovaquie, OE = Autriche, HB9 = Suisse, HB0 = Liechtenstein, PA = Pays-Bas, SP = Pologne, SM = Suède, LA = Norvège, OZ = Danemark, OH = Finlande, OK = Rép. Tchèque, CT = Portugal, DL = Allemagne, EA = Espagne, ES = Estonie, HA = Hongrie, 9A = Croatie, S5 = Slovénie, I = Italie, 5B = Chypre, 9H = Malte, 3A = Monaco, C3 = Andorre, LZ = Bulgarie, T7 = Saint-Marin. "
            "Pays baltes : LY = Lituanie (L-Y) | YL = Lettonie (Y-L) | ES = Estonie. "
            "DOM-TOM et Corse : TK = Corse, FG = Guadeloupe, FM = Martinique, FY = Guyane, FR = Réunion, FO = Polynésie, FK = Nouv-Calédonie, FW = Wallis-et-Futuna, FT = TAAF, FH = Mayotte, FP = Saint-Pierre-et-Miquelon. Dans les DOM-TOM et en Corse, les indicatifs comportent obligatoirement 1 chiffre et 2 lettres au suffixe (ex: FG5KY, TK4KA, et jamais 3 lettres sans chiffre). Radio-clubs : le suffixe commence obligatoirement par la lettre K (ex: TK4KA en Corse, FG5KY en Guadeloupe). "
            "Séries France & Classes d'opérateurs : "
            "F4ABC = indicatif individuel Personnel classe 2 HAREC (F4K/F5K/F6K = Radio-Club métropole). Anciennes classes d'opérateurs par indicatif : Classe 1 (HAREC avec épreuve morse historique) = F2, F3, F5, F6, F8, F9 (ex: F5UXY appartient à la Classe 1) ; Classe 2 (HAREC sans morse) = F1, F4 ; Classe 3 (Novice) = F0. "
            "Étrangers en France : Ressortissant d'un pays d'Europe / CEPT vivant ou résidant en France = indicatif F5V (ex: F5Vxy). Ressortissant étranger hors UE / CEPT (ex: un radioamateur canadien) venant s'installer en France pour une durée indéterminée (> 3 mois) = les autorités lui attribuent un indicatif de type F4W (ex: F4Wxx). TM = indicatif spécial métropole, TO (ex: TO5XY) = indicatif spécial DOM, TX = TOM. FX = stations répétitrices (relais automatiques terrestres) et stations spatiales. "
            "Suffixe /MM (Maritime Mobile) : s'utilise UNIQUEMENT à bord d'un navire en mer naviguant dans les eaux maritimes / internationales (> 12 milles des côtes). À quai, amarré dans un port ou en eaux intérieures, la station est opérée comme mobile (/M) ou station normale sans /MM (ex: TKXXX/MM = radioamateur dont l'adresse est établie en Corse émettant à bord d'un bateau dans les eaux internationales). "
            "Régime indicatifs : 2 lettres (ex: F8ZZ) = JAMAIS réattribués | 3 lettres = réattribution possible | Indicatif décédé = non transmissible | Spécial (TM) = réattribuable après 6 mois | Liste orange annuaire = personnes physiques uniquement. "
            "Trafic CEPT temporaire à l'étranger : [Préfixe pays visité]/[Indicatif personnel d'origine] (ex: F4GWZ au Liechtenstein émet sous HB0/F4GWZ). "
            "Alphabet OACI : U = Uniform (et NON Uniforme), F = Foxtrot, R = Romeo, V = Victor, W = Whiskey, J = Juliett, Q = Quebec, S = Sierra, L = Lima."
        )
    },

Cet aide-mémoire permet de rappeler au SLM quelques règles de base. Mais il permet aussi de le refocaliser sur des différences subtiles pour un SLM, par exemple LY et YL ne sont pas le même pays. Sans cela, il a tendance à se mélanger les pinceaux. De même pour l’alphabet de l’OTAN qui se base sur de l’anglais, ainsi que probablement les mauvaises données d’entraînement comme F pour Foxtrot, et non Florida comme on l’entend souvent.

📌 Plan de bandes

   {
        "id": "bandplan_power_limits",
        "keywords": [
            "bande", "bandes", "gamme", "gammes", "fréquence", "fréquences", "frequence", "frequences",
            "longueur", "onde", "ondes", "hf", "vhf", "uhf", "shf", "vlf", "mf", "lf", "ehf", "hectométriques", "décamétriques", "métriques", "décimétriques", "centimétriques", "millimétriques",
            "160m", "80m", "40m", "30m", "20m", "17m", "15m", "12m", "10m", "6m", "2m", "70cm", "23cm", "1,240", "14 mètres", "21 mètres", "14m", "21m", "10 mhz", "28.770", "28,770",
            "largeur", "statut", "primaire", "exclusif", "secondaire", "puissance", "puissances", "pep", "watt", "watts",
            "classe 1", "classe 2", "classe 3", "novice", "134", "141", "10,450", "répétitrice", "répétitrices", "relais", "duplex", "décalage", "précision", "stabilité", "appel",
            "satellite", "satellites", "spatiale", "spatiales", "exclusivité", "exclusivite", "ande", "propriété", "propriete", "domaine public", "433,920", "télécommande", "telecommande"
        ],
        "text": (
            "Bandes, Limites, Puissances, Statuts & Fréquences ARCEP : "
            "Longueurs d'onde : VLF (3-30 kHz, myriamétriques) | LF (30-300 kHz, kilométriques) | MF (300 kHz-3 MHz, hectométriques, ex: 160m 1,8-2 MHz) | HF (3-30 MHz, décamétriques, ex: 80m, 40m, 20m, 15m, 10m) | VHF (30-300 MHz, métriques, ex: 6m, 2m) | UHF (300-3000 MHz, décimétriques, ex: 70cm, 23cm / 1,240 GHz qui est strictement UHF et NON SHF !) | SHF (3-30 GHz, centimétriques, ex: 10 GHz) | EHF (30-300 GHz, millimétriques). "
            "PIÈGE ANFR FRÉQUENCE VS MÈTRES : Si une question demande les limites de la 'bande des 21 mètres' ou de la 'bande des 14 mètres' : la réponse exacte est 'Aucune des limites proposées' ! En effet, 21 MHz est la bande des 15 mètres (et NON 21m) ; 14 MHz est la bande des 20 mètres (et NON 14m). La bande des 10 MHz = 30m (10,1-10,15 MHz). La bande 10m = 28-29,7 MHz (largeur 1,7 MHz). "
            "Limites bandes & Statuts France métropolitaine : "
            "- 160m = 1,810-1,850 MHz (Statut EXCLUSIF en France métropolitaine, 1,810 à 1,850 MHz est attribuée en exclusivité aux radioamateurs !). En Région 2 (DOM FG/FM/FY), 1,800-2,000 MHz partagée. "
            "- 80m = 3,500-3,800 MHz (Statut partagé à égalité de droit avec la Défense, co-primaire, et NON exclusive !). "
            "- 40m = 7,000-7,200 MHz (Statut Exclusif). "
            "- 30m = 10,100-10,150 MHz (Statut SECONDAIRE partagé, puissance max 250W PEP). "
            "- 20m (bande des 14 MHz) = 14,000-14,350 MHz (Statut Exclusif, limites globales 14,000 à 14,350 MHz pour le trafic général radioamateur ! Ne pas confondre avec le trafic satellite qui a une sous-bande plus restreinte). "
            "- 17m = 18,068-18,168 MHz (Statut Exclusif). "
            "- 15m = 21,000-21,450 MHz (Statut Exclusif). "
            "- 12m = 24,890-24,990 MHz (Statut Exclusif). "
            "- 10m = 28,000-29,700 MHz (Statut Exclusif, puissance max 250W PEP, y compris sur 28.770 kHz/MHz). "
            "- 6m = 50,000-52,000 MHz (Statut SECONDAIRE, relais répéteurs autorisés). "
            "- 2m = 144,000-146,000 MHz (Statut Exclusif). "
            "- 70cm = 430-440 MHz : 430-434 MHz = statut secondaire (Défense primaire) ; 434-440 MHz = statut PRIMAIRE (partagé à égalité de droits avec d'autres services primaires selon le RR). "
            "- 23cm = 1240-1300 MHz (UHF, Statut SECONDAIRE Défense/Radionavigation). "
            "Service satellite d'amateur : autorisé uniquement dans certaines sous-bandes : sur 7 MHz (7,000-7,100 MHz) ; sur 14 MHz (14,000 à 14,250 MHz UNIQUEMENT pour les satellites, mais le trafic général amateur s'étend bien jusqu'à 14,350 MHz !) ; sur 21 MHz (21,000-21,450 MHz) ; sur 28 MHz (28,000-29,700 MHz) ; sur 144 MHz (144-146 MHz). "
            "Puissances max F4 (classes 1 et 2 HAREC) : HF < 28 MHz = 500W PEP (sauf 30m=250W, 10m=250W) | VHF/UHF/SHF = 120W PEP (dont 144 MHz et bande 1240-1300 MHz = 120W max !). Classe 3 (Novice) = autorisée uniquement sur 144-146 MHz (2m) avec 10W PEP max. "
            "Bandes passantes max autorisées : Fréquences strictly inférieures à 28 MHz (< 28 MHz, ex: 14 MHz) = 6 kHz maximum | De 28 à 144 MHz (y compris à 28 MHz et sur 50,200 MHz) = 12 kHz maximum | 144 à 225 MHz = 20 kHz maximum | > 225 MHz = illimitée. "
            "Précision de fréquence : < 29,7 MHz = 10^-5 | > 29,7 MHz = 10^-4 (+/- 10^-4). "
            "Relais répéteurs décalage duplex : 2m (144 MHz) = -600 kHz | 70cm (430 MHz) = 1,6 MHz (-1,6 MHz ou +1,6 MHz). Fréquences d'appel FM : VHF 2m = 145,500 MHz | UHF 70cm = 433,500 MHz. "
            "Propriété du spectre : Selon l'article L41-1 du CPCE, l'ensemble du spectre radioélectrique fait partie du domaine public de l'ÉTAT (propriété de l'État, et NON de l'UIT ou de l'Europe). "
            "Brouillage télécommande 433,920 MHz (norme LPD433) : sur 430-434 MHz, les radioamateurs et les télécommandes commerciales sont tous deux des utilisateurs secondaires à égalité de droits (aucun n'est prioritaire sur l'autre, vous êtes à égalité de droit)."
        )
    },

Comme pour les humains (enfin moi surtout), il y a plein de détails subtils et purement arbitraires historiques dans les limites de bandes. Même si globalement le SLM connaît intrinsèquement à peu près les limites, il n’associe pas toujours les spécificités françaises. Il faut le lui rappeler.

📌 Propagation et ionosphère

    {
        "id": "propagation_ionosphere",
        "keywords": [
            "ionosphère", "ionosphere", "couche", "couches", "couche d", "couche e", "couche f", "f1", "f2", "sporadique", "muf", "propagation", "réflexion", "absorption", "décamétriques", "inde", "contact", "nuit", "jour",
            "main", "matin", "garder"
        ],
        "text": (
            "Ionosphère & Propagation : "
            "Couche D : absorbe les fréquences basses de la HF pendant le jour, disparaît complètement la nuit. "
            "Couche E : propagation sporadique E en été, permet liaisons VHF/HF inattendues. "
            "Couches F1 et F2 : couches de réflexion principales pour les liaisons HF longue distance (DX). Le jour, la couche F se scinde en F1 et F2 ; la nuit, elles fusionnent en une seule couche F. La MUF augmente le jour et baisse la nuit : pour refaire de jour un contact réussi la nuit, ou pour maintenir un contact toute la journée (ex: contact Inde à 10 MHz à 2h du matin), le soleil levant ionise l'ionosphère et fait monter la MUF le matin, puis elle baisse au coucher du soleil -> il faut monter en fréquence le matin/jour puis la diminuer le soir/nuit (en montant en fréquence puis en la diminuant). "
            "Ondes décamétriques (HF, 3-30 MHz) : se réfléchissent sur les couches ionosphériques F. "
            "MUF (Maximum Usable Frequency) : fréquence maximale utilisable pour une liaison par réflexion ionosphérique. Au-dessus de la MUF, l'onde traverse l'ionosphère vers l'espace."
        )
    },

Un classique des révisions ici…

📌 ITU, Notation, Classes d’émissions, etc.

    {
        "id": "itu_notation_emissions_regulations",
        "keywords": [
            "notation", "désignation", "designation", "uit", "classe", "classes", "émission", "émissions", "emission", "emissions",
            "modulation", "modulations", "a1a", "a3e", "j3e", "f3e", "a1b", "a2a", "a2b", "f2b", "g1d", "j7w", "f7w", "g2d", "f1b", "f3c", "j2d", "a8w", "mhz", "khz", "6m00", "28m5", "3k50",
            "2 tons", "deux tons", "vidéo", "video", "télévision", "television", "t/r 61-01", "t/r 61-02", "61-01", "61-02", "harec", "finalité", "sujet", "sujets", "autorisé", "autorisés", "astronomie", "météo", "radioguidage",
            "r.r.", "résolution", "resolution", "640", "catastrophe", "catastrophes", "taaf", "australes", "antarctiques", "ex-classe 2", "ex classe 2", "interdite", "interdit", "somme", "département", "departement", "utilisateurs",
            "handicapé", "handicape", "handicapés", "tiers-temps", "tiers temps", "cross-band", "cross band", "préfet", "prefet", "maire", "rayonnement", "champs", "exposition", "décret", "decret", "2002-775", "cem",
            "rayonnements", "essentiels", "non essentiels", "harmoniques", "langage clair", "claire"
        ],
        "text": (
            "Classes d'émission, Notation & Réglementation Internationale : "
            "Désignation UIT (3 caractères) : "
            "1er caractère (Modulation porteuse) : A = double bande latérale AM | J = bande latérale unique BLU avec porteuse supprimée | F = modulation de fréquence FM (amplitude de la porteuse constante) | G = modulation de phase PM | D = amplitude et angle modulés simultanément | C = bande latérale résiduelle VSB | W = combinaison. "
            "2e caractère (Signal modulant) : 1 = une seule voie numérique sans sous-porteuse modulante | 2 = une seule voie numérique avec sous-porteuse modulante | 3 = une seule voie analogique (phonie) | 8 = voies multiples analogiques | 7 = une seule voie numérique. "
            "3e caractère (Information transmise) : E = téléphonie (voix/phonie) | D = transmission de données (data, télégraphie pour machine, FT8, PSK) | F = télévision / vidéo | B = télégraphie automatique pour réception automatique (téléimprimeur, RTTY) | A = télégraphie manuelle auditive (CW) | W = combinaison de données, sons, vidéo (ex: A8W = Télévision et téléphonie simultanées). "
            "Combinaisons clés : "
            "- F1B = modulation de fréquence (F) sans sous-porteuse modulante (1), télégraphie pour réception automatique (B). "
            "- F2B = modulation de fréquence (F) avec sous-porteuse modulante (2), télégraphie automatique (B). "
            "- A2A = modulation d'amplitude (A), avec sous-porteuse modulante (2), télégraphie manuelle auditive (A). "
            "- A1A = CW (modulation d'amplitude sans sous-porteuse 1, télégraphie manuelle A, porteuse découpée en tout ou rien). "
            "- G1D = modulation de phase (G), numérique 1 voie sans sous-porteuse (1), données / data (D). "
            "- A3E = AM phonie | J3E = BLU phonie | F3E = FM phonie (la porteuse HF a un NIVEAU/AMPLITUDE STRICTEMENT CONSTANT, seule sa fréquence varie au rythme de la BF !) | F3C = FAX | J2D = Data. "
            "Rayonnements non essentiels (RR Appendice 3) : les rayonnements non essentiels sont les émissions non désirées qui ne sont pas dans le domaine des émissions hors bande passante nécessaire (définition officielle internationale, ne pas limiter aux seules harmoniques). "
            "Classes autorisées ex-classe 2 (F1 et F4) : TOUTES les classes d'émission sont autorisées sans exception (aucune n'est interdite). "
            "Notation Fréquences UIT : la lettre d'unité remplace le point décimal : 6 MHz = 6M00 (et non 6M), 28,5 MHz = 28M5, 3,5 kHz = 3K50. "
            "Examen ANFR & Aménagements : les candidats en situation de handicap bénéficient de plein droit d'un tiers-temps supplémentaire (+33% de temps, soit 20 minutes au lieu de 15 minutes par épreuve). "
            "Contrôle rayonnement électromagnétique (Décret 2002-775) : le Maire ou le Préfet peut prendre l'initiative de faire procéder au contrôle des valeurs limites d'exposition du public aux champs électromagnétiques par l'ANFR. "
            "Trafic trans-bande ('cross-band') et Langage clair : les transmissions doivent être effectuées en langage clair (les abréviations et codes Q font partie du langage clair convenu). Le trafic 'cross-band' est AUTORISÉ pour tous les opérateurs (y compris les opérateurs de classe 3) : prétendre que le cross-band leur est interdit est donc FAUX ! "
            "Générateur 2 tons : n'est plus obligatoire pour les radioamateurs (non obligatoire dans tous les cas). "
            "Finalité radioamateur (RR 1.56) : instruction individuelle, intercommunication et études techniques, à titre personnel et sans intérêt pécuniaire. "
            "Sujets autorisés : astronomie, météorologie. Sujets interdits : vente de matériel, radioguidage, propos politiques/religieux/commerciaux. "
            "Signification R.R. : RÈGLEMENT des Radiocommunications de l'UIT (et NON 'Réglementation' !). "
            "Résolution 640 du RR de l'UIT : traite de l'utilisation des fréquences amateurs en cas de catastrophes naturelles. "
            "Délivrance dans les TAAF : l'ANFR délivre les certificats d'opérateur et les indicatifs dans les Terres Australes et Antarctiques Françaises. "
            "Départements et bande 50 MHz : la bande 50 MHz n'est interdite dans AUCUN département en France métropolitaine (autorisée partout). "
            "Bande 1,810 à 1,830 MHz : bande 160m exclusive radioamateurs -> on y croise UNIQUEMENT des radioamateurs. "
            "Accords CEPT : Recommandation T/R 61-01 = libre circulation temporaire (< 3 mois) de sa station dans les pays CEPT membres. Recommandation T/R 61-02 = harmonisation de l'examen (certificat HAREC), ne traite pas des classes de licences nationales. Droit d'émission ANFR : nécessite à la fois le certificat d'opérateur ET l'indicatif d'appel personnel."
        )
    },

Les classes d’émission sont connues du SLM, mais un rappel attire son attention sur les lettres et leurs emplacements exacts. De même, quelques rappels d’évolution de la législation, comme le générateur 2 tons, sont indispensables. Enfin, il ignorait complètement la notation des fréquences ITU : 28,5 MHz = 28M5.

📌 Code Q et suffixe d’indicatif

    {
        "id": "q_codes_traffic",
        "keywords": [
            "code", "codes", "qcode", "qcodes", "qrl", "qtc", "qru", "qrm", "qrn", "qsb", "qrh", "qro", "qrp", "qth", "qsy", "qrt", "qrx", "qrv", "qtr", "qrk", "qsa", "qrz",
            "suffixe", "suffixes", "portable", "mobile", "maritime", "transportable", "r.r.", "règlement des radiocommunications", "heure", "trafic", "carnet", "urgence", "14,300", "2182", "73", "tnx", "pse",
            "journal", "journal de bord", "détention", "detention", "conservation", "conserver"
        ],
        "text": (
            "Codes Q, Trafic, Suffixes & Exploitation : "
            "QRL = La fréquence est-elle occupée ? / Êtes-vous occupé ? | QTC = Avez-vous des messages à transmettre ? | QRU = Rien pour vous / avez-vous du trafic pour moi ? | QRM = Brouillage artificiel par une autre émission | QRN = Parasites atmosphériques (orage) | QSB = Fading / variation de l'intensité du signal | QRH = Fréquence qui varie / instabilité | QRK = Lisibilité (1 à 5) | QSA = Force du signal (1 à 5) | QRO = Augmenter la puissance | QRP = Réduire la puissance (<= 5 W) | QRZ = Qui m'appelle ? | QTH = Position géographique / emplacement de la station | QSY = Changer de fréquence | QRT = Arrêt définitif ou temporaire de la station | QRX = Attente / rappel | QRV = Je suis prêt / disponible | QTR = Quelle est l'heure exacte ? / L'heure exacte UTC est... "
            "Abréviations CW : PSE = S'il vous plaît | TNX = Merci | 73 = Amitiés. "
            "Suffixes de station : /P = Station portable (portée à la main, alimentation autonome) | /M = Mobile terrestre (à bord d'un véhicule en mouvement) | /MM = Maritime Mobile (à bord d'un navire en mer / eaux maritimes internationales) | /A = Résidence secondaire. "
            "Station Transportable : station déplacée puis opérée à l'arrêt temporaire dans un lieu fixe. "
            "Carnet de trafic / Journal de bord : durée de conservation obligatoire = 1 AN si tenu (facultatif en France métropolitaine). Fréquences d'urgence : 14,300 MHz (HF) et 2182 kHz (MF)."
        )
    },

Rien de nouveau. Il les connaît, mais les rajouter le recentre sur ses connaissances.

📌 Formules d’électricité, code couleur, et assimilées

    {
        "id": "formulas_electricity_rf",
        "keywords": [
            "formule", "formules", "loi", "ohm", "ohms", "résistance", "résistances", "resistance", "resistances", "ésistance", "ésistances",
            "tension", "tensions", "courant", "courants", "intensité", "intensités", "intensite", "intensites",
            "puissance", "puissances", "crête", "eff", "umax", "ueff", "condensateur", "condensateurs", "capacité", "capacités", "capacite", "capacites",
            "inductance", "inductances", "bobine", "bobines", "transfo", "transformateur", "impédance", "impédances", "impedance", "impedances",
            "ros", "tos", "pire", "par", "gain", "db", "dbe", "dbi", "dbd", "yagi", "oscillogramme", "oscilloscope", "résonance", "resonance", "filtre", "filtres",
            "intermodulation", "im3", "image", "transistor", "transistors", "beta", "aop", "amplificateur", "ampli", "synoptique",
            "période", "periode", "pulsation", "shunt", "galvanomètre", "galvanometre", "voltmètre", "voltmetre", "ampèremètre", "amperemetre",
            "sélectivité", "selectivite", "calculer", "connaisant", "pr=", "pi=",
            "polarisation", "verticale", "champ", "magnétique", "électrique", "plie", "plié", "90", "pile", "interne", "diviseur", "coaxial", "affaiblissement", "guide", "guides",
            "base commune", "émetteur commun", "emetteur commun", "collecteur commun", "classe d", "pwm", "découpage", "normalisée", "normalisee", "série normalisée", "ground-plane", "ground plane", "radians", "45°", "pll", "vcxo", "vco", "comparateur", "boucle", "doublet",
            "passe bande", "passe-bande", "coupe bande", "coupe-bande", "coupure", "fréquence de coupure", "frequence de coupure", "charge", "quantité", "quantite", "asymétrique", "asymetrique", "symétrique", "symetrique", "bifilaire", "électromètre", "electrometre"
        ],
        "text": (
            "Formules Électricité, Radioélectricité, Composants, Antennes & Synoptiques : "
            "Lois fondamentales & Puissances : U = R*I | P = U*I = I^2*R = U^2/R | Pile réelle : U = E - (r*I) | Diviseur de tension : U2 = Utot * R2/(R1+R2). "
            "Série normalisée de puissance des résistances : calibres 0,125W (1/8W), 0,25W (1/4W), 0,5W (1/2W), 1W, 2W, 5W, 10W. Choisir toujours la puissance normalisée immédiatement supérieure à la puissance dissipée (ex: 12V * 100mA = 1,2W -> calibre normalisé minimal de 2 W). "
            "Résistances : Req série = R1+R2 | Req // = (R1*R2)/(R1+R2). Code couleur : Noir=0, Marron=1, Rouge=2, Orange=3, Jaune=4, Vert=5, Bleu=6, Violet=7, Gris=8, Blanc=9 | Or=5%, Argent=10%. Noir au 1er chiffre vaut 0 (Noir-Vert-Orange = 05*10^3 = 5 kΩ). Attention au calcul : 80 x 10^2 = 8000 Ω = 8 kΩ (et NON 800 Ω !). "
            "Condensateurs : Ceq // = C1+C2 | Ceq série = (C1*C2)/(C1+C2). Charge emmagasinée : Q = C * U (en Coulombs : ex: 1 µF * 100 V = 100 µC = 10^-4 C = 0,1 mC ; attention 10^-4 C = 100 µC et NON 0,01 mC). "
            "Inductances : Leq série = L1+L2 | Leq // = (L1*L2)/(L1+L2). Inductance bobine : L = µ * N^2 * S / l. Si on double la surface des spires S en conservant le nombre de spires N, la valeur de la bobine est MULTIPLIÉE PAR 2 (x 2). "
            "Transistor Bipolaire (3 montages fondamentaux) : "
            "- Base commune : Impédance d'entrée Ze très basse/faible, Zs très élevée/forte, gain en tension fort, gain en courant <= 1, déphasage 0°. "
            "- Émetteur commun : Impédance d'entrée Ze moyenne, Zs moyenne, fort gain en tension, fort gain en courant, déphasage 180° (inverseur). "
            "- Collecteur commun (suiveur) : Impédance d'entrée Ze très élevée/forte, Zs très basse/faible, gain en tension <= 1, fort gain en courant, déphasage 0°. "
            "Classes d'amplification : Classe A (360°, linéaire, faible rendement 25-50%) | Classe B (180°, push-pull) | Classe AB (180°-360°, compromis linéarité) | Classe C (< 180°, polarisé en inverse sans polarisation directe, rendement max > 80%, réservé CW/FM) | Classe D (à découpage/PWM, fonctionne sans polarisation, très haut rendement). "
            "Polarisation transistors : NPN a le collecteur au +, base au +, émetteur au -. PNP a l'émetteur relié au + (P comme +), collecteur au -, base au -. "
            "Diodes & FET : Grille de FET = isolée (impédance d'entrée quasi-infinie). Diode Zener = régulation de tension en polarisation inverse. Diode Varicap = condensateur variable par tension inverse. "
            "Instruments de mesure : Voltmètre branché en dérivation/parallèle, impédance d'entrée TRÈS ÉLEVÉE (infinie) pour ne pas perturber la mesure (ex: pour mesurer sur 1 MΩ, utiliser un voltmètre électronique de 100 MΩ/V ; un électromètre n'est pas un instrument approprié) | Ampèremètre branché en série, impédance quasi-nulle. Oscilloscope : période T = div * base_temps, f = 1/T. U_eff = U_max / 1,414. "
            "Transformateurs & Lignes : Transformateur alimenté par une pile (courant continu DC) = aucune induction, tension au secondaire strictement nulle (Us = 0 V) ! En alternatif : m = Ns/Np = Us/Up = Ip/Is | Zp/Zs = (Np/Ns)^2. Ligne quart d'onde adaptation : Z0 = √(Z1*Z2). Coax à air : Z0 = 138 log10(D/d). Câble coaxial = ligne ASYMÉTRIQUE (blindage relié à la masse). Ligne bifilaire (échelle à grenouille) = ligne SYMÉTRIQUE. "
            "Antennes : "
            "- Doublet demi-onde λ/2 : Longueur théorique (vide) L = 150 / f(MHz) (ex: à 7,059 MHz -> 150/7,059 = 21,25 m) | Longueur réelle pratique L = 142 / f(MHz) (raccourcissement 5 %). Impédance centre droit ≈ 73 Ω, plié 90° (V inversé) ≈ 36 Ω, trombone ≈ 300 Ω. "
            "- Ground-plane λ/4 verticale : avec radians horizontaux Z ≈ 36 Ω ; avec radians inclinés à 45° vers le bas, Z monte à 50 Ω (adaptation parfaite 50 Ω, ROS 1:1). "
            "- Antenne Ground-Plane 5/8 λ : 5/8 λ = 0,625 λ, elle est donc PLUS LONGUE qu'un dipôle demi-onde (λ/2 = 4/8 λ = 0,5 λ) et plus longue qu'une quart d'onde (λ/4). "
            "- Yagi : directeurs et réflecteurs augmentent le gain, réduisent l'angle d'ouverture et diminuent l'impédance au centre. Couplage 2 Yagi = +3 dB. "
            "- ROS / TOS : ROS = (1+√(Pr/Pi))/(1-√(Pr/Pi)) = Umax/Umin | TOS = (ROS-1)/(ROS+1) | Pr = Pi * [(ROS-1)/(ROS+1)]^2. "
            "Puissances : PIRE (dBi) = PAR (dBd) + 2,15 dB. Gain net = Gain antenne - Pertes câble. Décibels puissance : 10 log10(P1/P2) (+3dB=x2, +10dB=x10). "
            "Résonance LC & Filtres : f0 = 1/(2π√(LC)) | XL = 2πfL | XC = 1/(2πfC). Circuit LC série en ligne sur le signal = Filtre PASSE-BANDE (Z=0 minimale à f0, ne laisse passer que la résonance) | Circuit LC bouchon parallèle en ligne = Filtre COUPE-BANDE / Réjecteur (Z infinie à f0 si idéal sans pertes). Si le facteur de qualité Q et L, C sont donnés, l'impédance à la résonance du circuit bouchon vaut : Z = Q * √(L/C) (ex: L=25µH, C=100pF, Q=100 -> Z = 100 * √(25/100) = 50 kΩ). "
            "Filtres RC et RL (atténuation 6 dB/octave par composant réactif) : Fréquence de coupure fc = 1 / (2π*R*C) ou R/(2π*L) (ex: R=1 kΩ, C=100 pF -> fc = 1/(2π*1000*10^-10) ≈ 1,59 MHz ≈ 1,6 MHz). Topologies 1er ordre : Passe-bas = R série et C // à la masse (ou L série et R //) | Passe-haut = C série et R // à la masse (ou R série et L // à la masse, bobine en bas vers la masse). "
            "Synoptiques Récepteurs, Émetteurs & PLL : "
            "- Boucle PLL : comparateur de phase + filtre passe-bas de boucle + VCXO/VCO + diviseur. Sur un synoptique avec VCXO/multiplicateur, l'élément filtrant manquant dans la boucle est le filtre passe-bas ! "
            "- Récepteur superhétérodyne : Antenne -> RF -> Mélangeur (+ Oscillateur Local) -> FI -> Démodulateur -> Ampli BF -> HP. Étage de démodulation entre FI et BF : si un BFO est connecté = Détecteur de produit (CW/BLU) ; si aucun BFO n'est présent = Détecteur d'enveloppe (ou Détection AM). Démodulation FM = Discriminateur. Fréquence image = f_signal ± 2*f_FI. Avantage récepteur hétérodyne = meilleure sensibilité et sélectivité. "
            "- Émetteur : Modulateur AM = mélangeur AF + porteuse issue d'un Oscillateur Local (OL). Taux de modulation maximal sans distorsion = 100%. Émetteur BLU = micro -> BF -> modulateur équilibré -> filtre quartz -> mélangeur RF -> ampli linéaire -> antenne."
        )
    },

Le plus dur pour lui était les classes d’amplificateurs. Pour le reste, avoir ces informations le confirme dans sa voie initiale de réflexion plutôt que de partir dans tous les sens. Je ne l’ai pas dit, mais les traces d’exécution sont enregistrées par Inspect AI et on peut ainsi lire sa réflexion ainsi que sa réponse finale.

📌 Législation et urbanisme

    {
        "id": "urbanism_sanctions",
        "keywords": [
            "pylône", "pylônes", "pylone", "pylones", "hauteur", "mât", "mâts", "mat", "mats",
            "urbanisme", "mairie", "déclaration", "declaration", "antenne", "antennes", "station", "stations",
            "transportable", "sanction", "sanctions", "taxe", "taxes", "brouillage", "anfr", "usurpation", "radio-club", "f5v", "f5vxy", "cpce", "l39"
        ],
        "text": (
            "Urbanisme, Sanctions & ANFR : "
            "Urbanisme & Pylônes : Pylône ou mât de plus de 12 mètres = Déclaration préalable en Mairie (Code de l'Urbanisme). "
            "Taxes ANFR : Taxe annuelle d'utilisation des fréquences = SUPPRIMÉE (0 €). Taxe de contrôle pour brouillage = 450 €. "
            "Sanctions CPCE : Usurpation d'indicatif d'État ou de station = 1 an de prison et 30 000 € d'amende (Art L39 CPCE). Émission sans autorisation = 6 mois de prison et 30 000 € d'amende. Révocation de l'indicatif = autorité administrative (ministre / ANFR)."
        )
    }

Là encore, un simple rappel historique et une mise à jour des sanctions…

Solver Inspect AI

L’ajout dans la chaîne d’Inspect AI est alors assez simple. Il suffit de déclarer un solver et de l’insérer dans la liste des solveurs (anciennement appelée plan) de l’agent. La fonction solve est alors appelée pour chaque question et insère si nécessaire un mémento.

@solver
def memory_rag_retriever():
    """Inspect AI solver performing in-memory exact-word-boundary RAG retrieval."""
    async def solve(state: TaskState, generate: Generate) -> TaskState:
        query_text = state.user_prompt.text
...
        matched_chunks = [c["text"] for c in KNOWLEDGE_BASE if chunk_matches(c)]
        if matched_chunks:
            rag_context = (
                "\n\nMEMENTOS DE RÉFÉRENCE SPÉCIFIQUES POUR CETTE QUESTION :\n"
                + "\n".join([f"- {t}" for t in matched_chunks])
            )
            if state.messages and isinstance(state.messages[0], ChatMessageSystem):
                state.messages[0].content += rag_context
            else:
                state.messages.insert(0, ChatMessageSystem(content=rag_context))
        return state
    return solve

🔎 Résultats

Analysons maintenant les résultats. Bien que le prompt et le “RAG” aient été optimisés explicitement pour Ministral, j’ai quand même relancé certains des autres modèles par acquit de conscience. Et là, l’histoire devient très intéressante ! Sans surprise, avec le RAG, Ministral obtient le meilleur score en réglementation à ~85 % de taux de bonnes réponses. Pas très loin derrière, Gemma et Qwen3 sont à ~78 %, soit de très bons taux !

Regardons voir maintenant l’impact sur le taux de bonnes réponses en technique. C’est une bonne nouvelle : le RAG n’a aucun impact négatif sur la technique et gagne même quelques points. Ce n’était pas une évidence, car nous avions vu qu’augmenter ou légèrement modifier le prompt pouvait parfois perdre le SLM. Qwen3 regagne le même score qu’en zero-shot, et Gemma 4 obtient le même score que Qwen3. Ministral 3 reste en tête.

Même pour Ministral, Python lui apporte la certitude dans les calculs, en particulier sur les calculs de résonance LC, les décibels et les atténuateurs. Le score technique passe de ~78 % en zero-shot à ~87 % avec le RAG + Python (+9 points).

Par ailleurs, l’overtooling est redevenu raisonnable pour l’ensemble des modèles :

Le plus fou, c’est que les temps d’exécution restent tout à fait raisonnables même s’il y a un léger impact. On parle quand même d’une réponse moyenne de ~6 s / question sur une petite machine.

Là encore, fait incroyable de Gemma-4-E4B-it qui avec seulement 4 milliards de paramètres et un overtooling assez fort réussit tout de même à rivaliser. Avec le harnais RAG + Python, il bondit à 79,2 % et 100 % de réussite ANFR !

Conclusion

Il n’y a maintenant plus de doute possible : un SLM avec 8 Go de vRAM peut devenir radioamateur ! Le taux de réussite à l’examen est maintenant de 100 % 🏆, et il répond plus vite que nous. Pour rappel, il faut une note ≥ 10/20 en réglementation et en technique pour obtenir l’examen. Par ailleurs, si vous avez retenu les chunks ci-dessus, vous aussi pouvez devenir radioamateur.

J’aurais pu analyser encore les quelques erreurs résiduelles. Pour rappel, 100 % des erreurs techniques restantes sont liées à l’analyse d’images. La connaissance du RAG pourrait probablement être légèrement améliorée encore pour gagner quelques points en réglementation, par exemple en précisant les pièges de sous-bandes satellites (comme la restriction à 14,250 MHz) ou la distinction entre l’article S25 du RR (morse) et la recommandation CEPT T/R 61-01 (libre circulation). À ce stade, j’ai la compréhension suffisante de ce qu’il lui faut selon le contexte d’utilisation. Je vais donc m’arrêter là. Ce ne sont pas les idées qui manquent, comme l’intégration avec GNURadio via gr-mcp par exemple. Mais disons que dans un cadre purement off-line, je sais maintenant qu’un SLM peut aider.