[lora] declarative layouts, support-status registry - #2072
Merged
Zhichenzzz merged 15 commits intoAug 2, 2026
Conversation
…scriptors Function-level redesign of miles_plugins/lora on top of the #2017 layout, aimed at one-declaration support for new models: - spec/attach.py + spec/dims.py: architecture layouts become ProjectionBinding/ FusedAttach tables walked by one shared attach_layout(); dims.py is the only spec-side reader of MCore attribute names. GQA/MLA/fused-MLP specs are now tables; adapter attribute names are pinned (checkpoint keys unchanged). - registry.py: ModelEntry(spec, status, reason) with VALIDATED/STRUCTURAL/ UNSTABLE folds _RAW_MODE_BACKWARD_UNSTABLE and validation tribal knowledge into one field; adds default_target_modules() and preflight_native_lora() so launchers stop re-declaring family facts (preflight catches registered-but-unconvertible gaps like kimi_k25-without-a-bridge upfront). - modules/linear.py: adapters expose exports() -> ProjectionExport (with SGLangFusedGroup metadata); codec/sglang.py rewritten on the public descriptor - no more _active/_rows private access or isinstance ladders; the MLA fused_qkv_a special case is now a ServingGroup declaration in the MLA table. - spec/moe.py: validate_layer returns skipped targets; the orchestrator logs once per run (kills the module-global warn flag). - distributed.py: marked-grad cache moves onto the model chunk (id-keyed module-global could outlive rebuilt models). - miles_plugins/mbridge/kimi_k25.py: Kimi-K2.5 conversion bridge (DeepseekV3Bridge + text_config descent + language_model. prefix). - scripts/run_glm5_2_744b_a40b_lora_native.py: GLM-5.2 native (raw-mode) launcher; both native launchers now preflight before GPU work. tests/fast/miles_plugins/lora: 47 passed (baseline 47).
…names _convert_to_hf_core matched only the underscore spelling kimi_k25, but the direct HF weight iterator passes the config class name (kimik25config), so raw-mode K2.5 runs died at the first weight sync. Also accept the raw text-only provider's unprefixed embedding/output/final_layernorm names in convert_language_model_to_hf (the VL trainer's language_model. prefix is absent there; HF names keep the multimodal shell prefix either way).
gsm8k-length sequences (< index_topk=2048 keys) crash torch.topk with 'selected index k out of range' in raw-mode log-prob compute; the serving indexer clamps to context length. Pad the clamped result with -1, the existing invalid-index convention.
qwen3_5_moe, glm_moe_dsa -> VALIDATED (20-rollout native runs, logprob_abs_diff 0.0105 / 0.0096). kimi_k25 -> UNSTABLE with the measured raw-mode forward divergence vs SGLang (weights proven bit-identical; suspect mcore-MLA runtime numerics).
…s raw path verified correct
A surviving quantization_config sends SGLang through its CompressedTensors path, which serves the BF16 checkpoint with a degenerate context-free forward (identical next-token distribution at every position). Verified: overriding quantization_config to null restores per-position agreement with both the megatron raw forward and an HF-transformers reference (~0.01-0.05 logprob).
…0124 after the quantization_config strip fix
Per review feedback: SCREAMING-case module constants (QKV_PROJECTIONS + GQA_TARGETS pairs, _QKV_NAMES/_FC1_NAMES/_MLA_A_NAMES copies in two codecs, GQA/MLA family strings, singleton spec instances, _CANONICAL_ATTENTION_TARGETS) each duplicated a fact that some class already knew. Now: - specs are a hierarchy (LayoutSpec -> AttentionSpecBase -> GQA/MLA/GDN, HybridGQAGDN(GQAAttentionSpec), SharedOuterExpertMoESpec(GeneralExpert...)); each class declares its projections once, inline in its layout class attr. - supported_targets, canonical --target-modules order, and SGLang fused families all DERIVE from that declaration (registry.serving_fused_families feeds expand_sglang_target_modules, so a new layout extends serving expansion automatically). - split adapters take member projections from their FusedAttach instead of hardcoded name maps; MoE specs get MLP target names by injection. - ShardLayout / AttentionFamily str-enums replace bare 'column'/'gqa' strings. - no module-level spec singletons: instances are assembled in registry._build_model_specs(). tests/fast/miles_plugins/lora: 47 passed (baseline 47).
… generics - drop the COLUMN/ROW/REPLICATED alias line; call sites use ShardLayout.* (the enum definition is now the only place the strings exist). - MLA's _GENERIC_QKV_TARGETS derives from GQAAttentionSpec.layout.fused_targets (the parser's all-linear names ARE the GQA split-QKV names) instead of restating them. - inline the single-use HF-naming fallback defaults into resolve_hf_naming. Kept deliberately: _MLA_A_SERVING_GROUP (a named part of MLA's own layout declaration, referenced by two bindings) and codec/checkpoint.py's _MODEL_CHUNK_PREFIX (the checkpoint key format's single source of truth, private to its module) - neither duplicates a fact owned elsewhere. tests/fast/miles_plugins/lora: 47 passed.
…se comments - LoRASplitQKV / LoRASplitFC1 collapse into a LoRASplitAdapter base that owns the parameter layout, fused-drain forward, absent-slot zero-fill, and export descriptor; subclasses keep only their slot geometry and output packing (~90 duplicated lines gone). Per-projection export emission is shared in NativeLoRAAdapter._export_projections. - delete unused attach_layouts; fold single-caller resolve_registered_model_spec into _resolve_registered_entry. - trim registry evidence comments to one-liners and other commentary noise. tests/fast/miles_plugins/lora: 47 passed.
Zhichenzzz
requested review from
Shi-Dong,
fzyzcjy,
maocheng23,
yueming-yuan and
yushengsu-thu
as code owners
August 2, 2026 22:22
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
…he PR description)
… package - spec/layout.py now holds the whole declarative-layout mechanism: dimension resolvers (still the only spec-side reader of MCore attribute names), binding/group dataclasses, the attach walk, and the spec base classes. - codec/ was an uncommon name for three files that share no code; they move to the plugin root under conventional names: hf.py -> hf_adapter.py (HF/PEFT naming + import/export), sglang.py -> serving.py, checkpoint.py -> checkpointing.py.
This was referenced Aug 2, 2026
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.
Stacked on #2017 (base:
yusheng/lora-plugin-refactor). Keeps that PR's package layout; redesigns the function-level contracts so supporting a NEW model natively is a one-declaration exercise, plus the fixes found while validating four models end-to-end.Redesign
Classes carry the taxonomy; every fact is declared once and derived everywhere else.
spec/attach.py,spec/dims.py): an architecture spec is a class holding aModuleLayouttable — which projections exist, on which physical linear, with which shard geometry. One sharedattach_layout()implements the existence-check → target-filter → guard → build → hook walk;spec/dims.pyis the only spec-side reader of MCore attribute names. MLA's attach went from ~90 imperative lines to a table; a new layout is ~15 lines of facts.LayoutSpec→AttentionSpecBase→GQA/MLA/GDN,HybridGQAGDN(GQAAttentionSpec),SharedOuterExpertMoESpec(GeneralExpertMoESpec)):supported_targets, the canonical--target-modulesorder, and SGLang's fused-family expansion all derive from the layout declaration.registry.serving_fused_families()feedsexpand_sglang_target_modules, so a new architecture's fused groups reach serving-side expansion automatically.ShardLayout/AttentionFamilystr-enums replace the bare"column"/"gqa"strings; the parallel name tables that used to live incodec/sglang.pyandmodules/linear.pyare gone (split adapters take member projections from theirFusedAttach; MoE specs get MLP target names by injection).ModelEntry(spec, status, reason)withVALIDATED / STRUCTURAL / UNSTABLE: support status becomes one first-class field instead of_RAW_MODE_BACKWARD_UNSTABLEplus comments. Entries record this branch's e2e evidence.exports() -> ProjectionExport(withSGLangFusedGroupmetadata);codec/sglang.pyis rewritten on that API — no more_active/_rowsprivate access or isinstance ladders; the MLAfused_qkv_aspecial case is aServingGroupdeclaration in the MLA table.default_target_modules(hf_checkpoint)andpreflight_native_lora(...)(registry ∧ mbridge bridge ∧ model-args audit, no GPU) —run_lora_native.pystops re-declaring per-family target strings and fails in seconds instead of deep inside torchrun when a conversion bridge is missing.LoRASplitQKV/LoRASplitFC1collapse into a sharedLoRASplitAdapter; the marked-grad cache moves onto the model chunk (the id-keyed module global could outlive rebuilt models); MoE's module-level warn flag becomes a per-run report.Fixes found by running four models natively
miles_plugins/mbridge/kimi_k25.py(new): mbridge has no Kimi bridge, so raw-mode K2.5 conversion was impossible (bridge mode uses megatron.bridge's ownKimiK25VLbridge and never converts). ThinDeepseekV3Bridgesubclass:text_configdescent +language_model.prefix remap; vision weights are skipped by pull-based loading.megatron_to_hfkimi dispatch:_convert_to_hf_corematched onlykimi_k25, but the direct weight iterator passes the config class namekimik25config(dead branch); the converter also lacked the raw text-only provider's unprefixed embedding/output/final-layernorm names.convert_kimi_int4_to_bf16.pystripsquantization_config: a surviving one sends SGLang through its CompressedTensors path, which serves the BF16 checkpoint with a degenerate context-free forward (identical next-token distribution at every position) — rollouts are garbage and train/rolloutlogprob_abs_diffsits at ~2.2. Verified by a megatron-vs-HF-vs-SGLang three-way logprob comparison; with the config stripped all three agree.torch_dsa_topkclamps k to the key length: gsm8k-length sequences (<index_topk=2048 keys) crashedtorch.topkin raw-mode log-prob compute; pads with-1, the existing invalid-index convention.run_glm5_2_744b_a40b_lora_native.py(new): raw-mode GLM-5.2 launcher (the existing LoRA script is bridge-only). Its toy conversion must be single-rank: the convert tool pipeline-shards across its ranks, and any PP split of the 5-layer toy starts a stage on a DSA skip layer.Validation
20-rollout native GRPO runs (wandb
ch271828n-team/miles_lora_native), acceptance ≈ 0.01 train/rolloutlogprob_abs_diff:qwen3_5_moeflipped to VALIDATED)tests/fast/miles_plugins/lora: 47 passed at every step (baseline 47). Behavior-preservation smoke: a 2-rollout Qwen3-8B run on this branch reproduces the baseline's first-rollout logprob_abs_diff (0.00967 vs 0.00978). Adapter attribute names are pinned, so checkpoint keys are unchanged.🤖 Generated with Claude Code