Guide
Fine-tuning d'un modèle open source avec Hugging Face TRL
Affiner un LLM à poids ouverts avec SFTTrainer de TRL : formats de données, code minimal, LoRA via PEFT, réglages par défaut et pièges courants.
Mis à jour le
Pour affiner vous-même un modèle à poids ouverts, la voie la plus documentée est la bibliothèque TRL de Hugging Face et sa classe SFTTrainer (SFT pour Supervised Fine-Tuning, affinage supervisé). Elle accepte directement un jeu conversationnel, applique le gabarit de conversation du modèle et peut n'entraîner qu'un adaptateur LoRA. Ce guide suit la documentation de TRL lue le 15/11/2026 (version 1.18.0).
Le minimum qui fonctionne
L'exemple de démarrage de la documentation affine Qwen3 0.6B, un petit modèle ouvert, sur un jeu de conversations public :
from trl import SFTTrainer
from datasets import load_dataset
trainer = SFTTrainer(
model="Qwen/Qwen3-0.6B",
train_dataset=load_dataset("trl-lib/Capybara", split="train"),
)
trainer.train()
Le modèle est chargé par son identifiant sur le Hub de Hugging Face. Commencer sur un modèle de cette taille permet de vérifier toute la chaîne avant de passer à un modèle plus gros.
Les formats de données acceptés
| Format | Exemple d'une ligne | Sur quoi porte l'apprentissage par défaut |
|---|---|---|
| Texte brut | {"text": "..."} |
toute la séquence |
| Conversationnel | {"messages": [{"role": "user", ...}, {"role": "assistant", ...}]} |
toute la séquence |
| Prompt / complétion | {"prompt": "...", "completion": "..."} |
la complétion seulement |
| Prompt / complétion conversationnel | {"prompt": [{"role": "user", ...}], "completion": [{"role": "assistant", ...}]} |
la complétion seulement |
Sur un jeu conversationnel, le gabarit de conversation du modèle est appliqué automatiquement. Pour n'apprendre que les réponses de l'assistant, ajoutez assistant_only_loss=True dans SFTConfig ; la documentation précise que le gabarit doit alors contenir les balises {% generation %} et {% endgeneration %}, ajoutées automatiquement pour les familles connues comme Qwen3. Sur un jeu prompt / complétion, rien à faire : avec completion_only_loss laissé à sa valeur par défaut, la perte ne porte déjà que sur la complétion. La préparation des exemples est détaillée sur Jeu de données.
N'entraîner qu'un adaptateur LoRA
TRL s'intègre à PEFT : il suffit de passer une configuration LoRA.
from datasets import load_dataset
from trl import SFTConfig, SFTTrainer
from peft import LoraConfig
trainer = SFTTrainer(
"Qwen/Qwen3-0.6B",
train_dataset=load_dataset("trl-lib/Capybara", split="train"),
args=SFTConfig(learning_rate=1e-4, assistant_only_loss=True),
peft_config=LoraConfig(),
)
trainer.train()
La documentation indique qu'avec un adaptateur on utilise en général un taux d'apprentissage plus élevé, autour de 1e-4. Pour aller jusqu'à QLoRA, ajoutez une configuration de quantification (quantization_config) : TRL la combine avec peft_config. Le principe est expliqué sur LoRA et QLoRA.
Les réglages par défaut de SFTConfig
| Paramètre | Valeur par défaut |
|---|---|
learning_rate |
2e-5 |
num_train_epochs |
3 |
per_device_train_batch_size |
8 |
max_length |
1024 jetons (au-delà, la séquence est tronquée) |
gradient_checkpointing |
activé (économise la mémoire) |
bf16 |
activé si fp16 ne l'est pas |
packing |
désactivé |
Deux options utiles : packing=True regroupe plusieurs exemples courts dans une même séquence pour gagner en efficacité ; max_length doit être relevé si vos exemples sont longs, sinon la fin est coupée sans bruit.
Suivre l'entraînement
TRL journalise notamment loss (perte moyenne), mean_token_accuracy (part des jetons correctement prédits), learning_rate et grad_norm. Une perte qui baisse sur l'entraînement mais remonte sur la validation signale un surapprentissage : passez un eval_dataset pour le voir. La perte ne remplace pas une évaluation sur la tâche réelle : voir Évaluer un modèle affiné.
Trois pièges signalés par la documentation
- Le jeton de fin. Sur certains modèles de base dont le gabarit de conversation est prédéfini, il faut aligner le jeton de fin (
eos_tokendansSFTConfig), sinon le modèle ne s'arrête pas correctement. La documentation cite l'exemple deQwen/Qwen2.5-1.5Baveceos_token="<|im_end|>". - La précision de chargement. Si
dtypen'est pas précisé dansmodel_init_kwargs,SFTTrainercharge le modèle enfloat32, ce qui consomme plus de mémoire ; précisez{"dtype": torch.bfloat16}au besoin. - Les modèles de vision. Tronquer peut supprimer des jetons d'image ; la documentation recommande
max_length=Nonedans ce cas.
Après l'entraînement
trainer.save_model() enregistre le résultat ; push_to_hub() le publie sur le Hub (en dépôt privé si vous le réglez ainsi). Avec LoRA, seul l'adaptateur est enregistré, et il se recharge sur le modèle de base avec PeftModel.from_pretrained. Pour choisir le modèle de départ et vérifier sa licence, voir Meilleurs modèles open source ; pour le budget machine, Coût d'un fine-tuning.
Questions fréquentes
Quel taux d'apprentissage utiliser avec TRL ?
La valeur par défaut de SFTConfig est 2e-5 pour un entraînement complet. Pour un adaptateur LoRA, la documentation de TRL indique qu'on monte en général vers 1e-4, puisque seuls de nouveaux paramètres sont appris.
Le modèle apprend-il aussi les questions des utilisateurs ?
Par défaut, sur un jeu conversationnel, la perte porte sur toute la séquence. Pour n'apprendre que les réponses, passez assistant_only_loss=True ; sur un jeu prompt / completion, seule la complétion compte déjà par défaut.
Sources
Pages consultées pour écrire cet article :