Repository navigation
feat(speculative): add Kimi K3 EAGLE-3 training - #3286
Merged
Merged
Conversation
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Avoid import-time transformer mutation, remove the dead tokenizer fallback, and cover K3 MoE router-weight placement against reference inference for both loop and grouped-mm expert backends. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Accept the documented medium thinking effort with durable input validation, and prove both Kimi K3 model types resolve through local configs when the installed Transformers mapping has no builtin entry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Keep checkpoint-free initialization valid when attention residual mixing is disabled while preserving pruned pipeline-stage handling, with a CPU forward regression test for the no-residual configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Keep the upstream Moonshot attribution and license while marking NVIDIA modifications so the repository copyright check recognizes both files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Remove the identical MoE and dense branches around MLP weight initialization so the shared behavior is explicit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Kimi K3 interleaves KDA layers with NoPE MLA full-attention layers, which neither the dense EAGLE-3 draft nor the DeepSeek MLA draft (which always rotates the rope slice) can represent. Add a dedicated draft that mirrors one K3 MLA layer: Q-LoRA, the compressed KV latent, the unrotated rope slice, the sigmoid output gate, K3 RMSNorm and the SiTU MLP, with KDA, the routed experts and the attention-residual mixer left in the target. Everything EAGLE-3 specific is inherited from the DeepSeek MLA draft through a new _build_inner_model hook, so the TTT recurrence, the vocab-remap buffers and the trainer are reused unchanged. freeze_embeddings, which the recipe calls for every draft, is added to that shared MLA base. The frozen target is loaded through AutoModel's custom expert-parallel path (K3 has no HuggingFace implementation and its 896 routed experts do not fit on one GPU), and the combinations K3 cannot serve (non-colocated backends, context or tensor parallelism, sequence packing, parallel drafting) are rejected before the target is loaded. Signed-off-by: khazic <khazzz1c@gmail.com>
…ispatcher to torch Online EAGLE-3 supervision hooks one complete target forward, so a pipelined K3 target (whose layer ModuleDict holds only its own stage, keyed by global index) either raises a KeyError in the aux-layer capture or silently captures nothing. The README already said pp_size must stay 1; enforce it with the other gates, before the 93-layer target is loaded. The expert dispatcher defaulted to hybridep, which forces the DeepEP path even where that build is absent (the world_size==1 fallback hides it until the real multi-node run). Default to torch, the dispatcher K3's own SFT reference config runs expert parallelism with, and keep deepep/hybridep opt-in. Signed-off-by: khazic <khazzz1c@gmail.com>
The Kimi K3 base branch was squash-merged into main, so re-target this work onto main and keep main's version of every K3 file. Signed-off-by: khazic <khazzz1c@gmail.com>
The non-colocated EAGLE-3 target backends call _setup_online_target with draft_base_config=None, so reading .model_type unconditionally raised AttributeError before the backend dispatch. Signed-off-by: khazic <khazzz1c@gmail.com>
khazic
requested review from
a team,
HuiyingLi,
akoumpa,
athitten and
snowmanwwg
as code owners
July 29, 2026 09:41
Contributor
|
/claude review |
Contributor
|
/ok to test b1f4532 |
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Contributor
|
/ok to test ac45c67 |
HuiyingLi
approved these changes
Aug 11, 2026
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds EAGLE-3 draft training for a frozen Kimi K3 target, the EAGLE counterpart to the DSpark support in #3263.
Re-opens #3264, which GitHub closed automatically when its base branch
huiyingl/feat/kimi-k3was merged and deleted. Same work, now re-targeted atmain; the review history lives on #3264.Kimi K3 interleaves KDA layers with NoPE MLA full-attention layers, so neither the dense EAGLE-3 draft nor the DeepSeek MLA draft (which always rotates the rope slice) can represent it:
o_proj(attn)o_projSituAndMulMLP, K3 fp32-variance RMSNormKimiK3Eagle3DraftModelmirrors exactly one K3 MLA layer (Q-LoRA, the compressed KV latent, the gate, the SiTU MLP); KDA, the 896 routed experts and the attention-residual mixer stay in the target. Everything EAGLE-3 specific (the[embed, hidden]fused first layer, thecache_hiddenTTT recurrence with diagonal extension,d2t/t2d,project_hidden_states/compute_logits) is inherited from the DeepSeek MLA draft through one new_build_inner_modelhook, so the trainer, the checkpointer and the serve-side contract are reused unchanged.Positional information reaches the draft through the target hidden states it is conditioned on, exactly as it reaches the target's own MLA layers;
test_forward_is_position_id_invariantpins that contract.Recipe wiring
K3 has no HuggingFace implementation and its experts do not fit on one GPU, so the colocated target is built from the (possibly nested) text config through AutoModel's custom expert-parallel path rather than the generic
from_pretrained. A vision-language checkpoint is loaded as its text-onlyKimiK3ForCausalLM; the target config is a copy, so the draft config serialized intoconfig.jsonis untouched.Combinations K3 cannot serve are rejected up front, before the 93-layer target is loaded: non-colocated backends (SGLang/vLLM/remote have no K3 implementation), context and tensor parallelism (K3 owns CP end to end and declares
supports_tp=False), pipeline parallelism (aux capture hooks one non-pipelined forward), sequence packing (K3 owns its packed-attention path), and P-EAGLE.The target's expert dispatcher defaults to
torch, the dispatcher K3's own SFT reference config runs expert parallelism with;deepep/hybridepstay opt-in throughtarget_dispatchersince they need a matching DeepEP build.Also here
freeze_embeddings()on the shared MLA draft base. The recipe calls it for every draft, and it was missing, sofreeze_embeddings: trueraisedAttributeErroron the DeepSeek draft too. It matters for K3: the draft copies a 163840 x 7168 embedding table.DeepseekV3Eagle3DraftModel.Testing
tests/unit_tests/speculative/test_eagle3_kimi_k3_draft.py(16 tests): forward/TTT/packing shapes, NoPE position invariance, the output gate, backbone composition, the GQA andmla_use_noperejections, the vocab-remap and embedding-copy API, registry resolution for both architectures, and end-to-end training through the sharedEagle3TrainerModule.tests/unit_tests/recipes/llm/test_eagle3_kimi_k3_target.py(16 tests): backend defaults and overrides, every gate, and the resultingfrom_configcall including the untouched draft base config.tests/unit_tests/speculative/andtests/unit_tests/recipes/llm/pass locally: the failure list is identical to the onemainproduces on its own (25test_benchmark.pyfailures from a local environment gap, unrelated to this PR).Re-targeting onto main
mainnow carries the merged K3 model, so this branch mergesmainand keeps main's version of every K3 file. One fix was needed on top:_setup_online_targetwithdraft_base_config=None, so the K3 gate reading.model_typeunconditionally raisedAttributeErrorbefore the backend dispatch. It now reads throughgetattr. This is covered by main'stest_eagle3_vllm_backend.py/test_eagle3_sglang_backend.py, which fail without it.