Retrouver les 2,8 T de paramètres¶
Cet exercice est le meilleur test de compréhension de l'architecture : si vous retrouvez les totaux annoncés à partir du seul fichier de configuration, c'est que vous savez ce que contient chaque couche.
Résultat
2,779 T de paramètres au total et 104,0 G activés par jeton, contre 2,78 T et 104,2 G annoncés. Écart : 0,2 %.
Les constantes de départ¶
Toutes lues dans config.json :
d = 7168 # hidden_size
L = 93 # num_hidden_layers
nMLA = 24 # len(full_attn_layers)
nKDA = 69 # L - nMLA
V = 163840 # vocab_size
ell = 3584 # routed_expert_hidden_size (largeur latente)
dm = 3072 # moe_intermediate_size
E = 896 # num_experts
k = 16 # num_experts_per_token
Ns = 2 # num_shared_experts
Ilarge = 33792 # intermediate_size (FFN dense de la couche 1)
H = 96 # num_attention_heads
qlora = 1536 # q_lora_rank
kvlora = 512 # kv_lora_rank
qk_nope = 128 # qk_nope_head_dim
qk_rope = 64 # qk_rope_head_dim
vh = 128 # v_head_dim
kda_hd = 128 # linear_attn_config.head_dim
kda_H = 96 # linear_attn_config.num_heads
Bloc 1 — un expert routé¶
Un expert est un FFN à porte (gate, up, down) opérant dans l'espace
latent de dimension \(\ell\), avec une dimension interne \(d_m\) :
Le piège
Ne pas utiliser \(d = 7168\) ici. Les experts routés travaillent en dimension latente \(\ell = 3584\), c'est tout l'intérêt de LatentMoE. Utiliser \(d\) doublerait le total et donnerait ~5,5 T.
Bloc 2 — une couche MoE complète¶
| Composant | Formule | Valeur |
|---|---|---|
| 896 experts routés | \(896 \times 33{,}03\) M | 29,60 G |
| \(\mathbf{W}^{\downarrow}\) + \(\mathbf{W}^{\uparrow}\) | \(2 \times d \times \ell = 2 \times 7168 \times 3584\) | 51,4 M |
| 2 experts partagés | \(3 \times d \times (d_m \times N_s) = 3 \times 7168 \times 6144\) | 132,1 M |
| Routeur | \(d \times E = 7168 \times 896\) | 6,4 M |
| Total par couche MoE | 29,78 G |
Le point qui lève l'ambiguïté du rapport
Le rapport ne dit pas quelle dimension intermédiaire ont les experts partagés. Deux lectures possibles :
| Hypothèse | Experts partagés / couche | Total du modèle |
|---|---|---|
| intermédiaire = \(I_{\text{large}} = 33792\) | 726,7 M | > 2,80 T ❌ |
| intermédiaire = \(N_s \times d_m = 6144\) | 132,1 M | 2,779 T ✅ |
Seule la seconde reconstitue les totaux annoncés. C'est la contrainte d'arithmétique qui tranche l'ambiguïté du texte.
Sur les 92 couches MoE (toutes sauf la couche 1, dense) :
Bloc 3 — une couche Gated MLA¶
| Composant | Formule | Valeur |
|---|---|---|
| Compression Q | \(d \times q_{\text{lora}}\) | 11,0 M |
| Décompression Q | \(q_{\text{lora}} \times H \times (128+64)\) | 28,3 M |
| Compression KV | \(d \times (kv_{\text{lora}} + 64)\) | 4,1 M |
| Décompression KV | \(kv_{\text{lora}} \times H \times (128+128)\) | 12,6 M |
| Projection de sortie | \(H \times v_h \times d\) | 88,1 M |
| Porte de rang plein \(\mathbf{W}_g\) | \(d \times H \times v_h\) | 88,1 M |
| Total par couche MLA | 232,2 M |
Sur 24 couches : 5,57 G.
La porte coûte autant que la sortie
\(\mathbf{W}_g\) pèse exactement autant que \(\mathbf{W}_o\) : 88 M, soit 38 % de la couche. C'est le prix du passage au rang plein décidé par K3.
Bloc 4 — une couche KDA¶
| Composant | Formule | Valeur |
|---|---|---|
| Projections Q, K, V | \(3 \times d \times (H \times 128)\) | 264,2 M |
| Projection de sortie | \(H \times 128 \times d\) | 88,1 M |
| Porte de rang plein \(\mathbf{W}_g\) | \(d \times H \times 128\) | 88,1 M |
| ShortConv, \(\mathbf{W}_\beta\), \(\mathbf{W}_\alpha\) rang faible | — | négligeable |
| Total par couche KDA | 440,4 M |
Sur 69 couches : 30,4 G.
Pourquoi KDA est presque deux fois plus lourd que MLA
KDA projette à pleine largeur (\(7168 \to 12288\)) pour Q, K et V, soit trois matrices de 88 M. MLA compresse par des goulots de rang faible (512 et 1 536).
C'est le compromis : KDA n'a rien à compresser, puisqu'il ne stocke aucun cache qui croisse.
Bloc 5 — le reste¶
| Composant | Formule | Valeur |
|---|---|---|
| Embedding | \(V \times d = 163840 \times 7168\) | 1,17 G |
lm_head (non lié) |
\(V \times d\) | 1,17 G |
| FFN dense (couche 1) | \(3 \times d \times I_{\text{large}}\) | 0,73 G |
| Encodeur visuel | — | 0,40 G |
Le total¶
Annoncé : 2,78 T. Écart : 0,04 %.
Les paramètres activés¶
Seuls 16 des 896 experts travaillent par jeton. Tout le reste est actif.
| Composant | Valeur |
|---|---|
| 16 experts routés × 92 couches | \(92 \times 16 \times 33{,}03\) M = 48,6 G |
| \(\mathbf{W}^{\downarrow},\mathbf{W}^{\uparrow}\) × 92 | 4,73 G |
| Experts partagés × 92 | 12,15 G |
| Routeurs × 92 | 0,59 G |
| Couches MLA (24) | 5,57 G |
| Couches KDA (69) | 30,4 G |
| FFN dense | 0,73 G |
lm_head |
1,17 G |
| Total activé | 104,0 G |
Annoncé : 104,2 G. Écart : 0,2 %.
La vérification est concluante
Deux quantités indépendantes reconstruites à 0,2 % près à partir du seul fichier de configuration. Cela valide à la fois la compréhension de l'architecture et la cohérence de ce que Moonshot a publié.
Les 0,2 % résiduels s'expliquent par les termes négligés : projections de rang faible du gate \(\alpha\) de KDA, noyaux de ShortConv, gains de RMSNorm, biais par tête. Tous marginaux.
Le code¶
Extrait du script de vérification (verif-kimi-k3.py) :
def param_counts():
d, L, nMLA, nKDA, V = 7168, 93, 24, 69, 163840
ell, dm, E, k, Ns = 3584, 3072, 896, 16, 2
qlora, kvlora, qk_nope, qk_rope, vh, H = 1536, 512, 128, 64, 128, 96
kda_hd, kda_H, Ilarge = 128, 96, 33792
exp = 3 * ell * dm # un expert routé
moe = E * exp + (d * ell + ell * d) \
+ 3 * d * (dm * Ns) + d * E # une couche MoE
mla = (d * qlora + qlora * H * (qk_nope + qk_rope)) \
+ d * (kvlora + qk_rope) \
+ kvlora * H * (qk_nope + vh) \
+ H * vh * d + d * H * vh # une couche MLA
kda = 3 * (d * kda_H * kda_hd) + (kda_H * kda_hd * d) \
+ (d * kda_H * kda_hd) # une couche KDA
dense = 3 * d * Ilarge
total = 92 * moe + nMLA * mla + nKDA * kda + dense + 2 * V * d
act = 92 * (k * exp + 2 * d * ell + 3 * d * dm * Ns + d * E) \
+ nMLA * mla + nKDA * kda + dense + V * d
return total, act
Sortie vérifiée :
total = 2.779 T (papier 2,78 T)
actifs = 104.0 G (papier 104,2 G)
Exercices¶
Combien pèserait Kimi K3 avec 8 experts actifs au lieu de 16 ?
Les experts routés actifs passeraient de 48,6 G à 24,3 G. Le total activé tomberait à 79,7 G, soit −23 %. Le total de paramètres serait inchangé : c'est un paramètre de routage, pas de taille.
Quelle serait la taille du modèle si les experts opéraient à pleine largeur (\(\ell = d\)) ?
Un expert coûterait \(3 \times 7168 \times 3072 = 66{,}1\) M au lieu de 33,0 M. Les experts routés d'une couche : 59,2 G. Sur 92 couches : 5,45 T. Le modèle ferait environ 5,5 T — soit le double. C'est exactement l'économie que réalise LatentMoE.
Quelle part du modèle un jeton « voit-il » ?
\(104{,}0 / 2\,779 = 3{,}7\ \%\). Un jeton traverse moins de 4 % du modèle. Mais 100 % des paramètres doivent être résidents en mémoire, puisqu'on ne sait pas à l'avance quels experts seront choisis.
Chapitre précédent : Ce qui est public · Chapitre suivant : Implémenter KDA