Aller au contenu

Accueil / IA et LLM en local

Qwen 3.6 ou Gemma 4 sur Mac mini M4: ce que coûte la réflexion

Qwen 3.6 35B-A3B et Gemma 4 26B-A4B sur Mac mini M4 32 Go: diagnostic Kerberos et extraction JSON, réflexion activée puis désactivée. Temps, tokens et qualité.

Rémi Vernier
27 octobre 2026 · 10 min de lecture

Les modèles locaux récents activent souvent la réflexion par défaut. Nous allons voir ce qu’elle apporte, sur un Mac mini M4 32 Go, quand on confie à un modèle un diagnostic Kerberos ou l’extraction d’un événement du journal de sécurité. Sur nos essais, la réflexion multiplie le temps de réponse par 4 à 7. Sur le diagnostic, elle n’améliore nettement la réponse que pour l’un des deux modèles. Et pour l’extraction JSON, les vrais problèmes viennent d’ailleurs: de la façon dont le contenu est rangé dans la réponse de l’API.

Les deux modèles testés sont des MoE qui tiennent dans 32 Go de mémoire unifiée: Qwen 3.6 35B-A3B et Gemma 4 26B-A4B.

Les deux modèles et leur taille réelle

Qwen 3.6 35B-A3B est sorti en avril 2026. D’après sa fiche, c’est un modèle de 35B paramètres au total dont 3B activés, et les modèles Qwen3.6 fonctionnent par défaut en mode réflexion. Gemma 4 26B-A4B est la variante MoE de la famille Gemma 4: 25,2B paramètres au total, 3,8B actifs, avec 8 experts actifs sur 128, plus un expert partagé.

Sur la maquette, les deux modèles sont chargés en MLX, quantifiés en 4 bits:

  • qwen/qwen3.6-35b-a3b: 20.4 Go de poids, contexte chargé 8192 tokens (déjà en mémoire au moment du labo);
  • google/gemma-4-26b-a4b-qat: 15.6 Go de poids (version QAT, entraînée en tenant compte de la quantification), contexte chargé 8192 tokens, chargement mesuré: 15.5 s.

Les deux ensemble pèsent 36 Go: il n’est donc pas question de les garder chargés en même temps sur une machine de 32 Go. Avec 20.4 Go de poids, Qwen laisse aussi assez peu de marge pour le contexte. Ce point a son importance, car la fiche Qwen recommande de garder un contexte d’au moins 128K tokens pour préserver les capacités de réflexion. Avec nos 8192 tokens, nous sommes très loin de cette recommandation.

Protocole

Le labo a été exécuté automatiquement le 27 octobre 2026 sur le Mac mini M4 32 Go, via l’API locale de LM Studio (moteur mlx-llm-mac-arm64-apple-metal-advsimd 1.13.1). Chaque essai commence par un appel de chauffe, non compté. Les mesures sont la médiane des répétitions suivantes. La méthode est la même que celle décrite dans l’article MLX ou GGUF dans LM Studio sur Mac mini M4.

Deux tâches:

  1. Un diagnostic Kerberos. Un utilisateur prend une erreur 401 sur https://intranet.corp.local. IIS tourne sous CORP\svc-intranet et journalise KRB_AP_ERR_MODIFIED. Côté contrôleur de domaine, un 4769 passe en succès avec le type de chiffrement 0x12 (AES256). Un collègue a réinitialisé le mot de passe de svc-intranet et créé un compte svc-intranet-test qui porte le même SPN HTTP/intranet.corp.local. Nous demandons la cause, les commandes setspn et PowerShell, et les risques, en 3 parties et 250 mots maximum. Température 0.2. Réflexion on: max_tokens 3500, 1 répétition. Réflexion off: max_tokens 1200, 2 répétitions.
  2. Une extraction JSON contrainte depuis un événement 4625 (échec NTLM de m.durand depuis WKS-0457, statut 0xC000006D, sous-statut 0xC000006A). Le schéma JSON est passé par l’API: il n’apparaît pas dans le prompt, mais les deux modèles produisent exactement les mêmes clés. Température 0, max_tokens 800, 2 répétitions. La réflexion n’a pas été désactivée sur cette tâche: avec un schéma JSON imposé, l’appel passe par l’API compatible OpenAI de LM Studio, sur laquelle notre labo n’applique pas ce réglage. Les deux modèles tournaient donc avec leur réglage par défaut, réflexion active.

