Module 3 — Affinage supervisé sur des instructions
Le préentraînement produit un modèle qui continue un texte. Personne ne veut cela dans un assistant de support : on veut un modèle qui répond à une consigne. Ce module décrit l'étape qui transforme le premier en le second, l'affinage supervisé sur des instructions, souvent abrégé SFT pour supervised fine-tuning. Pour notre fil rouge, c'est ici que l'assistant apprend le ton de la marque et le format de réponse attendu par nos opérateurs.
Modèle de base et modèle instruit ne font pas le même métier
Un modèle de base à qui l'on donne l'entrée « Quel est le pays d'origine du fromage brie ? » peut répondre par un paragraphe qui commence par « Cette question est fréquente sur les forums de cuisine. Le brie est un fromage… ». Techniquement correct : il continue un texte plausible. Utilisable pour un opérateur, non : la réponse attendue est courte, factuelle, dans le format du canal (courriel, tchat, ticket).
Un modèle instruit produit à la place « Le brie est originaire de France, dans la région d'Île-de-France. » Cette différence de comportement ne tient à aucun changement d'architecture : c'est le même Transformer, mais entraîné en plus sur un jeu d'exemples de la forme « consigne → réponse attendue ».
Le format d'un jeu d'instructions
Un exemple typique tient dans trois champs : une consigne, une entrée optionnelle et une réponse cible.
{
"instruction": "Reformule ce message client en un ton professionnel et concis.",
"entree": "vraiment nul votre service, jamais vu ça, remboursez moi",
"reponse": "Bonjour, nous sommes désolés de la gêne occasionnée. Pourriez-vous préciser votre numéro de commande pour que nous puissions traiter votre remboursement ?"
}
Le modèle est entraîné à prédire la réponse conditionnellement à la consigne et à l'entrée, avec la même entropie croisée que pendant le préentraînement — mais uniquement sur les jetons de la réponse. Les jetons de l'invite reçoivent un masque de perte à zéro, sinon le modèle apprendrait à générer la consigne elle-même, ce qui n'a pas de sens.
# Illustration du masque de perte, pour un exemple unique
import torch
# Ids d'entree = consigne + reponse ; on masque les positions de la consigne.
ids = torch.tensor([[10, 22, 3, 45, 87, 91, 12, 4]]) # 8 jetons
longueur_invite = 3 # les 3 premiers sont l'invite
etiquettes = ids.clone()
etiquettes[:, :longueur_invite] = -100 # -100 ignore par la perte
Le -100 est la convention PyTorch pour ignorer une position dans CrossEntropyLoss. C'est cette petite ligne qui distingue un affinage utile d'un affinage qui empire le modèle.
Le gabarit de conversation, le vrai secret pratique
Un modèle instruit moderne parle en tours de dialogue, pas en paires consigne-réponse. Le format se matérialise par un gabarit de conversation qui ajoute des jetons spéciaux autour de chaque tour. Voici celui de la famille LLaMA 3 :
<|begin_of_text|><|start_header_id|>system<|end_header_id|>
Tu es l'assistant de support d'ACME, courtois et concis.<|eot_id|><|start_header_id|>user<|end_header_id|>
Ma commande n'est pas arrivée.<|eot_id|><|start_header_id|>assistant<|end_header_id|>
Je vais vérifier tout de suite. Pouvez-vous me donner votre numéro de commande ?<|eot_id|>
Ces jetons spéciaux ne sont pas des chaînes ordinaires : ils sont enregistrés dans le tokeniseur avec un id unique, et le modèle a appris à les reconnaître pendant son affinage. Utiliser le mauvais gabarit — celui d'une autre famille de modèles, ou une version obsolète — dégrade silencieusement la qualité, sans lever la moindre erreur.
La bibliothèque transformers gère cela pour vous :
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
messages = [
{"role": "system", "content": "Tu es l'assistant de support d'ACME, courtois et concis."},
{"role": "user", "content": "Ma commande n'est pas arrivée."},
]
invite = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
print(invite)
La méthode apply_chat_template lit le gabarit stocké dans le tokeniseur du modèle. Sortir de ce mécanisme — écrire soi-même « Utilisateur : … Assistant : … » — fonctionne parfois, mais avec des baisses de qualité de plusieurs points sur les jeux de référence, pour un gain zéro.
Qualité contre quantité : moins mais mieux
Un résultat contre-intuitif s'est imposé depuis 2023 : quelques milliers d'exemples de très haute qualité battent des centaines de milliers d'exemples médiocres. L'étude LIMA (Zhou et al., 2023) a montré qu'un jeu de 1 000 réponses écrites par des humains soigneux, sur des thèmes variés, suffit à transformer un bon modèle de base en un modèle instruit compétitif.
La raison tient à la nature de la tâche. Le préentraînement a déjà installé les capacités linguistiques et de raisonnement ; l'affinage sur instructions ne les crée pas, il les révèle. Le modèle apprend surtout un format et un style ; il n'apprend presque aucune nouvelle connaissance factuelle. Un jeu bruyant, avec des réponses factuellement fausses ou mal formatées, apprend au modèle à imiter précisément ces défauts.
| Volume | Qualité | Résultat typique |
|---|---|---|
| 1 000 exemples | très soignés, révisés à la main | modèle instruit propre, ton cohérent |
| 50 000 exemples | qualité moyenne, générés par un autre LLM | qualité comparable, plus de biais et d'erreurs répétés |
| 500 000 exemples | corpus public non filtré | régression du modèle sur des tâches simples |
Pour notre assistant de support, l'implication est directe : on privilégie deux à cinq mille exemples révisés par des opérateurs expérimentés, plutôt que dix fois plus généré par un modèle. La différence se voit dès la première itération.
LoRA et l'affinage à budget maigre
Affiner tous les poids d'un modèle de 8 milliards de paramètres demande une machine avec suffisamment de mémoire — l'optimiseur Adam stocke deux moments par paramètre, ce qui triple la mémoire nécessaire par rapport à l'inférence. LoRA (Low-Rank Adaptation) contourne le problème en ne modifiant qu'un très petit nombre de paramètres additionnels.
L'idée est simple. Pour une matrice de poids , on gèle et on apprend une correction
avec un rang typiquement entre 8 et 64. Le nombre de paramètres à entraîner passe de à , souvent une réduction de plus de cent fois. À l'inférence, on peut soit fusionner dans , soit garder les deux séparés pour servir plusieurs adaptations d'un même modèle de base.
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
modele = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B")
config = LoraConfig(r=16, lora_alpha=32, target_modules=["q_proj", "v_proj"], task_type="CAUSAL_LM")
modele = get_peft_model(modele, config)
modele.print_trainable_parameters()
# Sortie typique : 4 194 304 parametres entrainables sur 8 e9, soit 0,05 pour cent
Sur une seule carte A100 de 40 Go, un affinage LoRA d'un modèle de 8 milliards de paramètres sur cinq mille exemples tient en quelques heures. C'est ce qui rend l'adaptation d'un LLM ouvert accessible à une équipe de trois personnes.
Une erreur fréquente est de vouloir « apprendre au modèle notre catalogue produit » par SFT. Cela marche mal : les faits nouveaux ne s'ancrent pas de façon fiable, et le modèle continue de mélanger vos produits avec ceux qu'il a vus au préentraînement. Les faits doivent être servis par un système de récupération (module 6 et cours 18), pas par affinage.
Avant tout affinage, demandez-vous : « ce que je veux améliorer est-il un format, un ton ou une connaissance ? » Format et ton se règlent par affinage sur quelques milliers d'exemples. Connaissance = récupération. Comportement complexe = alignement (module suivant). Cette grille de décision évite les mois perdus à réentraîner un modèle qui aurait dû rester générique.
En résumé
- Un modèle de base continue un texte, un modèle instruit suit des consignes ; la seule différence est un affinage supervisé sur des paires consigne-réponse, avec masque de perte sur les jetons de l'invite.
- Le gabarit de conversation encode les tours de dialogue par des jetons spéciaux ; utiliser le gabarit officiel du modèle est indispensable et gratuit.
- Qualité prime sur quantité : quelques milliers d'exemples soignés battent des centaines de milliers d'exemples médiocres, parce que l'affinage révèle des capacités existantes plutôt que de les créer.
- LoRA rend l'affinage accessible en n'entraînant que 0,05 pour cent des poids, avec une qualité presque identique à un affinage complet.
Module suivant : au-delà du format, comment aligner le modèle sur des préférences humaines pour qu'il choisisse entre deux réponses toutes deux formellement correctes.