localaiforum
Connexion
Guide › Les fondamentaux

À l'intérieur du transformer

Tout ce que vous pouvez exécuter localement est un transformer, et l'architecture tient sur une serviette en papier : transformer les jetons en vecteurs, les pousser à travers N couches identiques où les jetons se regardent entre eux, projeter le vecteur final vers des scores de vocabulaire. Aucune analyse différentielle nécessaire — des produits scalaires et un softmax portent tout le spectacle. Cette page parcourt le chemin une fois, lentement.

Le flux résiduel

Imaginez un tapis roulant traversant le modèle. À chaque couche, des sous-modules lisent le tapis et y rajoutent leur contribution — rien ne remplace, tout s'accumule :

x = embed(token_ids) + positions      # les jetons deviennent des vecteurs (dim ~4k)
for layer in range(N):                # N ≈ 32 pour un modèle 8B
    x = x + attention(x)              # les jetons échangent de l'information
    x = x + ffn(x)                    # chaque jeton se transforme lui-même
logits = unembed(x[-1])               # dernière position → score par entrée de vocabulaire
p = softmax(logits)                   # probabilité sur chaque jeton suivant
  • Embedding : chaque identifiant de jeton indexe une table de vecteurs apprise. L'information de position y est mélangée (embeddings rotatifs dans les modèles modernes), ainsi « le chien mord l'homme » diffère de « l'homme mord le chien ».
  • Les couches sont identiques en forme, différentes en contenu. Les couches précoces gèrent la syntaxe et les motifs de surface ; les couches profondes portent le sens, les faits et le comportement de tâche.
  • Dés-embedding : le vecteur final est comparé à chaque entrée du vocabulaire ; le softmax transforme les scores en probabilités. L'échantillonnage en choisit une (échantillonnage).

L'auto-attention en quatre jetons

Le mécanisme d'échange. Le vecteur de chaque jeton produit trois vecteurs dérivés : une requête (ce que je cherche), une clé (ce que j'annonce) et une valeur (ce que je remets si je suis sélectionné). Phrase : « The cat sat on ». Que devrait aspirer la position de « sat » ?

token:          The     cat     sat     on
q·k scores:     1.2     4.1     3.0     0.4      (produits scalaires, illustratif)
softmax →        0.05    0.60    0.31   0.04     (les poids somment à 1.0)

output("sat") = 0.05·v(The) + 0.60·v(cat) + 0.31·v(sat) + 0.04·v(on)

« sat » prête attention surtout à « cat » — le sujet dont il a besoin. Chaque position fait cela simultanément. Une contrainte en fait un modèle de langage : le masquage causal — chaque jeton ne peut regarder que les jetons antérieurs, jamais les postérieurs, si bien qu'une seule passe entraîne chaque prédiction de jeton suivant de la séquence d'un coup.

Voilà tout l'outillage mathématique : des scores de similarité (produits scalaires), normalisés en un mélange (softmax), sur des vecteurs de valeur.

En recette, une tête d'attention à une position :

  1. Calculez les vecteurs requête, clé et valeur pour chaque jeton.
  2. Multipliez scalairement la requête par la clé de chaque jeton antérieur ; divisez par √(head_dim).
  3. Passez les scores au softmax en des poids sommant à 1.
  4. Produisez la somme pondérée des valeurs de ces jetons.
  5. Concaténez les sorties de toutes les têtes et projetez — c'est la contribution d'attention de la couche.

Multi-têtes : des motifs en parallèle

Une tête = un triplet requête/clé/valeur = un type de relation qu'elle peut exprimer (sujet↔verbe, adjectif↔nom, coréférence). Les couches exécutent plusieurs têtes en parallèle (p. ex. 32) sur des tranches de dimension inférieure et concatènent les résultats. Plus de têtes signifie plus de types de relations par couche — de la largeur de motifs, pas de la profondeur de pensée.

  • Les têtes sont fixées à l'entraînement ; la « réflexion » entre positions est ce que l'attention réécrit dans le flux résiduel.
  • Dimension de tête (p. ex. 128) × têtes (p. ex. 32) = dimension cachée (4096) : les têtes sont des tranches parallèles du même tapis roulant, pas des modèles séparés.