Nous ne comparons donc réflexion on et off que sur le diagnostic.

Résultats

Essai Modèle Réflexion max_tokens Sortie (dont réflexion) Vitesse 1er token Durée totale
e1 Kerberos Qwen 3.6 on 3500 3499 (3347) 37.4 tok/s 0.69 s 92.6 s
e2 Kerberos Qwen 3.6 off 1200 502 (0) 39.2 tok/s 0.69 s 13.5 s
e3 Kerberos Gemma 4 on 3500 1667 (1276) 29 tok/s 0.65 s 58.1 s
e4 Kerberos Gemma 4 off 1200 448 (0) 29.6 tok/s 0.08 s 15.6 s
e5 JSON 4625 Qwen 3.6 défaut (on) 800 149 (148) 39.1 tok/s 0.76 s 4.6 s
e6 JSON 4625 Gemma 4 défaut (on) 800 126 (0) 30 tok/s 0.08 s 4.8 s

Quatre choses ressortent de ce tableau.

-> La vitesse de génération ne dépend presque pas de la réflexion: 37.4 contre 39.2 tok/s pour Qwen, 29 contre 29.6 pour Gemma. La réflexion ne ralentit pas la génération, elle ajoute simplement des tokens à produire. Toute la différence de durée vient donc du volume.

-> Qwen est plus rapide que Gemma (environ 37 à 39 tok/s contre 29 à 30), alors que ses poids sont plus lourds (20.4 Go contre 15.6 Go). Cela va à l’encontre de l’intuition « plus gros fichier, plus lent ». En revanche, c’est cohérent avec le nombre de paramètres actifs par token: 3B pour Qwen, 3,8B pour Gemma.

-> Le temps jusqu’au premier token est trompeur dès que la réflexion est activée. Les 0.69 s de Qwen en mode on correspondent au premier token de réflexion, pas au premier mot de la réponse. En divisant les tokens de réflexion par la vitesse, nous obtenons un ordre de grandeur (calculé, non mesuré) du délai avant le premier token utile: environ 90 s pour Qwen (3347 / 37.4) et 44 s pour Gemma (1276 / 29).

-> Gemma répond en 0.08 s au premier token en mode off, contre 0.65 s en mode on et 0.69 à 0.76 s pour Qwen dans tous les cas. Le prompt est identique d’une répétition à l’autre, donc la réutilisation du cache de prompt est une explication plausible côté Gemma. Pourquoi Qwen n’en profiterait pas, je ne sais pas le dire avec certitude à partir de ces seules mesures.

Tokens générés sur le diagnostic Kerberos Qwen 3.6, réflexion on 3347 réflexion Gemma 4, réflexion on 1276 réflexion 391 réponse Qwen 3.6, réflexion off 502 réponse Gemma 4, réflexion off 448 réponse max_tokens = 3500 152 réponse, tronquée réflexion réponse visible
Répartition des tokens de sortie: Qwen consomme presque tout le budget en réflexion.

Qwen en mode réflexion bute sur max_tokens

L’essai e1 est le résultat le plus instructif du labo. Qwen produit 3499 tokens pour un plafond de 3500. 3347 d’entre eux (96 %) partent dans la réflexion, ce qui laisse 152 tokens pour une réponse limitée à 250 mots. La génération s’arrête au milieu de la deuxième partie:

code
**Partie 2 : Vérification & Correction**
Vérifiez les SPN avec :

Après 92.6 secondes d’attente, nous n’avons donc aucune commande. Gemma s’en sort mieux avec le même plafond: 1276 tokens de réflexion (77 % de la sortie) et une réponse complète en 58.1 s. Le rapport on/off est de 6.9 en durée pour Qwen (92.6 / 13.5) et de 3.7 pour Gemma (58.1 / 15.6).

Sur un poste interactif, 3500 tokens paraissent déjà généreux pour une réponse de 250 mots. Avec Qwen 3.6, ce n’est pas le cas. Un plafond trop bas en mode réflexion ne donne pas une réponse plus courte: il donne une réponse coupée, ou vide.

Lecture de la qualité des réponses

