Aller au contenu
Cercle IA Tech · Fine-tuning Un site du réseau Cercle IA Tech

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

  1. 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_token dans SFTConfig), sinon le modèle ne s'arrête pas correctement. La documentation cite l'exemple de Qwen/Qwen2.5-1.5B avec eos_token="<|im_end|>".
  2. La précision de chargement. Si dtype n'est pas précisé dans model_init_kwargs, SFTTrainer charge le modèle en float32, ce qui consomme plus de mémoire ; précisez {"dtype": torch.bfloat16} au besoin.
  3. Les modèles de vision. Tronquer peut supprimer des jetons d'image ; la documentation recommande max_length=None dans 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 :

  1. https://huggingface.co/docs/trl/sft_trainer
  2. https://huggingface.co/docs/peft/quicktour
  3. https://huggingface.co/docs/peft/index

À lire aussi