La FFN : là où vivent les paramètres

La seconde moitié de chaque couche est un réseau à deux matrices appliqué à chaque jeton indépendamment : dilater le vecteur (~4×), non-linéarité, reprojeter. Dans un modèle dense typique, environ deux tiers de tous les paramètres vivent ici, pas dans l'attention. L'intuition utile : une mémoire clé-valeur — la première matrice retient des motifs à détecter, la seconde ce qu'il faut ajouter au tapis quand un motif se déclenche. Une grande part de ce que les gens appellent « les faits du modèle » est stockée dans les poids de la FFN (voir paramètres).

Composant Part des paramètres (7–9B dense typique)
Attention (Q, K, V, O) ~10–15%
FFN ~60–70%
Embedding + tête de sortie ~10–25% (croît avec la taille du vocabulaire)

Comptez les paramètres vous-même

Les fiches modèles publient cinq nombres ; multipliez-les et vous tombez sur le compte de paramètres. Pour un vrai modèle ouvert de classe 8B (32 couches, dimension cachée 4096, 32 têtes dont 8 têtes KV, largeur FFN 14336, vocabulaire ~128k) :

attention/layer:  q: 4096×4096 + k,v: 2×(4096×1024) + o: 4096×4096
                  ≈ 42M par couche × 32 couches            ≈ 1.3B
FFN/layer:        3 × (4096×14336), gated ≈ 176M × 32      ≈ 5.6B
embeddings:       2 × (128k × 4096), entrée + tête sortie  ≈ 1.1B
total                                                      ≈ 8.0B

L'arithmétique colle au « 8B » de la fiche modèle presque exactement. Deux leçons s'en dégagent : la FFN domine le compte de paramètres (donc le budget mémoire), et un grand vocabulaire coûte environ un milliard de paramètres avant même que la première couche ne tourne — ce qui explique en partie pourquoi les modèles multilingues à gros vocabulaire pèsent plus que leurs cousins denses ne le suggèrent.

GQA : le correctif du coût de l'attention

Pendant la génération, chaque nouveau jeton doit lire les clés et valeurs de chaque jeton antérieur — stockées dans le cache KV. L'attention multi-têtes originelle stocke un K et un V par tête et par jeton. L'attention à requêtes groupées (GQA) partage une poignée de têtes KV entre plusieurs têtes de requête (p. ex. 32 têtes de requête, 8 têtes KV), réduisant le cache de 4× à un coût de qualité négligeable. L'attention multi-requêtes (MQA) partage une seule tête KV. En pratique, tous les modèles ouverts modernes utilisent la GQA ; ces économies expliquent en grande partie pourquoi le long contexte est utilisable du tout (cache KV).

Longueur de contexte = portée d'attention

L'attention laisse chaque jeton voir chaque jeton antérieur, donc le calcul de préremplissage croît de façon quadratique avec la longueur du prompt et le cache croît linéairement avec chaque jeton généré. Un modèle « à contexte 128k » y parvient par des astuces positionnelles et une extension entraînée, et la qualité près du bout lointain de la fenêtre est habituellement plus faible qu'au début. Ne remplissez de longues fenêtres que quand c'est nécessaire.

Testez vous-même : placez un fait au début de la fenêtre, bourrez le milieu de remplissage, interrogez-le. La plupart des modèles réussissent près du début et de la fin de la fenêtre et fléchissent au milieu — le motif bien connu du « lost in the middle ». Considérez le contexte annoncé comme une capacité, pas une garantie de qualité.

Pourquoi cela suffit

De cette seule structure vous pouvez dériver les faits pratiques : besoin mémoire = poids + cache KV (calcul de VRAM) ; vitesse de décodage = la vitesse à laquelle vous pouvez relire les poids (préremplissage vs décodage) ; la capacité suit le nombre de paramètres (paramètres) ; coût du contexte = portée d'attention. L'architecture est simple — les milliards de poids entraînés qu'elle contient sont la partie que personne n'aurait pu écrire à la main.

Voir aussi : qu'est-ce qu'un LLM · cache KV · préremplissage vs décodage · paramètres