## Summary LTX-2 (`ltx-core`, `ltx-pipelines`, `ltx-trainer`) is a third-party dependency developed and provided by Lightricks. It is governed by the [LTX Community License Agreement](https://github.com/Lightricks/LTX-2/blob/main/LICENSE), **not** the Apache 2.0 license that covers NVIDIA Model Optimizer. Per legal guidance, all integration points must clearly surface this to users. - Add `[!WARNING]` license notice blocks at the top of all LTX-2-related READMEs (`examples/diffusers`, `examples/diffusers/distillation`, `examples/windows/diffusers/qad_example`) - Add `warnings.warn(UserWarning)` at every LTX package import site in Python files, covering both top-level and lazy imports: - `examples/diffusers/distillation/distillation_trainer.py` - `examples/diffusers/quantization/calibration.py` - `examples/diffusers/quantization/pipeline_manager.py` - `examples/windows/diffusers/qad_example/sample_example_qad_diffusers.py` - `modelopt/torch/export/diffusers_utils.py` - `modelopt/torch/quantization/plugins/diffusion/ltx2.py` - Add license notice comment to `requirements.txt` files that list LTX packages, so the obligation is visible at install time - Update `.github/CODEOWNERS` so all `requirements*.txt` files (covering variants like `requirements-dev.txt`) are owned by `@NVIDIA/modelopt-setup-codeowners` regardless of location, via a last-match-wins rule **Design notes:** - For library files (`diffusers_utils.py`, `ltx2.py`), the warning is placed at the lazy import site inside functions — it fires only when LTX-2 code paths are actually invoked, not at module import time, to avoid polluting non-LTX users - For example entry-point scripts that are LTX-2-only, the warning fires at module load time (after all imports, to satisfy ruff E402) ## Test plan - [ ] Confirm `pre-commit run --all-files` passes (ruff, mypy, markdownlint, bandit all clean) - [ ] Verify warning appears at runtime when running an LTX-2 quantization or distillation example - [ ] Confirm non-LTX code paths (FLUX, SDXL, SD3) do not emit the warning 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added third-party license notices across documentation and requirements files clarifying LTX-2 packages are governed by the LTX Community License Agreement rather than NVIDIA Model Optimizer's Apache 2.0 license. * **Chores** * Updated code ownership configuration for requirements files. * Added runtime warnings to notify when LTX-2 dependencies are accessed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Keval Morabia <28916987+kevalmorabia97@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
LTX-2 Distillation Training with ModelOpt
Warning
Third-Party License Notice — LTX-2
LTX-2 is a third-party model and set of packages developed and provided by Lightricks. LTX-2 is not covered by the Apache 2.0 license that governs NVIDIA Model Optimizer.
By installing and using LTX-2 packages (
ltx-core,ltx-pipelines,ltx-trainer) with NVIDIA Model Optimizer, you must comply with the LTX Community License Agreement.Any derivative models or fine-tuned weights produced from LTX-2 using NVIDIA Model Optimizer (including quantized or distilled checkpoints) remain subject to the LTX Community License Agreement and are not covered by Apache 2.0.
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 nodesGPUS_PER_NODE: Number of GPUs per nodeNODE_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.