Files
Model-Optimizer/examples/diffusers/distillation
Keval Morabia 82f1d216d1 Add Security and IP related contributing guide and configure coderabbit to catch such issues (#935)
### What does this PR do?

- Add Security related coding practices in `SECURITY.md` and merge with
`2_security.rst`
- Update `CONTRIBUTING.md` for instructions to follow if copying code
from other repositories
- Update PR template
- Cleanup dependency files
- New API `mto.load_modelopt_state` doing the insecure `torch.load(f,
weights_only=False)` instead of doing it separately everywhere. This
also allows us to later improve the input validation for
`modelopt_state_path` or use safer alternatives to `torch.load`

### Testing
<!-- Mention how have you tested your change if applicable. -->

N/A

### Before your PR is "*Ready for review*"

Make sure you read and follow [Contributor
guidelines](https://github.com/NVIDIA/Model-Optimizer/blob/main/CONTRIBUTING.md)
and your commits are signed (`git commit -s -S`).

Make sure you read and follow the [Security Best
Practices](https://github.com/NVIDIA/Model-Optimizer/blob/main/SECURITY.md#security-coding-practices-for-contributors)
(e.g. hardcoded `trust_remote_code=True`, `torch.load(...,
weights_only=True)`, `pickle`, etc.).

- Is this change backward compatible?: ✅ <!--- If ❌, explain why. -->
- If you copied code from any other source, did you follow IP policy in
[CONTRIBUTING.md](https://github.com/NVIDIA/Model-Optimizer/blob/main/CONTRIBUTING.md#-copying-code-from-other-sources)?:
✅ <!--- Mandatory -->
- Did you write any new necessary tests?: NA <!--- Mandatory for new
features or examples. -->
- Did you add or update any necessary documentation and update
[Changelog](https://github.com/NVIDIA/Model-Optimizer/blob/main/CHANGELOG.rst)?:
NA <!--- Only for new features, API changes, critical bug fixes or
backward incompatible changes. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Expanded and reorganized security guidance and contributor procedures;
updated PR template and several READMEs with clearer security,
submission, and installation instructions
* Replaced an older security document with an enhanced, centralized
security guidance

* **Chores**
* Adjusted example dependency lists and optional extras (adds, removals,
and version constraints)
* Enabled automated incremental reviews, added pre-merge security
checks, and introduced a knowledge-base of coding/security guidelines
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Keval Morabia <28916987+kevalmorabia97@users.noreply.github.com>
2026-03-03 03:49:15 +05:30
..

LTX-2 Distillation Training with ModelOpt

Knowledge distillation for LTX-2 DiT models using NVIDIA ModelOpt. A frozen teacher guides a trainable student through a combined loss:

L_total = α × L_task + (1-α) × L_distill

Currently supported:

  • Quantization-Aware Distillation (QAD) — student uses ModelOpt fake quantization

Planned:

  • Sparsity-Aware Distillation (SAD) — student uses ModelOpt sparsity

Installation

# From the distillation example directory
cd examples/diffusers/distillation

# Install Model-Optimizer (from repo root)
pip install -e ../../..

# Install all dependencies (ltx-trainer, ltx-core, ltx-pipelines, omegaconf)
pip install -r requirements.txt

Quick Start

1. Prepare Your Dataset

Use the ltx-trainer preprocessing to extract latents and text embeddings:

python -m ltx_trainer.preprocess \
    --input_dir /path/to/videos \
    --output_dir /path/to/preprocessed \
    --model_path /path/to/ltx2/checkpoint.safetensors

2. Configure

Copy and edit the example config:

cp configs/distillation_example.yaml configs/my_experiment.yaml

Key settings to update:

model:
  model_path: "/path/to/ltx2/checkpoint.safetensors"
  text_encoder_path: "/path/to/gemma/model"

data:
  preprocessed_data_root: "/path/to/preprocessed/data"

distillation:
  distillation_alpha: 0.5       # 1.0 = pure task loss, 0.0 = pure distillation
  quant_cfg: "FP8_DEFAULT_CFG"  # or INT8_DEFAULT_CFG, NVFP4_DEFAULT_CFG, null

# IMPORTANT: disable ltx-trainer's built-in quantization
acceleration:
  quantization: null

3. Run Training

Single GPU

python distillation_trainer.py --config configs/my_experiment.yaml

Multi-GPU (Single Node) with Accelerate

accelerate launch \
    --config_file configs/accelerate/fsdp.yaml \
    --num_processes 8 \
    distillation_trainer.py --config configs/my_experiment.yaml

Multi-node Training with Accelerate

To launch on multiple nodes, make sure to set the following environment variables on each node:

  • NUM_NODES: Total number of nodes
  • GPUS_PER_NODE: Number of GPUs per node
  • NODE_RANK: Unique rank/index of this node (0-based)
  • MASTER_ADDR: IP address of the master node (rank 0)
  • MASTER_PORT: Communication port (e.g., 29500)

Then run this (on every node):

accelerate launch \
    --config_file configs/accelerate/fsdp.yaml \
    --num_machines $NUM_NODES \
    --num_processes $((NUM_NODES * GPUS_PER_NODE)) \
    --machine_rank $NODE_RANK \
    --main_process_ip $MASTER_ADDR \
    --main_process_port $MASTER_PORT \
    distillation_trainer.py --config configs/my_experiment.yaml

Config overrides can be passed via CLI using dotted notation:

accelerate launch ... distillation_trainer.py \
    --config configs/my_experiment.yaml \
    ++distillation.distillation_alpha=0.6 \
    ++distillation.quant_cfg=INT8_DEFAULT_CFG \
    ++optimization.learning_rate=1e-5

Configuration Reference

Calibration

Before training begins, calibration runs full denoising inference to collect activation statistics for accurate quantizer scales. This is cached as a step-0 checkpoint and reused on subsequent runs.

Parameter Default Description
calibration_prompts_file null Text file with one prompt per line. Use the HuggingFace dataset 'Gustavosta/Stable-Diffusion-Prompts' if null.
calibration_size 128 Number of prompts (each runs a full denoising loop)
calibration_n_steps 30 Denoising steps per prompt
calibration_guidance_scale 4.0 CFG scale (should match inference-time)

Checkpoint Resume

Parameter Default Description
resume_from_checkpoint null "latest" to auto-detect, or explicit path
must_save_by null Minutes after which to save and exit (for Slurm time limits)
restore_quantized_checkpoint null Restore a pre-quantized model (skips calibration)
save_quantized_checkpoint null Path to save the final quantized model

Custom Quantization Configs

To define custom quantization configs, add entries to CUSTOM_QUANT_CONFIGS in distillation_trainer.py:

CUSTOM_QUANT_CONFIGS["MY_FP8_CFG"] = {
    "quant_cfg": mtq.FP8_DEFAULT_CFG["quant_cfg"],
    "algorithm": "max",
}

Then reference it in your YAML: quant_cfg: MY_FP8_CFG.