Rappelons d’abord la bonne lecture du cas. Le 4769 en succès montre que le KDC a bien délivré un ticket pour HTTP/intranet.corp.local. Avec un SPN en double, ce ticket peut être chiffré avec la clé de svc-intranet-test, alors que IIS cherche à le déchiffrer avec celle de svc-intranet. D’où KRB_AP_ERR_MODIFIED. En pratique, cette erreur se lit d’ailleurs en général côté client, dans le journal Système. La réinitialisation du mot de passe n’est pas la cause en soi. Pour vérifier, nous recherchons les doublons et nous comparons le numéro de version de clé (kvno) du ticket présent dans le cache du client avec l’attribut msDS-KeyVersionNumber des deux comptes. Cette méthode est détaillée dans Kerberos: lire un ticket de service avec klist et Wireshark.

shell
setspn -Q HTTP/intranet.corp.local
setspn -X
klist get HTTP/intranet.corp.local
Get-ADUser svc-intranet -Properties msDS-KeyVersionNumber,ServicePrincipalName
Get-ADUser svc-intranet-test -Properties msDS-KeyVersionNumber,ServicePrincipalName
setspn -D HTTP/intranet.corp.local CORP\svc-intranet-test

Comparons maintenant les quatre réponses avec cette lecture.

Gemma, réflexion on (e3): c’est la meilleure réponse du lot. La cause est juste (doublon de SPN, ambiguïté sur le compte qui doit déchiffrer). Les commandes sont les bonnes: setspn -Q, un Get-ADObject filtré sur ServicePrincipalName, puis setspn -D sur le compte de test. Gemma signale aussi le vrai risque (retirer le SPN du mauvais compte) et pense au klist purge sur les postes.

Gemma, réflexion off (e4): les commandes sont les mêmes, l’analyse un peu plus floue (« le contrôleur de domaine ne peut pas garantir l’identité unique du service »), mais l’idée que le KDC peut choisir le mauvais compte est bien là. Le gain apporté par la réflexion est réel mais faible, pour 42 secondes de plus.

Qwen, réflexion off (e2): c’est la réponse la plus fragile. Le modèle invente une « collision de hachage ». Il propose Get-ADServiceAccount, qui ne renvoie que des comptes de service managés (MSA, gMSA) et ne trouvera jamais un compte utilisateur comme svc-intranet. Son filtre -like n’a d’ailleurs pas de caractère générique. Les setspn -L par compte et le setspn -D final restent corrects.

Qwen, réflexion on (e1): la cause est mieux formulée qu’en mode off. Le modèle voit bien le ticket chiffré avec la clé d’un compte et déchiffré avec celle de l’autre. Il y ajoute pourtant une « désynchronisation des clés AES256 » due à la réinitialisation, qui est discutable. Et la réponse s’arrête avant les commandes.

Aucun des quatre ne propose setspn -X, ni ne s’étonne que le doublon ait pu être créé. Les contrôleurs de domaine récents vérifient normalement l’unicité des SPN à l’écriture. C’est exactement le type de remarque qu’un administrateur senior ferait.

Extraction JSON: deux pièges

Sur l’événement 4625, les deux modèles répondent en moins de 5 secondes. Aucun des deux n’est utilisable tel quel.

Qwen (e5): la réponse finale est vide. Les 149 tokens de sortie sont comptés comme de la réflexion, et c’est là que se trouve le JSON, d’ailleurs correct:

json
{"event_id": 4625, "heure": "2026-10-24T02:13:47Z", "ordinateur": "SRV-FIC01.corp.local",
 "compte": "m.durand", "domaine": "CORP", "type_ouverture_session": 3,
 "statut": "0xC000006D", "sous_statut": "0xC000006A", "ip_source": "10.20.30.45",
 "station_source": "WKS-0457", "package_authentification": "NTLM"}

Un workflow qui lit uniquement le contenu de la réponse reçoit une chaîne vide. Le modèle a bien travaillé, mais c’est l’analyse de la sortie (ce qui est classé réflexion ou réponse) qui a dérapé.

Gemma (e6) remplit bien le champ de réponse avec un JSON syntaxiquement valide, conforme au schéma… et faux:

json
{"event_id": 0, "heure": "2thought", "ordinateur": "SRV-FIC01.corp.local", "compte": "m.durand",
 "domaine": "CORP", "type_ouverture_session": 3, "statut": "0xC000006D", "sous_statut": "0xC000006A",
 "ip_source": ": ", "station_source": "WKS-0457", "package_authentification": "NTLM"}

