TRL documentation
RLOO Trainer
RLOO Trainer
Visão geral
O TRL oferece suporte ao RLOO Trainer para o treinamento de modelos de linguagem, conforme descrito no artigo 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 e Sara Hooker.
O resumo do artigo é o seguinte:
O alinhamento de IA na forma de Aprendizado por Reforço a partir de Feedback Humano (RLHF) é cada vez mais tratado como um ingrediente crucial para modelos de linguagem de grande escala de alto desempenho. A Otimização de Política Próxima (PPO) tem sido posicionada pela literatura recente como o método canônico para a parte de RL do RLHF. No entanto, ela envolve tanto alto custo computacional quanto ajuste sensível de hiperparâmetros. Postulamos que a maioria dos princípios motivacionais que levaram ao desenvolvimento da PPO é menos uma preocupação prática no RLHF e defendemos um método menos custoso computacionalmente que preserva e até aumenta o desempenho. Revisitamos a formulação do alinhamento a partir de preferências humanas no contexto de RL. Mantendo a simplicidade como princípio orientador, mostramos que muitos componentes da PPO são desnecessários em um contexto de RLHF e que variantes de otimização no estilo REINFORCE, muito mais simples, superam tanto a PPO quanto os métodos “livres de RL” recém-propostos, como DPO e RAFT. Nosso trabalho sugere que a adaptação cuidadosa às características de alinhamento de LLMs permite se beneficiar da otimização de RL online a baixo custo.
Este método de pós-treinamento foi contribuído por Costa Huang e posteriormente refatorado por Shirin Yamani.
Início rápido
Este exemplo demonstra como treinar um modelo usando o método RLOO. Treinamos um modelo Qwen 0.5B Instruct com os prompts do conjunto de dados DeepMath-103K. Você pode visualizar os dados do conjunto de dados aqui:
Abaixo está o script para treinar o modelo. accuracy_reward precisa do math-verify, que você pode instalar com 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()Execute o script usando o seguinte comando:
torchrun --nproc_per_node 8 train_rloo.py
Olhando mais a fundo para o método RLOO
RLOO é um algoritmo de aprendizado online, o que significa que ele melhora iterativamente usando os dados gerados pelo próprio modelo treinado durante o treinamento. A intuição por trás do objetivo do RLOO é maximizar a vantagem das conclusões geradas, garantindo que o modelo permaneça próximo à política de referência. Para entender como o RLOO funciona, ele pode ser dividido em quatro etapas principais: gerar conclusões, calcular a vantagem, estimar a divergência de KL e calcular a perda.

