feat: add mtp support - #667
Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
67c54ac to
c849d4b
Compare
f965680 to
3580c7a
Compare
8946ce0 to
1115a50
Compare
|
@curnane-lab Great work! We believe that fine-tuning MTP is now a very important task. The current Qwen3.5 and later models have very high MTP performance. Modifying the current PR to fine-tune MTP and integrating it into the current main branch would be very meaningful. However, we believe that the amount of data required for MTP pretraining is too large, similar to Eagle3. No dedicated implementation is needed. We look forward to your feedback. |
Agreed — fine-tuning is the useful path here. I'll drop the from-scratch pretraining part, keep only native-MTP init, and rework it as a strategy in the unified |
Per PR sgl-project#667 review feedback: drop the standalone from-scratch pretraining script and keep only native-MTP fine-tuning, integrated into the typed YAML + algorithm-plugin architecture. - specforge/algorithms/mtp/: new built-in registration. build_draft initializes the draft from the native mtp.* weights in the target checkpoint and shares/freezes target embed_tokens + lm_head. - strategies/base.py: MTPTrainStrategy adapting OnlineMTPModel to the trainer StepOutput contract. - modeling/draft/mtp.py: register Qwen3_5MTPDraftModel in DRAFT_REGISTRY; configs/qwen3.5-4b-mtp.json architectures fixed accordingly. - Offline capture persists input_ids/loss_mask/target_last_hidden_states (final post-norm hidden only); new mtp reader/normalizer/collator triple. - examples/configs/qwen3.5-4b-mtp-offline.yaml replaces the deleted torchrun example; scripts/train_mtp.py and modeling/target/mtp_target_model.py removed (dead on the new architecture). - tests: CPU unit tests for OnlineMTPModel/strategy/native-init/registration; builtin contract/parity, launch topology and recipe goldens updated. - docs: add missing model.use_liger_kernel row to examples/configs/README.md (pre-existing test_recipe_readme failure on main).
Hi @jiapingW , the rework you suggested is done: MTP is now a strategy in the unified Online managed-local training on Ascend NPU (16x A3)Qwen3.5-4B MTP head trained end-to-end on the managed-local NPU stack — a single
|
|
Can you merge the commits to less? |
941ce3c to
a1c124b
Compare
Done. |
678a8c5 to
d984060
Compare
Modifications
|
|
@curnane-lab We therefore do not plan to introduce separate strategies such as The intended structure is approximately: |
e86b487 to
a77d0fb
Compare
a77d0fb to
055b0a8
Compare
Hi @jiapingW, thanks for the review. The branch has been reworked accordingly. Architecture now follows your sketch: one One thing to confirm: the review assigns "owns merging" to CPU tests ( |
bd98e92 to
4a3bed4
Compare
|
Could you grant me permission to submit patches? I am making some relevant fixes, including RoPE alignment and model export with merged MTP weights. @curnane-lab |
Done, you've been added as a collaborator on the fork. Feel free to push the RoPE alignment and export fixes directly to the PR branch. Thanks for picking these up! |
|
I have updated it. You can see the last commit. If you think is OK, you can help use the qwen3.5 to run a simple training pipeline to test it. Then I'll merge it. Thanks. @curnane-lab |

Motivation
This PR adds training support for Multi-Token Prediction (MTP) to SpecForge, targeting Qwen3.5-4B. MTP is natively supported by Qwen3.5 and by SGLang/vLLM through per-target
*_mtp.pymodules, so the trained weights must match the target's native checkpoint layout to be loadable at inference time.Modifications
specforge/modeling/draft/mtp.py: Qwen3.5 MTP draft model (Qwen3_5MTPDraftModel) matching the official Qwen3.5-4B architecture (head_dim=256,attn_output_gate, partial rotary). Saves weights in the flatmtp.layers.*layout required by SGLang/vLLM.specforge/core/mtp.py:OnlineMTPModeltraining wrapper (next-token shift, CE loss, per-position accuracy metrics).scripts/train_mtp.py: end-to-end MTP training script with FSDP, BF16 optimizer, optional native-MTP finetune init, and frozen/shared embed/lm_head.specforge/modeling/target/mtp_target_model.py: standalone MTP data generators for SGLang, HF, and custom target backends, decoupled fromEagle3TargetModel.specforge/modeling/target/eagle3_target_model.py: minimal changes — CPU-first HF target loading for NPU memory, andcapture_aux_hidden_statesflag for SGLangextend().scripts/merge_mtp_to_base.py: merges trained MTP weights back into the base model checkpoint for direct serving.configs/qwen3.5-4b-mtp.json&examples/run_qwen3.5_4b_mtp_online_npu.sh: draft config and NPU training example.Related Issues
Accuracy & Performance Evaluation
Qwen3.5-4B (target model) with the HF backend is used to regenerate responses for 10K samples from Open-PerfectBlend. The regenerated QA pairs serve as training data for MTP head.
Training Configuration
Evaluation was performed on GSM8K (500 samples,
max_new_tokens=512,temperature=0.0) for both the fine-tuned MTP head and the original Qwen3.5-4B native MTP head, served withqwen3_5_mtpspeculative decoding (num_speculative_tokens=1,enforce_eager=true).The trained MTP head — initialized and trained from scratch with
--no-init-from-native-mtp— achieves on-par end-to-end latency and throughput with the original native MTP head (within 2%), confirming that the randomly-initialized MTP head can be trained to match the native head and that the trained weights are correctly loaded and functionally aligned with the serving path.Checklist