Le « thought » qui apparaît dans le champ heure évoque le marqueur de canal de réflexion de Gemma 4. Dans LM Studio, des utilisateurs ont dû régler à la main le découpage de la réflexion, avec les chaînes de début et de fin <|channel> et <channel|>. Notre hypothèse est donc un conflit entre le décodage contraint par le schéma et ce marqueur, mais elle reste à confirmer. Ce qui est sûr: un JSON valide n’est pas un JSON juste. Un event_id à 0 sur un 4625 doit être rejeté par une validation métier, pas seulement par la validation du schéma.

Limites de ces mesures

  • Un seul prompt par tâche, une seule répétition en mode on et deux en mode off. Ce sont des tendances, pas une statistique.
  • Température 0.2 en mode réflexion, alors que Qwen recommande temperature=1.0, top_p=0.95, top_k=20, presence_penalty=1.5 pour les tâches générales en mode réflexion. Ces réglages peuvent changer la longueur de la réflexion, dans un sens que nous n’avons pas mesuré.
  • Contexte chargé à 8192 tokens, très en dessous des 128K recommandés pour Qwen.
  • Pas de comparaison réflexion on et off sur l’extraction JSON, puisque le réglage n’a pas pu être appliqué avec un schéma imposé. Et un plafond de 3500 tokens qui pénalise directement Qwen sur e1.

Réglages recommandés dans LM Studio et dans un workflow

Pour Qwen 3.6, la réflexion est active par défaut. Avec llama.cpp, Unsloth indique qu’il faut passer –chat-template-kwargs ‘{« enable_thinking »:false}’ pour la désactiver. Pour Gemma 4, c’est l’inverse: la réflexion s’active en ajoutant <|think|> au prompt système, comme l’indique la documentation. Dans LM Studio, le découpage de la réflexion se règle modèle par modèle: il faut ouvrir le modèle depuis l’onglet My Models pour trouver Reasoning Parsing.

Pour vérifier le comportement sur votre propre machine, le plus simple est d’interroger l’API compatible OpenAI et de regarder la réponse brute, contenu et réflexion séparés:

shell
curl -s http://localhost:1234/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemma-4-26b-a4b-qat",
    "temperature": 0,
    "max_tokens": 800,
    "messages": [{"role": "user", "content": "Extrais les champs de cet événement Windows en JSON..."}],
    "response_format": {"type": "json_schema", "json_schema": {"name": "evt4625", "strict": true,
      "schema": {"type": "object", "properties": {"event_id": {"type": "integer"}}, "required": ["event_id"]}}}
  }' | jq '.usage, .choices[0].message'

À partir de ces essais, voici ce que je retiens pour la maquette:

  1. Extraction, classification, normalisation de journaux: réflexion off quand le moteur permet de la couper (vérifiez-le dans la réponse brute), température 0, et une validation métier après la validation du schéma (plages de valeurs, format ISO 8601 de l’heure, adresse IP valide).
  2. Dans un workflow n8n, tester le cas « contenu vide, réflexion non vide » et le traiter comme une erreur. Nous retrouvons la même logique de contrôle dans l’article sur le RAG local avec LM Studio et n8n.
  3. Diagnostic interactif: Gemma 4 avec réflexion si l’on accepte une minute d’attente, sinon Gemma ou Qwen sans réflexion, en relisant les commandes PowerShell proposées.
  4. Si la réflexion de Qwen 3.6 est activée, prévoir un max_tokens bien au delà de 3500. Sur ce prompt, 3500 n’a pas suffi. Il faut aussi surveiller le temps réel avant le premier token de réponse, pas le temps jusqu’au premier token affiché par l’API.

Dernière remarque, côté sécurité: les deux modèles ont proposé des commandes qui modifient l’annuaire (setspn -D) sans demander quel compte était réellement utilisé par le pool d’applications. Sur ce cas, c’est le bon compte. Mais dans un workflow où un agent exécute lui-même ses commandes, c’est exactement la ligne qui doit rester soumise à validation humaine.

Rémi Vernier

Rémi Vernier

Responsable des opérations cybersécurité dans un grand groupe international. Identité, Active Directory, Entra ID, cloud hybride, et désormais SAP, IA et modèles en local.

Tous les articles → LinkedIn →

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *