Un guide complet pour enseigner de nouvelles compétences aux modèles d'IA : fine-tuning supervisé (SFT), LoRA/QLoRA, RLHF, DPO, GRPO, distillation de modèles, fusion de modèles et évaluation. Du concept à la production — avec du code fonctionnel à chaque étape.
Le pré-entraînement donne au modèle une connaissance large du monde, mais une seule compétence : prédire le token suivant. Le modèle a vu Wikipédia, du code, des livres et le web — mais il ne sait pas être utile, suivre des instructions ou refuser des requêtes dangereuses. Le fine-tuning est le processus qui enseigne ces comportements après le pré-entraînement.
L'industrie a convergé vers une échelle d'entraînement standard que suivent tous les grands modèles de pointe (GPT-4o, Claude Opus 4.6, Llama 4, Gemini 2.5). Chaque étape s'appuie sur la précédente — vous ne pouvez pas sauter le SFT pour passer directement au RLHF.
graph LR A[Raw Text Corpus] -->|Pretraining cross-entropy| B[Base Model] B -->|Supervised Fine-Tuning| C[Instruction-Following Model] C -->|RLHF / DPO / GRPO| D[Aligned Model] D -->|Evaluation & Red-teaming| E[Production Model]
Prédiction auto-supervisée du token suivant sur d'immenses corpus. Encode la connaissance du monde.
Fine-tuning supervisé sur des paires instruction-réponse. Apprend au modèle à être utile.
RLHF, DPO ou GRPO sur des données de préférences humaines. Rend les sorties sûres et préférées.
Benchmarks automatisés + red-teaming. Détecter les régressions avant la mise en production.
Le SFT entraîne le modèle à prédire les tokens de l'assistant à partir d'un contexte de conversation. Le détail clé est le loss masking : la perte d'entropie croisée est calculée uniquement sur les tokens de l'assistant, pas sur le prompt système ni sur les tours de l'utilisateur. Cela empêche le modèle d'« apprendre » le côté utilisateur de la conversation.
Trois formats dominent le paysage du SFT. ChatML est devenu le plus largement adopté grâce à ses tokens spéciaux sans ambiguïté.
<|im_start|>system You are a helpful AI assistant specialized in European AI regulation. <|im_end|> <|im_start|>user What are the key obligations under the EU AI Act for high-risk systems? <|im_end|> <|im_start|>assistant High-risk AI systems under the EU AI Act (in force August 2024) must comply with... <|im_end|>
| Paramètre | Valeur typique | Notes |
|---|---|---|
| Learning rate | 2e-5 | Plus faible qu'au pré-entraînement ; décroissance en cosinus |
| Epochs | 2–3 | Plus d'époques → surapprentissage sur les petits jeux de données |
| Batch size (effective) | 64–128 | Utiliser l'accumulation de gradient pour une faible mémoire GPU |
| Warmup ratio | 0.1 | 10 % des étapes pour le warmup du LR |
| Max sequence length | 2048–8192 | Faire correspondre à votre fenêtre de contexte d'inférence |
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import SFTConfig, SFTTrainer
from datasets import load_dataset
import torch
model_name = "meta-llama/Llama-4-Scout-17B-16E-Instruct" # 2026: Llama 4 Scout replaces Llama 3.1 8B
model = AutoModelForCausalLM.from_pretrained(
model_name, torch_dtype=torch.bfloat16, device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
dataset = load_dataset("HuggingFaceH4/ultrachat_200k", split="train_sft")
sft_config = SFTConfig(
output_dir="./sft-llama-4-scout",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=2e-5,
lr_scheduler_type="cosine",
warmup_ratio=0.1,
logging_steps=10,
save_strategy="epoch",
bf16=True,
)
trainer = SFTTrainer(
model=model,
args=sft_config,
train_dataset=dataset,
processing_class=tokenizer,
)
trainer.train()
trainer.save_model()Le fine-tuning complet modifie l'ensemble des ~7 milliards de paramètres d'un modèle 7B. En bfloat16, cela représente 14 Go rien que pour le stockage des paramètres, sans compter les gradients et les états de l'optimiseur. LoRA (Low-Rank Adaptation, Hu et al. 2021) exploite une observation empirique clé : les variations de poids pendant le fine-tuning sont de faible rang.
Au lieu d'apprendre une mise à jour de poids complète ΔW ∈ ℝ^(d×k), LoRA apprend deux petites matrices : A ∈ ℝ^(d×r) et B ∈ ℝ^(r×k) où r ≪ min(d, k). À l'inférence, l'adaptateur est réintégré : W′ = W + αAB/r. Une fois fusionné, le surcoût d'inférence est nul.
from peft import LoraConfig, TaskType, get_peft_model
config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
bias="none",
)
model = get_peft_model(base_model, config)
model.print_trainable_parameters()
# trainable params: 83,886,080 || all params: 8,030,261,248 || trainable%: 1.044
# After training, merge adapter back into the base weights
merged = model.merge_and_unload()
merged.save_pretrained("./my-lora-merged")| Méthode | Paramètres entraînables | RAM GPU (8B) | Qualité | Vitesse d'entraînement |
|---|---|---|---|---|
| Full Fine-Tuning | 7B (100%) | ~80 GB | Optimale | La plus lente |
| LoRA r=4 | ~21M (0.3%) | ~16 GB | Bonne | Rapide |
| LoRA r=16 | ~83M (1.0%) | ~18 GB | Très bonne | Rapide |
| LoRA r=64 | ~335M (4.1%) | ~24 GB | Proche du FT complet | Modérée |
Même avec LoRA, le modèle de base chargé en bfloat16 nécessite 16 Go pour un modèle 8B — au-delà des budgets GPU grand public. QLoRA (Dettmers et al. 2023) résout cela en quantifiant le modèle de base gelé en NormalFloat 4 bits (NF4) et en entraînant les adaptateurs LoRA en précision bfloat16.
NormalFloat4 est théoriquement optimal du point de vue de l'information pour des poids de réseau de neurones distribués normalement. Moins d'erreur qu'int4 ou fp4.
Les états de l'optimiseur sont automatiquement paginés vers la RAM CPU lorsque la mémoire GPU se remplit, évitant les plantages OOM pendant l'entraînement.
Quantifie les constantes de quantification elles-mêmes, économisant environ 0,5 bit supplémentaire par paramètre.
| Modèle | VRAM FP16 | VRAM QLoRA | GPU minimal |
|---|---|---|---|
| Llama 4 Scout (17B) | 34 GB | 10 GB | RTX 4090 24GB |
| Llama 4 Maverick (70B-class) | 140 GB | 40 GB | 2× A100 40GB |
| Llama 4 Behemoth (frontier) | 800+ GB | ~200 GB | 8× H100 80GB |
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-4-Maverick-17B-128E-Instruct", # 2026: Llama 4 Maverick replaces Llama 3.1 70B
quantization_config=bnb_config,
device_map="auto",
)
# Now apply LoRA to the 4-bit model — same LoraConfig + get_peft_model as beforeLe Reinforcement Learning from Human Feedback (RLHF) a été la percée qui a transformé GPT-3 en InstructGPT puis en GPT-4o. Il aligne le comportement du modèle sur les préférences humaines — pas seulement le suivi d'instructions, mais le fait de rendre les sorties véritablement préférées, sûres et utiles.
Affiner le modèle de base sur un ensemble curé de démonstrations de suivi d'instructions de haute qualité. Cela crée la politique de départ que le RLHF améliorera.
Entraîner un classifieur sur des préférences humaines par paires : étant données deux complétions (y_w, y_l) au même prompt, laquelle est la meilleure ? Perte : log σ(r(x, y_w) − r(x, y_l)).
Utiliser la Proximal Policy Optimization pour maximiser le score du modèle de récompense tout en restant proche de la politique SFT (la pénalité de divergence KL empêche le reward hacking).
graph LR A[Base Model] -->|SFT on demos| B[SFT Model] B -->|Sample completions| C[Completion Pairs] C -->|Human labelers rank| D[Preference Dataset] D -->|Train| E[Reward Model] B -->|Initialize policy| F[Policy Model] F -->|Rollout + PPO| G[RL Optimization] E -->|Score rollouts| G G -->|Converged| H[RLHF Model]
Le DPO (Direct Preference Optimization) (Rafailov et al. 2023) élimine entièrement le modèle de récompense. Il a montré mathématiquement que la politique RLHF optimale peut être exprimée directement comme une fonction des données de préférences, réduisant un pipeline en trois étapes à une seule étape de fine-tuning.
La perte DPO optimise directement la politique sur des paires de préférences (prompt, chosen, rejected) en utilisant le modèle SFT comme référence gelée. Pas de PPO, pas de modèle de récompense, pas de collecte distincte de données d'entraînement pour le RM.
from trl import DPOConfig, DPOTrainer
from datasets import load_dataset
# Dataset needs: prompt, chosen, rejected columns
dataset = load_dataset("HuggingFaceH4/ultrafeedback_binarized", split="train_prefs")
dpo_config = DPOConfig(
output_dir="./dpo-output",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=5e-7, # much smaller than SFT lr
beta=0.1, # KL penalty coefficient
bf16=True,
)
trainer = DPOTrainer(
model=sft_model, # your SFT fine-tuned model
ref_model=sft_ref_model, # frozen reference
args=dpo_config,
train_dataset=dataset,
processing_class=tokenizer,
)
trainer.train()La Group Relative Policy Optimization (GRPO) (utilisée dans DeepSeek-R1) élimine le modèle de référence. Pour chaque prompt, elle échantillonne plusieurs sorties et utilise la récompense moyenne du groupe comme référence pour l'estimation de l'avantage. C'est moins coûteux que le PPO (pas de modèle de valeur) et mieux adapté aux tâches de raisonnement où l'on peut vérifier la justesse de manière programmatique.
| Méthode | Calcul | Stabilité | Besoins en données | Notes |
|---|---|---|---|---|
| RLHF (PPO) | Très élevé | Faible | Classements humains | 4 modèles en mémoire ; risque de reward hacking |
| DPO | Faible | Élevée | Paires de préférences | Pas de modèle de récompense ; pipeline plus simple |
| GRPO | Moyen | Moyenne | Échantillons de rollout | Pas de modèle de référence ; adapté au raisonnement |
| SimPO | Faible | Élevée | Paires de préférences | Pas de modèle de référence ; récompense en log-prob moyen |
La distillation de connaissances entraîne un petit modèle « élève » à imiter un grand modèle « enseignant ». L'idée clé est que l'enseignant fournit des distributions de probabilité douces sur le vocabulaire (logits) plutôt que des étiquettes one-hot. Ces cibles douces encodent bien plus d'information — elles révèlent quels tokens sont sémantiquement proches de la bonne réponse, offrant à l'élève un signal d'entraînement plus riche.
La perte combinée : L = α × L_CE(étiquettes dures) + (1 − α) × L_KL(logits de l'élève ‖ logits de l'enseignant). La mise à l'échelle par température T > 1 adoucit la distribution de l'enseignant, répartissant la masse de probabilité sur davantage de tokens et rendant les étiquettes douces encore plus informatives.
graph TB A["Large Teacher (70B)"] -->|"Generate on training data"| B[Soft Logits] C[Input Prompt] --> A C --> D["Small Student (7B)"] B -->|KL Loss| D E[Ground Truth] -->|CE Loss| D D -->|Both losses| F[Distilled Student]
L'élève imite les sorties de l'enseignant — générer les complétions de l'enseignant, entraîner l'élève à les reproduire. Utilisée par DeepSeek-R1-Distill pour transférer les traces de raisonnement.
Faire correspondre les représentations intermédiaires (états cachés, motifs d'attention) entre les couches de l'enseignant et de l'élève. Transfère la connaissance structurelle, pas seulement les sorties de surface.
Un petit modèle de brouillon propose des séquences de tokens ; le grand modèle les vérifie en parallèle. Atteint une accélération d'inférence de 2 à 4× sans perte de qualité.
L'élève génère les tokens ; l'enseignant les note. Évite le biais d'exposition (décalage de distribution entre entraînement et test) courant dans la distillation hors ligne.
La fusion de modèles combine plusieurs checkpoints affinés en un seul modèle sans aucun entraînement supplémentaire. C'est peu coûteux, rapide et étonnamment efficace pour combiner des compétences spécialisées — code, mathématiques, suivi d'instructions — en un seul modèle déployable. Les modèles fusionnés apparaissent fréquemment en tête du HuggingFace Open LLM Leaderboard.
Interpolation douce entre deux checkpoints de modèle dans l'espace des poids. Traite les poids comme des points sur une hypersphère. Idéale pour mélanger deux modèles étroitement liés.
Calculer ΔW = W_FT − W_base pour chaque modèle affiné, puis additionner les deltas. Permet de composer des capacités ou de soustraire des comportements indésirables.
Résout les conflits entre modèles : élaguer les paramètres de faible magnitude, élire le signe dominant pour chaque poids, puis fusionner. Gère proprement 3 modèles ou plus.
Supprime aléatoirement des deltas de poids de fine-tuning (avec une probabilité p) et redimensionne les survivants pour préserver la norme. Réduit les interférences entre modèles.
# mergekit config.yaml
models:
- model: meta-llama/Llama-4-Scout-17B-16E
parameters:
weight: 0.4
- model: ./llama-4-scout-code-finetuned
parameters:
weight: 0.3
- model: ./llama-4-scout-math-finetuned
parameters:
weight: 0.3
merge_method: ties
base_model: meta-llama/Llama-4-Scout-17B-16E
parameters:
density: 0.7
normalize: truemergekit-yaml config.yaml ./merged-model --cuda
La qualité des données est le facteur le plus déterminant de la réussite du fine-tuning — plus important que l'architecture du modèle, la durée d'entraînement ou le choix de l'optimiseur. Un jeu de données mal curé garantit de mauvais résultats, quoi qu'il en soit par ailleurs.
Exemples rédigés par des experts ; meilleur rapport signal/bruit. Utilisé pour les comportements critiques.
Génération synthétique avec des modèles de pointe. Idéal pour amorcer la couverture d'un domaine à grande échelle.
Faire évoluer des instructions de départ vers des variantes plus difficiles et plus diversifiées. Utilisé dans WizardLM et OpenHermes.
Nécessite un filtrage qualité agressif : déduplication, filtre de longueur, filtre de perplexité, filtre de sécurité.
{
"conversations": [
{"from": "system", "value": "You are an expert in EU AI regulation."},
{"from": "human", "value": "Explain the risk categories in the EU AI Act."},
{"from": "gpt", "value": "The EU AI Act categorizes AI systems into four risk levels..."}
]
}from openai import OpenAI # or use Mistral/Llama locally
client = OpenAI()
def generate_training_example(topic: str, difficulty: str) -> dict:
prompt = (
f"Generate a challenging {difficulty}-level question about {topic} "
"and a comprehensive expert answer."
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.8,
)
content = response.choices[0].message.content
# Parse and structure output (question/answer split)...
return {"instruction": topic, "response": content}La boucle de fine-tuning est : entraîner → évaluer sur un jeu de validation → diagnostiquer les modes d'échec → améliorer les données → réentraîner. Une bonne évaluation est ce qui transforme les tâtonnements en amélioration systématique.
Benchmark multi-tours de 80 questions réparties sur 8 catégories (rédaction, mathématiques, code, etc.). GPT-4 note chaque réponse de 1 à 10.
Taux de victoire de votre modèle face à un modèle de référence (GPT-4o) tel que jugé par GPT-4o. Évaluation automatisée rapide de la qualité du suivi d'instructions.
Précision du suivi d'instructions sur des contraintes vérifiables (p. ex. « répondre en moins de 100 mots »). Variantes de notation stricte et souple.
Benchmarks de génération de code. Métrique Pass@k : fraction de problèmes résolus en k tentatives. Cas de test exécutables comme vérité terrain.
import json
from openai import OpenAI
client = OpenAI()
def evaluate_response(question: str, answer: str, judge_model: str = "gpt-4o") -> dict:
prompt = f"""Rate the following AI assistant response on a scale of 1-10.
Question: {question}
Answer: {answer}
Evaluate: helpfulness (1-10), factuality (1-10), safety (1-10).
Return JSON: {{"helpfulness": N, "factuality": N, "safety": N, "rationale": "..."}}"""
response = client.chat.completions.create(
model=judge_model,
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"},
)
return json.loads(response.choices[0].message.content)| Run | Modèle de base | Méthode | Jeu de données | MT-Bench | AlpacaEval Win% | Notes |
|---|---|---|---|---|---|---|
| v1 | Llama-4-Scout | SFT | UltraChat 200K | 7.4 | 70% | Référence |
| v2 | Llama-4-Scout | SFT+DPO | + UltraFeedback | 8.0 | 76% | +DPO a amélioré la sécurité |
| v3 | Llama-4-Scout | SFT+DPO (r=16) | + UltraFeedback | 8.1 | 77% | LoRA r=16 vs FT complet |
Le fine-tuning est puissant mais n'est pas toujours le bon outil. La décision dépend de ce que vous essayez de changer : connaissance, comportement, format ou préférences. Un mauvais choix coûte des semaines d'ingénierie et de calcul.
| Scénario | Meilleure approche | Pourquoi |
|---|---|---|
| Ancrer les réponses dans les documents de l'entreprise | RAG | La connaissance peut changer ; le FT ne se met pas à jour facilement |
| Vouloir un ton/style cohérent | SFT | Le ton est un format, pas une connaissance |
| Usage d'une terminologie spécifique à un domaine | SFT + peu de données | Modifier le comportement par défaut à moindre coût |
| Gérer des formats de sortie spécifiques | SFT | Le respect d'un schéma est une compétence apprise |
| Réduire les sorties nuisibles | DPO / RLHF | L'alignement sur les préférences cible directement cela |
| Avoir besoin de capacités de raisonnement | GRPO ou distiller depuis R1 | Les schémas de raisonnement sont entraînables |
| Ajouter de nouvelles connaissances factuelles | RAG (pas FT) | Le FT mémorise, ne peut pas citer ses sources |
| Réduire les coûts d'API à grande échelle | Affiner un petit modèle | Égaler la qualité d'un grand modèle sur une tâche étroite |
| Prototype / expérience rapide | Ingénierie de prompts d'abord | Coût d'entraînement nul ; valider le concept d'abord |
Commencez tout en bas. Ne montez que lorsque le niveau actuel est véritablement insuffisant — chaque marche ajoute du coût, de la complexité et de la latence.
Que vous ayez besoin d'un assistant spécialisé dans un domaine, de modèles alignés sur les préférences ou de déploiements de production distillés — notre équipe en a construit et livré. Parlons de votre cas d'usage.