TRL documentation
IW-OPD
IW-OPD
In the paper On the Position Bias of On-Policy Distillation, the authors introduce Importance-Weighted On-Policy Distillation (IW-OPD). IW-OPD addresses position bias in on-policy distillation by reweighting sampled-token updates according to accumulated teacher-student prefix discrepancy. Early tokens keep larger weights, while later tokens after high drift are downweighted.
To use IW-OPD, you can use the experimental.iw_opd.IWOPDTrainer class in trl.experimental.iw_opd.
IW-OPD is currently part of the
trl.experimentalnamespace. APIs may change without notice while the feature is iterated on.
Usage
from trl.experimental.iw_opd import IWOPDConfig, IWOPDTrainer
training_args = IWOPDConfig(
distillation_objective="iw_opd",
iw_opd_gamma=0.5,
)
trainer = IWOPDTrainer(
model="Qwen/Qwen3-0.6B",
teacher_model="...",
train_dataset=...,
args=training_args,
)
trainer.train()IW-OPD is an on-policy objective: distillation_objective="iw_opd" requires lmbda=1.0 (the default). iw_opd_gamma is the importance-weight amplification from Algorithm 1 of the paper.
IWOPDTrainer
class trl.experimental.iw_opd.IWOPDTrainer
< source >( model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.Module, str, NoneType] = Noneteacher_model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.Module, str] = Noneargs: trl.experimental.iw_opd.iw_opd_config.IWOPDConfig | None = Nonedata_collator: collections.abc.Callable[[list[typing.Any]], dict[str, typing.Any]] | None = Nonetrain_dataset: datasets.arrow_dataset.Dataset | None = Noneeval_dataset: datasets.arrow_dataset.Dataset | dict[str, datasets.arrow_dataset.Dataset] | None = Noneprocessing_class: transformers.tokenization_utils_base.PreTrainedTokenizerBase | transformers.image_processing_utils.BaseImageProcessor | transformers.feature_extraction_utils.FeatureExtractionMixin | transformers.processing_utils.ProcessorMixin | None = Nonecompute_metrics: collections.abc.Callable[[transformers.trainer_utils.EvalPrediction], dict] | None = Nonecallbacks: list[transformers.trainer_callback.TrainerCallback] | None = Noneoptimizers: tuple = (None, None)preprocess_logits_for_metrics: collections.abc.Callable[[torch.Tensor, torch.Tensor], torch.Tensor] | None = Nonepeft_config: typing.Optional[ForwardRef('PeftConfig')] = None )
Trainer for Importance-Weighted On-Policy Distillation (IW-OPD).
IW-OPD (On the Position Bias of On-Policy Distillation) reweights the sampled-token distillation signal by accumulated teacher-student prefix discrepancy, downweighting later tokens whose supervision has drifted out of distribution. Select it with distillation_objective=“iw_opd”.
This trainer is a frozen snapshot of the pre-refactor
DistillationTrainer, kept as the home for IW-OPD (a teacher-guided policy-gradient method that does not fit the stable, full-vocabularyDistillationTrainer). It is not actively maintained and will not track that trainer’s later improvements.
Supports:
- Generalized JSD loss (forward KL, reverse KL, or interpolated JSD via beta)
- Sampled-token IW-OPD objective (distillation_objective=“iw_opd”)
- On-policy / off-policy mixing via lmbda (buffered across gradient accumulation)
- Local teacher model or external teacher via vLLM server
- Student on-policy generation via vLLM or model.generate()
- Liger kernel for memory-efficient fused JSD loss
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
Parameters
- resume_from_checkpoint (
strorbool, optional) — If astr, local path to a saved checkpoint as saved by a previous instance ofTrainer. If abooland equalsTrue, load the last checkpoint in args.output_dir as saved by a previous instance ofTrainer. If present, training will resume from the model/optimizer/scheduler states loaded here. - trial (
optuna.Trialordict[str, Any], optional) — The trial run or the hyperparameter dictionary for hyperparameter search. - ignore_keys_for_eval (
list[str], optional) — A list of keys in the output of your model (if it is a dictionary) that should be ignored when gathering predictions for evaluation during the training.
Returns
~trainer_utils.TrainOutput
Object containing the global step count, training loss, and metrics.
Main training entry point.
Will save the model, so you can reload it using from_pretrained().
Will only save from the main process.
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )
Parameters
- commit_message (
str, optional, defaults to"End of training") — Message to commit while pushing. - blocking (
bool, optional, defaults toTrue) — Whether the function should return only when thegit pushhas finished. - token (
str, optional, defaults toNone) — Token with write permission to overwrite Trainer’s original args. - revision (
str, optional) — The git revision to commit from. Defaults to the head of the “main” branch. - kwargs (
dict[str, Any], optional) — Additional keyword arguments passed along to~Trainer.create_model_card.
Upload self.model and self.processing_class to the 🤗 model hub on the repo self.args.hub_model_id.
IWOPDConfig
class trl.experimental.iw_opd.IWOPDConfig
< 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 = <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 = Truelabel_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 = Falsemax_length: int | None = 1024temperature: float = 1.0lmbda: float = 1.0beta: float = 1.0distillation_objective: str = 'iw_opd'iw_opd_gamma: float = 0.5iw_opd_epsilon: float = 1e-08reverse_kl_top_1_mode: str = 'sampled'max_completion_length: int = 512max_prompt_length: int | None = Nonedisable_dropout: bool = Trueteacher_model_name_or_path: str | None = Noneteacher_model_revision: str | None = Noneteacher_model_init_kwargs: dict[str, typing.Any] | str | None = Noneuse_teacher_server: bool = Falseteacher_model_server_url: str | None = Noneloss_top_k: int = 1loss_add_tail: bool = Truenum_generations: int = 1generation_batch_size: int | None = Nonetop_p: float = 0.95top_k: int = 0use_vllm: bool = Falsevllm_mode: str = 'colocate'vllm_server_base_url: str | None = Nonevllm_server_host: str = '0.0.0.0'vllm_server_port: int = 8001vllm_server_timeout: float = 240.0vllm_group_port: int = 51216vllm_gpu_memory_utilization: float = 0.3vllm_tensor_parallel_size: int = 1vllm_max_model_length: int | None = Nonevllm_model_impl: str = 'vllm'vllm_structured_outputs_regex: str | None = Nonevllm_sync_frequency: int = 1vllm_enable_sleep_mode: bool = Falselog_completions: bool = Falselog_completions_steps: int = 100num_completions_to_print: int | None = None )
Parameters that control the model
- model_init_kwargs (
dict[str, Any], optional) — Keyword arguments forAutoModelForCausalLM.from_pretrained, used when themodelargument of the trainer is provided as a string. Therevisionvalue is also used when loading the processing class. - trust_remote_code (
bool, optional, defaults toFalse) — Whether to allow loading models and tokenizers that ship custom Python code from the Hub. Forwarded to from_pretrained and from_pretrained, for both the student and teacher. - max_length (
intorNone, optional, defaults to1024) — Maximum total sequence length (prompt + completion) for tokenization and truncation.
Parameters that control the distillation
- temperature (
float, optional, defaults to1.0) — Temperature for sampling during generation and for computing the distillation loss. Higher values produce softer probability distributions. - lmbda (
float, optional, defaults to1.0) — Probability of using on-policy (student-generated) data for each gradient accumulation slice. A value of0.0means fully off-policy (dataset completions only),1.0means fully on-policy. - beta (
float, optional, defaults to1.0) — Interpolation coefficient for the Generalized Jensen-Shannon Divergence loss. When0.0, the loss is the forward KL divergence. When1.0, the loss is the reverse KL divergence. When0.5, it is the standard JSD. - distillation_objective (
str, optional, defaults to"iw_opd") — Objective to optimize."iw_opd"uses the sampled-token Importance-Weighted On-Policy Distillation objective."jsd"keeps the generalized JSD/KL objective. - iw_opd_gamma (
float, optional, defaults to0.5) — Importance-weight amplification fordistillation_objective="iw_opd". - iw_opd_epsilon (
float, optional, defaults to1e-8) — Stabilizer used when normalizing IW-OPD prefix weights. - reverse_kl_top_1_mode (
str, optional, defaults to"sampled") — Selection rule for the reverse-KL top-1 token whenbeta > 0andloss_top_k == 1."sampled"uses the actual completion token in the batch."argmax"uses the student’s highest-probability token. This setting does not affect the forward-KL support, which always uses the teacher’s top-1 token. Ignored whenbeta == 0orloss_top_k != 1. - max_completion_length (
int, optional, defaults to512) — Maximum number of tokens to generate per completion during on-policy generation. - max_prompt_length (
intorNone, optional) — Maximum number of tokens for the prompt. IfNone, auto-computed asmax_length - max_completion_length. Prompts are truncated according to the tokenizer’struncation_sidesetting. - disable_dropout (
bool, optional, defaults toTrue) — Whether to disable dropout in the student model during training.
Parameters that control the teacher model
- teacher_model_name_or_path (
strorNone, optional) — Model name or path for the teacher model. Used when the teacher is loaded locally. - teacher_model_revision (
strorNone, optional) — Model revision of the teacher model (e.g., branch name, tag, or commit hash). - teacher_model_init_kwargs (
dict[str, Any]orNone, optional) — Keyword arguments passed toAutoModelForCausalLM.from_pretrainedwhen instantiating the teacher model from a string. - use_teacher_server (
bool, optional, defaults toFalse) — Whether to use an external vLLM teacher server instead of a local teacher model. - teacher_model_server_url (
strorNone, optional) — Base URL of a vLLM server hosting the teacher model (e.g.,"http://localhost:8000"). When set, teacher logprobs are fetched from the server instead of running a local forward pass whenuse_teacher_server=True. - loss_top_k (
int, optional, defaults to1) — Number of top tokens to use when computing the JSD/KL loss. Both student and teacher distributions are restricted to these K tokens and re-normalized before computing divergence. If 0, the full vocabulary is used. For local teachers, the general support rule is teacher top-k for forward KL, student top-k for reverse KL, and the union for mixed JSD. Whenbeta > 0andloss_top_k == 1, the forward support still uses the teacher’s top-1 token, while the reverse top-1 token is controlled byreverse_kl_top_1_mode. Whenuse_teacher_server=True, the pure forward path (beta=0) requires this to be positive and uses the teacher’s top-k logprobs for the forward term. Whenbeta > 0, server-backed distillation requiresloss_top_k == 1and only supports"sampled"reverse top-1 tokens. - loss_add_tail (
bool, optional, defaults toTrue) — Whether to append a tail bucket that represents the remaining probability mass outside the selected top-k support when computing the loss.
Parameters that control on-policy generation
- num_generations (
int, optional, defaults to1) — Number of completions to generate per prompt during on-policy generation. - generation_batch_size (
intorNone, optional) — Number of unique prompts per worker per optimizer step. IfNone, computed from(per_device_train_batch_size * gradient_accumulation_steps) // num_generations. - top_p (
float, optional, defaults to0.95) — Top-p (nucleus) sampling parameter for on-policy generation. - top_k (
int, optional, defaults to0) — Top-k sampling parameter for on-policy generation.0disables top-k filtering.
Parameters that control vLLM for student generation
- use_vllm (
bool, optional, defaults toFalse) — Whether to use vLLM for generating on-policy completions from the student model. - vllm_mode (
str, optional, defaults to"colocate") — Mode for student vLLM integration. Either"server"or"colocate". - vllm_server_base_url (
strorNone, optional) — Base URL for the student vLLM server. If provided,vllm_server_hostandvllm_server_portare ignored. - vllm_server_host (
str, optional, defaults to"0.0.0.0") — Host of the student vLLM server. - vllm_server_port (
int, optional, defaults to8001) — Port of the student vLLM server. - vllm_server_timeout (
float, optional, defaults to240.0) — Timeout for connecting to the student vLLM server. - vllm_group_port (
int, optional, defaults to51216) — Port for the vLLM weight-update group (NCCL communicator). - vllm_gpu_memory_utilization (
float, optional, defaults to0.3) — GPU memory utilization for the colocated student vLLM engine. - vllm_tensor_parallel_size (
int, optional, defaults to1) — Tensor parallel size for the colocated student vLLM engine. - vllm_max_model_length (
intorNone, optional) — Maximum model sequence length for the colocated vLLM engine. - vllm_model_impl (
str, optional, defaults to"vllm") — Model implementation backend for vLLM. Use"vllm"or"transformers". - vllm_structured_outputs_regex (
strorNone, optional) — Regex pattern for vLLM structured outputs. - vllm_sync_frequency (
int, optional, defaults to1) — Frequency (in training steps) to synchronize student model weights to the vLLM engine. - vllm_enable_sleep_mode (
bool, optional, defaults toFalse) — Enable vLLM sleep mode to offload student weights during the optimizer step.
Parameters that control logging
- log_completions (
bool, optional, defaults toFalse) — Whether to log a sample of (prompt, completion) pairs everylog_completions_stepssteps. Ifrichis installed, it prints the sample. Ifwandband/ortrackiologging is enabled, it logs it towandband/ortrackio. - log_completions_steps (
int, optional, defaults to100) — Number of steps between logging completions. Only used iflog_completionsisTrue. - num_completions_to_print (
intorNone, optional) — Number of completions to print. IfNone, all completions are logged.
Configuration class for the experimental.iw_opd.IWOPDTrainer.
Extends TrainingArguments with parameters specific to knowledge distillation. This config is independent of SFTConfig — all necessary fields are declared here.
Using HfArgumentParser we can turn this class into argparse arguments that can be specified on the command line.