transformers
b6d5084f - Add AXK2 from SKT (#47528)

Commit
31 days ago
Add AXK2 from SKT (#47528) * Add A.X K2, the SKT's flagship LLM * Add fused gate * fix code from bug of the attention_mask is None case * delete redundant comment * change several default config values * refactor AXK2 to inherit from deepseek_v3/v32 and address review feedback - indexer: inherit DeepseekV32Indexer; key cache moved out of the module into the shared Cache (past_key_values.update_indexer backed by DynamicIndexedLayer/StaticIndexedLayer, dispatched via config.layer_types=deepseek_sparse_attention); stateful prefill reset removed - MoE: router inherits DeepseekV32TopkRouter with a non-grouped top-k forward (released model ships n_group=None); routing now lives inside the router; experts inherit the stacked-3D implementation (@use_experts_implementation, expert-parallel friendly) - attention: inherit DeepseekV3Attention; single canonical path — q LoRA always on, interleaved RoPE imported from deepseek_v3, output gate always applied via linear_gate - fused checkpoint layout is handled at load time by the new SplitFusedAttentionGate weight converter (splits the block-diagonal q_b_proj into q_b_proj + linear_gate, re-fused on save); the split is lossless and removes all runtime fused/unfused branches - SGA no longer forces eager attention: the indexer top-k is folded into an additive sparse mask consumed by eager and SDPA; _supports_sdpa=T flash/flex disabled (same as deepseek_v32) - config: mlp_layer_types / layer_types are computed in the config; rope_interleave / gated_norm / attention_output_gate toggles removed (single released architecture) * change model type to snake case, and rebase * refactor AXK2 to inherit from deepseek_v3.2 and address review feedback - config: rewrite in @strict style inheriting DeepseekV32Config (class-level typed attributes, __post_init__ for derived fields, automatic docstring); drop pretraining_tp / moe_layer_freq / the rope-float override; attribute_map = {"num_local_experts": "n_routed_experts"}; inherit base_model_ep_plan - inherit the DSA stack from deepseek_v3.2 (AXK2Indexer / AXK2Attention / AXK2DecoderLayer / AXK2PreTrainedModel / AXK2Model / AXK2ForCausalLM), overriding only the A.X-K2 deltas - gated RMSNorm reuses CLIPMLP (bias-free, SiLU, gated_norm_rank); gate weights bridged W_down/W_up -> mlp.fc1/fc2 by the converter - indexer key LayerNorm eps set explicitly to 1e-5; indexer reads the pre-norm q - attention output gate renamed linear_gate -> g_proj; validate q_lora_rank is set - rename fused-checkpoint conversion op SplitFusedAttentionGate -> SplitFusedMLAGate (+ FuseMLAGate reverse) - _keys_to_ignore_on_load_unexpected = ["inv_freq"]; drop the legacy "AXK2" -> "axk2" conversion alias (model unreleased; aligned on model_type="axk2") - add docs (model_doc/axk2.md + toctree) and tests/models/axk2 - bump copyrights to 2026 Verified on the release-candidate light checkpoint: loads with no missing/unexpected keys and greedy generation is identical to the pre-refactor implementation ("대한민국의 수도는" -> " 서울입니다. 서울은 대한민국의 정치, 경제, 문화의 중심지로"). * address second review round: tests, MiniMax router, config cleanup - tests: add tests/models/axk2 (AXK2ModelTest(CausalLMModelTester) fast tests + slow integration) and SplitFusedMLAGate / FuseMLAGate unit tests in tests/utils/test_core_model_loading.py - router: inherit MiniMaxM2TopKRouter (non-grouped sigmoid) instead of DeepseekV32TopkRouter, keeping e_score_correction_bias on the router and fp32 routing (forward math unchanged) - config: drop n_group / topk_group / first_k_dense_replace via AttributeError(); mlp_layer_types is derived from the legacy first_k_dense_replace / moe_layer_freq kwargs in __post_init__ - attention: drop the runtime q_lora_rank check (q_lora_rank: int is enforced by @strict at config construction) - decoder: post_attention_layernorm written as a ternary - docs: drop dtype/device_map from the examples (auto under the hood) * fix converter round-trip + skip DSA-incompatible generation tests - SplitFusedMLAGate: pass an already-unfused q_b_proj through unchanged (only the fused vLLM layout is split), so save/load round-trips work and g_proj loads from its own key; add a passthrough unit test in tests/utils/test_core_model_loading.py - skip static-cache / compile generation tests (the SGA indexer mask uses a dynamic cache length), mirroring glm_moe_dsa Full fast suite on GPU: 113 passed, 2173 subtests passed, 146 skipped (deepspeed deselected — this env lacks mpi4py; they run in CI). * address final review: config super() trick, op refactor, test cleanup - config: call PreTrainedConfig.__post_init__/validate_architecture directly instead of super() so only A.X-K2's own derivations run (drops the duplicated DeepSeek-V3.2 __post_init__ block); validate_architecture now requires a positive q_lora_rank - router (AXK2TopkRouter): unpack `_, topk_indices = torch.topk(...)` and comment the only deltas over MiniMax-M2 (optional top-k norm + routed scaling) - core_model_loading: SplitFusedMLAGate/FuseMLAGate follow PermuteForRope (self.config attribute + separate _split/_fuse application methods) - unquote AXK2Config type annotations - tests: drop n_group/topk_group/first_k_dense_replace from the tester (derive mlp_layer_types); remove vestigial pipeline_model_mapping/fx_compatible/ test_torchscript; move AXK2_CHECKPOINT to an integration-test class attribute; wrap expected text in Expectations; replace test_sdpa_matches_eager_generation with test_logits; fold the fused-gate op test into TestConvertAndLoadStateDict via a dummy-model load path (no standalone TestCase). Re-checked the padding skips on GPU — they still fail (DSA selection flips past index_topk), kept skipped. * self-contained integration tests pushed, ready for your local CI; logits Expectations recorded on A100 so a GPU-specific key may need adding * use a small randomized checkpoint for integration tests * address review: g_proj TP plan entry, TP-shard-safe gate converter, adopt expand_kv, cleanup - add `layers.*.self_attn.g_proj: colwise` to the TP plan (the output gate emits one scalar per attention-output column, so it shards with the heads) - fix SplitFusedMLAGate/FuseMLAGate to derive the head count from the tensor shape: under tensor parallelism the conversion runs on each rank's head-aligned row shard, and the config-derived head count crashed on it; add a row-shard unit test - verify TP end to end: 2-GPU DistributedConfig(tp_size=2) smoke test vs a single-GPU reference — max |logit diff| 1.2e-7, greedy tokens identical - adopt the `expand_kv` split from #47460; bit-identical logits and greedy tokens on a seeded tiny model before/after - regenerate from modular: picks up yarn_apply_mscale and the causal_mask_mapping API from the rebased parents (generated files were stale) - drop the two converter-workaround comments flagged in review - tester: mlp_layer_types = ["dense", "sparse"] (shared tester default is 2 layers) - spell out abbreviated variable names in the MLA-gate loading tests * fix output_capturing dynamo NameError + point integration tests at hf-internal-testing/tiny-axk2 * support fused attention gate (attn_gate_fused) + grouped routing for A.X-K2 releases The released A.X-K2 checkpoints (e.g. A.X-K2-Preview) ship the attention output gate fused into `q_b_proj` (vLLM block-diagonal layout) and use DeepSeek-V3-style grouped expert routing. - attn_gate_fused config flag: keep `q_b_proj` fused and split the activation in the forward (matches the reference/vLLM kernel), instead of splitting the weight at load. Required for the fp8 releases, whose 128-block scales cannot be split along the per-head query/gate boundary; the fused matrix is 128-aligned and loads directly. The unfused SplitFusedMLAGate path stays for bf16 checkpoints. - filter_checkpoint_conversions hook: a model can drop registered conversions that don't apply to its config (the mapping is keyed by model_type and can't see config). A.X-K2 drops the SplitFusedMLAGate converter when attn_gate_fused, so fp8 loading doesn't trip the merge-only scale-folding / many-to-many arity guard. - n_group/topk_group grouped routing (0.0 group masking, matching the SKT reference), with validate_architecture pairing/divisibility checks; conversion mapping stacks per-expert projections. - tests: grouped router vs reference, fused-gate layout + save/load roundtrip, hub-layout roundtrip. Verified bit-identical to the SKT reference implementation on the Preview architecture (grouped + fused gate + SGA sparse); Light non-grouped parity unchanged. Native fp8 GEMM needs a compute-capability >= 8.9 GPU to exercise (A100 force-dequantizes fp8 to bf16), so the fp8 inference path should be confirmed on CI hardware. * keep the attention output gate fused (q_gate_proj) instead of splitting at load Per review: the split-at-load path doesn't make sense given the released checkpoints are fused (and fp8, which can't be split), so drop it and always use the fused variation under a clearer name. - AXK2Attention keeps the query up-projection and output gate fused in a single `q_gate_proj` (doubled input -> per-head [query | gate]) and splits the activation in the forward, matching the vLLM-style released layout. Renamed from `q_b_proj` since it also carries the gate. - drop SplitFusedMLAGate/FuseMLAGate and the two-path `attn_gate_fused` flag entirely; the checkpoint's `q_b_proj` is a plain 1->1 rename to `q_gate_proj` on load (fp8-safe: no weight split, and the prefix renames the `weight_scale_inv` companion too). Reverses to `q_b_proj` on save. - AXK2Attention is standalone (nn.Module) rather than inheriting DeepseekV32Attention, so there is no leftover `q_b_proj` from the parent's conditional q-projection. - TP: the per-head activation split uses `-1` (not the global head count) so colwise sharding of `q_gate_proj` (each rank holds whole heads) stays correct. Verified: fused forward is bit-identical to the SKT reference on the Preview architecture (grouped routing + fused gate + SGA); fp8 checkpoint loads and matches bf16 within quant error; 2-GPU tp_plan="auto" matches the single-GPU reference (max |logit diff| 1.2e-7). Light parity unchanged. * fix repo and fixup modular + clean tests * rm this * repo fixes * add integration test (depends on upstream main axk1 merge) * fix * try fixing --------- Co-authored-by: minsangkim <kmswin1@sktelecom.com>
Author
Parents
Loading