TRL documentation
Intégration de PEFT
Intégration de PEFT
TRL prend en charge les méthodes PEFT (Parameter-Efficient Fine-Tuning) pour un entraînement de modèles efficace en mémoire. PEFT permet d'ajuster finement de grands modèles de langage en n'entraînant qu'un petit nombre de paramètres supplémentaires tout en gardant le modèle de base figé, réduisant ainsi considérablement les coûts de calcul et les besoins en mémoire.
Ce guide explique comment utiliser PEFT avec différents formateurs TRL, y compris les techniques LoRA, QLoRA et prompt tuning.
Pour un exemple complet et fonctionnel, consultez le notebook SFT avec LoRA/QLoRA.
Installation
Pour utiliser PEFT avec TRL, installez les dépendances requises :
pip install trl[peft]
Pour la prise en charge de QLoRA (quantification 4 bits et 8 bits), installez également :
pip install bitsandbytes
Démarrage rapide
Tous les formateurs TRL prennent en charge PEFT via l'argument peft_config. La manière la plus simple d'activer PEFT consiste à utiliser l'interface en ligne de commande avec le drapeau --use_peft :
python trl/scripts/sft.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/Capybara \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--output_dir Qwen2-0.5B-SFT-LoRASinon, vous pouvez passer une configuration PEFT directement dans votre code Python :
from peft import LoraConfig
from trl import SFTTrainer
# Configure LoRA
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# Configure training - note the higher learning rate for LoRA (10x base rate)
training_args = SFTConfig(
learning_rate=2.0e-4, # 10x the base rate (2.0e-5) for LoRA
...
)
# Create trainer with PEFT
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
peft_config=peft_config,
)Trois façons de configurer PEFT
TRL propose trois méthodes différentes pour configurer PEFT, chacune adaptée à des cas d’usage distincts :
1. Utilisation des drapeaux CLI (le plus simple)
La façon la plus simple d’activer PEFT est d’utiliser le drapeau --use_peft avec l’interface en ligne de commande. Cette méthode est idéale pour des expériences rapides et des configurations standard :
python trl/scripts/sft.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/Capybara \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--lora_dropout 0.05 \
--output_dir Qwen2-0.5B-SFT-LoRAAvantages : Configuration rapide, aucun code requis
Inconvénients : Limité à LoRA, moins d'options de personnalisation
2. Passer peft_config à Trainer (Recommandé)
Pour un contrôle plus fin, passez une configuration PEFT directement au formateur. C'est l'approche recommandée pour la plupart des cas d'utilisation :
from peft import LoraConfig
from trl import SFTConfig, SFTTrainer
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset,
peft_config=peft_config, # Pass config here
)Avantages : Contrôle total, prend en charge toutes les méthodes PEFT (LoRA, Prompt Tuning, etc.)
Inconvénients : Nécessite du code Python
3. Application de PEFT directement au modèle (avancé)
Pour une flexibilité maximale, vous pouvez appliquer PEFT à votre modèle avant de le passer à l'entraîneur :
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
from trl import SFTConfig, SFTTrainer
# Load base model
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")
# Apply PEFT configuration
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, peft_config)
# Pass PEFT-wrapped model to trainer
trainer = SFTTrainer(
model=model, # Already has PEFT applied
args=training_args,
train_dataset=dataset,
# Note: no peft_config needed here
)Avantages : Contrôle maximal, utile pour les architectures de modèles personnalisées ou les configurations complexes
Inconvénients : Plus verbeux, nécessite une compréhension des mécanismes internes de PEFT
Considérations sur le taux d'apprentissage
Lors de l'utilisation de LoRA ou d'autres méthodes PEFT, il est généralement nécessaire d'utiliser un taux d'apprentissage plus élevé (environ 10 fois supérieur) par rapport à l'ajustement fin complet. Cela s'explique par le fait que les méthodes PEFT n'entraînent qu'une petite fraction des paramètres, ce qui exige un taux d'apprentissage plus important pour obtenir des mises à jour de paramètres similaires.
Taux d'apprentissage recommandés :
| Trainer | Ajustement complet | Avec LoRA (10x) |
|---|---|---|
| SFT | 2.0e-5 | 2.0e-4 |
| DPO | 5.0e-7 | 5.0e-6 |
| GRPO | 1.0e-6 | 1.0e-5 |
| Prompt Tuning | N/A | de 1.0e-2 à 3.0e-2 |
Pourquoi 10x ? Les adaptateurs LoRA comportent nettement moins de paramètres entraînables que le modèle complet. Un taux d'apprentissage plus élevé compense ce nombre réduit de paramètres, garantissant ainsi un entraînement efficace. Pour une explication détaillée, consultez ce billet de blog.
Pour de bonnes pratiques supplémentaires sur l'utilisation efficace de LoRA, consultez la documentation LoRA Without Regret.
PEFT avec différents formateurs
Les formateurs de TRL prennent en charge les configurations PEFT pour divers paradigmes d'entraînement. Vous trouverez ci-dessous des exemples détaillés pour chaque formateur principal.
Ajustement fin supervisé (SFT)
Le SFTTrainer est utilisé pour l’ajustement fin supervisé sur des jeux de données d’instructions.
Avec LoRA
python trl/scripts/sft.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/Capybara \
--learning_rate 2.0e-4 \
--num_train_epochs 1 \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 8 \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--output_dir Qwen2-0.5B-SFT-LoRAExemple en Python
from peft import LoraConfig
from trl import SFTConfig, SFTTrainer
# Configure LoRA
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules=["q_proj", "v_proj"], # optional: specify target modules
)
# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
learning_rate=2.0e-4, # 10x the base rate for LoRA
...
)
# Create trainer with PEFT config
trainer = SFTTrainer(
model="Qwen/Qwen2-0.5B", # can pass model name or loaded model
args=training_args,
train_dataset=dataset,
peft_config=peft_config, # pass PEFT config here
)
trainer.train()Optimisation des préférences directes (DPO)
Le DPOTrainer implémente l'apprentissage par préférences à partir des retours humains.
Avec LoRA
python trl/scripts/dpo.py \
--model_name_or_path Qwen/Qwen2-0.5B-Instruct \
--dataset_name trl-lib/ultrafeedback_binarized \
--learning_rate 5.0e-6 \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 8 \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--output_dir Qwen2-0.5B-DPO-LoRAExemple en Python
from peft import LoraConfig
from trl import DPOConfig, DPOTrainer
# Configure LoRA
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# Configure training with higher learning rate for LoRA
training_args = DPOConfig(
learning_rate=5.0e-6, # 10x the base rate for DPO with LoRA
...
)
# Create trainer with PEFT config
trainer = DPOTrainer(
model="Qwen/Qwen2-0.5B", # can pass model name or loaded model
args=training_args,
train_dataset=dataset,
peft_config=peft_config, # pass PEFT config here
)
trainer.train()Remarque : Lors de l'utilisation de PEFT avec DPO, vous n'avez pas besoin de fournir un modèle de référence séparé (ref_model). Le formateur utilise automatiquement le modèle de base figé comme référence.
Optimisation de politique relative par groupe (GRPO)
Le GRPOTrainer optimise les politiques à l'aide de récompenses basées sur des groupes.
Avec LoRA
python trl/scripts/grpo.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/math-reasoning \
--learning_rate 1.0e-5 \
--per_device_train_batch_size 2 \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--output_dir Qwen2-0.5B-GRPO-LoRAExemple en Python
from peft import LoraConfig
from trl import GRPOConfig, GRPOTrainer
# Configure LoRA
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# Configure training with higher learning rate for LoRA
training_args = GRPOConfig(
learning_rate=1.0e-5, # 10x the base rate for GRPO with LoRA
...
)
# Create trainer with PEFT config
trainer = GRPOTrainer(
model="Qwen/Qwen2-0.5B", # can pass model name or loaded model
args=training_args,
train_dataset=dataset,
peft_config=peft_config, # pass PEFT config here
)
trainer.train()QLoRA : Adaptation de rang faible quantifiée
QLoRA combine la quantification sur 4 bits avec LoRA pour permettre l'ajustement fin de très grands modèles sur du matériel grand public. Cette technique peut réduire les besoins en mémoire jusqu'à 4 fois par rapport à LoRA standard.
Fonctionnement de QLoRA
- Quantification 4 bits : le modèle de base est chargé en précision 4 bits à l'aide de
bitsandbytes - Poids figés : Les poids du modèle quantifié restent figés pendant l'entraînement
- Adaptateurs LoRA : Seuls les paramètres de l'adaptateur LoRA sont entraînés en haute précision
- Efficacité mémoire : Permet l'ajustement fin de modèles comme Llama-70B sur un seul GPU grand public
Utiliser QLoRA avec TRL
Il suffit de combiner load_in_4bit=True avec la configuration PEFT :
Ligne de commande
python trl/scripts/sft.py \
--model_name_or_path meta-llama/Llama-2-7b-hf \
--dataset_name trl-lib/Capybara \
--load_in_4bit \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 16 \
--output_dir Llama-2-7b-QLoRAExemple en Python
Passez quantization_config directement au trainer en même temps que peft_config — le trainer charge et quantise le modèle pour vous. L'argument quantization_config est également disponible sur SFTTrainer, DPOTrainer, GRPOTrainer et RLOOTrainer.
import torch
from peft import LoraConfig
from transformers import BitsAndBytesConfig
from trl import SFTConfig, SFTTrainer
# Configure 4-bit quantization
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
# Configure LoRA
peft_config = LoraConfig(
r=32,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
learning_rate=2.0e-4, # 10x the base rate for QLoRA
...
)
# Create trainer with quantization and PEFT config
trainer = SFTTrainer(
model="meta-llama/Llama-2-7b-hf",
args=training_args,
train_dataset=dataset,
quantization_config=bnb_config,
peft_config=peft_config,
)
trainer.train()Options de configuration de QLoRA
La BitsAndBytesConfig offre plusieurs options pour optimiser la mémoire et les performances :
import torch
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # or "fp4"
bnb_4bit_compute_dtype=torch.bfloat16, # Compute dtype for 4-bit base models
bnb_4bit_use_double_quant=True, # Nested quantization for additional memory savings
)Paramètres de configuration :
bnb_4bit_quant_type: Type de données de quantification ("nf4"ou"fp4"). NF4 est recommandé.bnb_4bit_compute_dtype: le dtype utilisé pour le calcul. Utilisezbfloat16pour une meilleure stabilité de l'entraînement.bnb_4bit_use_double_quant: Active la quantification imbriquée pour économiser environ 0,4 bit supplémentaire par paramètre.
Quantification 8 bits
Pour une précision légèrement supérieure au détriment des économies de mémoire, vous pouvez utiliser la quantification 8 bits :
from transformers import BitsAndBytesConfig, AutoModelForCausalLM
bnb_config = BitsAndBytesConfig(load_in_8bit=True)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantization_config=bnb_config,
device_map="auto",
)Ou via la ligne de commande :
python trl/scripts/sft.py \
--model_name_or_path meta-llama/Llama-2-7b-hf \
--load_in_8bit \
--use_peft \
--lora_r 32 \
--lora_alpha 16Points de contrôle pré-quantifiés
Certains points de contrôle sont publiés quantifiés, comme gpt-oss en MXFP4 ou Mistral Medium 3.5 en FP8. Ces poids ne peuvent pas être entraînés sur place, donc lorsque vous passez un tel point de contrôle par son nom, l’entraîneur le charge déquantifié, avec ou sans peft_config. Le modèle occupe alors la mémoire de ses poids déquantifiés, par exemple environ 42 Go en bfloat16 pour gpt-oss-20b, contre 13 Go pour son point de contrôle MXFP4. Pour le charger en bfloat16, comme pour tout autre modèle :
from trl import SFTConfig
training_args = SFTConfig(model_init_kwargs={"dtype": "bfloat16"})Les points de contrôle FP8 nécessitent transformers 5.0.0 ou une version ultérieure.
Prompt Tuning
Le prompt tuning est une autre technique PEFT qui apprend des prompts doux (embeddings continus) préfixés à l'entrée, tout en gardant le modèle entier figé. Cette approche est particulièrement efficace pour les grands modèles.
Fonctionnement du Prompt Tuning
- Jetons virtuels : Ajoute des plongements continus apprenables (jetons virtuels) à l'entrée
- Modèle figé : l'intégralité du modèle de base reste figée
- Invites spécifiques à la tâche : chaque tâche apprend ses propres embeddings d'invite
- Efficacité extrême : Seuls les embeddings du prompt sont entraînés (généralement 8 à 20 jetons)
Utiliser le Prompt Tuning avec TRL
from peft import PromptTuningConfig, PromptTuningInit, TaskType
from trl import SFTConfig, SFTTrainer
# Configure Prompt Tuning
peft_config = PromptTuningConfig(
task_type=TaskType.CAUSAL_LM,
prompt_tuning_init=PromptTuningInit.TEXT,
num_virtual_tokens=8,
prompt_tuning_init_text="Classify if the tweet is a complaint or not:",
tokenizer_name_or_path="Qwen/Qwen2-0.5B",
)
# Configure training with higher learning rate for Prompt Tuning
training_args = SFTConfig(
learning_rate=2.0e-2, # Prompt Tuning typically uses 1e-2 to 3e-2
...
)
# Create trainer with PEFT config
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset,
peft_config=peft_config, # pass PEFT config here
)
trainer.train()Configuration du Prompt Tuning
from peft import PromptTuningConfig, PromptTuningInit, TaskType
peft_config = PromptTuningConfig(
task_type=TaskType.CAUSAL_LM, # Task type
prompt_tuning_init=PromptTuningInit.TEXT, # Initialize from text
num_virtual_tokens=8, # Number of virtual tokens
prompt_tuning_init_text="Your initialization text here",
tokenizer_name_or_path="model_name",
)Paramètres de configuration :
task_type: le type de tâche (TaskType.CAUSAL_LMpour la modélisation de langage)prompt_tuning_init: Méthode d'initialisation (TEXT,RANDOM)num_virtual_tokens: Nombre de jetons virtuels à préfixer (généralement 8 à 20)prompt_tuning_init_text: Texte pour initialiser les jetons virtuels (lors de l'utilisation de l'initialisationTEXT)tokenizer_name_or_path: Tokenizer pour l’initialisation à partir de texte
Prompt Tuning et LoRA
| Fonctionnalité | Prompt Tuning | LoRA |
|---|---|---|
| Paramètres entraînés | ~0.001% | ~0.1-1% |
| Utilisation de la mémoire | Minimal | Faible |
| Vitesse d'entraînement | Le plus rapide | Rapide |
| Modification de modèle | Aucun | Couches d'adaptation |
| Idéal pour | Grands modèles, nombreuses tâches | Ajustement fin général |
| Taux d'apprentissage | Plus élevé (1e-2 à 3e-2) | Standard (1e-4 à 3e-4) |
Configurations avancées de PEFT
Paramètres de configuration LoRA
from peft import LoraConfig
peft_config = LoraConfig(
r=16, # LoRA rank
lora_alpha=32, # LoRA scaling factor
lora_dropout=0.05, # Dropout probability
bias="none", # Bias training strategy
task_type="CAUSAL_LM", # Task type
target_modules=["q_proj", "v_proj"], # Modules to apply LoRA
modules_to_save=None, # Additional modules to train
)Paramètres clés :
r: rang de LoRA (valeurs typiques : 8, 16, 32, 64). Un rang plus élevé signifie plus de paramètres, mais potentiellement de meilleures performances.lora_alpha: Facteur d'échelle (généralement 2 fois le rang). Contrôle l'amplitude des mises à jour LoRA.lora_dropout: Probabilité de dropout pour les couches LoRA (typique : 0,05-0,1).target_modules: Modules auxquels appliquer LoRA. Choix courants :["q_proj", "v_proj"]: requête et valeur d'attention (efficace en mémoire)["q_proj", "k_proj", "v_proj", "o_proj"]: Toutes les projections d'attention["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]: Toutes les couches linéaires
modules_to_save: Modules supplémentaires à entraîner entièrement (par exemple,["embed_tokens", "lm_head"])
Sélection du module cible
Vous pouvez spécifier les modules auxquels appliquer LoRA. Schémas courants :
# Minimal (most memory efficient)
target_modules=["q_proj", "v_proj"]
# Attention only
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]
# All linear layers (best performance, more memory)
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]Utilisation des arguments de ligne de commande
Les scripts TRL acceptent les paramètres PEFT via la ligne de commande :
python trl/scripts/sft.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/Capybara \
--use_peft \
--lora_r 32 \
--lora_alpha 16 \
--lora_dropout 0.05 \
--lora_target_modules q_proj v_proj \
--output_dir outputDrapeaux disponibles :
--use_peft: Activer PEFT--lora_r: rang de LoRA (par défaut : 16)--lora_alpha: alpha de LoRA (par défaut : 32)--lora_dropout: dropout de LoRA (par défaut : 0.05)--lora_target_modules: Modules cibles (séparés par des espaces)--lora_modules_to_save: Modules supplémentaires à entraîner--use_rslora: Activer Rank-Stabilized LoRA--use_dora: Activer Weight-Decomposed LoRA (DoRA)--load_in_4bit: Active la quantification en 4 bits (QLoRA)--load_in_8bit: Activer la quantification en 8 bits
Enregistrer et charger des modèles PEFT
Enregistrement
Après l’entraînement, enregistrez vos adaptateurs PEFT :
# Save the adapters
trainer.save_model("path/to/adapters")
# Or manually
model.save_pretrained("path/to/adapters")Cela n'enregistre que les poids de l'adaptateur (quelques Mo) plutôt que le modèle complet (plusieurs Go).
Chargement
Charger un modèle PEFT pour l’inférence :
from transformers import AutoModelForCausalLM
from peft import PeftModel
# Load base model
base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")
# Load PEFT adapters
model = PeftModel.from_pretrained(base_model, "path/to/adapters")
# Optionally merge adapters into base model for faster inference
model = model.merge_and_unload()Pousser vers le Hub
Vous pouvez facilement partager vos adaptateurs PEFT sur le Hugging Face Hub :
# Push adapters to Hub
model.push_to_hub("username/model-name-lora")
# Load from Hub
from peft import PeftModel
model = PeftModel.from_pretrained(base_model, "username/model-name-lora")Entraînement multi-GPU
PEFT fonctionne parfaitement avec la prise en charge multi-GPU de TRL via accelerate :
# Configure accelerate
accelerate config
# Launch training
accelerate launch trl/scripts/sft.py \
--model_name_or_path Qwen/Qwen2-0.5B \
--dataset_name trl-lib/Capybara \
--use_peft \
--lora_r 32 \
--lora_alpha 16Pour QLoRA avec plusieurs GPU, le modèle de base est automatiquement fragmenté :
accelerate launch trl/scripts/sft.py \
--model_name_or_path meta-llama/Llama-2-70b-hf \
--load_in_4bit \
--use_peft \
--lora_r 32Parallélisme de pipeline naïf (NPP) pour les grands modèles
Pour les très grands modèles (>60B paramètres), TRL prend en charge le parallélisme de pipeline naïf (Naive Pipeline Parallelism, NPP), qui répartit le modèle et les adaptateurs sur plusieurs GPU. Les activations et les gradients sont communiqués entre les GPU, en prenant en charge le type de données int8 ainsi que d'autres types.

