Nous entraînons des modèles RWKV à piloter les 231 outils réels de notre assistant Gungnir. Ce billet documente un résultat que nous n'attendions pas si tôt : après un seul epoch de state-tuning, facturé 0,53 $ de GPU, notre RNN local de 2,9 milliards de paramètres obtient exactement le même score global qu'un modèle cloud dix fois plus gros sur notre banc d'essai. Et le résultat se réplique au bit près.
Tout ce qui suit est vérifiable : le banc, les schémas d'outils, les générations brutes, les scripts et les empreintes cryptographiques des modèles sont publiés. Un relecteur hostile est le bienvenu.
Un assistant agentique reçoit une demande en langage naturel et doit décider quel outil appeler. Sur Gungnir, cela veut dire choisir parmi 231 fonctions dont beaucoup se ressemblent : archiver ou supprimer une carte, chercher dans les mails ou sur le web, cinq variantes d'analyse de coûts. Il faut ensuite remplir les arguments requis sans en inventer. Et quand l'utilisateur dit simplement merci, la bonne réponse est de ne rien appeler du tout.
Les gros modèles cloud font cela correctement. Notre pari est qu'un petit modèle récurrent, exécutable sur une machine ordinaire, peut apprendre le même métier. L'enjeu dépasse notre produit : un RNN n'a pas de KV cache, son état de session occupe une taille constante quelle que soit la longueur de la conversation, ce qui change l'économie du service d'agents en local. Nous avions déjà exploré cette famille d'architectures pour la recherche documentaire ; ici nous nous attaquons à la décision d'action.
Nous avons construit un juge de 82 cas sur les schémas d'outils réels de Gungnir, réparti en cinq catégories : sélection difficile (23 cas de quasi-doublons, le piège archiver contre supprimer), remplissage d'arguments (22), sélection simple (18), abstention (17 cas où aucun outil ne doit être appelé) et multi-étapes (2).
Trois précautions structurent ce juge :
Le juge, les schémas des 231 outils, les scripts et les sorties brutes sont publiés dans le dépôt du banc (lien en fin d'article), aux côtés du code de Gungnir qui est lui-même ouvert.
La cible est qwen/qwen3-30b-a3b-instruct-2507, un mixture-of-experts de 30 milliards de paramètres réputé pour le function-calling, interrogé via OpenRouter dans son mode normal : les 231 schémas bruts dans le contexte. Score : 58/82 (70 %), avec une abstention parfaite (17/17).
Côté RWKV, notre pipeline est différent et assumé comme tel : un retriever (un embedder RWKV de 144 M que nous avions fine-tuné pour la recherche) présélectionne les 40 outils les plus plausibles, mesuré à 100 % de rappel sur le juge, et le modèle choisit parmi eux. Un petit modèle à 4 096 tokens de contexte natif ne peut pas avaler 31 000 tokens de schémas ; le retrieval n'est pas une optimisation, c'est la condition d'existence du pipeline local. Les deux systèmes répondent aux mêmes 82 requêtes, chacun avec son échafaudage.
Au passage, le choix du checkpoint de départ a réservé une leçon. Nous avons mesuré trois générations successives de RWKV-7 2,9B publiées par BlinkDL : la plus récente (G1h, juillet 2026) est significativement moins bonne en sélection d'outil que la précédente (G1g, mai 2026) : 29/82 contre 38/82, dominée dans toutes les catégories, p = 0,012 en test apparié. Le progrès des checkpoints généralistes n'est pas monotone sur une capacité étroite. Mesurez votre cas d'usage avant de mettre à jour ; nous avons failli entraîner sur le mauvais point de départ.
RWKV-7 est un réseau récurrent : il maintient un état interne qui résume tout ce qu'il a lu. Le state-tuning, proposé par l'écosystème RWKV-PEFT, n'entraîne que l'état initial de chaque couche : 5,2 M de paramètres sur 2,9 Md, soit 0,18 % du modèle, les poids restant gelés. L'artefact produit est un fichier de 11 Mo qui se pose sur le modèle de base au chargement. On peut y penser comme une disposition d'esprit apprise : le modèle démarre chaque requête déjà configuré pour le métier d'appel d'outils.
Les données : 2 623 exemples construits sur les schémas réels, dont 312 cas d'abstention (12 %). La construction est vérifiable par principe : pour chaque outil, un générateur produit des requêtes qui l'exigent, et l'appel correct constitue le label, validé contre le schéma. Chaque exemple reproduit le format exact du déploiement, top-40 du retriever inclus, outils frères côte à côte pour apprendre les nuances.
L'entraînement : 1 epoch, 2 556 pas, contexte 6 144, bf16, sur une RTX 3090 louée 0,22 $ de l'heure. Durée : environ 2 heures. Coût : 0,53 $. La loss passe de 1,40 à 0,05.
Le tableau complet, tous modèles évalués sur les mêmes 82 cas avec le même scoreur :
| Catégorie (nb de cas) | G1g base | G1g + state-tuning | Qwen3-30B (231 bruts) | Qwen3-30B (+ top-40) |
|---|---|---|---|---|
| Abstention (17) | 0 | 12 | 17 | 17 |
| Arguments (22) | 9 | 19 | 17 | 20 |
| Sélection difficile (23) | 12 | 16 | 14 | 17 |
| Sélection simple (18) | 7 | 11 | 10 | 16 |
| Multi-étapes (2) | 0 | 0 | 0 | 1 |
| Global (82) | 28 (34 %) | 58 (70 %) | 58 (70 %) | 71 (86 %) |
Trois lectures :
L'effet d'entraînement est massif et ciblé. De 28 à 58 cas réussis. Sur les 34 cas où les deux versions divergent, l'entraînée gagne 32 fois et perd 2 fois (p = 6,9×10⁻⁸, test de McNemar exact). L'abstention passe de 0/17 à 12/17 : le modèle a appris à se taire. Le remplissage d'arguments passe de 9/22 à 19/22. Ce sont précisément les deux comportements que le jeu de données ciblait.
L'égalité avec Qwen n'est pas une imitation. Sur le run de référence, les deux systèmes obtiennent 58/82 mais ne sont d'accord que sur 50 cas : chacun réussit 16 cas que l'autre rate. Le RWKV entraîné devance le 30B sur les arguments, la sélection difficile et la sélection simple ; Qwen conserve l'avantage sur l'abstention (17/17 contre 12/17).
Et la cible elle-même fluctue, pas nous. Quatre exécutions de Qwen via l'API, toutes à température 0, donnent 57, 57, 58 et 61 sur 82 : le service n'est pas déterministe (les grands MoE servis en ligne ne le sont généralement pas). Notre 58, lui, se recalcule au caractère près sur n'importe quelle machine. La parité s'entend donc ainsi : un score déterministe posé au centre de la fourchette de variation du modèle cloud.
Le format est appris, plus contraint. Le modèle de base avait besoin d'une grammaire formelle pour produire du JSON valide ; entraîné, il n'en a plus : une seule sortie non parsable sur 82, en génération libre. Et aucun faux refus : sur les 65 cas qui exigent un appel, le modèle entraîné n'a jamais refusé à tort. Le gain d'abstention ne s'est pas payé en excès de prudence.
L'objection évidente contre le tableau ci-dessus : notre modèle reçoit un top-40 trié par retriever, Qwen navigue dans 231 schémas bruts. La parité vient-elle du modèle ou de la présélection ? Nous avons fait le test avant que vous ne le demandiez : mêmes 82 cas, même top-40 par cas, envoyés à Qwen.
Réponse : Qwen + top-40 = 71/82 (86 %). La présélection lui vaut 13 cas. Deux conclusions, chacune à sa place :
Nous avons refait la totalité de la chaîne sur une seconde machine : ré-entraînement complet depuis le modèle de base, puis ré-évaluation des 82 cas. Résultat : 58/82, mêmes catégories, mêmes cas réussis et ratés, et les 164 générations (82 pour la base, 82 pour le modèle entraîné) sont identiques caractère par caractère. Les deux checkpoints entraînés portent la même empreinte SHA-256.
La chaîne est en fait déterministe de bout en bout : état initial nul, ordre de données fixe, génération gloutonne. Ce n'est donc pas une moyenne avec sa marge d'erreur, c'est un point exact que quiconque peut recalculer. Nous préférons cette propriété à un intervalle de confiance.
Un résultat n'est utile que si son périmètre est net. Le nôtre :
Le dépôt public du banc : git.scarletwolf.cloud/kevin/rwkv-toolcaller-bench (miroir : Codeberg). Il contient : le juge (82 cas), les schémas des 231 outils, les scripts d'évaluation et de scoring, les générations brutes de tous les runs (y compris celles qui nous sont défavorables), les courbes de loss, les recettes d'entraînement pod par pod, et les empreintes SHA-256 du modèle de base et des états entraînés (les fichiers de 11 Mo sont inclus). L'environnement exact est épinglé : commit RWKV-PEFT, versions de torch et de peft, image Docker. La référence cloud est qwen3-30b-a3b-instruct-2507 via OpenRouter.
Matériel requis pour tout refaire : une carte à architecture Ampere ou plus récente (le bf16 est requis par les kernels d'entraînement RWKV-7 ; les T4 gratuites de Kaggle ne peuvent pas), environ 2 heures, moins d'un dollar.
La nuit de la rédaction, le deuxième barreau de l'échelle a rendu son verdict : un LoRA (r=32, environ 1 % des paramètres, 2 epochs sur les mêmes données, 0,90 $) atteint 61/82 (74 %).
| Catégorie | State (rung 1) | LoRA (rung 2) |
|---|---|---|
| Abstention | 12/17 | 15/17 |
| Arguments | 19/22 | 16/22 |
| Sélection difficile | 16/23 | 16/23 |
| Sélection simple | 11/18 | 14/18 |
| Global | 58 | 61 |
Trois précisions d'honnêteté avant d'applaudir. Un, l'écart global avec le state n'est pas statistiquement établi (11 cas gagnés contre 8 perdus, p = 0,65) : à ce stade, LoRA et state sont au même niveau, avec des profils différents. Deux, contrairement au state, le LoRA part d'une initialisation aléatoire : ce run n'est pas reproductible au bit près, et sa variance entre runs reste à mesurer. Trois, l'avance de Qwen à échafaudage égal reste significative (p = 0,04).
Ce que le profil raconte est plus intéressant que le score : le LoRA absorbe mieux l'abstention (15/17, il ne reste que deux pièges) et la sélection simple, mais régresse sur les arguments (16/22 contre 19/22). Plus de capacité d'adaptation ne domine pas partout : elle déplace le compromis.
La nuit suivante, trois expériences de plus, ciblant les faiblesses identifiées. Nous avons ajouté 162 exemples construits exprès : 113 « pièges actionnables » (des demandes qui sonnent comme une action mais qu'aucun outil ne couvre, le type précis d'abstention qui résistait) et 49 « chercher avant d'agir ». Puis réentraîné les deux méthodes sur ces données v3, et tenté une composition.
| Catégorie | state v3 | LoRA v3 | combo (état v3 + LoRA v3) |
|---|---|---|---|
| Abstention | 16/17 | 17/17 | 17/17 |
| Arguments | 18/22 | 15/22 | 17/22 |
| Sélection difficile | 15/23 | 15/23 | 17/23 |
| Sélection simple | 12/18 | 12/18 | 8/18 |
| Multi-étapes | 0/2 | 0/2 | 0/2 |
| Global | 61 | 59 | 59 |
Quatre enseignements :
La barre reste 71/82, le score du 30B avec le même échafaudage : l'écart est désormais de 10 cas, concentré sur la sélection. Et une réplication sur outils publics est prévue, sur un juge neuf tenu privé jusqu'à la mesure.
Souveraineté et économie. Les requêtes d'un agent transportent le contexte de travail complet de l'utilisateur ; les faire traiter localement supprime la question du transfert. Et un RNN sert des sessions longues à mémoire constante, là où le KV cache d'un transformer croît avec la conversation.
Les 82 cas du juge n'apparaissent pas dans les données d'entraînement : 17 sont écrits à la main, 65 générés par une autre famille de modèle avec filtre de similarité, et le juge a été figé avant la première mesure. La loss très basse (0,05) indique une forte adaptation au format ; le score sur ces cas jamais vus mesure la généralisation.
C'est le barreau le moins cher de l'échelle (0,2 % des paramètres, 0,53 $) et il était prévu comme simple test de plomberie avant un LoRA. Il a atteint la cible seul. Le LoRA est en cours pour chercher mieux.
Que la compétence est un fichier. On charge le modèle de base une fois, et on peut échanger des états spécialisés par tâche, à chaud, sans dupliquer les 5,6 Go de poids. C'est un mode de déploiement en soi pour les agents locaux.
Le dépôt du banc est public, le code de Gungnir aussi. Les liens sont dans la section Reproduire. Si vous trouvez une faille dans le protocole, écrivez-nous, c'est le but de la publication.