Gerando complementos
Em cada etapa de treinamento, amostramos um lote de prompts e geramos um conjunto de completions para cada prompt (denotado como ).
Calculando a recompensa
No RLOO, a recompensa consiste em dois componentes: a recompensa fornecida pelo modelo de recompensa (ou função de recompensa) e uma penalidade KL que desencoraja a política de se desviar demais de uma política de referência fixa
- Para cada uma das sequências geradas condicionadas a uma consulta , calculamos uma recompensa escalar usando um modelo de recompensa .
- Concorrentemente, estimamos a divergência de KL entre a política atual e a política de referência fixa ao longo da sequência. A estimativa de KL para a sequência é:
A recompensa final atribuída à sequência é a seguinte:
onde controla a intensidade da penalidade KL.
Em um cenário puramente online (
num_iterations = 1, padrão), os dados são gerados pela política atual. Nesse caso, a penalidade KL é calculada diretamente usando a política atual.No cenário mais geral (por exemplo, múltiplas etapas de gradiente por lote), os dados são gerados por um snapshot anterior . Para manter a penalidade consistente com a distribuição de amostragem, o KL é definido em relação a esta política:
Equivalentemente, para uma sequência amostrada , a estimativa de Monte Carlo é:
Calculando a vantagem
Uma vez que as recompensas para cada conclusão tenham sido calculadas, calculamos uma linha de base como a recompensa média de todos os outros amostras no mesmo lote, excluindo a amostra atual. Essa linha de base é usada para reduzir a variância da estimativa do gradiente da política. A vantagem para cada conclusão é então obtida como a diferença entre a própria recompensa e essa linha de base de exclusão de um elemento.
Formalmente, para um lote de G conclusões, a linha de base para a conclusão é:
e em seguida a vantagem para cada conclusão é calculada como a diferença entre sua recompensa e a linha de base:
Calculando a perda
A perda REINFORCE é simplesmente definida como:
Na prática, executar múltiplas etapas de gradiente no mesmo lote torna as ações efetivamente off-policy em relação aos parâmetros atuais. Para corrigir isso, introduzimos a razão de amostragem de importância. Para evitar atualizações excessivamente grandes quando a política muda entre a amostragem e as etapas de gradiente, aplicamos um limite (clip) a essa razão:
Em um ambiente totalmente online, de etapa única (padrão), e isso se reduz ao REINFORCE padrão.
Diferente do GRPO, o RLOO não faz backpropagation de gradientes através do termo KL. Aqui, o KL é usado puramente para modelagem de recompensa: ele é calculado sob
no_grade incorporado à recompensa escalar , que se torna a vantagem destacada .Em outras palavras, o único caminho pelo qual o gradiente entra na política é o termo da razão de importância , e o termo KL não faz backpropagation para a política.
Em contraste, GRPO adiciona um termo KL explícito e diferenciável ao seu objetivo, calculado em tempo real com a política atual , de modo que seu gradiente flui tanto pelo termo de razão quanto pela penalidade KL.
Métricas registradas
Durante o treinamento e a avaliação, registramos as seguintes métricas:
num_tokens: O número total de tokens processados até o momento, incluindo tanto os prompts quanto as conclusões.step_time: O tempo médio (em segundos) por etapa de treinamento (incluindo a geração).completions/mean_length: O comprimento médio das conclusões geradas.completions/min_length: O comprimento mínimo das conclusões geradas.completions/max_length: O comprimento máximo das conclusões geradas.completions/mean_terminated_length: O comprimento médio das conclusões geradas que terminam com EOS.completions/min_terminated_length: O comprimento mínimo das conclusões geradas que terminam com EOS.completions/max_terminated_length: O comprimento máximo das conclusões geradas que terminam com EOS.completions/clipped_ratio: A proporção de conclusões truncadas (clipped).rewards/{reward_func_name}/mean: A recompensa média de uma função de recompensa específica.rewards/{reward_func_name}/std: O desvio padrão da recompensa de uma função de recompensa específica.reward: A recompensa média geral após somar as recompensas entre as funções (ponderada porreward_weights).reward_std: O desvio padrão dos recompensas somadas entre as funções (ponderado porreward_weights), calculado sobre o lote completo.frac_reward_zero_std: A fração de amostras no lote de geração com desvio padrão de recompensa igual a zero, o que implica que há pouca diversidade para aquele prompt (todas as respostas estão corretas ou incorretas).entropy: Entropia média das previsões de tokens entre as conclusões geradas. (Semask_truncated_completions=True, os tokens das sequências mascaradas são excluídos.)aux_loss: A perda auxiliar de balanceamento de carga de um modelo Mixture-of-Experts, antes de ser escalada porrouter_aux_loss_coefe adicionada à perda. Registrada apenas quando o modelo é um modelo MoE erouter_aux_loss_coefé diferente de zero.kl: A divergência KL média entre o modelo e o modelo de referência, calculada sobre as conclusões geradas. Registrado apenas sebetafor diferente de zero.clip_ratio/region_mean: A proporção de probabilidades de sequência em que o objetivo RLOO é limitado para permanecer dentro da região de confiança: . Um valor mais alto significa que mais amostras são limitadas, o que restringe o quanto a política pode mudar.clip_ratio/low_mean: A proporção média das probabilidades de sequência que foram cortadas no limite inferior da região de confiança: .clip_ratio/low_min: O menor indicador de recorte por conclusão no limite inferior da região de confiança: .clip_ratio/high_mean: A razão média das probabilidades de sequência que foram cortadas no limite superior da região de confiança: .clip_ratio/high_max: O maior indicador de recorte por conclusão no limite superior da região de confiança: .
Personalização
Acelere o treinamento com geração impulsionada por vLLM
A geração é frequentemente o principal gargalo ao treinar com métodos online. Para acelerar a geração, você pode usar vLLM, um motor de inferência de alto rendimento e baixa latência para LLMs. Para ativá-lo, primeiro instale o pacote com
pip install trl[vllm]
Suportamos duas formas de usar o vLLM durante o treinamento: modo servidor e modo colocalizado.
Opção 1: Modo Colocate
Neste modo, o vLLM é executado dentro do processo do trainer e compartilha a memória da GPU com o modelo de treinamento. Isso evita a inicialização de um servidor separado e pode melhorar a utilização da GPU, mas pode levar a disputas de memória nas GPUs de treinamento. Este é o modo padrão.
from trl import RLOOConfig
training_args = RLOOConfig(
...,
use_vllm=True, # vllm_mode="colocate" by default
)Opção 2: Modo servidor
Neste modo, o vLLM é executado em um processo separado (e usando GPUs separadas) e se comunica com o treinador via HTTP. Isso é ideal se você tiver GPUs dedicadas para inferência.
Inicie o servidor vLLM:
VLLM_SERVER_DEV_MODE=1 vllm serve <model_name> \ --weight-transfer-config '{"backend": "nccl"}' \ --logprobs-mode processed_logprobs \ --max-logprobs -1Ative o modo de servidor no seu script de treinamento:
from trl import RLOOConfig training_args = RLOOConfig( ..., use_vllm=True, vllm_mode="server", )
Certifique-se de que o servidor está usando GPUs diferentes das do trainer; caso contrário, você pode encontrar erros do NCCL. Você pode especificar as GPUs a serem usadas com a variável de ambiente
CUDA_VISIBLE_DEVICES.
Dependendo do tamanho do modelo e dos requisitos gerais de memória de GPU para o treinamento, você pode precisar ajustar o parâmetro
vllm_gpu_memory_utilizationem RLOOConfig para evitar subutilização ou erros de memória insuficiente.Fornecemos um HF Space para ajudar a estimar a utilização recomendada de memória de GPU com base na configuração do seu modelo e nas configurações do experimento. Basta usá-lo da seguinte forma para obter a recomendação de
vllm_gpu_memory_utilization:Se o valor recomendado não funcionar no seu ambiente, sugerimos adicionar uma pequena margem (por exemplo, +0.05 ou +0.1) ao valor recomendado para garantir estabilidade.
Se você ainda estiver recebendo erros de memória insuficiente, defina
vllm_enable_sleep_modecomo True e os parâmetros e o cache do vllm serão descarregados durante a etapa de otimização. Para mais informações, consulte Reduzindo o uso de memória com o vLLM Sleep Mode.
Por padrão, o RLOO usa
MASTER_ADDR=localhosteMASTER_PORT=12345para o vLLM, mas você pode sobrescrever esses valores definindo as variáveis de ambiente de acordo.
Para mais informações, consulte Aceleração do treinamento com vLLM.
RLOO em escala: treinar um modelo de 70B+ em vários nós
Ao treinar modelos grandes como Qwen2.5-72B, você precisa de várias otimizações-chave para tornar o treinamento eficiente e escalável em várias GPUs e nós. Essas incluem:
- DeepSpeed ZeRO Stage 3: o ZeRO utiliza paralelismo de dados para distribuir os estados do modelo (pesos, gradientes, estados do otimizador) entre várias GPUs e CPUs, reduzindo os requisitos de memória e computação em cada dispositivo. Como modelos grandes não cabem em uma única GPU, o uso do ZeRO Stage 3 é obrigatório para treinar esse tipo de modelo. Para mais detalhes, consulte DeepSpeed Integration.
- torchrun: o lançador do PyTorch inicia um processo por GPU em cada nó e os conecta por meio de um ponto de encontro comum. Para mais detalhes, consulte Distributing Training.
- vLLM: Consulte a seção anterior para saber como usar o vLLM para acelerar a geração.
Abaixo está um exemplo de script SLURM para treinar um modelo de 70B com RLOO em vários nós. Este script treina um modelo em 4 nós e usa o 5º nó para geração com 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}" torchrun \
--nnodes 4 \
--nproc_per_node 8 \
--node_rank $SLURM_PROCID \
--rdzv_backend c10d \
--rdzv_endpoint ${NODELIST[0]}:29500 \
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,
deepspeed="examples/deepspeed_configs/zero3.json",
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()Usando uma função de recompensa personalizada
O RLOOTrainer suporta o uso de funções de recompensa personalizadas em vez de modelos de recompensa densos. Para garantir compatibilidade, sua função de recompensa deve atender aos seguintes requisitos:
As funções de recompensa podem ser chamadas síncronas em Python ou corrotinas assíncronas async def. Quando você fornece várias funções de recompensa assíncronas, elas são aguardadas de forma concorrente (executadas em paralelo via asyncio.gather), de modo que suas latências se sobrepõem.
Argumentos de entrada:
A função deve aceitar os seguintes argumentos como palavras-chave:
prompts(contém os prompts),completions(contém as completions geradas),completion_ids(contém as conclusões tokenizadas),trainer_state(TrainerState): O estado atual do trainer. Isso pode ser usado para implementar funções de recompensa dinâmicas, como aprendizado por currículo, em que a recompensa é ajustada com base no progresso do treinamento.log_extra: uma funçãolog_extra(column: str, values: list)para adicionar colunas extras à tabela de completions. Veja o Exemplo 6.log_metric: uma função chamávellog_metric(name: str, value: float)para registrar métricas escalares como gráficos ao lado dekl,entropy, etc. Veja o Exemplo 6.- Todos os nomes de colunas (exceto
prompt) que o conjunto de dados pode ter. Por exemplo, se o conjunto de dados contiver uma coluna chamadaground_truth, a função será chamada comground_truthcomo argumento de palavra-chave.
A maneira mais fácil de atender a esse requisito é usar
**kwargsna assinatura da função.Dependendo do formato do conjunto de dados, a entrada variará:
- Para o formato padrão,
promptsecompletionsserão listas de strings. - Para o formato conversacional,
promptsecompletionsserão listas de dicionários de mensagens.
- Para o formato padrão,
Valor de retorno: A função deve retornar uma lista de floats. Cada float representa a recompensa correspondente a uma única conclusão.
Exemplo 1: Recompensar conclusões mais longas
Abaixo está um exemplo de uma função de recompensa para um formato padrão que recompensa conclusões mais longas:
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]Você pode testá-lo da seguinte forma:
>>> 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]Exemplo 1.1: Recompensar conclusões mais longas (com base no número de caracteres)
Mesmo que no exemplo anterior, mas desta vez a função de recompensa é baseada no número de caracteres em vez de tokens.
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]Você pode testá-lo da seguinte forma:
>>> 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]Exemplo 2: Recompensar conclusões com um formato específico
Abaixo está um exemplo de uma função de recompensa que verifica se a conclusão possui um formato específico. Este exemplo é inspirado na função format reward usada no artigo DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. Ele foi projetado para um formato conversacional, em que os prompts e as conclusões consistem em mensagens estruturadas.
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]Você pode testar esta função da seguinte forma:
>>> 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]Exemplo 3: Recompensar conclusões com base em uma referência
Abaixo está um exemplo de uma função de recompensa que verifica se a conclusão está correta. Este exemplo é inspirado na função de recompensa de precisão usada no artigo DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.
Este exemplo é projetado para o formato padrão, onde o conjunto de dados contém uma coluna chamada 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)]Você pode testar esta função da seguinte forma:
>>> 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]Exemplo 4: Funções de recompensa multitarefa
Abaixo está um exemplo de uso de múltiplas funções de recompensa no RLOOTrainer. Neste exemplo, definimos duas funções de recompensa específicas para tarefas: math_reward_func e coding_reward_func. A math_reward_func recompensa problemas de matemática com base na sua correção, enquanto a coding_reward_func recompensa problemas de programação com base em se a solução funciona.
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()Neste exemplo, o math_reward_func e o coding_reward_func são projetados para funcionar com um conjunto de dados misto que contém problemas de matemática e de programação. A coluna task no conjunto de dados é usada para determinar qual função de recompensa aplicar a cada problema. Se não houver uma função de recompensa relevante para uma amostra no conjunto de dados, a função de recompensa retornará None, e o RLOOTrainer continuará com as funções e tarefas válidas. Isso permite que o RLOOTrainer lide com múltiplas funções de recompensa com diferentes aplicabilidades.
Observe que o RLOOTrainer ignorará as recompensas None retornadas pelas funções de recompensa e considerará apenas as recompensas retornadas pelas funções relevantes. Isso garante que o modelo seja treinado nas tarefas relevantes e ignore as tarefas para as quais não há uma função de recompensa relevante.
Exemplo 5: Funções de recompensa assíncronas
Funções de recompensa personalizadas também podem ser definidas como corrotinas async def. Isso é útil se a sua recompensa depender de I/O lento (por exemplo, chamar um serviço remoto). Quando você passa várias funções de recompensa assíncronas, o RLOOTrainer as executa de forma concorrente, de modo que a latência delas se sobrepõe.
Abaixo está um exemplo mínimo de uma função de recompensa assíncrona que simula uma operação limitada por 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]Exemplo 6: Registro de colunas e métricas extras
Abaixo está um exemplo de uma função de recompensa que registra colunas extras na tabela de conclusões e métricas escalares como gráficos.
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 rewardsPassando a função de recompensa para o treinador
Para usar sua função de recompensa personalizada, passe-a para o RLOOTrainer da seguinte forma:
from trl import RLOOTrainer
trainer = RLOOTrainer(
reward_funcs=reward_func,
...,
)Você pode passar várias funções de recompensa como uma lista; essa lista pode incluir tanto funções síncronas quanto assíncronas:
from trl import RLOOTrainer
trainer = RLOOTrainer(
reward_funcs=[reward_func, async_reward_func1, async_reward_func2],
...,
)e a recompensa será calculada como a soma das recompensas de cada função, ou como a soma ponderada, se reward_weights for fornecido na configuração.
Observe que o RLOOTrainer suporta múltiplas funções de recompensa de diferentes tipos. Consulte a documentação dos parâmetros para mais detalhes.
Treinando Modelos de Visão e Linguagem
O RLOO suporta o treinamento de Vision-Language Models (VLMs) em conjuntos de dados multimodais que contêm tanto texto quanto imagens.
Modelos Suportados
Testado com:
- Gemma3 — por exemplo,
google/gemma-3-4b-it - LLaVA-NeXT — por exemplo,
llava-hf/llava-v1.6-mistral-7b-hf - Qwen2-VL — por exemplo,
Qwen/Qwen2-VL-2B-Instruct - Qwen2.5-VL — por exemplo,
Qwen/Qwen2.5-VL-3B-Instruct - SmolVLM2 — por exemplo,
HuggingFaceTB/SmolVLM2-2.2B-Instruct
A compatibilidade com todos os VLMs não é garantida. Se você acredita que um modelo deve ser suportado, sinta-se à vontade para abrir uma issue no GitHub — ou, melhor ainda, enviar um pull request com as alterações necessárias.
Início rápido
Use rloo_vlm.py para fazer o fine-tuning de um VLM. Comando de exemplo para treinamento em lmms-lab/multimodal-open-r1-8k-verified:
torchrun --nproc_per_node 8 examples/rloo_visual_math/rloo_visual_math.py \
--deepspeed examples/deepspeed_configs/zero3.json \
--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_completionsDicas de configuração
- Use LoRA nas camadas de projeção de visão-linguagem
- Ative a quantização de 4 bits para reduzir o uso de memória
- VLMs exigem muita memória — comece com tamanhos de lote menores
- A maioria dos modelos é compatível com o vLLM (modos
serverecolocate)
Formato do Conjunto de Dados
Cada amostra de treinamento deve incluir:
prompt: Texto formatado por meio do modelo de chat do processadorimage/images: Imagem PIL ou lista de Imagens PIL
O trainer trata automaticamente a conversão de imagem para tensor por meio do processador de imagens do modelo.
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 )
Parâmetros
- model (
strou PreTrainedModel ou PeftModel) — Modelo a ser treinado. Pode ser:- Uma string, sendo o model id de um modelo pré-treinado hospedado em um repositório de modelos no huggingface.co, ou um
caminho para um diretório contendo pesos de modelo salvos usando
save_pretrained, por exemplo,
'./my_model_directory/'. O modelo é carregado usando<ModelArchitecture>.from_pretrained(onde<ModelArchitecture>é derivado da configuração do modelo) com os argumentos de palavra-chave emargs.model_init_kwargs. Sedtypenão for especificado emargs.model_init_kwargs, o padrão éfloat32. Isso difere de from_pretrained, onde (desde a versão 5 do Transformers) o dtype é inferido a partir da configuração do modelo. - Um objeto PreTrainedModel. Somente modelos de linguagem causais são suportados.
- Um objeto PeftModel. Somente modelos de linguagem causais são suportados.
- Uma string, sendo o model id de um modelo pré-treinado hospedado em um repositório de modelos no huggingface.co, ou um
caminho para um diretório contendo pesos de modelo salvos usando
save_pretrained, por exemplo,
- reward_funcs (
RewardFunc | list[RewardFunc]) — Funções de recompensa a serem usadas para calcular as recompensas. Para calcular as recompensas, chamamos todas as funções de recompensa com os prompts e as conclusões e somamos as recompensas. Pode ser:-
Uma única função de recompensa, como:
-
Uma string: o ID do modelo de um modelo pré-treinado hospedado em um repositório de modelos no huggingface.co, ou um caminho para um diretório contendo pesos de modelo salvos usando save_pretrained, por exemplo,
'./my_model_directory/'. O modelo é carregado usando from_pretrained comnum_labels=1e os argumentos de palavra-chave emargs.model_init_kwargs. -
Um objeto PreTrainedModel: apenas modelos de classificação de sequência são suportados.
-
Uma função de recompensa personalizada: a função recebe os prompts e as conclusões geradas, além de quaisquer colunas adicionais no conjunto de dados. Ela deve retornar uma lista de recompensas. Funções de recompensa personalizadas podem ser síncronas ou assíncronas e também podem retornar
Nonequando a recompensa não se aplica a essas amostras. Isso é útil para treinamento multitarefa, em que diferentes funções de recompensa se aplicam a diferentes tipos de amostras. Quando uma função de recompensa retornaNonepara uma amostra, essa função de recompensa é excluída do cálculo da recompensa para aquela amostra. Para mais detalhes, consulte Usando uma função de recompensa personalizada.O estado do trainer também é passado para a função de recompensa. O estado do trainer é uma instância de TrainerState e pode ser acessado por meio do argumento
trainer_statena assinatura da função de recompensa.
-
-
Uma lista de funções de recompensa, em que cada item pode ser independentemente qualquer um dos tipos acima. A mistura de diferentes tipos dentro da lista (por exemplo, um ID de modelo em string e uma função de recompensa personalizada) é permitida.
-
- args (RLOOConfig, opcional) —
Configuração para este treinador. Se
None, uma configuração padrão é usada. - train_dataset (Dataset ou IterableDataset) —
Dataset a ser usado para o treinamento. Ele deve incluir uma coluna
"prompt". Colunas adicionais no dataset são ignoradas. O formato das amostras pode ser:- Padrão: Cada amostra contém texto simples.
- Conversacional: cada amostra contém mensagens estruturadas (por exemplo, papel e conteúdo).
Quando
train_dataseté um IterableDataset (por exemplo, um dataset em streaming),max_stepsdeve ser definido nos argumentos de treinamento, pois seu comprimento não pode ser inferido e o número total de etapas de treinamento é necessário para limitar o loop de treinamento e configurar o agendador de taxa de aprendizado. - eval_dataset (Dataset, IterableDataset, DatasetDict, IterableDatasetDict ou
dict[str, Dataset | IterableDataset]) — Dataset a ser usado para avaliação. Ele deve atender aos mesmos requisitos quetrain_dataset. - processing_class (PreTrainedTokenizerBase, ProcessorMixin, opcional) —
Classe de processamento usada para processar os dados. O lado do padding deve ser definido como “left”. Se
None, a classe de processamento é carregada a partir do nome do modelo com from_pretrained. Um token de padding,tokenizer.pad_token, deve ser definido. Se a classe de processamento não tiver definido um token de padding,tokenizer.eos_tokenserá usado como padrão. - reward_processing_classes (PreTrainedTokenizerBase ou
list[PreTrainedTokenizerBase], opcional) — Classes de processamento correspondentes às funções de recompensa especificadas emreward_funcs. Pode ser:- Uma única classe de processamento: usada quando
reward_funcscontém apenas uma função de recompensa. - Uma lista de classes de processamento: deve corresponder à ordem e ao comprimento das funções de recompensa em
reward_funcs. Se definido comoNone, ou se um elemento da lista correspondente a um PreTrainedModel forNone, o tokenizer do modelo é carregado automaticamente usando from_pretrained. Para elementos emreward_funcsque são funções de recompensa personalizadas (não PreTrainedModel), as entradas correspondentes emreward_processing_classessão ignoradas.
- Uma única classe de processamento: usada quando
- callbacks (lista de TrainerCallback, opcional) —
Lista de callbacks para personalizar o loop de treinamento. Adicionará esses à lista de callbacks padrão detalhada aqui.
Se você deseja remover um dos callbacks padrão utilizados, use o método remove_callback.
- optimizers (
tuple[torch.optim.Optimizer | None, torch.optim.lr_scheduler.LambdaLR | None], opcional, padrão(None, None)) — Uma tupla contendo o otimizador e o agendador a serem usados. Por padrão, será uma instância deAdamWno seu modelo e um agendador dado por get_linear_schedule_with_warmup controlado porargs. - quantization_config (BitsAndBytesConfig, opcional) —
Configuração de quantização usada ao carregar o modelo a partir de um identificador de modelo. Combine com
peft_configpara treinamento QLoRA. Ignorado se o modelo já estiver instanciado. - peft_config (PeftConfig, opcional) —
Configuração PEFT usada para envolver o modelo. Se
None, o modelo não é envolvido.
Trainer para o método Reinforce Leave One Out (RLOO). Este algoritmo foi inicialmente proposto no artigo Back to Basics: Revisiting REINFORCE Style Optimization for Learning from Human Feedback in LLMs.
Exemplo:
>>> 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()treino
< 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
Parâmetros
- resume_from_checkpoint (
stroubool, opcional) — Se for umstr, caminho local para um checkpoint salvo por uma instância anterior deTrainer. Se for umboole for igual aTrue, carrega o último checkpoint em args.output_dir salvo por uma instância anterior deTrainer. Se presente, o treinamento será retomado a partir dos estados do modelo/otimizador/agendador carregados aqui. - trial (
optuna.Trialoudict[str, Any], opcional) — A execução do trial ou o dicionário de hiperparâmetros para a busca de hiperparâmetros. - ignore_keys_for_eval (
list[str], opcional) — Uma lista de chaves na saída do seu modelo (se for um dicionário) que devem ser ignoradas ao coletar previsões para avaliação durante o treinamento.
Retorna
~trainer_utils.TrainOutput
Objeto contendo a contagem de etapas globais, a perda de treinamento e as métricas.
Ponto de entrada principal do treinamento.
Salvará o modelo, para que você possa recarregá-lo usando from_pretrained().
Salvará apenas a partir do processo principal.
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )
Parâmetros
- commit_message (
str, opcional, padrão"End of training") — Mensagem a ser commitada durante o push. - blocking (
bool, opcional, padrãoTrue) — Se a função deve retornar apenas quando ogit pushtiver terminado. - token (
str, opcional, padrãoNone) — Token com permissão de escrita para sobrescrever os argumentos originais do Trainer. - revision (
str, opcional) — A revisão git de onde o commit será feito. O padrão é o topo do ramo “main”. - kwargs (
dict[str, Any], opcional) — Argumentos de palavra-chave adicionais passados para~Trainer.create_model_card.
Envie self.model e self.processing_class para o hub de modelos do 🤗 no repositório 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 )
Parâmetros que controlam o modelo e o modelo de referência
- model_init_kwargs (
stroudict[str, Any], opcional) — Argumentos de palavra-chave para from_pretrained, usados quando o argumentomodeldo RLOOTrainer é fornecido como uma string. O valor derevisiontambém é usado ao carregar as classes de processamento. - trust_remote_code (
bool, opcional, padrãoFalse) — Se permite carregar modelos e tokenizers que incluem código Python personalizado do Hub. Encaminhado para from_pretrained e from_pretrained. Também aplicado a cargas de reward-model e reward-tokenizer. - router_aux_loss_coef (
float, opcional) — Coeficiente da perda auxiliar de balanceamento de carga para modelos Mixture-of-Experts (MoE), adicionada à perda de treinamento com esse peso. Quando não definido, o valor declarado na configuração do modelo é utilizado. Defina como0.0para desativá-la. Falha quando usado com um modelo não-MoE. - disable_dropout (
bool, opcional, padrãoFalse) — Se deve desabilitar o dropout no modelo. Isso é útil para treinar com um modelo de referência, pois impede que o modelo gere logprobs diferentes para a mesma entrada.
Parâmetros que controlam o pré-processamento dos dados
- remove_unused_columns (
bool, opcional, padrãoFalse) — Se deve manter apenas a coluna"prompt"no conjunto de dados. Se você usar uma função de recompensa personalizada que requer qualquer coluna além de"prompts"e"completions", deve manter isso comoFalse. - num_generations (
int, opcional, padrão é2) — Número de gerações por prompt a amostrar. O tamanho efetivo do lote (num_processes * per_device_batch_size * gradient_accumulation_steps) deve ser divisível por este valor.- gradient_accumulation_steps) deve ser divisível por este valor.
- num_generations_eval (
int, opcional) — Número de gerações a amostrar durante a avaliação. Isso permite usar menos gerações durante a avaliação para economizar computação. SeNone, usa o valor denum_generations. - max_completion_length (
intouNone, opcional, padrão512) — Comprimento máximo da conclusão gerada. - ds3_gather_for_generation (
bool, opcional, padrãoTrue) — Esta configuração se aplica ao DeepSpeed ZeRO-3. Se habilitado, os pesos do modelo de política são reunidos para a geração, melhorando a velocidade de geração. No entanto, desabilitar esta opção permite treinar modelos que excedem a capacidade de VRAM de uma única GPU, embora com o custo de uma geração mais lenta. Desabilitar esta opção não é compatível com a geração do vLLM. - shuffle_dataset (
bool, opcional, padrãoTrue) — Se deve embaralhar o conjunto de dados de treinamento. - pad_to_multiple_of (
intoustr, opcional, padrão"auto") — Se definido, os ids dos prompts e dos completions serão preenchidos até um múltiplo deste valor."auto"preenche até um múltiplo de 128 no Neuron (AWS Trainium), que compila uma vez por forma de entrada, e não preenche em outros ambientes.
Parâmetros que controlam a geração
- generation_batch_size (
int, opcional) — Tamanho do lote a ser usado para a geração. Se forNone, o valor padrão é o tamanho efetivo do lote de treinamento:per_device_train_batch_size * num_processes * steps_per_generation. Em outras palavras, há um lote de geração processado por etapa de otimização. Exclusivo mutuamente comsteps_per_generation. - steps_per_generation (
int, opcional) — Número de etapas por geração. SeNone, o valor padrão égradient_accumulation_steps. Exclusivo comgeneration_batch_size. - temperature (
float, opcional, padrão1.0) — Temperatura para amostragem. Quanto maior a temperatura, mais aleatórias são as conclusões. - top_p (
float, opcional, padrão1.0) — Float que controla a probabilidade cumulativa dos tokens principais a serem considerados. Deve estar em (0, 1]. Defina como1.0para considerar todos os tokens. - top_k (
int, opcional, padrão0) — Número de tokens do vocabulário com maior probabilidade a serem mantidos para o filtro top-k. Se0, o filtro top-k é desativado e todos os tokens são considerados. - min_p (
float, opcional) — Probabilidade mínima do token, que será escalada pela probabilidade do token mais provável. Deve ser um valor entre0.0e1.0. Valores típicos estão na faixa de0.01-0.2. - generation_kwargs (
dict[str, Any], opcional) — Argumentos de palavra-chave adicionais para passar ao GenerationConfig (se estiver usando transformers) ouSamplingParams(se estiver usando vLLM) ao amostrar as conclusões. Isso pode ser usado para personalizar ainda mais o comportamento da geração, como definirsuppress_tokens,num_beams, etc. Se contiver chaves que conflitam com os outros parâmetros de geração (comomin_p,top_p, etc.), eles os substituirão. - chat_template_kwargs (
dict[str, Any], opcional) — Argumentos de palavra-chave adicionais para passar à funçãoapply_chat_templateao gerar completions. - repetition_penalty (
float, opcional, padrão1.0) — Float que penaliza novos tokens com base em sua presença no prompt e no texto gerado até o momento. Valores >1.0incentivam o modelo a usar novos tokens, enquanto valores <1.0incentivam o modelo a repetir tokens. - cache_implementation (
str, opcional) — Implementação do método de cache para uma geração mais rápida quandouse_vllmestá definido comoFalse.
Parâmetros que controlam a aceleração da geração com vLLM
- use_vllm (
bool, opcional, padrãoFalse) — Se deve usar o vLLM para gerar completions. Se definido comoTrue, o trainer usará o vLLM para geração em vez do padrão model.generate(). Requer quevllmesteja instalado. - vllm_mode (
str, opcional, padrão é"colocate") — Modo a ser usado para a integração com o vLLM quandouse_vllmestá definido comoTrue. Deve ser um dos valores"server"ou"colocate"."server": O trainer enviará solicitações de geração para um servidor vLLM separado. Certifique-se de que um servidor vLLM está em execução (inicie comvllm serve)."colocate": o vLLM será executado no mesmo processo e compartilhará as GPUs de treinamento. Isso evita a necessidade de um servidor separado, mas pode causar contenda de recursos com o treinamento.
- vllm_model_impl (
str, opcional, padrão"vllm") — Implementação do modelo a ser usada para o vLLM. Deve ser uma das opções"transformers"ou"vllm"."transformers": Use o backendtransformerspara a implementação do modelo."vllm": Use a bibliotecavllmpara a implementação do modelo. - vllm_enable_sleep_mode (
bool, opcional, padrãoFalse) — Ativa o modo de suspensão do vLLM para descarregar pesos/cache durante o passo do otimizador. Mantém o uso de memória da GPU baixo, mas acordar o mecanismo adiciona latência de transferência entre host e dispositivo. - vllm_structured_outputs_regex (
str, opcional) — Regex para saídas estruturadas do vLLM. SeNone(padrão), as saídas estruturadas ficam desativadas.
Parâmetros que controlam o servidor vLLM (usados apenas quando `vllm_mode` é `"server"`)
- vllm_server_base_url (
str, opcional) — URL base para o servidor vLLM (por exemplo,"http://localhost:8000"). Se fornecida,vllm_server_hostevllm_server_portsão ignorados. - vllm_server_host (
str, opcional, padrão"0.0.0.0") — Host do servidor vLLM para conexão. Ignorado sevllm_server_base_urlfor fornecido. - vllm_server_port (
int, opcional, padrão8000) — Porta do servidor vLLM para conexão. Ignorado sevllm_server_base_urlfor fornecido. - vllm_server_timeout (
float, opcional, padrão240.0) — Duração total do tempo limite, em segundos, para aguardar que o servidor vLLM esteja ativo. Se o servidor não estiver ativo após o tempo limite, umConnectionErrorserá lançado. - vllm_group_port (
int, opcional, padrão51216) — Número da porta para o grupo de atualização de pesos. Isso é usado para se comunicar com o servidor vLLM. A menos que a porta esteja ocupada, não há necessidade de alterá-la.
Parâmetros que controlam a execução do vLLM co-localizado (usados apenas quando `vllm_mode` é `"colocate"`)
- vllm_gpu_memory_utilization (
float, opcional, padrão0.3) — Controla a utilização de memória de GPU para o vLLM. Esta configuração só se aplica quandovllm_modeestá definido como"colocate". Se você estiver usandovllm_mode="server", este parâmetro deve ser passado separadamente ao iniciar o servidor vLLM por meio da flag--vllm_gpu_memory_utilization. - vllm_max_model_length (
int, opcional) — Janela de contexto para o vLLM. Defina-a com pelo menos o comprimento máximo do prompt no conjunto de dados maismax_completion_length; se omitida, ela é inferida a partir da configuração do modelo. - vllm_tensor_parallel_size (
int, opcional, padrão1) — Controla o tamanho da paralelização de tensor para o vLLM. Essa configuração só se aplica quandovllm_modeestá definido como"colocate". Se você estiver usandovllm_mode="server", este parâmetro deve ser passado separadamente ao iniciar o servidor vLLM por meio da flag--vllm_tensor_parallel_size.
Parâmetros que controlam o treinamento
- beta (
float, opcional, padrão0.05) — Coeficiente KL. Se for0.0, o modelo de referência não é carregado, o que reduz o uso de memória e melhora a velocidade de treinamento. - num_iterations (
int, opcional, padrão1) — Número de iterações por lote (denotado como μ no algoritmo). - epsilon (
float, opcional, padrão0.2) — Valor para o recorte (clipping). - epsilon_high (
float, opcional) — Valor superior de epsilon para o recorte. Se não for especificado, o valor padrão será o mesmo do limite inferior especificado no argumentoepsilon. O paper DAPO recomenda0.28. - reward_weights (
list[float], opcional) — Pesos para cada função de recompensa. Deve corresponder ao número de funções de recompensa. SeNone, todas as recompensas são ponderadas igualmente com peso1.0. - normalize_advantages (
bool, opcional, padrãoFalse) — Se as vantagens devem ser normalizadas. A normalização é feita por lote de geração para ter média0.0e desvio padrão de1.0. - reward_clip_range (
tuple[float, float], opcional) — Intervalo de recorte para recompensas como (mínimo, máximo). SeNone, nenhum recorte é aplicado. - mask_truncated_completions (
bool, opcional, padrãoFalse) — Quando habilitado, as conclusões truncadas são excluídas do cálculo da perda, evitando que sejam penalizadas incorretamente e introduzam ruído durante o treinamento. De acordo com o DAPO, essa é uma boa prática para a estabilidade do treinamento. - sync_ref_model (
bool, opcional, padrãoFalse) — Se deve sincronizar o modelo de referência com o modelo ativo a cadaref_model_sync_stepspassos, usando o parâmetroref_model_mixup_alpha. Essa sincronização origina-se do artigo TR-DPO. - ref_model_mixup_alpha (
float, opcional, padrão0.6) — parâmetro α do paper TR-DPO, que controla a mistura entre a política atual e a política de referência anterior durante as atualizações. A política de referência é atualizada de acordo com a equação:π_ref = α * π_θ + (1 - α) * π_ref_prev. Para usar este parâmetro, você deve definirsync_ref_model=True. - ref_model_sync_steps (
int, opcional, padrão512) — parâmetro τ do paper TR-DPO, que determina a frequência com que a política atual é sincronizada com a política de referência. Para usar este parâmetro, você deve definirsync_ref_model=True.
Parâmetros que controlam o registro de logs
- log_completions (
bool, opcional, padrãoFalse) — Se deve registrar uma amostra de pares (prompt, completion) a cadalogging_stepspassos. Se orichestiver instalado, ele imprime a amostra. Se o registro dowandbe/ou dotrackioestiver habilitado, ele registra a amostra nowandbe/ou notrackio. - log_multimodal (
bool, opcional, padrãoTrue) — Se deve registrar conteúdo multimodal (imagens, vídeos, etc.) junto com as conclusões. Desative isso para reduzir o tamanho do log ao usar dados multimodais de alta resolução. - num_completions_to_print (
int, opcional) — Número de conclusões a serem exibidas comrich. SeNone, todas as conclusões são registradas. - log_unique_prompts (
bool, opcional, padrãoFalse) — Se deve registrar prompts únicos. SeTrue, apenas prompts únicos são registrados. SeFalse, todos os prompts são registrados.
Parâmetros que controlam a aceleração da geração com o continuous batching do Transformers
- use_transformers_continuous_batching (
bool, opcional, padrãoFalse) — Se deve usar o motor de continuous batching do transformers para gerar completions. Requertransformers>=5.8.0. - transformers_continuous_batching_config (
dict, opcional) — Argumentos de palavra-chave paraContinuousBatchingConfig.
Parâmetros obsoletos
Classe de configuração para o RLOOTrainer.
Esta classe inclui apenas os parâmetros específicos para o treinamento RLOO. Para a lista completa de argumentos de treinamento, consulte a documentação de TrainingArguments. Observe que os valores padrão nesta classe podem diferir daqueles em TrainingArguments.
Usando HfArgumentParser, podemos transformar essa classe em argumentos argparse que podem ser especificados na linha de comando.
Esses parâmetros possuem valores padrão diferentes de TrainingArguments:
logging_steps: O valor padrão é10em vez de500.gradient_checkpointing: O padrão éTrueem vez deFalse.bf16: Padrão éTruesefp16não estiver definido, em vez deFalse.learning_rate: O valor padrão é1e-6em vez de5e-5.
Referências
- Artigo RLOO
- Artigo Back to Basics: Revisitando a Otimização no Estilo REINFORCE para Aprendizado a partir de Feedback Humano em LLMs
- Artigo - REINFORCE++: Uma abordagem simples e eficiente para alinhar grandes modelos de linguagem
- Post no blog - Colocando RL de volta no RLHF
- Post no blog - Desvendando o RLHF e suas variantes: avanços e insights práticos de engenharia
- Youtube - RLOO: Uma otimização de baixo custo para aprendizado com feedback humano em LLMs
Guia de migração da implementação antiga (0.21 e anteriores)
Com o lançamento da versão 0.22.0, reformulamos o RLOOTrainer para que ele esteja mais alinhado com outros treinadores online da biblioteca, como o GRPOTrainer. Esta nova implementação introduz várias alterações nos parâmetros de configuração e na estrutura geral do treinador. Abaixo está um resumo das principais alterações para o RLOOConfig:
| TRL ≤ 0.21.x | TRL ≥ 0.22.0 |
|---|---|
rloo_k | renomeado para num_generations |
cliprange | renomeado para epsilon |
kl_coef | renomeado para beta |
exp_name | renomeado para run_name. Use run_name = f"{exp_name}__{seed}__{int(time.time())}" para replicar o comportamento antigo |
normalize_reward | renomeado para normalize_advantages. Observação: isso sempre normalizava as vantagens (apesar do nome antigo) |
num_ppo_epochs | renomeado para num_iterations (padrão: 1) |
token_level_kl | removido – o KL agora é calculado apenas no nível da sequência |
dataset_num_proc | removido – não era utilizado |
num_mini_batches | renomeado para steps_per_generation |
total_episodes | use max_steps=total_episodes / gradient_accumulation_steps em vez disso |
local_rollout_forward_batch_size | removido – agora definido automaticamente como per_device_train_batch_size (ou per_device_eval_batch_size durante a avaliação) |
num_sample_generations | removido – use logging_steps para controlar a frequência de registro de logs da geração |
response_length | renomeado para max_completion_length (padrão: 512) |
stop_token | removido |
stop_token_id | removido – use processing_class.eos_token_id no lugar |
missing_eos_penalty | removido – replicar com uma função de recompensa personalizada que verifica se eos_token_id está em completion_ids |
Abaixo está um resumo das principais alterações para o RLOOTrainer:
| TRL ≤ 0.21.x | TRL ≥ 0.22.0 |
|---|---|
config | renomeado para args |
reward_model | renomeado para reward_funcs, que agora suporta tanto modelos de recompensa quanto funções de recompensa personalizadas |
policy | renomeado para model |
ref_policy | removido – o modelo de referência agora é criado automaticamente a partir de model |
data_collator | removido |