Comment utiliser NPP
Chargez votre modèle avec un device_map personnalisé pour le répartir sur plusieurs appareils :
from transformers import AutoModelForCausalLM
from peft import LoraConfig
# Create custom device map (see accelerate documentation)
device_map = {
"model.embed_tokens": 0,
"model.layers.0": 0,
# ... distribute layers across GPUs
"lm_head": 0, # Must be on GPU 0
}
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-70b-hf",
device_map=device_map,
peft_config=lora_config,
)
- Gardez le module
lm_headsur la première GPU (device 0) pour éviter les erreurs- Consultez ce tutoriel sur les mappages de périphériques pour une configuration appropriée
- Exécuter les scripts d’entraînement directement (sans
accelerate launch) :python script.py- Le parallélisme de données n'est pas encore pris en charge avec NPP
Ressources
Exemples et notebooks TRL
- Carnet d'exemples SFT avec LoRA/QLoRA - Exemple complet et fonctionnel montrant les implémentations LoRA et QLoRA
- Répertoire des exemples TRL - Collection de scripts d'entraînement démontrant PEFT avec différents formateurs
- Recettes du livre de cuisine TRL - Guides pas à pas pour les scénarios de formation PEFT courants
Documentation
- Documentation PEFT - Documentation officielle de la bibliothèque PEFT
- Documentation TRL - Documentation complète de TRL avec des guides d'utilisation des formateurs
- LoRA sans regret - Bonnes pratiques pour utiliser LoRA efficacement
Articles de recherche
- Article LoRA - Méthodologie et résultats originaux de LoRA
- Article QLoRA - Ajustement fin efficace avec quantification sur 4 bits
- Article sur le Prompt Tuning - La puissance de l'échelle pour le Prompt Tuning efficace en paramètres