TRL documentation
RLOO Trainer
RLOO Trainer
Aperçu
TRL prend en charge le RLOO Trainer pour l’entraînement de modèles de langage, tel que décrit dans l’article Back to Basics: Revisiting REINFORCE Style Optimization for Learning from Human Feedback in LLMs de Arash Ahmadian, Chris Cremer, Matthias Gallé, Marzieh Fadaee, Julia Kreutzer, Ahmet Üstün et Sara Hooker.
L'abstract de l'article est le suivant :
L’alignement de l’IA, sous la forme de l’apprentissage par renforcement à partir des retours humains (RLHF), est de plus en plus considéré comme un ingrédient crucial pour les grands modèles de langage à haute performance. L’optimisation de politique proximale (PPO) a été positionnée par la littérature récente comme la méthode canonique pour la partie RL du RLHF. Cependant, elle implique à la fois un coût de calcul élevé et un réglage sensible des hyperparamètres. Nous posons que la plupart des principes motivationnels qui ont conduit au développement de PPO sont moins une préoccupation pratique dans le contexte du RLHF, et nous plaidons pour une méthode moins coûteuse en calcul qui préserve, voire augmente, les performances. Nous réexaminons la formulation de l’alignement à partir des préférences humaines dans le contexte de l’apprentissage par renforcement. En gardant la simplicité comme principe directeur, nous montrons que de nombreux composants de PPO sont inutiles dans un contexte de RLHF et que des variantes d’optimisation de type REINFORCE, bien plus simples, surpassent à la fois PPO et les méthodes « sans RL » récemment proposées, telles que DPO et RAFT. Notre travail suggère qu’une adaptation soignée aux caractéristiques d’alignement des LLM permet de tirer parti de l’optimisation RL en ligne à faible coût.
Cette méthode de post-entraînement a été proposée par Costa Huang puis refactorisée par Shirin Yamani.
Démarrage rapide
Cet exemple montre comment entraîner un modèle à l'aide de la méthode RLOO. Nous entraînons un modèle Qwen 0.5B Instruct avec les prompts du jeu de données DeepMath-103K. Vous pouvez consulter les données du jeu de données ici :
Voici le script pour entraîner le modèle. accuracy_reward nécessite math-verify, que vous pouvez installer avec pip install trl[math_verify].
# train_rloo.py
from datasets import load_dataset
from trl import RLOOTrainer
from trl.rewards import accuracy_reward
dataset = load_dataset("trl-lib/DeepMath-103K", split="train")
trainer = RLOOTrainer(
model="Qwen/Qwen2-0.5B-Instruct",
reward_funcs=accuracy_reward,
train_dataset=dataset,
)
trainer.train()Exécutez le script à l'aide de la commande suivante :
accelerate launch train_rloo.py
Explorer plus en profondeur la méthode RLOO
RLOO est un algorithme d'apprentissage en ligne, ce qui signifie qu'il s'améliore de manière itérative en utilisant les données générées par le modèle entraîné lui-même pendant l'entraînement. L'intuition derrière l'objectif de RLOO est de maximiser l'avantage des complétions générées, tout en veillant à ce que le modèle reste proche de la politique de référence. Pour comprendre le fonctionnement de RLOO, il peut être décomposé en quatre étapes principales : génération des complétions, calcul de l'avantage, estimation de la divergence KL et calcul de la perte.

