Le meilleur moteur pour un agent local sur Qwen3.8-27B
Lancez MTPLX avec Qwen3.8-27B-MTPLX-Optimized-Speed et --mtp --depth 3.
Nous avons mesuré onze configurations sur huit moteurs, sur un seul M5 Max. Pour du travail d'agent, il gagne sur toutes les mesures qui comptent, et le deuxième n'est pas près :
| MTPLX Optimized-Speed | llama.cpp b10434 +MTP | Ollama 0.32.13 | |
|---|---|---|---|
| Premier jeton | 99 ms | 125 ms | 240 ms |
| Premier jeton, 56k froid | 301 ms | 365 ms | 574 ms |
| Réutilisation de préfixe | 7 530 / 7 530 | 7 526 / 7 530 | 0 / 7 530 |
| Débit | 44,4 tok/s | 31,8 | 32,8 |
| Mémoire | 27 Go | 36,8 Go | 30,3 Go |
Soit +40 % de débit, 26 ms de latence en moins par tour, et 10 Go de mémoire en moins que le meilleur des autres. C'est ce que nous faisons tourner en production.
Pourquoi ces mesures, et pas les tokens par seconde
Un agent n'est pas un chat. Il ne déroule pas une longue réponse d'un trait — il enchaîne des dizaines de tours courts, et chaque tour relit tout ce qui précède. Le chiffre que vous ressentez est donc le temps au premier jeton, payé une fois par tour, et il dépend presque entièrement de la capacité du moteur à garder le prompt précédent en cache.
L'écart sur cette mesure est de 335× dans notre tableau — de 99 ms à 33 secondes. L'écart sur le débit est de 5 %. Voilà tout l'argument : pour un agent, choisissez sur la latence et la réutilisation de préfixe ; le débit départage les ex æquo.
Deux moteurs réutilisent au token près (MTPLX, llama.cpp). Un réutilise par blocs de 1 024 tokens et recalcule 1 386 tokens à chaque tour, indéfiniment (oMLX, 1 968 ms). Trois ne réutilisent rien du tout et repaient le prompt entier à chaque fois — mlx-vlm à 9 982 ms, rapid-mlx à 33 195 ms. Sur une session d'agent de 60 tours, ce dernier coûte 33 minutes d'attente pure.
Le tableau complet
« À chaud » et « à 56k » sont des tok/s. Premier jeton sur le tour à chaud ; @56k sur un prompt froid de 55 839 tokens.
| Moteur | Poids | À chaud | À 56k | Premier jeton | @56k | Mémoire | tok/s/W |
|---|---|---|---|---|---|---|---|
| MTPLX Bare-Speed | MTPLX 4 bits g64 | 56,0 | 46,5 | 101 ms | 322 ms | 22,0 Go | 0,694 |
| MTPLX Optimized-Speed | MTPLX 4 bits g32 | 44,4 | 37,5 | 99 ms | 301 ms | 27,0 Go | 0,623 |
| mlx-vlm + drafter MTP | MLX 4 bits ⁽¹⁾ | 43,3 | 28,9 | 9 982 ms | 100 733 ms | 15,5 Go | 0,744 |
| MTPLX Optimized-Quality | MTPLX 8 bits g64 | 40,8 | 30,3 | 118 ms | 100 243 ms | 32,9 Go | 0,575 |
| Ollama 0.32.13 | GGUF (non déclaré) | 32,8 | 21,7 | 240 ms | 574 ms | 30,3 Go | 0,451 |
| llama.cpp b10434 + MTP | GGUF Q5_K_XL ⁽²⁾ | 31,8 | 22,7 | 125 ms | 365 ms | 36,8 Go | 0,395 |
| rapid-mlx 0.12.11 | MLX 4 bits ⁽¹⁾ | 30,2 | 24,7 | 33 195 ms | 287 548 ms | 15,0 Go | 0,544 |
| oMLX 0.6.0-dev | oQ4e-mtp (tiers) | 29,8 | 24,6 | 1 968 ms | 1 991 ms | 16,7 Go | 0,512 |
| mlx-lm 0.31.3 | MLX 4 bits ⁽¹⁾ | 28,8 | 24,0 | 432 ms | 799 ms | 14,6 Go | 0,472 |
| LM Studio 0.4.21 +MTP | GGUF Q5_K_XL ⁽²⁾ | 27,8 | 23,4 | 419 ms | 825 ms | 36,3 Go | 0,422 |
| LM Studio 0.4.21 par défaut | GGUF Q5_K_XL ⁽²⁾ | 23,1 | 18,7 | 359 ms | 865 ms | 35,2 Go | 0,351 |
⁽¹⁾ ⁽²⁾ = fichier de poids identique au bit près. Les lignes MTPLX ont tourné sur la
2.6.0. Une cellule, un export. Toutes les colonnes sont des médianes du tour à chaud.
tok/s/W divise le débit de décodage par la puissance du SoC entier (de 58 à 83 W
selon le moteur) — pas du GPU seul, qui classerait autrement.
Comment le lire. Les écarts de débit inférieurs à 8 % sont du bruit : d'Ollama à LM Studio+MTP (32,8 à 27,8), ces moteurs sont à égalité, pas classés. Les deux entrées à 100 secondes sont des défauts de cache, pas une vitesse de moteur : Optimized-Quality fait 118 ms à chaud et revient à 498 ms sur le tour 56k répété. La mémoire n'est pas comparable entre familles (llama.cpp mappe son fichier : 36,8 Go résidents = 19,4 Go physiques).
Ce qui surprend : le serveur ne compte presque pas
mlx-vlm, mlx-lm et rapid-mlx ont servi le même fichier,
lmstudio-community/Qwen3.8-27B-MLX-4bit, snapshot 6067b15c, octet pour octet. Deux
d'entre eux tournaient nus, sans spéculation :
30,2 contre 28,8 tok/s. Un écart de 4,9 % — sous notre propre bruit de relance.
Changer de serveur MLX ne rapporte rien. Le troisième, mlx-vlm, atteint 43,3 — mais il tournait avec le drafter MTP chargé. Ces +50 % viennent du drapeau, pas du serveur — voir l'annexe sur la prédiction multi-token, qui arrive à la même conclusion par l'autre bout.
Choisir sous une autre contrainte
Notre recommandation optimise le travail d'agent. Si la vôtre diffère, le tableau répond déjà :
- Empreinte minimale → mlx-lm, 14,6 Go. Vous perdez la granularité du cache de préfixe.
- Meilleure autonomie → mlx-vlm, 0,744 tok/s/W. Inutilisable pour un agent (9 982 ms au premier jeton), excellent en traitement par lots.
- Débit brut → MTPLX Bare-Speed, 56,0 tok/s. Nous le déconseillons : l'auteur des quantifications publie une divergence par rapport à bf16 de 0,0376 contre 0,0220 pour Optimized-Speed — 36× plus loin de bf16 que le build 8 bits. Sa mesure, pas la nôtre, non reproduite.
- Vous êtes déjà sur llama.cpp → restez-y. Ajoutez
--spec-type draft-mtpet vous comblez l'essentiel de l'écart ; 125 ms au premier jeton conviennent à un agent.
Faites-le tourner avec le raisonnement actif
Qwen recommande xhigh pour le travail agentique et avertit qu'un effort plus faible
« peut conduire à une analyse insuffisante, à davantage d'échecs et à des reprises
répétées ». MTPLX 2.7.1 signale par ailleurs le raisonnement désactivé comme un problème
connu sur Qwen3.8. high n'existe pas sur ce modèle — low, medium, xhigh seulement,
et xhigh est la valeur par défaut.
⚠️ À noter : le niveau d'effort est une variable de gabarit de conversation, pas un champ d'API — envoyé comme paramètre de requête ordinaire, il est ignoré en silence. Il doit être posé au lancement.
Quatre limites qui changent votre lecture
- Rien ici n'a mené une tâche à son terme. La sortie était plafonnée à 400 tokens et chaque exécution a atteint ce plafond. Ce sont des débits de flux sur des continuations tronquées.
- Le raisonnement était coupé pour toutes les mesures, afin de rendre les moteurs comparables. Ce n'est pas ainsi que nous déployons — voir plus haut. Nous n'avons aucun chiffre sur ce que le raisonnement coûte à chaque moteur.
- Les réglages n'étaient pas symétriques. llama.cpp a reçu des drapeaux de cache
explicites que les moteurs MLX n'ont pas eus ; MTPLX tournait en
--profile turbo; les paramètres d'échantillonnage et les limites thermiques diffèrent d'un moteur à l'autre. Les écarts entre familles sont indicatifs, pas propres. - Nous recommandons le moteur qui seul sait lire son propre format de quantification, mesuré avec notre propre outil, publié sur notre propre site. Les lignes MTPLX sont les seules où moteur et format de poids ne peuvent pas être séparés. Pesez-le en conséquence — la table des drapeaux, en annexe, est la partie de cette page qu'il ne nous coûte rien d'avoir juste.
Deux moteurs à MTP natif, vmlx et vllm-mlx, n'ont pas pu être mesurés à temps.
Annexe : le drapeau MTP, moteur par moteur
Qwen3.8 embarque une tête de prédiction multi-token dans ses poids. Le modèle propose plusieurs tokens d'avance, le moteur les vérifie en une passe. Quatre des six moteurs qui la supportent la livrent éteinte.
| Moteur | Drapeau | Activé d'origine ? |
|---|---|---|
| MTPLX ⁽ᵐ⁾ | --mtp --depth 3 |
oui |
| vmlx ⁽ᵈ⁾ | --native-mtp-depth |
oui |
| llama.cpp ⁽ᵐ⁾ | --spec-type draft-mtp --spec-draft-n-max 4 |
non |
| LM Studio ⁽ᵐ⁾ | --speculative-draft-mtp |
non |
| mlx-vlm ⁽ᵐ⁾ | --draft-kind mtp --draft-model mlx-community/Qwen3.8-27B-MTP-4bit |
non |
| vllm-mlx ⁽ᵈ⁾ | --enable-mtp |
non |
| Ollama · mlx-lm · rapid-mlx | pas de support | — |
⁽ᵐ⁾ attesté par nos propres lignes de lancement et journaux. ⁽ᵈ⁾ d'après la documentation du projet uniquement.
Nous avons mesuré ce que coûte l'ignorance : même fichier de poids, même contexte de 65 536, même séquence thermique, tout identique sauf deux drapeaux. LM Studio passe de 23,1 à 27,8 tok/s, soit +19,9 %. Aucune interface graphique ne le montre. Sur mlx-vlm, la même tête vaut +50 %.
À noter : le drafter est embarqué dans le GGUF pour llama.cpp et LM Studio, mais mlx-vlm exige un second dépôt téléchargé à côté.
Vérifiez qu'il est réellement engagé — un drapeau accepté n'est pas un drapeau qui fonctionne :
# llama.cpp / LM Studio — le journal doit mentionner un contexte de draft au démarrage
grep -i "draft" server.log # « creating MTP draft context »
# tout moteur compatible OpenAI — le taux d'acceptation doit être à 0,9 ou plus
curl -s localhost:8080/v1/chat/completions -d '…' | jq '.timings'
Reproduire ceci
Chaque chiffre vient d'une carte certifiée produite par asiai, via un chemin unique et scripté, avec gates de solitude, preuves d'identité du modèle servi et échantillonnage thermique. Exports bruts, lignes de lancement complètes et texte des prompts : demandez-les et nous les publions.
Si vous ne retenez qu'une chose : vérifiez si votre moteur dispose de la prédiction multi-token, et si elle est activée.