Files
losewayy a02efe36b5 [feat](kt-kernel): add AVX2 RAWINT4 routed-expert LoRA SFT backend (#2243)
* [feat](kt-kernel): add AVX2 RAWINT4 routed-expert LoRA SFT backend

* [fix](kt-kernel): fix RAWINT4 SFT wrapper and clamp gradients

Allow the RAWINT4 production wrapper on AVX2 runtimes and reject shared backward pools before construction. Preserve FP32 clamp decisions across BF16 caches, remove unused configuration state, and cover rectangular dimensions, multiblock dX, clamp boundaries, and production wrapper tasks with tighter LoRA gradient checks.

* [fix](kt-kernel): plumb swiglu_limit through the RAWINT4 SFT python path

The production wrapper hard-zeroed swiglu_limit for every format except MXFP4, and both SFT python gates rejected non-zero values for RAWINT4 even though MOESFTConfig carries the field and the AVX2 kernel implements the clamp in forward plus the gradient mask in backward. RAWINT4_SFT now accepts a finite non-negative swiglu_limit end to end, while the AMX K2 part (which computes plain SiLU) fails fast instead of silently dropping the clamp. The production-wrapper contract test is parametrized over swiglu_limit 0 and 2, a model-config plumb test covers plain and nested text_config shapes, the __main__ entry exercises both limits, and bench_rawint4_sft.py gains --swiglu-limit.
2026-10-12 19:30:24 +08:00

1459 lines
62 KiB
Python

# Model wrapping entry points for SFT
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import gc
import importlib.util as _u
import json
import logging
import os
from pathlib import Path
from typing import Any
import torch
import torch.nn as nn
from .arch import (
KTAMXConfigError,
KTAMXNotAvailableError,
_get_layers_prefix,
_get_model_container_and_layers,
get_moe_arch_config,
get_moe_module,
)
from .layer import KTMoELayerWrapper, KTRoutedExpertsWrapper
from .lora import LoRAExperts
from .base import _supports_authoritative_optimizer_grads
from .backend import (
FP8_BACKEND,
INT8_BACKEND,
MXFP4_BACKEND,
MXFP4_SFT_METHOD,
RAWINT4_BACKEND,
RAWINT4_GROUP_SIZE,
RAWINT4_SFT_METHOD,
RAWINT4_WEIGHT_LAYOUT,
get_fp8_runtime,
get_int8_runtime,
get_mxfp4_runtime,
get_rawint4_checkpoint_contract,
get_rawint4_runtime,
)
from .checkpoint import load_full_weight_layer, resolve_full_weight_checkpoint
from .conv3d_compat import patch_vlm_conv3d
from .dist_utils import _distributed_rank_world_size
from .weights import (
_clear_original_expert_weights,
extract_moe_weights,
load_block_fp8_experts_from_checkpoint_files,
load_experts_from_checkpoint_files,
load_rawint4_experts_from_checkpoint_files,
)
logger = logging.getLogger(__name__)
KT_KERNEL_AVAILABLE = _u.find_spec("kt_kernel") is not None
if KT_KERNEL_AVAILABLE:
try:
from kt_kernel.experts import KTMoEWrapper
except Exception:
KTMoEWrapper = None
KT_KERNEL_AVAILABLE = False
else:
KTMoEWrapper = None
def _supports_checkpoint_forward_reuse(full_weight_grad: bool, lora_rank: int) -> bool:
return (full_weight_grad and lora_rank == 0) or (not full_weight_grad and lora_rank > 0)
def _validate_rawint4_activation_policy(expert_weight_format: str | None, activation_policy: Any) -> None:
"""Keep ordinary caching distinct from checkpoint-forward reuse."""
if expert_weight_format == "rawint4" and activation_policy.cpu == "retain" and activation_policy.gpu == "recompute":
raise KTAMXConfigError(
"RAWINT4 SFT v1 supports activation_policy cpu=retain,gpu=retain "
"for ordinary forward/backward caching, but checkpoint-forward reuse "
"(cpu=retain,gpu=recompute) is not supported"
)
def _native_fp8_block_size(model_config: Any) -> tuple[int, int]:
"""Read and strictly validate the checkpoint's native FP8 contract."""
text_config = getattr(model_config, "text_config", None)
quant_config = getattr(model_config, "quantization_config", None)
if quant_config is None and text_config is not None:
quant_config = getattr(text_config, "quantization_config", None)
if quant_config is None:
raise KTAMXConfigError(
"native FP8 SFT requires model quantization_config metadata"
)
def read(name: str):
if isinstance(quant_config, dict):
return quant_config.get(name)
return getattr(quant_config, name, None)
quant_method = str(read("quant_method") or "").lower()
if "fp8" not in quant_method:
raise KTAMXConfigError(
"native FP8 SFT requires an FP8 checkpoint, got "
f"quant_method={quant_method!r}"
)
block_size = read("weight_block_size")
if block_size is None:
block_size = read("weight_block_shape")
if block_size is None or tuple(block_size) != (128, 128):
raise KTAMXConfigError(
"native FP8 SFT requires weight_block_size=[128, 128], "
f"got {block_size!r}"
)
return (128, 128)
def _resolve_raw_safetensors_checkpoint_files(
model_name_or_path: str,
) -> tuple[list[str] | None, dict | None]:
"""Resolve raw safetensors, including a dependency-light local fallback."""
resolved_files, resolved_metadata = _resolve_checkpoint_files(
model_name_or_path=model_name_or_path
)
if resolved_files and all(str(path).endswith(".safetensors") for path in resolved_files):
return [str(path) for path in resolved_files], resolved_metadata
checkpoint_path = Path(model_name_or_path)
if checkpoint_path.is_file() and checkpoint_path.suffix == ".safetensors":
return [str(checkpoint_path)], None
if not checkpoint_path.is_dir():
return None, None
index_path = checkpoint_path / "model.safetensors.index.json"
if index_path.is_file():
with index_path.open(encoding="utf-8") as handle:
metadata = json.load(handle)
weight_map = metadata.get("weight_map")
if not isinstance(weight_map, dict) or not weight_map:
raise KTAMXConfigError(
f"invalid safetensors index without weight_map: {index_path}"
)
files = sorted(
{str(checkpoint_path / filename) for filename in weight_map.values()}
)
missing = [path for path in files if not os.path.isfile(path)]
if missing:
raise FileNotFoundError(
f"safetensors index references missing shard: {missing[0]}"
)
return files, metadata
files = sorted(str(path) for path in checkpoint_path.glob("*.safetensors"))
return (files, None) if files else (None, None)
def _sync_rank0_wrap_error(
error: BaseException | None,
*,
context: str,
rank: int,
world_size: int,
) -> None:
"""Make a rank-0-only wrapping stage fail coherently on every rank."""
if world_size <= 1:
if error is not None:
raise error
return
import torch.distributed as dist
if not dist.is_initialized():
if error is not None:
raise error
return
payload = [
None
if error is None
else f"{type(error).__name__}: {error}"
]
dist.broadcast_object_list(payload, src=0)
if payload[0] is None:
return
if rank == 0 and error is not None:
raise error
raise RuntimeError(f"{context}: rank 0 failed: {payload[0]}")
# =============================================================================
# Device-map builders
# =============================================================================
def _get_kt_config(kt_plugin: Any):
"""Resolve a private KTConfig from a compatible public container."""
from .config import KTConfig
if isinstance(kt_plugin, KTConfig):
return kt_plugin
return KTConfig.from_object(kt_plugin)
def _device_map_model_contract(config: Any) -> tuple[int, str, str, str]:
"""Resolve text-layer count and non-layer module paths for device maps."""
text_config = getattr(config, "text_config", None)
effective_config = text_config if text_config is not None else config
num_layers = getattr(effective_config, "num_hidden_layers", None)
if isinstance(num_layers, bool) or not isinstance(num_layers, int) or num_layers <= 0:
raise KTAMXConfigError("model text config has invalid num_hidden_layers")
layers_prefix = _get_layers_prefix(config)
if layers_prefix == "language_model.model.layers":
return (
num_layers,
"language_model.model.embed_tokens",
"language_model.model.norm",
"language_model.lm_head",
)
if layers_prefix == "model.language_model.layers":
return (
num_layers,
"model.language_model.embed_tokens",
"model.language_model.norm",
"lm_head",
)
return num_layers, "model.embed_tokens", "model.norm", "lm_head"
def build_kt_device_map(config, kt_plugin, device: str = "cuda:0") -> dict[str, str | int]:
"""
Build device_map for KT model loading with hybrid GPU/CPU expert placement.
"""
moe_config = get_moe_arch_config(config)
layers_prefix = _get_layers_prefix(config)
num_layers, embed_path, norm_path, lm_head_path = _device_map_model_contract(config)
num_experts = moe_config.expert_num
cfg = _get_kt_config(kt_plugin)
num_gpu_experts = getattr(cfg, "kt_num_gpu_experts", 0) or 0
device_map: dict[str, str | int] = {}
device_map[embed_path] = device
device_map[norm_path] = device
device_map[lm_head_path] = device
for layer_idx in range(num_layers):
layer_prefix = f"{layers_prefix}.{layer_idx}"
device_map[layer_prefix] = device
moe_prefix = f"{layer_prefix}.{moe_config.moe_layer_attr}"
for expert_idx in range(num_experts):
expert_key = f"{moe_prefix}.{moe_config.experts_attr}.{expert_idx}"
if expert_idx < num_gpu_experts:
device_map[expert_key] = device
else:
device_map[expert_key] = "cpu"
logger.info(f"Built KT device_map: {num_gpu_experts} GPU experts, {num_experts - num_gpu_experts} CPU experts")
return device_map
def build_kt_device_map_simplified(config, kt_plugin, device: str = "cuda:0") -> dict[str, str | int]:
"""
Simplified device_map builder: map full layers to GPU, override routed experts to CPU.
"""
moe_config = get_moe_arch_config(config)
layers_prefix = _get_layers_prefix(config)
num_layers, embed_path, norm_path, lm_head_path = _device_map_model_contract(config)
cfg = _get_kt_config(kt_plugin)
num_gpu_experts = getattr(cfg, "kt_num_gpu_experts", 0) or 0
device_map: dict[str, str | int] = {}
device_map[embed_path] = device
device_map[norm_path] = device
device_map[lm_head_path] = device
for layer_idx in range(num_layers):
layer_prefix = f"{layers_prefix}.{layer_idx}"
device_map[layer_prefix] = device
experts_prefix = f"{layer_prefix}.{moe_config.moe_layer_attr}.{moe_config.experts_attr}"
if num_gpu_experts == 0:
device_map[experts_prefix] = "cpu"
else:
return build_kt_device_map(config, kt_plugin, device=device)
logger.info("Built simplified KT device_map: all layers on GPU, routed experts on CPU")
return device_map
# =============================================================================
# MoE layer wrapping
# =============================================================================
def wrap_moe_layers_with_kt_wrapper(model: nn.Module, kt_plugin: Any) -> list[KTMoELayerWrapper]:
"""
Replace model's MoE layers with KTMoEWrapper-based wrappers.
Loads expert weights into the C++ KT kernel. No LoRA initialization ---
LoRA is handled by PEFT and later adapted via kt_adapt_peft_lora().
Only rank 0 initializes KT kernel and loads weights.
"""
if not KT_KERNEL_AVAILABLE:
raise KTAMXNotAvailableError("kt_kernel not found. Please install kt_kernel to enable KT MoE support.")
# Only global rank 0 initializes KT. Launcher env fallback matters when
# model construction happens before init_process_group().
distributed_rank, distributed_world_size = _distributed_rank_world_size()
is_rank_0 = distributed_rank == 0
moe_config = get_moe_arch_config(model.config)
patched_conv3d = patch_vlm_conv3d(model)
if patched_conv3d:
logger.info(f"Patched KT VLM Conv3D modules: {patched_conv3d}")
_text_cfg = getattr(model.config, "text_config", model.config)
hidden_size = _text_cfg.hidden_size
cfg = _get_kt_config(kt_plugin)
activation_policy = cfg.kt_activation_policy
# Read lora_rank/lora_alpha for C++ wrapper initialization (buffer allocation only)
# Use explicit None checks: lora_rank=0 is a valid value (full mode, no LoRA),
# but `or` pattern would treat 0 as falsy and replace it with 1.
_raw_rank = getattr(cfg, "kt_lora_rank", None)
lora_rank = _raw_rank if _raw_rank is not None else 1
_raw_alpha = getattr(cfg, "kt_lora_alpha", None)
lora_alpha = _raw_alpha if _raw_alpha is not None else 1.0
_raw_dropout = getattr(cfg, "kt_lora_dropout", None)
lora_dropout = _raw_dropout if _raw_dropout is not None else 0.0
# Read full_weight_grad mode
_raw_fwg = getattr(cfg, "kt_full_weight_grad", None)
full_weight_grad = _raw_fwg if _raw_fwg is not None else False
train_mode = getattr(cfg, "kt_train_mode", "lora")
# Full and hybrid are explicit modes. LlamaFactory exposes a default
# lora_rank even for full tuning, which must not silently turn Full into
# Hybrid. Preserve the legacy fallback for callers without train_mode.
if train_mode == "full":
lora_rank = 0
elif full_weight_grad and train_mode != "hybrid" and lora_rank > 0:
_has_explicit_lora_rank = getattr(cfg, "kt_lora_rank", None) is not None
if not _has_explicit_lora_rank:
lora_rank = 0
# Read LoRA Experts configuration
_raw_le = getattr(cfg, "kt_use_lora_experts", None)
use_lora_experts = bool(_raw_le) if _raw_le is not None else False
lora_expert_num = getattr(cfg, "kt_lora_expert_num", 2) or 2
lora_expert_intermediate_size = getattr(cfg, "kt_lora_expert_intermediate_size", 1024) or 1024
if is_rank_0:
logger.info(
f"LoRA Experts config: use_lora_experts={use_lora_experts}, "
f"num={lora_expert_num}, intermediate_size={lora_expert_intermediate_size}"
)
if full_weight_grad:
logger.info(f"Full weight gradient mode enabled (lora_rank={lora_rank})")
wrappers: list[KTMoELayerWrapper] = []
moe_layer_count = 0
kt_backend_map = {
"AMXBF16": "AMXBF16_SFT",
FP8_BACKEND: "AMXFP8_SFT",
"AMXFP8": "AMXFP8_SFT",
INT8_BACKEND: "INT8_SFT",
"AMXINT8": "INT8_SFT",
RAWINT4_BACKEND: RAWINT4_SFT_METHOD,
MXFP4_BACKEND: MXFP4_SFT_METHOD,
"AMXINT4_KGroup": RAWINT4_SFT_METHOD,
"AMXINT4": "AMXINT4_SFT",
"AMXBF16_SkipLoRA": "AMXBF16_SFT_SkipLoRA",
"AMXINT8_SkipLoRA": "AMXINT8_SFT_SkipLoRA",
"AMXINT4_SkipLoRA": "AMXINT4_SFT_SkipLoRA",
}
# Case-insensitive matching remains for compatibility, but an unknown
# backend must never silently turn a requested quantized run into BF16.
_kt_backend_map_lower = {k.lower(): v for k, v in kt_backend_map.items()}
kt_backend = str(getattr(cfg, "kt_backend", "AMXBF16"))
kt_method = kt_backend_map.get(kt_backend) or _kt_backend_map_lower.get(kt_backend.lower())
if kt_method is None:
raise KTAMXConfigError(
f"Unknown kt_backend {kt_backend!r}; expected one of {sorted(kt_backend_map)}"
)
if kt_backend not in kt_backend_map:
logger.warning(
f"kt_backend '{kt_backend}' matched via case-insensitive lookup -> '{kt_method}'. "
f"Please use the exact name from: {list(kt_backend_map.keys())}"
)
if "SkipLoRA" in kt_method:
logger.info(f"Using SkipLoRA backend: {kt_method} (MoE LoRA gradients will be skipped)")
force_fused_expert_lora = bool(
getattr(cfg, "kt_force_fused_expert_lora", False)
)
if force_fused_expert_lora and "SkipLoRA" in kt_method:
raise KTAMXConfigError(
"kt_force_fused_expert_lora is incompatible with SkipLoRA backends"
)
requested_num_gpu_experts = int(getattr(cfg, "kt_num_gpu_experts", 0) or 0)
expert_weight_format = getattr(cfg, "kt_expert_weight_format", None)
if expert_weight_format == "int8":
if kt_method != "INT8_SFT":
raise KTAMXConfigError(
"kt_expert_weight_format='int8' requires kt_backend='auto' or 'INT8'"
)
if full_weight_grad or train_mode != "lora" or lora_rank <= 0:
raise KTAMXConfigError(
"INT8 SFT supports frozen-base LoRA only; Full and Hybrid are not supported"
)
if requested_num_gpu_experts != 0 or use_lora_experts:
raise KTAMXConfigError(
"INT8 SFT requires all base experts and LoRA execution on CPU"
)
if not bool(getattr(cfg, "kt_share_backward_bb", False)):
raise KTAMXConfigError("INT8 SFT requires kt_share_backward_bb=true")
if expert_weight_format == "fp8":
if kt_method != "AMXFP8_SFT":
raise KTAMXConfigError(
"kt_expert_weight_format='fp8' requires kt_backend='auto' or 'FP8'"
)
if full_weight_grad or train_mode != "lora" or lora_rank <= 0:
raise KTAMXConfigError(
"FP8 SFT supports frozen-base LoRA only; Full and Hybrid are not supported"
)
if requested_num_gpu_experts != 0 or use_lora_experts:
raise KTAMXConfigError(
"FP8 SFT requires all base experts and LoRA execution on CPU"
)
if not bool(getattr(cfg, "kt_share_backward_bb", False)):
raise KTAMXConfigError("FP8 SFT requires kt_share_backward_bb=true")
if getattr(cfg, "kt_weight_lifecycle", "persistent") != "persistent":
raise KTAMXConfigError("FP8 SFT requires persistent checkpoint weights")
if expert_weight_format == "rawint4":
if kt_method != RAWINT4_SFT_METHOD:
raise KTAMXConfigError("kt_expert_weight_format='rawint4' requires " "kt_backend='auto' or 'RAWINT4'")
if full_weight_grad or train_mode != "lora" or lora_rank != 8:
raise KTAMXConfigError("RAWINT4 SFT v1 supports frozen-base rank-8 LoRA only")
if float(lora_dropout) != 0.0:
raise KTAMXConfigError("RAWINT4 SFT v1 requires lora_dropout=0")
if requested_num_gpu_experts != 0 or use_lora_experts:
raise KTAMXConfigError("RAWINT4 SFT requires all base experts and LoRA execution on CPU")
if bool(getattr(cfg, "kt_share_backward_bb", False)):
raise KTAMXConfigError(
"RAWINT4 SFT computes backward directly from packed weights; "
"kt_share_backward_bb must be false"
)
if not force_fused_expert_lora:
raise KTAMXConfigError("RAWINT4 SFT requires kt_force_fused_expert_lora=true")
if getattr(cfg, "kt_weight_lifecycle", "persistent") != "persistent":
raise KTAMXConfigError("RAWINT4 SFT requires persistent checkpoint weights")
cpu_activation_retain = activation_policy.cpu == "retain"
reuse_checkpoint_forward = cpu_activation_retain and activation_policy.gpu == "recompute"
if cpu_activation_retain and (
not _supports_checkpoint_forward_reuse(full_weight_grad, lora_rank)
or kt_method
not in {
"AMXBF16_SFT",
"AMXFP8_SFT",
"INT8_SFT",
RAWINT4_SFT_METHOD,
MXFP4_SFT_METHOD,
}
or requested_num_gpu_experts != 0
or use_lora_experts
):
raise KTAMXConfigError(
"activation_policy.cpu=retain requires CPU-only AMXBF16 Full/LoRA "
"or frozen-base INT8/FP8/RAWINT4/MXFP4 LoRA; Hybrid, GPU-expert, "
"LoRA-expert, generic INT4, and SkipLoRA paths are not supported"
)
_validate_rawint4_activation_policy(expert_weight_format, activation_policy)
if is_rank_0:
logger.warning(
"KT activation policy: cpu=%s, gpu=%s, "
"checkpoint_forward_reuse=%s, share_cache_pool=%s, world_size=%d",
activation_policy.cpu,
activation_policy.gpu,
reuse_checkpoint_forward,
not cpu_activation_retain,
distributed_world_size,
)
uses_authoritative_optimizer_grads = _supports_authoritative_optimizer_grads(
kt_method,
requested_num_gpu_experts,
full_weight_grad=full_weight_grad,
lora_rank=lora_rank,
)
int8_runtime = None
int8_runtime_error = None
if expert_weight_format == "int8" and is_rank_0:
try:
int8_runtime = get_int8_runtime()
except RuntimeError as exc:
int8_runtime_error = KTAMXNotAvailableError(str(exc))
if expert_weight_format == "int8":
_sync_rank0_wrap_error(
int8_runtime_error,
context="selecting the INT8 SFT kernel",
rank=distributed_rank,
world_size=distributed_world_size,
)
if int8_runtime is not None:
logger.info(
"KT INT8 SFT dispatch: configured_backend=%s, logical_backend=%s, "
"cpu_variant=%s, effective_kernel=%s, weight_layout=%s",
kt_backend,
INT8_BACKEND,
int8_runtime.cpu_variant,
int8_runtime.kernel,
int8_runtime.weight_layout,
)
fp8_runtime = None
fp8_runtime_error = None
if expert_weight_format == "fp8" and is_rank_0:
try:
fp8_runtime = get_fp8_runtime()
except RuntimeError as exc:
fp8_runtime_error = KTAMXNotAvailableError(str(exc))
if expert_weight_format == "fp8":
_sync_rank0_wrap_error(
fp8_runtime_error,
context="selecting the native FP8 SFT kernel",
rank=distributed_rank,
world_size=distributed_world_size,
)
if fp8_runtime is not None:
logger.info(
"KT FP8 SFT dispatch: configured_backend=%s, logical_backend=%s, "
"cpu_variant=%s, effective_kernel=%s, weight_layout=%s",
kt_backend,
FP8_BACKEND,
fp8_runtime.cpu_variant,
fp8_runtime.kernel,
fp8_runtime.weight_layout,
)
rawint4_runtime = None
rawint4_runtime_error = None
rawint4_contract = None
if expert_weight_format == "rawint4":
try:
rawint4_contract = get_rawint4_checkpoint_contract(model.config)
except ValueError as exc:
raise KTAMXConfigError(str(exc)) from exc
if expert_weight_format == "rawint4" and is_rank_0:
try:
rawint4_runtime = get_rawint4_runtime()
except RuntimeError as exc:
rawint4_runtime_error = KTAMXNotAvailableError(str(exc))
if expert_weight_format == "rawint4":
_sync_rank0_wrap_error(
rawint4_runtime_error,
context="selecting the RAWINT4 SFT kernel",
rank=distributed_rank,
world_size=distributed_world_size,
)
if rawint4_runtime is not None:
logger.info(
"KT RAWINT4 SFT dispatch: configured_backend=%s, logical_backend=%s, "
"cpu_variant=%s, effective_kernel=%s, weight_layout=%s",
kt_backend,
RAWINT4_BACKEND,
rawint4_runtime.cpu_variant,
rawint4_runtime.kernel,
rawint4_runtime.weight_layout,
)
threadpool_count = getattr(cfg, "kt_threadpool_count", 1) if getattr(cfg, "kt_tp_enabled", False) else 1
fp8_block_size = None
if expert_weight_format == "fp8":
fp8_block_size = _native_fp8_block_size(model.config)
if hidden_size % 128 or moe_config.intermediate_size % 128:
raise KTAMXConfigError(
"FP8 SFT requires hidden and routed intermediate dimensions divisible by 128"
)
if (
threadpool_count < 1
or moe_config.intermediate_size % threadpool_count
or (moe_config.intermediate_size // threadpool_count) % 128
):
raise KTAMXConfigError(
"FP8 SFT requires each TP intermediate slice divisible by 128; "
f"intermediate_size={moe_config.intermediate_size}, "
f"threadpool_count={threadpool_count}"
)
if expert_weight_format == "rawint4":
if threadpool_count not in {1, 2}:
raise KTAMXConfigError(f"RAWINT4 SFT v1 supports TP1/TP2 only, got {threadpool_count}")
if hidden_size % RAWINT4_GROUP_SIZE or moe_config.intermediate_size % RAWINT4_GROUP_SIZE:
raise KTAMXConfigError(
"RAWINT4 SFT requires hidden and routed intermediate dimensions " f"divisible by {RAWINT4_GROUP_SIZE}"
)
if (
moe_config.intermediate_size % threadpool_count
or (moe_config.intermediate_size // threadpool_count) % RAWINT4_GROUP_SIZE
):
raise KTAMXConfigError(
"RAWINT4 SFT requires every TP intermediate slice divisible by "
f"{RAWINT4_GROUP_SIZE}; intermediate_size={moe_config.intermediate_size}, "
f"threadpool_count={threadpool_count}"
)
kt_weight_path = getattr(cfg, "kt_weight_path", None)
# Native FP8 and RAWINT4 use kt_weight_path as raw-checkpoint provenance,
# not as a pre-packed .kt directory.
use_kt_weight_path = kt_weight_path is not None and expert_weight_format not in {"fp8", "rawint4"}
if use_kt_weight_path:
logger.info(
"Loading %s weights from kt_weight_path: %s",
expert_weight_format or "pre-quantized",
kt_weight_path,
)
checkpoint_files = getattr(cfg, "kt_checkpoint_files", None)
sharded_metadata = getattr(cfg, "kt_sharded_metadata", None)
# When kt_expert_checkpoint_path is set, always resolve from it (overrides any existing
# checkpoint_files which may come from AttnOnlyBf16 and lack expert weights).
kt_expert_checkpoint_path = getattr(cfg, "kt_expert_checkpoint_path", None)
full_weight_checkpoint = resolve_full_weight_checkpoint(kt_expert_checkpoint_path)
use_full_weight_checkpoint = full_weight_checkpoint is not None
if use_full_weight_checkpoint and use_kt_weight_path:
raise KTAMXConfigError(
"A KT Full checkpoint and kt_weight_path were both selected. "
"Choose exactly one authoritative expert weight source."
)
if use_full_weight_checkpoint:
logger.info(f"Loading expert weights from KT Full checkpoint: {full_weight_checkpoint}")
elif kt_expert_checkpoint_path:
logger.info(f"Resolving expert checkpoint files from kt_expert_checkpoint_path={kt_expert_checkpoint_path!r}")
resolved_files, resolved_meta = _resolve_checkpoint_files(model_name_or_path=kt_expert_checkpoint_path)
if resolved_files and all(f.endswith(".safetensors") for f in resolved_files):
checkpoint_files = resolved_files
sharded_metadata = resolved_meta
cfg.kt_checkpoint_files = checkpoint_files
cfg.kt_sharded_metadata = sharded_metadata
logger.info(f"Resolved {len(checkpoint_files)} checkpoint files from kt_expert_checkpoint_path")
else:
logger.warning(
f"Failed to resolve checkpoint files from kt_expert_checkpoint_path={kt_expert_checkpoint_path!r}"
)
if expert_weight_format in {"fp8", "rawint4"} and not checkpoint_files and kt_weight_path:
logger.info(
"Resolving native %s checkpoint files from kt_weight_path=%r",
expert_weight_format.upper(),
kt_weight_path,
)
resolved_files, resolved_meta = _resolve_raw_safetensors_checkpoint_files(kt_weight_path)
if resolved_files:
checkpoint_files = resolved_files
sharded_metadata = resolved_meta
cfg.kt_checkpoint_files = checkpoint_files
cfg.kt_sharded_metadata = sharded_metadata
use_checkpoint_files = bool(checkpoint_files) and not use_kt_weight_path and not use_full_weight_checkpoint
if expert_weight_format == "int8":
if not use_kt_weight_path:
raise KTAMXConfigError(
"INT8 SFT requires kt_weight_path with pre-quantized .kt weights"
)
if use_full_weight_checkpoint or kt_expert_checkpoint_path:
raise KTAMXConfigError(
"INT8 SFT does not support Full checkpoints or online expert conversion"
)
if expert_weight_format == "fp8":
if use_full_weight_checkpoint:
raise KTAMXConfigError("FP8 SFT does not support KT Full checkpoints")
if expert_weight_format == "rawint4":
if use_full_weight_checkpoint or kt_expert_checkpoint_path:
raise KTAMXConfigError(
"RAWINT4 SFT reads packed experts from the source checkpoint and "
"does not support KT Full or alternate expert checkpoints"
)
logger.debug(
f"Weight source: kt_weight_path={kt_weight_path!r}, "
f"kt_expert_checkpoint_path={kt_expert_checkpoint_path!r}, "
f"full_weight_checkpoint={full_weight_checkpoint!r}, "
f"checkpoint_files count={len(checkpoint_files) if checkpoint_files else 0}, "
f"use_kt_weight_path={use_kt_weight_path}, use_full_weight_checkpoint={use_full_weight_checkpoint}, "
f"use_checkpoint_files={use_checkpoint_files}"
)
if use_full_weight_checkpoint:
logger.info("Loading expert weights from a KT Full checkpoint.")
elif use_checkpoint_files:
logger.info("Loading expert weights from checkpoint files (online conversion).")
elif use_kt_weight_path and bool(checkpoint_files):
logger.info("BF16 checkpoint files available for backward gradient computation.")
elif (
not use_kt_weight_path
and not use_full_weight_checkpoint
and bool(getattr(cfg, "kt_skip_expert_loading", False))
):
# If HF expert weights were skipped during `from_pretrained`, we must source expert weights externally.
model_name_or_path = getattr(getattr(model, "config", None), "name_or_path", None)
if model_name_or_path:
resolved_files, resolved_meta = _resolve_checkpoint_files(model_name_or_path=model_name_or_path)
if resolved_files and all(f.endswith(".safetensors") for f in resolved_files):
checkpoint_files = resolved_files
sharded_metadata = resolved_meta
cfg.kt_checkpoint_files = checkpoint_files
cfg.kt_sharded_metadata = sharded_metadata
use_checkpoint_files = True
logger.info("KT skip_expert_loading enabled; using checkpoint files for online expert loading.")
if not use_checkpoint_files:
raise KTAMXConfigError(
"KT skip_expert_loading is enabled but no `kt_weight_path` was provided and no safetensors checkpoint "
"files could be resolved for on-the-fly expert loading."
)
if expert_weight_format == "fp8" and not use_checkpoint_files:
raise KTAMXConfigError(
"FP8 SFT requires raw safetensors checkpoint files. Point "
"kt_weight_path at model_name_or_path or set kt_expert_checkpoint_path."
)
if expert_weight_format == "rawint4" and not use_checkpoint_files:
raise KTAMXConfigError(
"RAWINT4 SFT requires raw compressed-tensors safetensors checkpoint "
"files. Point kt_weight_path at model_name_or_path."
)
model_container, layers = _get_model_container_and_layers(model, purpose="wrapping")
logger.info(f"Total layers={len(layers)}, is_rank_0={is_rank_0}")
from .arch import detect_fused_experts as _detect_fused
expert_layer_indices = [
layer_idx
for layer_idx, layer in enumerate(layers)
if get_moe_module(layer, moe_config) is not None
]
ephemeral_store = None
ephemeral_requested = (
getattr(cfg, "kt_weight_lifecycle", "persistent") == "ephemeral"
)
ephemeral_open_error = None
if is_rank_0 and ephemeral_requested:
try:
from .ephemeral import EphemeralKTWeightStore
ephemeral_store = EphemeralKTWeightStore.open(
kt_weight_path,
layer_indices=expert_layer_indices,
numa_count=threadpool_count,
expert_num=moe_config.expert_num,
hidden_size=hidden_size,
intermediate_size=moe_config.intermediate_size,
)
except BaseException as exc:
ephemeral_open_error = exc
if ephemeral_requested:
_sync_rank0_wrap_error(
ephemeral_open_error,
context="opening ephemeral INT8 weights",
rank=distributed_rank,
world_size=distributed_world_size,
)
persistent_manifest_error = None
if (
is_rank_0
and expert_weight_format == "int8"
and not ephemeral_requested
):
try:
from .weight_manifest import validate_persistent_int8_weights
validated_manifest = validate_persistent_int8_weights(
kt_weight_path,
layer_indices=expert_layer_indices,
numa_count=threadpool_count,
expert_num=moe_config.expert_num,
hidden_size=hidden_size,
intermediate_size=moe_config.intermediate_size,
)
logger.info(
"Validated persistent INT8 weights: manifest=%s, schema=%d%s, "
"layout=%s, layers=%d, files=%d, bytes=%d",
validated_manifest.path,
validated_manifest.schema_version,
" (legacy compatibility)" if validated_manifest.is_legacy else "",
validated_manifest.layout,
len(validated_manifest.layer_indices),
validated_manifest.file_count,
validated_manifest.size_bytes,
)
except BaseException as exc:
persistent_manifest_error = exc
if expert_weight_format == "int8" and not ephemeral_requested:
_sync_rank0_wrap_error(
persistent_manifest_error,
context="validating persistent INT8 weights",
rank=distributed_rank,
world_size=distributed_world_size,
)
for layer_idx, layer in enumerate(layers):
moe_module = get_moe_module(layer, moe_config)
if moe_module is None:
continue
_layer_experts = getattr(moe_module, moe_config.experts_attr, None)
_layer_is_fused = _detect_fused(_layer_experts)
if expert_weight_format in {"int8", "fp8", "rawint4", "mxfp4"} and not _layer_is_fused and not force_fused_expert_lora:
raise KTAMXConfigError(
f"{expert_weight_format.upper()} LoRA with non-fused runtime experts requires "
"kt_force_fused_expert_lora=true"
)
_use_fused_expert_lora = _layer_is_fused or force_fused_expert_lora
logger.debug(
"Wrapping MoE layer %s (method=%s, fused=%s, force_fused_lora=%s)",
layer_idx,
kt_method,
_layer_is_fused,
force_fused_expert_lora,
)
# Only rank 0 loads weights and initializes KT kernel
gate_proj, up_proj, down_proj = None, None, None
block_fp8_weights = None
rawint4_weights = None
wrapper = None
weight_source_error = None
if is_rank_0:
try:
# Get block_size from quantization_config if available (for legacy FP8 dequant)
_quant_cfg = getattr(model.config, "quantization_config", None)
_block_size = None
if _quant_cfg is not None:
_block_size = (
_quant_cfg.get("weight_block_size")
if isinstance(_quant_cfg, dict)
else getattr(_quant_cfg, "weight_block_size", None)
)
if use_full_weight_checkpoint:
expected_shapes = {
"gate_proj": (
int(moe_config.expert_num),
int(moe_config.intermediate_size),
int(hidden_size),
),
"up_proj": (
int(moe_config.expert_num),
int(moe_config.intermediate_size),
int(hidden_size),
),
"down_proj": (
int(moe_config.expert_num),
int(hidden_size),
int(moe_config.intermediate_size),
),
}
gate_proj, up_proj, down_proj = load_full_weight_layer(
full_weight_checkpoint,
layer_idx=layer_idx,
expected_shapes=expected_shapes,
)
elif expert_weight_format == "mxfp4":
get_mxfp4_runtime()
if moe_config.router_type != "precomputed":
raise KTAMXConfigError("MXFP4 SFT currently supports DeepSeek V4 routed experts only")
elif use_kt_weight_path:
logger.debug(f"Layer {layer_idx}: forward + backward from kt_weight_path (.kt files)")
elif expert_weight_format == "fp8":
layers_prefix = _get_layers_prefix(model.config)
block_fp8_weights = load_block_fp8_experts_from_checkpoint_files(
checkpoint_files=checkpoint_files,
sharded_metadata=sharded_metadata,
layers_prefix=layers_prefix,
moe_config=moe_config,
layer_idx=layer_idx,
hidden_size=hidden_size,
block_size=fp8_block_size,
)
elif expert_weight_format == "rawint4":
layers_prefix = _get_layers_prefix(model.config)
rawint4_weights = load_rawint4_experts_from_checkpoint_files(
checkpoint_files=checkpoint_files,
sharded_metadata=sharded_metadata,
layers_prefix=layers_prefix,
moe_config=moe_config,
layer_idx=layer_idx,
hidden_size=hidden_size,
group_size=RAWINT4_GROUP_SIZE,
)
elif use_checkpoint_files:
layers_prefix = _get_layers_prefix(model.config)
gate_proj, up_proj, down_proj = load_experts_from_checkpoint_files(
checkpoint_files=checkpoint_files,
sharded_metadata=sharded_metadata,
layers_prefix=layers_prefix,
moe_config=moe_config,
layer_idx=layer_idx,
block_size=_block_size,
)
else:
gate_proj, up_proj, down_proj = extract_moe_weights(moe_module, moe_config)
gate_proj = gate_proj.cpu().to(torch.bfloat16).contiguous()
up_proj = up_proj.cpu().to(torch.bfloat16).contiguous()
down_proj = down_proj.cpu().to(torch.bfloat16).contiguous()
except BaseException as exc:
weight_source_error = exc
_sync_rank0_wrap_error(
weight_source_error,
context=f"resolving expert weights for layer {layer_idx}",
rank=distributed_rank,
world_size=distributed_world_size,
)
chunked_prefill_size = getattr(cfg, "kt_model_max_length", None)
if chunked_prefill_size is None:
chunked_prefill_size = getattr(model.config, "max_position_embeddings", 4096)
# Rank 0 receives the concatenation of every rank's local rows. Model
# configs are homogeneous across ranks, so the sum of local maxima is
# the per-rank capacity multiplied by world size.
rank0_chunked_prefill_size = int(chunked_prefill_size) * distributed_world_size
# Only rank 0 creates KTMoEWrapper and loads weights
construct_error = None
if is_rank_0:
try:
wrapper = KTMoEWrapper(
layer_idx=layer_idx,
num_experts=moe_config.expert_num,
num_experts_per_tok=moe_config.num_experts_per_tok,
hidden_size=hidden_size,
moe_intermediate_size=moe_config.intermediate_size,
gpu_experts_mask=None,
num_gpu_experts=0,
cpuinfer_threads=getattr(cfg, "kt_num_threads", 1),
threadpool_count=threadpool_count,
weight_path=kt_weight_path or "",
chunked_prefill_size=rank0_chunked_prefill_size,
method=kt_method,
mode="sft",
lora_rank=lora_rank,
lora_alpha=lora_alpha,
lora_dropout=lora_dropout,
max_cache_depth=getattr(cfg, "kt_max_cache_depth", 2),
group_size=32 if expert_weight_format in {"rawint4", "mxfp4"} else 128,
zero_point=expert_weight_format not in {"rawint4", "mxfp4"},
swiglu_limit=float(getattr(_text_cfg, "swiglu_limit", 0.0))
if expert_weight_format in {"mxfp4", "rawint4"}
else 0.0,
full_weight_grad=full_weight_grad,
)
except BaseException as exc:
try:
if ephemeral_store is not None:
ephemeral_store.cleanup()
except BaseException:
logger.exception(
"Cleanup failed after constructing ephemeral INT8 layer %s",
layer_idx,
)
construct_error = exc
_sync_rank0_wrap_error(
construct_error,
context=f"constructing KT layer {layer_idx}",
rank=distributed_rank,
world_size=distributed_world_size,
)
load_error = None
if is_rank_0:
try:
# The current SFT wrapping path routes all experts through KT even
# when the loading config requested GPU experts. Preserve that
# configuration's legacy gradient lifecycle until the hybrid
# routed-expert path supports authoritative buffers end to end.
wrapper._uses_authoritative_optimizer_grads = uses_authoritative_optimizer_grads
# These flags are consumed while the C++ config is built.
wrapper.share_backward_bb = cfg.kt_share_backward_bb
wrapper.reuse_checkpoint_forward = reuse_checkpoint_forward
wrapper.activation_policy = activation_policy
wrapper.share_cache_pool = not cpu_activation_retain
physical_to_logical_map = torch.arange(
moe_config.expert_num,
dtype=torch.int64,
device="cpu",
)
if expert_weight_format == "fp8":
logger.debug(
"Layer %s: packing raw per-expert FP8 checkpoint tensors",
layer_idx,
)
wrapper.load_block_fp8_weights(
block_fp8_weights,
physical_to_logical_map,
)
block_fp8_weights = None
elif expert_weight_format == "rawint4":
logger.debug(
"Layer %s: loading packed RAWINT4 checkpoint tensors",
layer_idx,
)
wrapper.load_rawint4_weights(
rawint4_weights,
physical_to_logical_map,
)
rawint4_weights = None
elif use_kt_weight_path:
logger.debug(
f"Layer {layer_idx}: calling wrapper.load_weights() "
"(C++ direct .kt load)"
)
wrapper.load_weights(physical_to_logical_map)
if ephemeral_store is not None:
# load_weights() returns only after C++ copied every file
# into its owned BufferB storage.
ephemeral_store.consume_layer(layer_idx)
else:
logger.debug(
f"Layer {layer_idx}: calling wrapper.load_weights_from_tensors() "
f"(BF16 tensor path, gate_proj shape={gate_proj.shape if gate_proj is not None else None})"
)
wrapper.load_weights_from_tensors(
gate_proj=gate_proj,
up_proj=up_proj,
down_proj=down_proj,
physical_to_logical_map_cpu=physical_to_logical_map,
)
if full_weight_grad:
wrapper.init_full_weight_grad_buffers(
gate_proj=wrapper.gate_proj if wrapper.gate_proj is not None else gate_proj,
up_proj=wrapper.up_proj if wrapper.up_proj is not None else up_proj,
down_proj=wrapper.down_proj if wrapper.down_proj is not None else down_proj,
)
else:
wrapper.gate_proj = None
wrapper.up_proj = None
wrapper.down_proj = None
except BaseException as exc:
if ephemeral_store is not None:
try:
ephemeral_store.cleanup()
except BaseException:
logger.exception(
"Cleanup failed after loading ephemeral INT8 layer %s",
layer_idx,
)
load_error = exc
_sync_rank0_wrap_error(
load_error,
context=f"loading KT layer {layer_idx}",
rank=distributed_rank,
world_size=distributed_world_size,
)
# Create LoRA Experts if enabled
lora_experts = None
if use_lora_experts:
lora_experts = LoRAExperts(
num_experts=lora_expert_num,
hidden_size=hidden_size,
intermediate_size=lora_expert_intermediate_size,
device="cuda",
dtype=torch.bfloat16,
)
layer_wrapper_cls = KTRoutedExpertsWrapper if moe_config.router_type == "precomputed" else KTMoELayerWrapper
layer_wrapper = layer_wrapper_cls(
original_moe=moe_module,
wrapper=wrapper,
lora_params=None,
moe_config=moe_config,
hidden_size=hidden_size,
layer_idx=layer_idx,
lora_experts=lora_experts,
full_weight_grad=full_weight_grad,
uses_authoritative_optimizer_grads=uses_authoritative_optimizer_grads,
activation_policy=activation_policy,
)
layer_wrapper._fused_experts = _layer_is_fused
layer_wrapper._use_fused_expert_lora = _use_fused_expert_lora
layer_wrapper._force_fused_expert_lora = force_fused_expert_lora
layer_wrapper._lora_rank = lora_rank
layer_wrapper._lora_alpha = float(lora_alpha)
layer_wrapper._kt_owner_rank = 0
layer_wrapper._kt_world_size_at_wrap = distributed_world_size
layer_wrapper._kt_expert_weight_format = expert_weight_format or "bf16"
if rawint4_contract is not None:
layer_wrapper._kt_rawint4_quantization = {
"bits": rawint4_contract.bits,
"group_size": rawint4_contract.group_size,
"signed": rawint4_contract.signed,
"symmetric": rawint4_contract.symmetric,
"zero_point": rawint4_contract.zero_point,
"format": rawint4_contract.format,
"weight_layout": RAWINT4_WEIGHT_LAYOUT,
}
if moe_config.router_type != "precomputed":
setattr(layer, moe_config.moe_layer_attr, layer_wrapper)
# Base weights have been copied into the C++ kernel's internal BufferB format.
# In full_weight_grad mode, the authoritative copies are gate_proj_buf etc.
# Always release local references to save ~1 GB/layer.
del gate_proj, up_proj, down_proj, block_fp8_weights, rawint4_weights
wrappers.append(layer_wrapper)
moe_layer_count += 1
# Replace original expert weights with zero-storage placeholders.
# Experts remain in the model tree (via wrapper.experts) so PEFT can discover them.
# Rank 0 already copied weights to C++ kernel via load_weights_from_tensors.
# gate_proj_buf serves as the authoritative copy in full_weight_grad mode.
_clear_original_expert_weights(
moe_module,
moe_config,
full_weight_grad=full_weight_grad,
empty_placeholders=expert_weight_format in {"int8", "fp8", "rawint4", "mxfp4"},
)
if moe_config.router_type == "precomputed":
setattr(moe_module, moe_config.experts_attr, layer_wrapper)
ephemeral_finish_error = None
if ephemeral_store is not None:
try:
ephemeral_store.finish()
except BaseException as exc:
try:
ephemeral_store.cleanup()
except BaseException:
logger.exception("Cleanup failed while finishing ephemeral INT8 weights")
ephemeral_finish_error = exc
if ephemeral_requested:
_sync_rank0_wrap_error(
ephemeral_finish_error,
context="finishing ephemeral INT8 weights",
rank=distributed_rank,
world_size=distributed_world_size,
)
logger.info(f"Wrapped {moe_layer_count} MoE layers with KTMoEWrapper")
model._kt_expert_weight_format = expert_weight_format or "bf16"
if rawint4_contract is not None:
model._kt_rawint4_quantization = {
"bits": rawint4_contract.bits,
"group_size": rawint4_contract.group_size,
"signed": rawint4_contract.signed,
"symmetric": rawint4_contract.symmetric,
"zero_point": rawint4_contract.zero_point,
"format": rawint4_contract.format,
"weight_layout": RAWINT4_WEIGHT_LAYOUT,
}
# Link wrappers for async backward repack (higher layer triggers repack for lower)
for i in range(1, len(wrappers)):
if wrappers[i].wrapper is not None and wrappers[i - 1].wrapper is not None:
wrappers[i].wrapper._next_backward_wrapper = wrappers[i - 1].wrapper
if wrappers and wrappers[0].wrapper is not None:
wrappers[0].wrapper._next_backward_wrapper = None
gc.collect()
return wrappers
# =============================================================================
# Plugin builder
# =============================================================================
def _build_kt_plugin_from_args(model_args: Any, finetuning_args: Any | None = None):
"""
Build a KTransformersPlugin from model_args and optional finetuning_args.
Imported here to avoid circular dependency --- callers that need the plugin
class should import it from the appropriate dataclasses module.
"""
from .config import KTConfig
from accelerate.utils.dataclasses import KTransformersPlugin
# Map LlamaFactory finetuning_type to kt_train_mode
finetuning_type = getattr(finetuning_args, "finetuning_type", None) if finetuning_args else None
kt_train_mode_map = {
"full": "full",
"freeze": "hybrid",
"lora": "lora",
"galore": "full",
"badam": "full",
}
kt_train_mode = kt_train_mode_map.get(finetuning_type, None) if finetuning_type else None
configured_lora_rank = getattr(finetuning_args, "lora_rank", None) if finetuning_args else None
configured_lora_alpha = getattr(finetuning_args, "lora_alpha", None) if finetuning_args else None
configured_lora_dropout = getattr(finetuning_args, "lora_dropout", None) if finetuning_args else None
if kt_train_mode == "full":
configured_lora_rank = None
configured_lora_alpha = None
configured_lora_dropout = None
kt_config = KTConfig(
kt_backend=getattr(model_args, "kt_backend", None),
kt_num_threads=getattr(model_args, "kt_num_threads", None),
kt_tp_enabled=getattr(model_args, "kt_tp_enabled", None),
kt_threadpool_count=getattr(model_args, "kt_threadpool_count", None),
kt_max_cache_depth=getattr(model_args, "kt_max_cache_depth", None),
kt_num_gpu_experts=getattr(model_args, "kt_num_gpu_experts", None),
kt_weight_path=getattr(model_args, "kt_weight_path", None),
kt_expert_weight_format=getattr(model_args, "kt_expert_weight_format", None),
kt_weight_lifecycle=getattr(model_args, "kt_weight_lifecycle", None),
kt_expert_checkpoint_path=getattr(model_args, "kt_expert_checkpoint_path", None),
kt_force_fused_expert_lora=getattr(model_args, "kt_force_fused_expert_lora", None),
kt_use_lora_experts=getattr(model_args, "kt_use_lora_experts", None),
kt_lora_expert_num=getattr(model_args, "kt_lora_expert_num", None),
kt_lora_expert_intermediate_size=getattr(model_args, "kt_lora_expert_intermediate_size", None),
kt_lora_rank=configured_lora_rank,
kt_lora_alpha=configured_lora_alpha,
kt_lora_dropout=configured_lora_dropout,
kt_model_max_length=getattr(model_args, "model_max_length", None),
kt_train_mode=kt_train_mode,
kt_activation_policy=getattr(model_args, "activation_policy", None),
)
return KTransformersPlugin(enabled=True, kt_config=kt_config)
def get_kt_loading_kwargs(
config,
kt_plugin,
torch_dtype: torch.dtype | str | None = torch.bfloat16,
trust_remote_code: bool | None = None,
token: str | None = None,
) -> dict[str, Any]:
"""Get kwargs for AutoModel.from_pretrained() for KT loading."""
kwargs: dict[str, Any] = {
"config": config,
"torch_dtype": torch_dtype,
"device_map": "cpu",
"low_cpu_mem_usage": True,
}
if trust_remote_code is not None:
kwargs["trust_remote_code"] = trust_remote_code
if token is not None:
kwargs["token"] = token
return kwargs
def _resolve_checkpoint_files(
model_name_or_path: str,
cache_dir: str | None = None,
revision: str | None = None,
token: str | None = None,
trust_remote_code: bool | None = None,
) -> tuple[list[str] | None, dict | None]:
"""Resolve HF checkpoint files. Depends on transformers internals."""
try:
import inspect
from transformers.modeling_utils import _get_resolved_checkpoint_files
except Exception:
return None, None
try:
common = {
"pretrained_model_name_or_path": model_name_or_path,
"variant": None,
"gguf_file": None,
"use_safetensors": None,
"user_agent": {"file_type": "model", "framework": "pytorch"},
"is_remote_code": bool(trust_remote_code),
"transformers_explicit_filename": None,
}
if "download_kwargs" in inspect.signature(_get_resolved_checkpoint_files).parameters:
common["download_kwargs"] = {
"cache_dir": cache_dir,
"force_download": False,
"local_files_only": False,
"token": token,
"revision": revision or "main",
"subfolder": "",
}
checkpoint_files, sharded_metadata = _get_resolved_checkpoint_files(**common)
else:
checkpoint_files, sharded_metadata = _get_resolved_checkpoint_files(
**common,
subfolder="",
from_tf=False,
from_flax=False,
cache_dir=cache_dir,
force_download=False,
proxies=None,
local_files_only=False,
token=token,
revision=revision or "main",
commit_hash=None,
)
except Exception:
return None, None
return checkpoint_files, sharded_metadata
def load_kt_model(
config,
model_args: Any | None = None,
finetuning_args: Any | None = None,
kt_plugin=None,
model_name_or_path: str | None = None,
trust_remote_code: bool | None = None,
token: str | None = None,
torch_dtype: torch.dtype | str | None = torch.bfloat16,
**kwargs,
) -> nn.Module:
"""Load model with KTMoEWrapper backend."""
from .arch import (
get_moe_arch_config,
move_non_experts_to_gpu,
KTAMXConfigError,
)
if kt_plugin is None:
if model_args is None:
raise KTAMXConfigError("Either kt_plugin or model_args must be provided to load_kt_model().")
kt_plugin = _build_kt_plugin_from_args(model_args, finetuning_args)
if model_name_or_path is None and model_args is not None:
model_name_or_path = getattr(model_args, "model_name_or_path", None)
if model_name_or_path is None:
raise KTAMXConfigError("model_name_or_path is required to load_kt_model().")
if trust_remote_code is None and model_args is not None:
trust_remote_code = getattr(model_args, "trust_remote_code", None)
if token is None and model_args is not None:
token = getattr(model_args, "hf_hub_token", None)
cache_dir = getattr(model_args, "cache_dir", None) if model_args is not None else None
revision = getattr(model_args, "revision", None) if model_args is not None else None
_ = get_moe_arch_config(config)
logger.info("Loading model with KTMoEWrapper backend")
from transformers import AutoModelForCausalLM
from transformers.integrations.kt import set_kt_config, unset_kt_config
loading_kwargs = get_kt_loading_kwargs(
config,
kt_plugin,
torch_dtype=torch_dtype,
trust_remote_code=trust_remote_code,
token=token,
)
if model_args is not None:
for key in ("cache_dir", "revision"):
value = getattr(model_args, key, None)
if value is not None:
loading_kwargs[key] = value
loading_kwargs.update(kwargs)
cfg = _get_kt_config(kt_plugin)
auto_full_weight_checkpoint = resolve_full_weight_checkpoint(model_name_or_path)
if auto_full_weight_checkpoint is not None and getattr(cfg, "kt_expert_checkpoint_path", None) is None:
cfg.kt_expert_checkpoint_path = auto_full_weight_checkpoint
plugin_config = getattr(kt_plugin, "kt_config", None)
if isinstance(plugin_config, dict):
plugin_config["kt_expert_checkpoint_path"] = auto_full_weight_checkpoint
elif plugin_config is not None:
setattr(plugin_config, "kt_expert_checkpoint_path", auto_full_weight_checkpoint)
else:
setattr(kt_plugin, "kt_expert_checkpoint_path", auto_full_weight_checkpoint)
logger.info("Detected KT Full checkpoint in model directory: %s", auto_full_weight_checkpoint)
expert_weight_format = getattr(cfg, "kt_expert_weight_format", None)
native_fp8_experts = expert_weight_format == "fp8"
native_rawint4_experts = expert_weight_format == "rawint4"
native_checkpoint_experts = native_fp8_experts or native_rawint4_experts or expert_weight_format == "mxfp4"
if native_checkpoint_experts:
# Native quantized kt_weight_path is raw-checkpoint provenance; KT owns
# and loads the routed experts without materializing them in Transformers.
cfg.kt_skip_expert_loading = True
skip_expert_loading = getattr(cfg, "kt_skip_expert_loading", None)
needs_checkpoint_resolution = (
(native_checkpoint_experts and not getattr(cfg, "kt_checkpoint_files", None))
or skip_expert_loading is None
or (
bool(skip_expert_loading)
and not getattr(cfg, "kt_checkpoint_files", None)
and not getattr(cfg, "kt_weight_path", None)
)
)
if needs_checkpoint_resolution:
checkpoint_files, sharded_metadata = _resolve_checkpoint_files(
model_name_or_path=model_name_or_path,
cache_dir=cache_dir,
revision=revision,
token=token,
trust_remote_code=trust_remote_code,
)
if checkpoint_files and all(f.endswith(".safetensors") for f in checkpoint_files):
if native_checkpoint_experts or getattr(cfg, "kt_weight_path", None) is None:
cfg.kt_skip_expert_loading = True
else:
cfg.kt_skip_expert_loading = False
cfg.kt_checkpoint_files = checkpoint_files
cfg.kt_sharded_metadata = sharded_metadata
else:
if not native_checkpoint_experts:
cfg.kt_skip_expert_loading = False
if native_checkpoint_experts:
checkpoint_files = getattr(cfg, "kt_checkpoint_files", None)
if not checkpoint_files or not all(
str(path).endswith(".safetensors") for path in checkpoint_files
):
raise KTAMXConfigError(
f"native {expert_weight_format.upper()} SFT requires raw "
"safetensors checkpoint files; "
"no Transformers expert-materialization fallback is supported"
)
cfg.kt_skip_expert_loading = True
# Transformers consumes the resolved fields while from_pretrained runs;
# Accelerate deliberately keeps those fields opaque under plugin.kt_config.
set_kt_config(cfg)
try:
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, **loading_kwargs)
finally:
unset_kt_config()
moe_config = get_moe_arch_config(config)
local_rank = int(os.environ.get("LOCAL_RANK", "0"))
move_non_experts_to_gpu(model, moe_config, device=f"cuda:{local_rank}")
existing_wrappers = getattr(model, "_kt_wrappers", None)
if existing_wrappers:
logger.info(f"MoE layers already wrapped ({len(existing_wrappers)} layers), skipping re-wrap")
wrappers = existing_wrappers
else:
wrappers = wrap_moe_layers_with_kt_wrapper(model, kt_plugin)
model._kt_wrappers = wrappers
model._kt_tp_enabled = bool(getattr(cfg, "kt_tp_enabled", False))
model._kt_use_lora_experts = bool(getattr(cfg, "kt_use_lora_experts", False))
model._kt_full_weight_grad = bool(getattr(cfg, "kt_full_weight_grad", False))
model._kt_train_mode = getattr(cfg, "kt_train_mode", "lora")
model._kt_expert_weight_format = getattr(cfg, "kt_expert_weight_format", None) or "bf16"
logger.info("Model loaded with KTMoEWrapper backend successfully")
return model