Générer des complétions
À chaque étape d'entraînement, nous échantillonnons un lot de prompts et générons un ensemble de complétions pour chaque prompt (notées ).
Calculer la récompense
Dans RLOO, la récompense se compose de deux éléments : la récompense fournie par le modèle de récompense (ou la fonction de récompense) et une pénalité KL qui décourage la politique de s'écarter trop d'une politique de référence fixe
- Pour chacune des séquences générées conditionnées par une requête , nous calculons une récompense scalaire à l'aide d'un modèle de récompense .
- Simultanément, nous estimons la divergence de KL entre la politique actuelle et la politique de référence fixe sur la séquence. L'estimation de KL pour la séquence est :
La récompense finale attribuée à la séquence est alors la suivante :
où contrôle l'intensité de la pénalité KL.
Dans un contexte purement en ligne (
num_iterations = 1, par défaut), les données sont générées par la politique actuelle. Dans ce cas, la pénalité KL est calculée directement à l'aide de la politique actuelle.Dans un contexte plus général (par exemple, plusieurs étapes de gradient par lot), les données sont plutôt générées par un instantané antérieur . Pour maintenir la pénalité cohérente avec la distribution d'échantillonnage, la divergence KL est définie par rapport à cette politique :
De manière équivalente, pour une séquence échantillonnée , l'estimation de Monte Carlo est :
Calcul de l'avantage
Une fois les récompenses de chaque complétion calculées, nous déterminons une ligne de base en prenant la récompense moyenne de tous les autres échantillons du même lot, en excluant l'échantillon courant. Cette ligne de base est utilisée pour réduire la variance de l'estimation du gradient de politique. L'avantage de chaque complétion est ensuite obtenu en soustrayant cette ligne de base leave-one-out de sa propre récompense.
Formellement, pour un lot de G complétions, la référence pour la complétion est :
puis l'avantage pour chaque complétion est calculé comme la différence entre sa récompense et la ligne de base :
Calcul de la perte
La perte REINFORCE est simplement définie comme :
En pratique, effectuer plusieurs pas de gradient sur le même lot rend les actions effectivement hors politique par rapport aux paramètres actuels. Pour corriger cela, nous introduisons le ratio d'échantillonnage d'importance. Pour éviter des mises à jour excessivement importantes lorsque la politique change entre l'échantillonnage et les pas de gradient, nous tronquons ce ratio :
Dans un contexte entièrement en ligne, en une seule étape (par défaut), et cela se réduit à REINFORCE standard.
Contrairement à GRPO, RLOO ne rétropropage pas les gradients à travers le terme KL. Ici, le KL est utilisé uniquement pour la mise en forme de la récompense : il est calculé sous
no_gradet intégré à la récompense scalaire , qui devient l'avantage détaché .En d'autres termes, le seul chemin par lequel le gradient pénètre dans la politique est le terme du ratio d'importance , et le terme KL ne rétropropage pas dans la politique.
En revanche, GRPO ajoute un terme KL explicite et différentiable à son objectif, calculé à la volée avec la politique actuelle , de sorte que son gradient traverse à la fois le terme de ratio et la pénalité KL.
Métriques journalisées
Lors de l'entraînement et de l'évaluation, nous enregistrons les métriques suivantes :
num_tokens: le nombre total de jetons traités jusqu'à présent, prompts et complétions inclus.step_time: le temps moyen (en secondes) par étape d'entraînement (génération incluse).completions/mean_length: La longueur moyenne des complétions générées.completions/min_length: La longueur minimale des complétions générées.completions/max_length: La longueur maximale des complétions générées.completions/mean_terminated_length: La longueur moyenne des complétions générées qui se terminent par EOS.completions/min_terminated_length: Longueur minimale des complétions générées qui se terminent par EOS.completions/max_terminated_length: La longueur maximale des complétions générées qui se terminent par EOS.completions/clipped_ratio: Le ratio des complétions tronquées (clippées).rewards/{reward_func_name}/mean: la récompense moyenne issue d'une fonction de récompense spécifique.rewards/{reward_func_name}/std: l'écart-type de la récompense issue d'une fonction de récompense spécifique.reward: La récompense moyenne globale après avoir additionné les récompenses sur l'ensemble des fonctions (pondérées parreward_weights).reward_std: l'écart-type des récompenses cumulées sur l'ensemble des fonctions (pondérées parreward_weights), calculé sur le lot complet.frac_reward_zero_std: La proportion d'échantillons du lot de génération dont l'écart-type de la récompense est nul, ce qui implique qu'il y a peu de diversité pour ce prompt (toutes les réponses sont correctes ou incorrectes).entropy: Entropie moyenne des prédictions de jetons sur l’ensemble des complétions générées. (Simask_truncated_completions=True, les jetons des séquences masquées sont exclus.)aux_loss: perte auxiliaire d'équilibrage de charge d'un modèle Mixture-of-Experts, avant d'être mise à l'échelle parrouter_aux_loss_coefet ajoutée à la perte. Journalisée uniquement lorsque le modèle est un modèle MoE et querouter_aux_loss_coefest non nul.kl: divergence KL moyenne entre le modèle et le modèle de référence, calculée sur les complétions générées. Journalisé uniquement sibetaest non nul.clip_ratio/region_mean: Le ratio des probabilités de séquences pour lesquelles l'objectif RLOO est tronqué afin de rester dans la région de confiance : . Une valeur plus élevée signifie que plus d'échantillons sont tronqués, ce qui limite l'ampleur des modifications de la politique peut subir.clip_ratio/low_mean: Le ratio moyen des probabilités de séquences qui ont été rognées sur la borne inférieure de la région de confiance : .clip_ratio/low_min: L'indicateur de clip minimal par complétion sur la borne inférieure de la région de confiance : .clip_ratio/high_mean: Le ratio moyen des probabilités de séquence qui ont été rognées sur la borne supérieure de la région de confiance : .clip_ratio/high_max: L'indicateur de clip maximal par complétion sur la borne supérieure de la région de confiance : .
Personnalisation
Accélérer l'entraînement avec la génération propulsée par vLLM
La génération est souvent le principal goulot d'étranglement lors de l'entraînement avec des méthodes en ligne. Pour accélérer la génération, vous pouvez utiliser vLLM, un moteur d'inférence à haut débit et faible latence pour les LLM. Pour l'activer, installez d'abord le package avec
pip install trl[vllm]
Nous prenons en charge deux façons d'utiliser vLLM pendant l'entraînement : le mode serveur et le mode colocalisé.
Option 1 : Mode Colocate
Dans ce mode, vLLM s’exécute dans le processus d’entraînement et partage la mémoire GPU avec le modèle d’entraînement. Cela évite de démarrer un serveur séparé et peut améliorer l’utilisation des GPU, mais peut entraîner une concurrence mémoire sur les GPU d’entraînement. C’est le mode par défaut.
from trl import RLOOConfig
training_args = RLOOConfig(
...,
use_vllm=True, # vllm_mode="colocate" by default
)Option 2 : Mode serveur
Dans ce mode, vLLM s’exécute dans un processus distinct (et utilise des GPU séparés) et communique avec l’entraîneur via HTTP. C’est idéal si vous disposez de GPU dédiés à l’inférence.
Démarrer le serveur vLLM :
VLLM_SERVER_DEV_MODE=1 vllm serve <model_name> \ --weight-transfer-config '{"backend": "nccl"}' \ --logprobs-mode processed_logprobs \ --max-logprobs -1Activer le mode serveur dans votre script d’entraînement :
from trl import RLOOConfig training_args = RLOOConfig( ..., use_vllm=True, vllm_mode="server", )
Assurez-vous que le serveur utilise des GPU différents de ceux du formateur, sinon vous risquez de rencontrer des erreurs NCCL. Vous pouvez spécifier les GPU à utiliser avec la variable d’environnement
CUDA_VISIBLE_DEVICES.
En fonction de la taille du modèle et des besoins globaux en mémoire GPU pour l’entraînement, vous devrez peut-être ajuster le paramètre
vllm_gpu_memory_utilizationdans RLOOConfig afin d’éviter une sous-utilisation ou des erreurs de mémoire insuffisante.Nous mettons à disposition un HF Space pour vous aider à estimer l'utilisation recommandée de la mémoire GPU en fonction de la configuration de votre modèle et des paramètres de votre expérience. Utilisez-le simplement comme suit pour obtenir la recommandation de
vllm_gpu_memory_utilization:Si la valeur recommandée ne fonctionne pas dans votre environnement, nous suggérons d'ajouter une petite marge (par exemple, +0.05 ou +0.1) à la valeur recommandée pour garantir la stabilité.
Si vous rencontrez toujours des erreurs de mémoire insuffisante, définissez
vllm_enable_sleep_modesur True et les paramètres vllm ainsi que le cache seront déchargés pendant l'étape d'optimisation. Pour plus d'informations, consultez Réduire l'utilisation de la mémoire avec le mode veille de vLLM.
Par défaut, RLOO utilise
MASTER_ADDR=localhostetMASTER_PORT=12345pour vLLM, mais vous pouvez remplacer ces valeurs en définissant les variables d’environnement en conséquence.
Pour plus d'informations, consultez Accélérer l'entraînement avec vLLM.
RLOO à grande échelle : entraîner un modèle de 70B+ sur plusieurs nœuds
Lors de l'entraînement de grands modèles comme Qwen2.5-72B, plusieurs optimisations clés sont nécessaires pour rendre l'entraînement efficace et scalable sur plusieurs GPU et nœuds. Elles incluent :
- DeepSpeed ZeRO Stage 3 : ZeRO exploite le parallélisme de données pour distribuer les états du modèle (poids, gradients, états de l’optimiseur) sur plusieurs GPU et CPU, réduisant ainsi les besoins en mémoire et en calcul sur chaque appareil. Comme les grands modèles ne peuvent pas tenir sur un seul GPU, l’utilisation de ZeRO Stage 3 est requise pour entraîner ce type de modèles. Pour plus de détails, voir DeepSpeed Integration.
- Accelerate : Accelerate est une bibliothèque qui simplifie l’entraînement distribué sur plusieurs GPU et nœuds. Elle fournit une API simple pour lancer l’entraînement distribué et gère les complexités de l’entraînement distribué, telles que le parallélisme de données, l’accumulation de gradients et le chargement distribué des données. Pour plus de détails, voir Distributing Training.
- vLLM : Reportez-vous à la section précédente pour savoir comment utiliser vLLM afin d’accélérer la génération.
Voici un exemple de script SLURM pour entraîner un modèle de 70B avec RLOO sur plusieurs nœuds. Ce script entraîne un modèle sur 4 nœuds et utilise le 5e nœud pour la génération propulsée par vLLM.
#!/bin/bash
#SBATCH --nodes=5
#SBATCH --gres=gpu:8
# Get the list of allocated nodes
NODELIST=($(scontrol show hostnames $SLURM_JOB_NODELIST))
# Assign the first 4 nodes for training and the 5th node for vLLM
TRAIN_NODES="${NODELIST[@]:0:4}" # Nodes 0, 1, 2, 3 for training
VLLM_NODE="${NODELIST[4]}" # Node 4 for vLLM
# Run training on the first 4 nodes (Group 1)
srun --nodes=4 --ntasks=4 --nodelist="${NODELIST[@]:0:4}" accelerate launch \
--config_file examples/accelerate_configs/deepspeed_zero3.yaml \
--num_processes 32 \
--num_machines 4 \
--main_process_ip ${NODELIST[0]} \
--machine_rank $SLURM_PROCID \
--rdzv_backend c10d \
train_rloo.py \
--server_ip $VLLM_NODE &
# Run vLLM server on the 5th node (Group 2)
srun --nodes=1 --ntasks=1 --nodelist="${NODELIST[4]}" env VLLM_SERVER_DEV_MODE=1 vllm serve Qwen/Qwen2.5-72B --tensor-parallel-size 8 \
--weight-transfer-config '{"backend": "nccl"}' \
--logprobs-mode processed_logprobs \
--max-logprobs -1 &
waitimport argparse
from datasets import load_dataset
from trl import RLOOTrainer, RLOOConfig
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--vllm_server_host", type=str, default="", help="The server IP")
args = parser.parse_args()
# Example dataset from TLDR
dataset = load_dataset("trl-lib/tldr", split="train")
# Dummy reward function: count the number of unique characters in the completions
def reward_num_unique_chars(completions, **kwargs):
return [len(set(c)) for c in completions]
training_args = RLOOConfig(
output_dir="Qwen2.5-72B-RLOO",
per_device_train_batch_size=4,
bf16=True,
use_vllm=True,
vllm_mode="server",
vllm_server_host=args.vllm_server_host.replace("ip-", "").replace("-", "."), # from ip-X-X-X-X to X.X.X.X
)
trainer = RLOOTrainer(model="Qwen/Qwen2.5-72B", args=training_args, reward_funcs=reward_num_unique_chars, train_dataset=dataset)
trainer.train()
if __name__=="__main__":
main()Utiliser une fonction de récompense personnalisée
Le RLOOTrainer prend en charge l'utilisation de fonctions de récompense personnalisées à la place des modèles de récompense denses. Pour garantir la compatibilité, votre fonction de récompense doit satisfaire aux exigences suivantes :
Les fonctions de récompense peuvent être des fonctions Python synchrones ou des coroutines asynchrones async def. Lorsque vous fournissez plusieurs fonctions de récompense asynchrones, elles sont attendues de manière concurrente (exécutées en parallèle via asyncio.gather) afin que leur latence se superpose.
Arguments d'entrée :
La fonction doit accepter les éléments suivants en tant qu'arguments nommés :
prompts(contient les prompts),completions(contient les complétions générées),completion_ids(contient les complétions tokenisées),trainer_state(TrainerState) : l'état actuel du formateur. Il peut être utilisé pour implémenter des fonctions de récompense dynamiques, comme l'apprentissage par curriculum, où la récompense est ajustée en fonction de la progression de l'entraînement.log_extra: un appelablelog_extra(column: str, values: list)pour ajouter des colonnes supplémentaires au tableau des complétions. Voir l’exemple 6.log_metric: un appelablelog_metric(name: str, value: float)pour journaliser des métriques scalaires sous forme de graphiques aux côtés dekl,entropy, etc. Voir l’exemple 6.- Tous les noms de colonnes (sauf
prompt) que le jeu de données peut contenir. Par exemple, si le jeu de données contient une colonne nomméeground_truth, la fonction sera appelée avecground_truthen tant qu'argument par mot-clé.
La façon la plus simple de respecter cette exigence est d'utiliser
**kwargsdans la signature de la fonction.Selon le format du jeu de données, l'entrée variera :
- Pour le format standard,
promptsetcompletionsseront des listes de chaînes de caractères. - Pour le format conversationnel,
promptsetcompletionsseront des listes de dictionnaires de messages.
- Pour le format standard,
Valeur de retour : La fonction doit retourner une liste de flottants. Chaque flottant représente la récompense correspondant à une seule complétion.
Exemple 1 : Récompenser les complétions plus longues
Voici un exemple de fonction de récompense pour un format standard qui récompense les complétions plus longues :
def reward_func(completion_ids, **kwargs):
"""Reward function that assigns higher scores to longer completions (in terms of token count)."""
return [float(len(ids)) for ids in completion_ids]Vous pouvez le tester comme suit :
>>> prompts = ["The sky is", "The sun is"] # not used in the reward function, but the trainer will pass it
>>> completions = [" blue.", " in the sky."] # not used in the reward function, but the trainer will pass it
>>> completion_ids = [[6303, 13], [304, 279, 12884, 13]]
>>> reward_func(prompts=prompts, completions=completions, completion_ids=completion_ids)
[2.0, 4.0]Exemple 1.1 : Récompenser les complétions plus longues (en fonction du nombre de caractères)
Identique à l'exemple précédent, mais cette fois la fonction de récompense est basée sur le nombre de caractères plutôt que sur les jetons.
def reward_func(completions, **kwargs):
"""Reward function that assigns higher scores to longer completions (in terms of character count)."""
return [float(len(completion)) for completion in completions]Vous pouvez le tester comme suit :
>>> prompts = ["The sky is", "The sun is"]
>>> completions = [" blue.", " in the sky."]
>>> completion_ids = [[6303, 13], [304, 279, 12884, 13]] # not used in the reward function, but the trainer will pass it
>>> reward_func(prompts=prompts, completions=completions, completion_ids=completion_ids)
[6.0, 12.0]Exemple 2 : Récompenser les complétions avec un format spécifique
Voici un exemple de fonction de récompense qui vérifie si l’achèvement respecte un format spécifique. Cet exemple s’inspire de la fonction format reward utilisée dans l’article DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. Elle est conçue pour un format conversationnel, où les invites et les achèvements sont constitués de messages structurés.
import re
def format_reward_func(completions, **kwargs):
"""Reward function that checks if the completion has a specific format."""
pattern = r"^<think>.*?</think><answer>.*?</answer>$"
completion_contents = [completion[0]["content"] for completion in completions]
matches = [re.match(pattern, content) for content in completion_contents]
return [1.0 if match else 0.0 for match in matches]Vous pouvez tester cette fonction comme suit :
>>> prompts = [
... [{"role": "user", "content": "What is the result of (1 + 2) * 4?"}],
... [{"role": "user", "content": "What is the result of (3 + 1) * 2?"}],
... ]
>>> completions = [
... [{"role": "assistant", "content": "<think>The sum of 1 and 2 is 3, which we multiply by 4 to get 12.</think><answer>(1 + 2) * 4 = 12</answer>"}],
... [{"role": "assistant", "content": "The sum of 3 and 1 is 4, which we multiply by 2 to get 8. So (3 + 1) * 2 = 8."}],
... ]
>>> format_reward_func(prompts=prompts, completions=completions)
[1.0, 0.0]Exemple 3 : Récompenser les complétions sur la base d'une référence
Voici un exemple de fonction de récompense qui vérifie si la complétion est correcte. Cet exemple s’inspire de la fonction accuracy reward utilisée dans l’article DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.
Cet exemple est conçu pour le format standard, où le jeu de données contient une colonne nommée ground_truth.
import re
def reward_func(completions, ground_truth, **kwargs):
# Regular expression to capture content inside \boxed{}
matches = [re.search(r"\\boxed\{(.*?)\}", completion) for completion in completions]
contents = [match.group(1) if match else "" for match in matches]
# Reward 1 if the content is the same as the ground truth, 0 otherwise
return [1.0 if c == gt else 0.0 for c, gt in zip(contents, ground_truth)]Vous pouvez tester cette fonction comme suit :
>>> prompts = ["Problem: Solve the equation $2x + 3 = 7$. Solution:", "Problem: Solve the equation $3x - 5 = 10$."]
>>> completions = [r" The solution is \boxed{2}.", r" The solution is \boxed{6}."]
>>> ground_truth = ["2", "5"]
>>> reward_func(prompts=prompts, completions=completions, ground_truth=ground_truth)
[1.0, 0.0]Exemple 4 : Fonctions de récompense multi-tâches
Voici un exemple d'utilisation de plusieurs fonctions de récompense dans le RLOOTrainer. Dans cet exemple, nous définissons deux fonctions de récompense spécifiques à la tâche : math_reward_func et coding_reward_func. La fonction math_reward_func attribue une récompense aux problèmes de mathématiques en fonction de leur exactitude, tandis que la fonction coding_reward_func attribue une récompense aux problèmes de codage en fonction du fait que la solution fonctionne.
from datasets import Dataset
from trl import RLOOTrainer
# Define a dataset that contains both math and coding problems
dataset = Dataset.from_list(
[
{"prompt": "What is 2+2?", "task": "math"},
{"prompt": "Write a function that returns the sum of two numbers.", "task": "code"},
{"prompt": "What is 3*4?", "task": "math"},
{"prompt": "Write a function that returns the product of two numbers.", "task": "code"},
]
)
# Math-specific reward function
def math_reward_func(prompts, completions, task, **kwargs):
rewards = []
for prompt, completion, t in zip(prompts, completions, task):
if t == "math":
# Calculate math-specific reward
correct = check_math_solution(prompt, completion)
reward = 1.0 if correct else -1.0
rewards.append(reward)
else:
# Return None for non-math tasks
rewards.append(None)
return rewards
# Coding-specific reward function
def coding_reward_func(prompts, completions, task, **kwargs):
rewards = []
for prompt, completion, t in zip(prompts, completions, task):
if t == "code":
# Calculate coding-specific reward
works = test_code_solution(prompt, completion)
reward = 1.0 if works else -1.0
rewards.append(reward)
else:
# Return None for non-coding tasks
rewards.append(None)
return rewards
# Use both task-specific reward functions
trainer = RLOOTrainer(
model="Qwen/Qwen2-0.5B-Instruct",
reward_funcs=[math_reward_func, coding_reward_func],
train_dataset=dataset,
)
trainer.train()Dans cet exemple, math_reward_func et coding_reward_func sont conçus pour fonctionner avec un jeu de données mixte contenant à la fois des problèmes de mathématiques et de codage. La colonne task du jeu de données est utilisée pour déterminer quelle fonction de récompense appliquer à chaque problème. S'il n'existe pas de fonction de récompense pertinente pour un échantillon du jeu de données, la fonction de récompense renvoie None, et le RLOOTrainer poursuit avec les fonctions et tâches valides. Cela permet au RLOOTrainer de gérer plusieurs fonctions de récompense avec des domaines d'application différents.
Notez que le RLOOTrainer ignorera les récompenses None renvoyées par les fonctions de récompense et ne tiendra compte que des récompenses renvoyées par les fonctions pertinentes. Cela garantit que le modèle est entraîné sur les tâches pertinentes et ignore les tâches pour lesquelles il n’existe pas de fonction de récompense pertinente.
Exemple 5 : Fonctions de récompense asynchrones
Les fonctions de récompense personnalisées peuvent également être définies sous forme de coroutines async def. Cela est utile si votre récompense dépend d'une E/S lente (par exemple, l'appel d'un service distant). Lorsque vous passez plusieurs fonctions de récompense asynchrones, RLOOTrainer les exécute de manière concurrente afin que leur latence se superpose.
Voici un exemple minimal d'une fonction de récompense asynchrone qui simule une opération limitée par l'E/S :
import asyncio
async def async_reward_func(prompts, completions, **kwargs):
# Simulate an I/O-bound call (e.g., HTTP request, database lookup)
await asyncio.sleep(0.01)
# Simple toy reward: 1.0 if the completion is non-empty, else 0.0
return [1.0 if completion else 0.0 for completion in completions]Exemple 6 : Journalisation de colonnes et de métriques supplémentaires
Voici un exemple de fonction de récompense qui journalise des colonnes supplémentaires dans le tableau des complétions et des métriques scalaires sous forme de graphiques.
import re
def reward_func(completions, ground_truth, log_extra=None, log_metric=None, **kwargs):
extracted = [re.search(r"\\boxed\{(.*?)\}", c) for c in completions]
extracted = [m.group(1) if m else None for m in extracted]
rewards = [1.0 if e == gt else 0.0 for e, gt in zip(extracted, ground_truth)]
if log_extra:
log_extra("golden_answer", list(ground_truth))
log_extra("extracted_answer", [e or "[none]" for e in extracted])
if log_metric:
log_metric("accuracy", sum(rewards) / len(rewards))
return rewardsPasser la fonction de récompense à l'entraîneur
Pour utiliser votre fonction de récompense personnalisée, transmettez-la au RLOOTrainer comme suit :
from trl import RLOOTrainer
trainer = RLOOTrainer(
reward_funcs=reward_func,
...,
)Vous pouvez passer plusieurs fonctions de récompense sous forme de liste ; cette liste peut inclure à la fois des fonctions synchrones et asynchrones :
from trl import RLOOTrainer
trainer = RLOOTrainer(
reward_funcs=[reward_func, async_reward_func1, async_reward_func2],
...,
)et la récompense sera calculée comme la somme des récompenses de chaque fonction, ou comme la somme pondérée si reward_weights est fourni dans la configuration.
Notez que RLOOTrainer prend en charge plusieurs fonctions de récompense de types différents. Consultez la documentation des paramètres pour plus de détails.
Entraînement des modèles de vision et de langage
RLOO prend en charge l’entraînement de modèles Vision-Language (VLM) sur des jeux de données multimodaux contenant à la fois du texte et des images.
Modèles pris en charge
Testé avec :
- Gemma3 — par exemple,
google/gemma-3-4b-it - LLaVA-NeXT — par exemple,
llava-hf/llava-v1.6-mistral-7b-hf - Qwen2-VL — par exemple,
Qwen/Qwen2-VL-2B-Instruct - Qwen2.5-VL — par exemple,
Qwen/Qwen2.5-VL-3B-Instruct - SmolVLM2 — par exemple,
HuggingFaceTB/SmolVLM2-2.2B-Instruct
La compatibilité avec tous les VLM n'est pas garantie. Si vous pensez qu'un modèle devrait être pris en charge, n'hésitez pas à ouvrir un ticket sur GitHub — ou mieux encore, à soumettre une pull request avec les modifications nécessaires.
Démarrage rapide
Utilisez rloo_vlm.py pour l’ajustement fin d’un VLM. Exemple de commande pour l’entraînement sur lmms-lab/multimodal-open-r1-8k-verified :
accelerate launch \
--config_file=examples/accelerate_configs/deepspeed_zero3.yaml \
examples/rloo_visual_math/rloo_visual_math.py \
--model_name_or_path Qwen/Qwen2.5-VL-3B-Instruct \
--output_dir rloo-Qwen2.5-VL-3B-Instruct \
--learning_rate 1e-5 \
--dtype bfloat16 \
--max_completion_length 1024 \
--use_vllm \
--vllm_mode colocate \
--use_peft \
--lora_target_modules "q_proj", "v_proj" \
--log_completionsConseils de configuration
- Utiliser LoRA sur les couches de projection vision-langage
- Activer la quantification 4 bits pour réduire l'utilisation de la mémoire
- Les VLM sont gourmands en mémoire — commencez par des tailles de lot plus petites
- La plupart des modèles sont compatibles avec vLLM (modes
serveretcolocate)
Format du jeu de données
Chaque exemple d'entraînement doit inclure :
prompt: texte formaté via le modèle de discussion du processeurimage/images: Image PIL ou liste d'Images PIL
Le formateur gère automatiquement la conversion des images en tenseurs via le processeur d'images du modèle.
RLOOTrainer
classe trl.RLOOTrainer
< source >( model: str | PreTrainedModel | PeftModelreward_funcs: str | transformers.modeling_utils.PreTrainedModel | collections.abc.Callable[..., list[float | None]] | list[str | transformers.modeling_utils.PreTrainedModel | collections.abc.Callable[..., list[float | None]]]args: trl.trainer.rloo_config.RLOOConfig | None = Nonetrain_dataset: datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset | None = Noneeval_dataset: datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset | datasets.dataset_dict.DatasetDict | datasets.dataset_dict.IterableDatasetDict | dict[str, datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset] | None = Noneprocessing_class: transformers.tokenization_utils_base.PreTrainedTokenizerBase | transformers.processing_utils.ProcessorMixin | None = Nonereward_processing_classes: transformers.tokenization_utils_base.PreTrainedTokenizerBase | list[transformers.tokenization_utils_base.PreTrainedTokenizerBase] | None = Nonecallbacks: list[transformers.trainer_callback.TrainerCallback] | None = Noneoptimizers: tuple[typing.Optional[torch.optim.Optimizer], typing.Optional[torch.optim.lr_scheduler.LambdaLR]] = (None, None)quantization_config: BitsAndBytesConfig | None = Nonepeft_config: PeftConfig | None = None )
Paramètres
- model (
strou PreTrainedModel ou PeftModel) — Modèle à entraîner. Peut être l'un des éléments suivants :- Une chaîne de caractères, correspondant à l'identifiant du modèle d'un modèle pré-entraîné hébergé dans un dépôt de modèles sur huggingface.co, ou à un
chemin vers un dossier contenant les poids du modèle enregistrés à l'aide de
save_pretrained, par exemple
'./my_model_directory/'. Le modèle est chargé à l'aide de<ModelArchitecture>.from_pretrained(où<ModelArchitecture>est dérivé de la configuration du modèle) avec les arguments nommés deargs.model_init_kwargs. Sidtypen'est pas spécifié dansargs.model_init_kwargs, la valeur par défaut estfloat32. Cela diffère de from_pretrained, où (depuis Transformers v5) le type de données est déduit de la configuration du modèle. - Un objet PreTrainedModel. Seuls les modèles de langage causaux sont pris en charge.
- Un objet PeftModel. Seuls les modèles de langage causaux sont pris en charge.
- Une chaîne de caractères, correspondant à l'identifiant du modèle d'un modèle pré-entraîné hébergé dans un dépôt de modèles sur huggingface.co, ou à un
chemin vers un dossier contenant les poids du modèle enregistrés à l'aide de
save_pretrained, par exemple
- reward_funcs (
RewardFunc | list[RewardFunc]) — Fonctions de récompense à utiliser pour le calcul des récompenses. Pour calculer les récompenses, nous appelons toutes les fonctions de récompense avec les prompts et les complétions, puis nous additionnons les récompenses. Peut être soit :-
Une fonction de récompense unique, telle que :
-
Une chaîne de caractères : l'identifiant du modèle d'un modèle pré-entraîné hébergé dans un dépôt de modèles sur huggingface.co, ou un chemin vers un dossier contenant les poids du modèle enregistrés à l'aide de save_pretrained, par exemple
'./my_model_directory/'. Le modèle est chargé à l'aide de from_pretrained avecnum_labels=1et les arguments de mot-clé deargs.model_init_kwargs. -
Un objet PreTrainedModel : seuls les modèles de classification de séquence sont pris en charge.
-
Une fonction de récompense personnalisée : la fonction reçoit les prompts et les complétions générées, ainsi que les colonnes supplémentaires du jeu de données. Elle doit renvoyer une liste de récompenses. Les fonctions de récompense personnalisées peuvent être synchrones ou asynchrones et peuvent également renvoyer
Nonelorsque la récompense ne s'applique pas à ces échantillons. Cela est utile pour l'entraînement multi-tâches où différentes fonctions de récompense s'appliquent à différents types d'échantillons. Lorsqu'une fonction de récompense renvoieNonepour un échantillon, cette fonction de récompense est exclue du calcul de la récompense pour cet échantillon. Pour plus de détails, voir Utiliser une fonction de récompense personnalisée.L’état du formateur est également transmis à la fonction de récompense. L’état du formateur est une instance de TrainerState et peut être consulté en accédant à l’argument
trainer_statede la signature de la fonction de récompense.
-
-
Une liste de fonctions de récompense, où chaque élément peut indépendamment être de l'un des types ci-dessus. Il est possible de mélanger différents types au sein de la liste (par exemple, un identifiant de modèle sous forme de chaîne et une fonction de récompense personnalisée).
-
- args (RLOOConfig, facultatif) —
Configuration de ce formateur. Si
None, une configuration par défaut est utilisée. - train_dataset (Dataset ou IterableDataset) —
Jeu de données à utiliser pour l'entraînement. Il doit inclure une colonne
"prompt". Toute colonne supplémentaire dans le jeu de données est ignorée. Le format des échantillons peut être l'un des deux suivants :- Standard : chaque échantillon contient du texte brut.
- Conversationnel : chaque échantillon contient des messages structurés (par exemple, le rôle et le contenu).
Lorsque
train_datasetest un IterableDataset (par exemple un jeu de données en streaming),max_stepsdoit être défini dans les arguments d’entraînement, car sa longueur ne peut pas être déduite et le nombre total d’étapes d’entraînement est nécessaire pour limiter la boucle d’entraînement et configurer le planificateur de taux d’apprentissage. - eval_dataset (Dataset, IterableDataset, DatasetDict, IterableDatasetDict ou
dict[str, Dataset | IterableDataset]) — Jeu de données à utiliser pour l'évaluation. Il doit répondre aux mêmes exigences quetrain_dataset. - processing_class (PreTrainedTokenizerBase, ProcessorMixin, facultatif) —
Classe de traitement utilisée pour traiter les données. Le côté de bourrage doit être défini sur « left ». Si
None, la classe de traitement est chargée à partir du nom du modèle avec from_pretrained. Un jeton de bourrage,tokenizer.pad_token, doit être défini. Si la classe de traitement n’a pas défini de jeton de bourrage,tokenizer.eos_tokensera utilisé par défaut. - reward_processing_classes (PreTrainedTokenizerBase ou
list[PreTrainedTokenizerBase], facultatif) — Classes de traitement correspondant aux fonctions de récompense spécifiées dansreward_funcs. Peut être soit :- Une seule classe de traitement : utilisée lorsque
reward_funcsne contient qu'une seule fonction de récompense. - Une liste de classes de traitement : doit correspondre à l’ordre et à la longueur des fonctions de récompense dans
reward_funcs. Si défini surNone, ou si un élément de la liste correspondant à un PreTrainedModel estNone, le tokenizer du modèle est chargé automatiquement à l’aide de from_pretrained. Pour les éléments dereward_funcsqui sont des fonctions de récompense personnalisées (non PreTrainedModel), les entrées correspondantes dansreward_processing_classessont ignorées.
- Une seule classe de traitement : utilisée lorsque
- callbacks (liste de TrainerCallback, facultatif) —
Liste de callbacks pour personnaliser la boucle d'entraînement. Ils seront ajoutés à la liste des callbacks par défaut détaillée ici.
Si vous souhaitez supprimer l'un des callbacks par défaut utilisés, utilisez la méthode remove_callback.
- optimizers (
tuple[torch.optim.Optimizer | None, torch.optim.lr_scheduler.LambdaLR | None], facultatif, par défaut(None, None)) — Un tuple contenant l'optimiseur et le planificateur à utiliser. Par défaut, une instance deAdamWest utilisée sur votre modèle ainsi qu'un planificateur défini par get_linear_schedule_with_warmup et contrôlé parargs. - quantization_config (BitsAndBytesConfig, facultatif) —
Configuration de quantification utilisée lors du chargement du modèle à partir d'un identifiant de modèle. À combiner avec
peft_configpour l'entraînement QLoRA. Ignoré si le modèle est déjà instancié. - peft_config (PeftConfig, facultatif) —
Configuration PEFT utilisée pour envelopper le modèle. Si
None, le modèle n'est pas enveloppé.
Trainer pour la méthode Reinforce Leave One Out (RLOO). Cet algorithme a été initialement proposé dans l'article Back to Basics: Revisiting REINFORCE Style Optimization for Learning from Human Feedback in LLMs.
Exemple :
>>> from trl import RLOOTrainer
>>> from trl.rewards import accuracy_reward
>>> from datasets import load_dataset
>>> dataset = load_dataset("trl-lib/DeepMath-103K", split="train")
>>> trainer = RLOOTrainer(
... model="Qwen/Qwen2.5-0.5B-Instruct",
... reward_funcs=accuracy_reward,
... train_dataset=dataset,
... )
>>> trainer.train()train
< source >( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput
Paramètres
- resume_from_checkpoint (
stroubool, facultatif) — Si c'est unestr, chemin local d'un point de contrôle enregistré par une instance précédente deTrainer. Si c'est unboolet vautTrue, charge le dernier point de contrôle dans args.output_dir enregistré par une instance précédente deTrainer. S'il est présent, l'entraînement reprendra à partir des états du modèle/optimiseur/planificateur chargés ici. - trial (
optuna.Trialoudict[str, Any], facultatif) — L’exécution de l’essai ou le dictionnaire d’hyperparamètres pour la recherche d’hyperparamètres. - ignore_keys_for_eval (
list[str], facultatif) — Une liste de clés dans la sortie de votre modèle (s’il s’agit d’un dictionnaire) qui doivent être ignorées lors de la collecte des prédictions pour l’évaluation pendant l’entraînement.
Retourne
~trainer_utils.TrainOutput
Objet contenant le nombre d'étapes globales, la perte d'entraînement et les métriques.
Point d'entrée principal de l'entraînement.
Enregistrera le modèle, ce qui vous permettra de le recharger à l'aide de from_pretrained().
N'enregistrera que depuis le processus principal.
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )
Paramètres
- commit_message (
str, facultatif, par défaut"End of training") — Message à committer lors de la poussée. - blocking (
bool, facultatif, par défautTrue) — Indique si la fonction doit ne renvoyer que lorsque legit pushest terminé. - token (
str, facultatif, par défautNone) — Jeton avec permission d’écriture pour écraser les arguments originaux du Trainer. - revision (
str, facultatif) — La révision git à partir de laquelle effectuer le commit. Par défaut, il s'agit de la tête de la branche « main ». - kwargs (
dict[str, Any], facultatif) — Arguments supplémentaires passés à~Trainer.create_model_card.
Téléchargez self.model et self.processing_class sur le hub de modèles 🤗 dans le dépôt self.args.hub_model_id.
RLOOConfig
classe trl.RLOOConfig
< source >( output_dir: str | None = Noneper_device_train_batch_size: int = 8num_train_epochs: float = 3.0max_steps: int = -1learning_rate: float = 1e-06lr_scheduler_type: transformers.trainer_utils.SchedulerType | str = 'linear'lr_scheduler_kwargs: dict | str | None = Nonewarmup_steps: float = 0optim: transformers.training_args.OptimizerNames | str = 'adamw_torch_fused'optim_args: str | None = Noneweight_decay: float = 0.0adam_beta1: float = 0.9adam_beta2: float = 0.999adam_epsilon: float = 1e-08optim_target_modules: None | str | list[str] = Nonegradient_accumulation_steps: int = 1average_tokens_across_devices: bool = Truemax_grad_norm: float = 1.0label_smoothing_factor: float = 0.0bf16: bool | None = Nonefp16: bool = Falsebf16_full_eval: bool = Falsefp16_full_eval: bool = Falsetf32: bool | None = Nonegradient_checkpointing: bool = Truegradient_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonetorch_compile: bool = Falsetorch_compile_backend: str | None = Nonetorch_compile_mode: str | None = Noneuse_liger_kernel: bool = Falseliger_kernel_config: dict[str, bool] | None = Noneuse_cache: bool = Falseneftune_noise_alpha: float | None = Nonetorch_empty_cache_steps: int | None = Noneauto_find_batch_size: bool = Falselogging_strategy: transformers.trainer_utils.IntervalStrategy | str = 'steps'logging_steps: float = 10logging_first_step: bool = Falselog_on_each_node: bool = Truelogging_nan_inf_filter: bool = Trueinclude_num_input_tokens_seen: str | bool = 'no'log_level: str = 'passive'log_level_replica: str = 'warning'disable_tqdm: bool | None = Nonereport_to: None | str | list[str] = 'none'run_name: str | None = Noneproject: str = 'huggingface'trackio_space_id: str | None = Nonetrackio_bucket_id: str | None = Nonetrackio_static_space_id: typing.Union[str, NoneType, typing.Literal[False]] = Noneeval_strategy: transformers.trainer_utils.IntervalStrategy | str = 'no'eval_steps: float | None = Noneeval_delay: float = 0per_device_eval_batch_size: int = 8prediction_loss_only: bool = Falseeval_on_start: bool = Falseeval_do_concat_batches: bool = Trueeval_use_gather_object: bool = Falseeval_accumulation_steps: int | None = Noneinclude_for_metrics: list[str] = <factory>batch_eval_metrics: bool = Falsesave_only_model: bool = Falsesave_strategy: transformers.trainer_utils.SaveStrategy | str = 'steps'save_steps: float = 500save_on_each_node: bool = Falsesave_total_limit: int | None = Noneenable_jit_checkpoint: bool = Falsepush_to_hub: bool = Falsehub_token: str | None = Nonehub_private_repo: bool | None = Nonehub_model_id: str | None = Nonehub_strategy: transformers.trainer_utils.HubStrategy | str = 'every_save'hub_always_push: bool = Falsehub_revision: str | None = Noneload_best_model_at_end: bool = Falsemetric_for_best_model: str | None = Nonegreater_is_better: bool | None = Noneignore_data_skip: bool = Falserestore_callback_states_from_checkpoint: bool = Falsefull_determinism: bool = Falseseed: int = 42data_seed: int | None = Noneuse_cpu: bool = Falseaccelerator_config: dict | str | None = Noneparallelism_config: accelerate.parallelism_config.ParallelismConfig | None = Nonedataloader_drop_last: bool = Falsedataloader_num_workers: int = 0dataloader_pin_memory: bool = Truedataloader_persistent_workers: bool = Falsedataloader_prefetch_factor: int | None = Nonedataloader_multiprocessing_context: str | None = Nonedataloader_in_order: bool = Trueremove_unused_columns: bool | None = Falselabel_names: list[str] | None = Nonetrain_sampling_strategy: str = 'random'length_column_name: str = 'length'ddp_find_unused_parameters: bool | None = Noneddp_bucket_cap_mb: int | None = Noneddp_broadcast_buffers: bool | None = Noneddp_static_graph: bool | None = Noneddp_backend: str | None = Noneddp_timeout: int = 1800fsdp: str | None = Nonefsdp_config: dict[str, typing.Any] | str | None = Nonedeepspeed: dict | str | None = Nonedebug: str | list[transformers.debug_utils.DebugOption] = ''skip_memory_metrics: bool = Truedo_train: bool = Falsedo_eval: bool = Falsedo_predict: bool = Falseresume_from_checkpoint: str | None = Nonelocal_rank: int = -1model_init_kwargs: dict[str, typing.Any] | str | None = Nonetrust_remote_code: bool = Falserouter_aux_loss_coef: float | None = Nonedisable_dropout: bool = Falsenum_generations: int | None = 2num_generations_eval: int | None = Nonemax_completion_length: int | None = 512ds3_gather_for_generation: bool = Trueshuffle_dataset: bool | None = Truepad_to_multiple_of: int | str | None = 'auto'generation_batch_size: int | None = Nonesteps_per_generation: int | None = Nonetemperature: float = 1.0top_p: float = 1.0top_k: int = 0min_p: float | None = Nonegeneration_kwargs: dict | str | None = Nonechat_template_kwargs: dict | str | None = Nonerepetition_penalty: float = 1.0cache_implementation: str | None = Noneuse_vllm: bool = Falsevllm_mode: str = 'colocate'vllm_model_impl: str = 'vllm'vllm_enable_sleep_mode: bool = Falsevllm_structured_outputs_regex: str | None = Nonevllm_server_base_url: str | None = Nonevllm_server_host: str = '0.0.0.0'vllm_server_port: int = 8000vllm_server_timeout: float = 240.0vllm_group_port: int = 51216vllm_gpu_memory_utilization: float = 0.3vllm_max_model_length: int | None = Nonevllm_tensor_parallel_size: int = 1beta: float = 0.05num_iterations: int = 1epsilon: float = 0.2epsilon_high: float | None = Nonereward_weights: list[float] | None = Nonenormalize_advantages: bool = Falsereward_clip_range: tuple[float, float] | None = Nonemask_truncated_completions: bool = Falsesync_ref_model: bool = Falseref_model_mixup_alpha: float = 0.6ref_model_sync_steps: int = 512log_completions: bool = Falselog_multimodal: bool = Truenum_completions_to_print: int | None = Nonelog_unique_prompts: bool = Falseuse_transformers_continuous_batching: bool = Falsetransformers_continuous_batching_config: dict | str | None = Noneuse_transformers_paged: bool = False )
Paramètres qui contrôlent le modèle et le modèle de référence
- model_init_kwargs (
stroudict[str, Any], facultatif) — Arguments par mot-clé pour from_pretrained, utilisés lorsque l’argumentmodeldu RLOOTrainer est fourni sous forme de chaîne de caractères. La valeur derevisionest également utilisée lors du chargement des classes de traitement. - trust_remote_code (
bool, facultatif, valeur par défautFalse) — Indique s'il faut autoriser le chargement de modèles et de tokenizers qui incluent du code Python personnalisé depuis le Hub. Transmis à from_pretrained et from_pretrained. S'applique également au chargement des modèles de récompense et des tokenizers de récompense. - router_aux_loss_coef (
float, facultatif) — Coefficient de la perte auxiliaire d’équilibrage de charge pour les modèles Mixture-of-Experts (MoE), ajoutée à la perte d’entraînement avec ce poids. Si non défini, la valeur déclarée par la configuration du modèle est utilisée. Définissez-le à0.0pour le désactiver. Échoue s’il est utilisé avec un modèle non-MoE. - disable_dropout (
bool, facultatif, valeur par défautFalse) — Indique s'il faut désactiver le dropout dans le modèle. Cela est utile pour l'entraînement avec un modèle de référence, car cela empêche le modèle de générer des logprobs différents pour la même entrée.
Paramètres qui contrôlent la prétraitement des données
- remove_unused_columns (
bool, facultatif, valeur par défautFalse) — Indique s'il faut ne conserver que la colonne"prompt"dans le jeu de données. Si vous utilisez une fonction de récompense personnalisée qui nécessite une colonne autre que"prompts"et"completions", vous devez laisser cette valeur àFalse. - num_generations (
int, facultatif, par défaut2) — Nombre de générations à échantillonner par invite. La taille de lot effective (num_processes * per_device_batch_size- gradient_accumulation_steps) doit être divisible par cette valeur.
- num_generations_eval (
int, facultatif) — Nombre de générations à échantillonner lors de l'évaluation. Cela permet d'utiliser moins de générations pendant l'évaluation afin d'économiser des calculs. SiNone, utilise la valeur denum_generations. - max_completion_length (
intouNone, facultatif, par défaut512) — Longueur maximale de la complétion générée. - ds3_gather_for_generation (
bool, facultatif, valeur par défautTrue) — Ce paramètre s’applique à DeepSpeed ZeRO-3. S’il est activé, les poids du modèle de politique sont regroupés pour la génération, ce qui améliore la vitesse de génération. Toutefois, désactiver cette option permet d’entraîner des modèles dont la taille dépasse la capacité VRAM d’une seule GPU, au prix d’une génération plus lente. La désactivation de cette option n’est pas compatible avec la génération vLLM. - shuffle_dataset (
bool, facultatif, par défautTrue) — Indique s'il faut mélanger le jeu de données d'entraînement. - pad_to_multiple_of (
intoustr, facultatif, valeur par défaut"auto") — Si défini, les identifiants des prompts et des complétions seront rembourrés jusqu'à un multiple de cette valeur."auto"rembourde jusqu'à un multiple de 128 sur Neuron (AWS Trainium), qui compile une fois par forme d'entrée, et ne rembourde pas ailleurs.
Paramètres qui contrôlent la génération
- generation_batch_size (
int, facultatif) — Taille de lot à utiliser pour la génération. SiNone, la valeur par défaut est la taille de lot effective d’entraînement :per_device_train_batch_size * num_processes * steps_per_generation. Autrement dit, un lot de génération est traité par étape d’optimisation. Mutuellement exclusif avecsteps_per_generation. - steps_per_generation (
int, facultatif) — Nombre d'étapes par génération. SiNone, la valeur par défaut estgradient_accumulation_steps. Mutuellement exclusif avecgeneration_batch_size. - temperature (
float, facultatif, par défaut1.0) — Température pour l'échantillonnage. Plus la température est élevée, plus les complétions sont aléatoires. - top_p (
float, facultatif, par défaut1.0) — Flottant qui contrôle la probabilité cumulée des jetons de tête à prendre en compte. Doit être dans (0, 1]. Définissez-le à1.0pour prendre en compte tous les jetons. - top_k (
int, facultatif, par défaut0) — Nombre de jetons du vocabulaire ayant la plus haute probabilité à conserver pour le filtrage top-k. Si la valeur est0, le filtrage top-k est désactivé et tous les jetons sont pris en compte. - min_p (
float, facultatif) — Probabilité minimale du jeton, qui sera mise à l'échelle par la probabilité du jeton le plus probable. Elle doit être une valeur comprise entre0.0et1.0. Les valeurs typiques se situent dans la plage0.01-0.2. - generation_kwargs (
dict[str, Any], facultatif) — Arguments supplémentaires à passer à GenerationConfig (si vous utilisez transformers) ouSamplingParams(si vous utilisez vLLM) lors de l'échantillonnage des complétions. Cela permet de personnaliser davantage le comportement de la génération, par exemple en définissantsuppress_tokens,num_beams, etc. S'il contient des clés qui entrent en conflit avec les autres paramètres de génération (commemin_p,top_p, etc.), ils les remplaceront. - chat_template_kwargs (
dict[str, Any], facultatif) — Arguments supplémentaires à passer à la fonctionapply_chat_templatelors de la génération des complétions. - repetition_penalty (
float, facultatif, par défaut1.0) — Flottant qui pénalise les nouveaux jetons en fonction de leur présence dans le prompt et dans le texte généré jusqu’à présent. Les valeurs >1.0encouragent le modèle à utiliser de nouveaux jetons, tandis que les valeurs <1.0encouragent le modèle à répéter les jetons. - cache_implementation (
str, facultatif) — Implémentation de la méthode de cache pour une génération plus rapide lorsqueuse_vllmest défini surFalse.
Paramètres qui contrôlent l'accélération de la génération propulsée par vLLM
- use_vllm (
bool, facultatif, valeur par défautFalse) — Indique s'il faut utiliser vLLM pour générer des complétions. Si défini surTrue, l'entraîneur utilisera vLLM pour la génération au lieu de model.generate() par défaut. Nécessite l'installation devllm. - vllm_mode (
str, facultatif, valeur par défaut"colocate") — Mode à utiliser pour l'intégration vLLM lorsqueuse_vllmest défini surTrue. Doit être l'un des"server"ou"colocate"."server": le formateur enverra les requêtes de génération à un serveur vLLM distinct. Assurez-vous qu’un serveur vLLM est en cours d’exécution (à démarrer avecvllm serve)."colocate": vLLM s’exécute dans le même processus et partage les GPU d’entraînement. Cela évite d’avoir besoin d’un serveur séparé, mais peut provoquer une concurrence pour les ressources avec l’entraînement.
- vllm_model_impl (
str, facultatif, par défaut"vllm") — Implémentation du modèle à utiliser pour vLLM. Doit être l'une des valeurs"transformers"ou"vllm"."transformers": utiliser le backendtransformerspour l'implémentation du modèle."vllm": utiliser la bibliothèquevllmpour l'implémentation du modèle. - vllm_enable_sleep_mode (
bool, facultatif, valeur par défautFalse) — Active le mode veille de vLLM pour décharger les poids et le cache pendant l'étape d'optimisation. Cela maintient l'utilisation de la mémoire GPU au plus bas, mais le réveil du moteur ajoute une latence de transfert hôte-appareil. - vllm_structured_outputs_regex (
str, facultatif) — Expression régulière pour les sorties structurées de vLLM. SiNone(par défaut), les sorties structurées sont désactivées.
Paramètres qui contrôlent le serveur vLLM (utilisés uniquement lorsque `vllm_mode` est `"server"`)
- vllm_server_base_url (
str, facultatif) — URL de base du serveur vLLM (par exemple,"http://localhost:8000"). Si fournie,vllm_server_hostetvllm_server_portsont ignorés. - vllm_server_host (
str, facultatif, par défaut"0.0.0.0") — Hôte du serveur vLLM auquel se connecter. Ignoré sivllm_server_base_urlest fourni. - vllm_server_port (
int, facultatif, par défaut8000) — Port du serveur vLLM auquel se connecter. Ignoré sivllm_server_base_urlest fourni. - vllm_server_timeout (
float, facultatif, valeur par défaut240.0) — Durée totale de temporisation, en secondes, à attendre pour que le serveur vLLM soit opérationnel. Si le serveur n'est pas opérationnel après le dépassement de ce délai, uneConnectionErrorest levée. - vllm_group_port (
int, facultatif, valeur par défaut51216) — Numéro de port du groupe de mise à jour des poids. Il est utilisé pour communiquer avec le serveur vLLM. Sauf si le port est occupé, il n'est pas nécessaire de le modifier.
Paramètres qui contrôlent l'exécution de vLLM co-localisée (utilisés uniquement lorsque `vllm_mode` est `"colocate"`)
- vllm_gpu_memory_utilization (
float, facultatif, valeur par défaut0.3) — Contrôle l'utilisation de la mémoire GPU pour vLLM. Ce paramètre ne s'applique que lorsquevllm_modeest défini sur"colocate". Si vous utilisezvllm_mode="server", ce paramètre doit être transmis séparément lors du démarrage du serveur vLLM via le drapeau--vllm_gpu_memory_utilization. - vllm_max_model_length (
int, facultatif) — Fenêtre de contexte pour vLLM. Réglez-la sur au moins la longueur maximale des prompts dans le jeu de données plusmax_completion_length; si elle est omise, elle est déduite de la configuration du modèle. - vllm_tensor_parallel_size (
int, facultatif, valeur par défaut1) — Contrôle la taille du parallélisme de tenseurs pour vLLM. Ce paramètre ne s’applique que lorsquevllm_modeest défini sur"colocate". Si vous utilisezvllm_mode="server", ce paramètre doit être transmis séparément lors du démarrage du serveur vLLM via le drapeau--vllm_tensor_parallel_size.
Paramètres qui contrôlent l'entraînement
- beta (
float, facultatif, par défaut0.05) — Coefficient KL. Si0.0, le modèle de référence n’est pas chargé, ce qui réduit l’utilisation de la mémoire et améliore la vitesse d’entraînement. - num_iterations (
int, facultatif, par défaut1) — Nombre d'itérations par lot (noté μ dans l'algorithme). - epsilon (
float, facultatif, valeur par défaut0.2) — Valeur pour le clipping. - epsilon_high (
float, facultatif) — Valeur epsilon supérieure pour le rognage. Si elle n'est pas spécifiée, elle prend par défaut la même valeur que la borne inférieure spécifiée dans l'argumentepsilon. L'article DAPO recommande0.28. - reward_weights (
list[float], facultatif) — Poids pour chaque fonction de récompense. Doit correspondre au nombre de fonctions de récompense. SiNone, toutes les récompenses sont pondérées également avec un poids de1.0. - normalize_advantages (
bool, facultatif, par défautFalse) — Indique s'il faut normaliser les avantages. La normalisation est effectuée par lot de génération pour obtenir une moyenne de0.0et un écart-type de1.0. - reward_clip_range (
tuple[float, float], facultatif) — Plage de rognage des récompenses sous la forme (min, max). SiNone, aucun rognage n'est appliqué. - mask_truncated_completions (
bool, facultatif, valeur par défautFalse) — Lorsqu’il est activé, les complétions tronquées sont exclues du calcul de la perte, ce qui empêche qu’elles soient pénalisées à tort et introduisent du bruit pendant l’entraînement. Selon l’article DAPO, il s’agit d’une bonne pratique pour la stabilité de l’entraînement. - sync_ref_model (
bool, facultatif, par défautFalse) — Indique s'il faut synchroniser le modèle de référence avec le modèle actif toutes lesref_model_sync_stepsétapes, en utilisant le paramètreref_model_mixup_alpha. Cette synchronisation provient de l'article TR-DPO. - ref_model_mixup_alpha (
float, facultatif, valeur par défaut0.6) — Paramètre α issu de l'article TR-DPO, qui contrôle le mélange entre la politique actuelle et la politique de référence précédente lors des mises à jour. La politique de référence est mise à jour selon l'équation :π_ref = α * π_θ + (1 - α) * π_ref_prev. Pour utiliser ce paramètre, vous devez définirsync_ref_model=True. - ref_model_sync_steps (
int, facultatif, valeur par défaut512) — paramètre τ issu de l’article TR-DPO, qui détermine la fréquence à laquelle la politique actuelle est synchronisée avec la politique de référence. Pour utiliser ce paramètre, vous devez définirsync_ref_model=True.
Paramètres qui contrôlent la journalisation
- log_completions (
bool, facultatif, par défautFalse) — Indique s'il faut consigner un échantillon de paires (prompt, completion) toutes leslogging_stepsétapes. Sirichest installé, l'échantillon est affiché. Si la journalisationwandbet/outrackioest activée, il est consigné danswandbet/outrackio. - log_multimodal (
bool, facultatif, valeur par défautTrue) — Indique s'il faut journaliser le contenu multimodal (images, vidéos, etc.) avec les complétions. Désactivez cette option pour réduire la taille des journaux lors de l'utilisation de données multimodales haute résolution. - num_completions_to_print (
int, facultatif) — Nombre de complétions à afficher avecrich. SiNone, toutes les complétions sont journalisées. - log_unique_prompts (
bool, facultatif, valeur par défautFalse) — Indique s'il faut journaliser les prompts uniques. SiTrue, seuls les prompts uniques sont journalisés. SiFalse, tous les prompts sont journalisés.
Paramètres qui contrôlent l'accélération de la génération grâce au batch continu de Transformers
- use_transformers_continuous_batching (
bool, facultatif, valeur par défautFalse) — Indique s'il faut utiliser le moteur de continuous batching de transformers pour générer des complétions. Nécessitetransformers>=5.8.0. - transformers_continuous_batching_config (
dict, facultatif) — Arguments par mot-clé pourContinuousBatchingConfig.
Paramètres obsolètes
Classe de configuration pour le RLOOTrainer.
Cette classe ne contient que les paramètres spécifiques à l’entraînement RLOO. Pour la liste complète des arguments d’entraînement, veuillez consulter la documentation de TrainingArguments. Notez que les valeurs par défaut de cette classe peuvent différer de celles de TrainingArguments.
À l’aide de HfArgumentParser, nous pouvons transformer cette classe en arguments argparse qui peuvent être spécifiés sur la ligne de commande.
Ces paramètres ont des valeurs par défaut différentes de TrainingArguments :
logging_steps: la valeur par défaut est10au lieu de500.gradient_checkpointing: la valeur par défaut estTrueau lieu deFalse.bf16: passe àTruepar défaut sifp16n’est pas défini, au lieu deFalse.learning_rate: la valeur par défaut est1e-6au lieu de5e-5.
Références
- Article RLOO
- Retour aux bases : réexamen de l’optimisation de type REINFORCE pour l’apprentissage à partir des retours humains dans les LLM
- Article - REINFORCE++ : une approche simple et efficace pour l’alignement des grands modèles de langage
- Article de blogue - Remettre le RL dans le RLHF
- Article de blog – Déchiffrer le RLHF et ses variantes : progrès et retours d’expérience en ingénierie pratique
- YouTube - RLOO : une optimisation rentable pour l'apprentissage à partir des retours humains sur les LLM
Guide de migration depuis l'ancienne implémentation (0.21 et versions antérieures)
Avec la publication de la version 0.22.0, nous avons repensé le RLOOTrainer pour qu'il soit plus aligné avec les autres entraîneurs en ligne de la bibliothèque, comme GRPOTrainer. Cette nouvelle implémentation introduit plusieurs modifications aux paramètres de configuration et à la structure générale de l'entraîneur. Voici un résumé des principales modifications pour RLOOConfig :
| TRL ≤ 0.21.x | TRL ≥ 0.22.0 |
|---|---|
rloo_k | renommé en num_generations |
cliprange | renommé en epsilon |
kl_coef | renommé en beta |
exp_name | renommé en run_name. Utilisez run_name = f"{exp_name}__{seed}__{int(time.time())}" pour reproduire l'ancien comportement |
normalize_reward | renommé en normalize_advantages. Remarque : cela normalisait toujours les avantages (malgré l'ancien nom) |
num_ppo_epochs | renommé en num_iterations (valeur par défaut : 1) |
token_level_kl | supprimé – KL est désormais calculé uniquement au niveau de la séquence |
dataset_num_proc | supprimé – il n’était pas utilisé |
num_mini_batches | renommé en steps_per_generation |
total_episodes | utilisez max_steps=total_episodes / gradient_accumulation_steps à la place |
local_rollout_forward_batch_size | supprimé – désormais automatiquement défini sur per_device_train_batch_size (ou per_device_eval_batch_size lors de l'évaluation) |
num_sample_generations | supprimé – utilisez logging_steps pour contrôler la fréquence de la journalisation de la génération |
response_length | renommé en max_completion_length (valeur par défaut : 512) |
stop_token | supprimé |
stop_token_id | supprimé – utilisez processing_class.eos_token_id à la place |
missing_eos_penalty | supprimé – à reproduire avec une fonction de récompense personnalisée vérifiant si eos_token_id est présent dans completion_ids |
Voici un résumé des principales modifications apportées à RLOOTrainer :
| TRL ≤ 0.21.x | TRL ≥ 0.22.0 |
|---|---|
config | renommé en args |
reward_model | renommé en reward_funcs, qui prend désormais en charge à la fois les modèles de récompense et les fonctions de récompense personnalisées |
policy | renommé en model |
ref_policy | supprimé – le modèle de référence est désormais créé automatiquement à partir de model |
data_collator | supprimé |