Kimi K2.5/2.6 LoRA + Megatron-LM backports for older runtime images - #5
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR brings Kimi K2.5/K2.6 grouped-expert LoRA support onto bridge-rebase-2026-05 and adds compatibility shims so the bridge can run against older Megatron-LM layouts (notably the radixark/miles:dev image) without requiring a container refresh.
Changes:
- Add “shared-outer” grouped-expert LoRA mode (
experts_shared_outer_loras) plus new adapter/linear wrappers and export logic for Kimi K2.5. - Backport Megatron-LM config imports by falling back to older
megatron.training.*_configmodule locations and inlining a stubDistributedInitConfigwhen needed. - Vendor a fallback
mimo.config.roleimplementation and guard MIMO imports to avoid ImportErrors on older Megatron-LM.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/megatron/bridge/peft/lora.py | Adds experts_shared_outer_loras flag and dispatch to shared-outer grouped-expert adapter/wrapper. |
| src/megatron/bridge/peft/lora_layers.py | Adds LoRAGroupedExpertLinear to plumb tokens_per_expert/splits through to adapters. |
| src/megatron/bridge/peft/utils.py | Implements shared-outer grouped-expert adapter machinery, stage-replicated gradient sync, and packed per-expert linear. |
| src/megatron/bridge/peft/canonical_lora.py | Allows linear_fc1 to fall back to an unfused adapter path for unsupported canonicalization cases. |
| src/megatron/bridge/models/kimi_vl/kimi_k25_vl_bridge.py | Overrides adapter export to HF to support mixed 2D/3D shared-outer grouped-expert LoRA weight layouts. |
| src/megatron/bridge/models/kimi_vl/utils.py | Fixes quantize_to_int4 device placement for weight_shape. |
| src/megatron/bridge/training/config.py | Adds try/except import fallback for older Megatron-LM config module layouts; backports DistributedInitConfig. |
| src/megatron/bridge/_compat/init.py | Introduces _compat package for vendored/compat symbols. |
| src/megatron/bridge/_compat/mimo_role.py | Vendors missing mimo.config.role (MIMO_LANGUAGE_MODULE_KEY, role/layout dataclasses). |
| src/megatron/bridge/data/megatron_mimo/dp_utils.py | Guards mimo.config.role import with fallback to vendored _compat module. |
| src/megatron/bridge/models/megatron_mimo/megatron_mimo_config.py | Guards mimo.config.role import with fallback. |
| src/megatron/bridge/models/megatron_mimo/megatron_mimo_ddp.py | Guards mimo.config.role import with fallback. |
| src/megatron/bridge/models/megatron_mimo/megatron_mimo_provider.py | Guards mimo.config.role import with fallback. |
| src/megatron/bridge/training/megatron_mimo_parallel_utils.py | Guards mimo.config.role import with fallback. |
| src/megatron/bridge/training/megatron_mimo_step.py | Guards mimo.config.role import with fallback. |
| src/megatron/bridge/training/train_megatron_mimo.py | Guards mimo.config.role import with fallback. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1542
to
+1543
| """:class:`ColumnParallelLinear` whose weight gradient is averaged across | ||
| the intra-PP-stage group in backward, keeping a logically-replicated |
Comment on lines
+1652
to
+1655
| if not hasattr(torch, "_grouped_mm"): | ||
| raise RuntimeError( | ||
| "PackedPerExpertLinear requires torch._grouped_mm (torch >= 2.9)." | ||
| ) |
Comment on lines
+101
to
+107
| experts_shared_outer_loras (bool): When True, grouped-expert LoRA | ||
| (``TE*ParallelGroupedLinear`` base modules) uses | ||
| :class:`SharedOuterGroupedExpertAdapter` — ``gate_up`` lora_A and | ||
| ``down`` lora_B are shared across experts (expert_dim=1), matching | ||
| SGLang's ``experts_shared_outer_loras=True`` serving contract (PR | ||
| #21466). Default False preserves the adapter layout selected by | ||
| ``share_expert_adapters``. |
Comment on lines
+146
to
+153
| def stream_adapter_weights_megatron_to_hf( | ||
| self, | ||
| megatron_model, | ||
| cpu: bool = True, | ||
| show_progress: bool = True, | ||
| ): | ||
| """Stream adapter weights with mixed-side emission for shared-outer grouped expert LoRA.""" | ||
| from megatron.bridge.models.conversion.model_bridge import HFWeightTuple |
yushengsu-thu
force-pushed
the
pr-3-kimi25-patch
branch
from
May 22, 2026 14:39
eb79709 to
9a9a0f4
Compare
…fig missing Wrap the nine `from megatron.training.config import ...` lines in a try/except. If the newer Megatron-LM layout (config dataclasses consolidated into the `megatron.training.config` package, introduced in commit 8b00c3c on 2026-03-30) is unavailable — e.g. when running against the older Megatron-LM bundled with the radixark/miles:dev image — fall back to the individual-file locations: - megatron.training.training_config: CheckpointConfig, LoggerConfig, SchedulerConfig, TrainingConfig, ValidationConfig - megatron.training.common_config: ProfilingConfig, RNGConfig - megatron.training.resilience_config: RerunStateMachineConfig, StragglerDetectionConfig DistributedInitConfig was added in the same migration commit and has no counterpart in the older layout, so we backport an inline stub mirroring the upstream definition.
Older Megatron-LM (e.g. radixark/miles:dev image) has megatron.core.models.mimo but is missing the config.role submodule. The seven bridge files that import MIMO_LANGUAGE_MODULE_KEY from it now wrap the import in try/except and fall back to a vendored copy at megatron.bridge._compat.mimo_role (verbatim copy of role.py from the Megatron-Bridge/3rdparty/Megatron-LM submodule). This unblocks loading megatron.bridge.training.config — and downstream bridge.models.megatron_mimo — against the older Megatron-LM, so non-MIMO training paths (qwen, etc.) can proceed without needing a docker image refresh.
…gatron-LM lacks it `from megatron.core.ssm.mamba_hybrid_layer_allocation import parse_hybrid_pattern` in `mamba_provider.py` fails on the `miles-main` branch of `radixark/Megatron-LM` (used in `radixark/miles:dev` docker image), because miles-main branched off NVIDIA upstream before MTP commit 300d1b655, which is when `parse_hybrid_pattern` was added to `megatron.core.ssm.mamba_hybrid_layer_allocation`. The failure blocks `from megatron.bridge.models import ...` at module-load on every Bridge consumer (gpt-oss-20b, Qwen, Kimi LoRA training), because `models/__init__.py:117` imports `nemotron_vl`, which then imports `mamba_provider`, which fails at its module-level import. `parse_hybrid_pattern` is only used inside method bodies for hybrid/Mamba layer parsing; non-Mamba consumers (gpt-oss MoE, Qwen, Kimi) never hit those code paths. So degrade `parse_hybrid_pattern` to None on ImportError — module loads, non-Mamba paths keep working, Mamba consumers get a clear `'NoneType' is not callable` at call-site instead. Same pattern as c41bfdc (megatron.training.config) and 6326bf5 (mimo.config.role): patch root-cause module-level imports rather than every downstream consumer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
yushengsu-thu
force-pushed
the
pr-3-kimi25-patch
branch
from
May 25, 2026 04:12
9a9a0f4 to
a812b48
Compare
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.
Summary
This PR is a follow-up to (and superset of) #3 — it brings the Kimi K2.5/K2.6 LoRA support onto
bridge-rebase-2026-05and adds two small backport shims so the same code can run against the older Megatron-LM bundled inradixark/miles:devwithout requiring a container refresh.It contains three commits, applied in this order on top of
bridge-rebase-2026-05:ff33f80support kimi 2.5/6 lora(logprob diff exist)c41bfdcbackport: try old Megatron-LM import paths when megatron.training.config missingtraining.configlayout6326bf5backport: vendor megatron.core.models.mimo.config.rolemegatron.core.models.mimo.config.roleNet diff: 16 files, +1,107 / −18.
1. Kimi K2.5/K2.6 LoRA (commit
ff33f80)Ports Nan's Kimi K2.5/K2.6 grouped-expert LoRA work onto this rebase. The K2.5 backbone is an MoE with MLA, and the new adapter machinery is needed so that LoRA can be applied to the grouped-expert linears (
TEColumnParallelGroupedLinear/TERowParallelGroupedLinear) while remaining compatible with SGLang's serving contract.src/megatron/bridge/peft/lora.py— addsexperts_shared_outer_loras: bool = FalsetoLoRA. WhenTrue, grouped-expert LoRA uses the newSharedOuterGroupedExpertAdapter:gate_uplora_Aanddownlora_Bare shared across local experts (expert_dim=1), matching SGLang PR #21466'sexperts_shared_outer_loras=Truecontract. DefaultFalsepreserves the existing layout selected byshare_expert_adapters. Op-fuser is disabled for the shared-outer path.src/megatron/bridge/peft/lora_layers.py— addsLoRAGroupedExpertLinear(subclass ofLoRALinear) that plumbstokens_per_expert/m_splitsfrom the grouped-MLP forward into the adapter so the per-expertGroupedLinearside can run.src/megatron/bridge/peft/utils.py(+415 lines) — the main payload:SharedGradAllReduceautograd function: identity forward, SUM-allreduce in backward across the intra-PP-stage group (tensor_and_data_parallel_groupwith CP). Keeps a logically-replicated weight in sync across EP replicas that neitherallreduce=Truenorallreduce=Falsecovers. SUM (not AVG) is correct: with N EP replicas each holding a partial loss-grad over its (token, expert) subset, total grad isΣ_r g_r; AVG would train at 1/N the intended rate.broadcast_across_intra_stage_group(weight): one-shot broadcast from group rank 0 on adapter__init__so per-rank-initialized weights start bit-identical.StageReplicatedColumnParallelLinear/StageReplicatedRowParallelLinear: ColumnParallel/RowParallel linears whose weight gradient is averaged across the intra-PP-stage group in backward (viaSharedGradAllReduce). Used withis_expert=Trueso the underlying TP group is the ETP group;allreduce=Falseis set automatically and the cross-EP axis is covered bySharedGradAllReduce.SharedOuterGroupedExpertAdapter: the new adapter class with mixed shapes —fc1has 2D sharedlora_A(hidden→rank) and 3D per-expertlora_B([N_local, 2*intermediate, rank]);fc2has 3D per-expertlora_Aand 2D sharedlora_B.HAVE_TE_COL_GRP_LINEAR/HAVE_TE_ROW_GRP_LINEARand TE grouped-linear class re-exports solora.pycan dispatch.src/megatron/bridge/peft/canonical_lora.py— whenlinear_fc1is matched but cannot be safely canonicalised (gate/up unfused with grouped-expert), fall through to an unfusedParallelLinearAdapterwrapped inLoRALinearrather than asserting.src/megatron/bridge/models/kimi_vl/kimi_k25_vl_bridge.py(+325 lines) — overridesstream_adapter_weights_megatron_to_hfonKimiK25VLBridgebecause the baseMegatronPeftBridgeemission can't handle the mixed 2D/3D shared-outer layout:_is_fused_fc1_gate_up: accepts 3D per-expertlinear_out([N_local, 2*intermediate_per_tp, rank]) in addition to the upstream 2D case._gather_expert_adapter_weight/_select_expert_adapter_weight: EP-aware gather/slice that handles both 2D (shared across experts) and 3D (per-expert packed) tensors.[1, …, …]under the.weight0HF name; per-expert side emitsNtimes under.weight0..weightN-1. Output matches SGLang's expected on-disk LoRA layout for the K2.5 grouped-expert path.src/megatron/bridge/models/kimi_vl/utils.py— small bug fix:quantize_to_int4now pinsweight_shapetoweight.device(previously stayed on CPU and tripped device-mismatch when called from CUDA code).2. Older Megatron-LM
training.configbackport (commitc41bfdc)src/megatron/bridge/training/config.pydoesfrom megatron.training.config import ...for nine config dataclasses. Upstream Megatron-LM commit8b00c3ce(2026-03-30) consolidated these into a newmegatron.training.configpackage, but the Megatron-LM bundled insideradixark/miles:devpredates that commit and still has the dataclasses scattered across individual modules. Result: importingmegatron.bridge.training.configblows up withImportError, which transitively blocks every recipe (qwen, gpt-oss, …) on that image.Fix: wrap the import block in
try/except ImportErrorand fall back to the older locations:megatron.training.training_config:CheckpointConfig,LoggerConfig,SchedulerConfig,TrainingConfig,ValidationConfigmegatron.training.common_config:ProfilingConfig,RNGConfigmegatron.training.resilience_config:RerunStateMachineConfig,StragglerDetectionConfigDistributedInitConfigwas added in commit8b00c3ceand has no counterpart on the older layout, so we inline a backport dataclass that mirrors the upstream definition field-for-field (kept in sync with newer Megatron-LM).Net effect: zero behaviour change on the newer Megatron-LM (the
trybranch succeeds), andmegatron.bridge.training.configbecomes importable on the older one.3. MIMO
config.rolevendored backport (commit6326bf5)The same older Megatron-LM has
megatron.core.models.mimobut is missing theconfig.rolesubmodule that newer bridge code imports (MIMO_LANGUAGE_MODULE_KEY). Seven bridge files transitively import it, and even non-MIMO training paths trip on it when importingmegatron.bridge.training.config→megatron.bridge.models.megatron_mimo.Fix: vendor a verbatim copy of
role.pyfrom the Megatron-LM submodule atsrc/megatron/bridge/_compat/mimo_role.py(+167 lines), add the_compatpackage init explaining its purpose, and wrap each of the seven import sites intry/except ImportError:Sites updated:
src/megatron/bridge/data/megatron_mimo/dp_utils.pysrc/megatron/bridge/models/megatron_mimo/megatron_mimo_config.pysrc/megatron/bridge/models/megatron_mimo/megatron_mimo_ddp.pysrc/megatron/bridge/models/megatron_mimo/megatron_mimo_provider.pysrc/megatron/bridge/training/megatron_mimo_parallel_utils.pysrc/megatron/bridge/training/megatron_mimo_step.pysrc/megatron/bridge/training/train_megatron_mimo.pyNet effect: zero behaviour change when running against a Megatron-LM that already ships
mimo.config.role; on older runtimes the vendored copy unblocks the import chain so non-MIMO recipes (qwen, gpt-oss, kimi, …) can proceed without needing a docker image refresh.Relationship to PR #3
PR #3 (
nanjiangwill:kimi25→bridge-rebase-2026-05) is the original Kimi K2.5/K2.6 contribution. This PR carries the same LoRA payload (commitff33f80) plus the two backport shims (commitsc41bfdc,6326bf5) so the result is runnable on theradixark/miles:devimage.If #3 lands first, this PR can be re-targeted onto the resulting tip and the diff will shrink to just the two backport commits. If this PR lands first, #3 can be closed or rebased.
Compatibility matrix
training.configpackagemimo.config.role8b00c3ce)radixark/miles:devbundledTest plan
python -c \"import megatron.bridge.training.config\"succeeds on both the upstream NeMo container andradixark/miles:dev.experts_shared_outer_loras=Trueconverges and adapter export produces SGLang-compatible weights.qwen2.5-0.5B,gpt-oss-20B) are unaffected (experts_shared_outer_lorasdefaults toFalse).bridge-rebase-2026-05.Made with Cursor