feat: add lora warm-start - #3874
Conversation
Enable GRPO to load a pre-trained LoRA adapter in order to continue LoRA fine-tuning from a SFT LoRA checkpoint. Signed-off-by: Peter St. John <pstjohn@nvidia.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
| checkpoints. Optimizer state is not loaded: warm starts begin with a | ||
| fresh optimizer. | ||
| """ | ||
| adapter_dir = _resolve_lora_adapter_dir(restore_from) |
There was a problem hiding this comment.
1 action item. Please fix this in this PR. setup.py:725
This is PR-introduced. With a relative restore_from, the symlink stores a relative target inside the temporary directory, so it resolves beneath that directory and dangles. A relative directory named model also skips staging, while AutoModel selects PEFT loading using the literal "/model" in path check.
AI-1
Normalize the resolved directory before basename/symlink handling and cover both relative-path cases.
| adapter_dir = _resolve_lora_adapter_dir(restore_from) | |
| adapter_dir = os.path.abspath(_resolve_lora_adapter_dir(restore_from)) |
| stripped_donor_keys = { | ||
| key[len(prefix) :] if key.startswith(prefix) else key for key in donor_keys | ||
| } | ||
| expected_keys = { |
There was a problem hiding this comment.
1 action item. Please fix this in this PR. setup.py:691
This is PR-introduced. For Qwen3-MoE with EP=1, donor_keys are HF-format names while expected_keys are native parameter names. AutoModel maps native lora_gate_and_up_A to PEFT base_layer.lora_B.weight, then performs the reverse mapping during load. This validator runs first and raises the new “donor adapter key mismatch” error for a valid donor.
AI-1
Compare keys in the same post-conversion namespace and add a Qwen3-MoE EP=1 save/warm-start round-trip test.
| ``gate_up_linear.weight0``) that do not appear in ``named_parameters()``, | ||
| so their coverage cannot be checked against parameter names. | ||
| """ | ||
| if _has_expert_parallelism(model): |
There was a problem hiding this comment.
1 action item. Please fix this in this PR. setup.py:674
This is PR-introduced. With EP>1, a QKV-only donor and a current QKV+FC configuration pass here because validation returns immediately. AutoModel’s EP loader then continues past missing or unmatched donor keys and only logs counts, leaving the missing FC adapters freshly initialized while warm-start reports success.
AI-1
Validate normalized complete adapter-key sets for EP checkpoints and add the QKV-only donor versus QKV+FC regression case.
| ckpt_cfg.load = restore_dir | ||
| # finetune=False is required for the adapter-only filter, but | ||
| # optimizer/RNG state must not come from the donor run. | ||
| ckpt_cfg.finetune = False |
There was a problem hiding this comment.
1 action item. Please fix this in this PR. setup.py:629
This is PR-introduced. Disabling optimizer and RNG restore does not make this donor load weights-only: Megatron-Bridge independently restores the singleton rerun state, and its PEFT filtering preserves non-model metadata. MCore then overwrites mode, iteration, state, and pending-rerun flags; resetting TrainState does not undo that.
AI-1
Preserve/reset the current RerunStateMachine around donor loading, or use a true weights-only path, and add a donor-with-pending-rerun regression test.
| "megatron.bridge.training.checkpointing", | ||
| reason="requires the mcore extra (Megatron-Bridge)", | ||
| ) | ||
| src = inspect.getsource(checkpointing) |
There was a problem hiding this comment.
1 action item. Please fix this in this PR. test_megatron_setup.py:3997
This test gap is PR-introduced. The five searched strings occur together in both the upstream adapter-filtering predicate and non-strict-load predicate. Removing either required block leaves every string elsewhere, so this tripwire still passes; the other warm-start tests mock the loader boundary.
AI-1
Replace this module-wide source search with a focused loader/storage-mocked behavior test that proves both adapter filtering and non-strict loading remain active.
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
|
Auto-sync is disabled for ready for review pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
/ok to test cc2a58a |
What does this PR do?
Adds LoRA warm-start support so a new training run can initialize its adapters from an existing checkpoint—for example, continuing from an SFT LoRA checkpoint with GRPO.
This supports both training backends:
adapter_model.safetensorsandadapter_config.json.iter_*checkpoint or checkpoint root.The implementation:
restore_fromto the AutoModel LoRA and Megatron PEFT configurations.restore_from.Issues
N/A
Usage
DTensor/AutoModel
restore_frommay point directly to the adapter directory or itsmodel/subdirectory.Megatron Core
restore_frommay point to aniter_XXXXXXXdirectory or a checkpoint root that resolves to one.The donor LoRA configuration must be compatible with the new run. In particular, adapter rank and scaling must match.
Testing
git diff --check: passedThe backend-specific tests were run in the prebuilt DTensor and Megatron container runtimes.
Before your PR is "Ready for review"
Additional Information
Warm-starting is distinct from resuming:
restore_frominitializes a new run from donor adapter weights.