项目简介
KTransformers 是一个研究项目,专注于通过 CPU-GPU 异构计算实现高效的 LLM 推理和微调。它提供高性能内核操作,并与 LLaMA-Factory 集成进行微调,支持 MoE 模型和各种量化技术。
README 预览
\n \n\n\n \n\n\n\n\n A Flexible Framework for Experiencing Cutting-edge LLM Inference/Fine-tune Optimizations\n 🎯 Overview | 🚀 Inference | 🎓 SFT | 🔥 Citation | 🚀 Roadmap(2026Q2) \n\n\n## 🎯 Overview\n\nKTransformers is a research project focused on efficient inference and fine-tuning of large language models through CPU-GPU heterogeneous computing. The project now exposes two user-facing capabilities from the kt-kernel source tree: [Inference](./kt-kernel/README.md) and [SFT](./doc/en/SFT/KTransformers-Fine-Tuning_Quick-Start.md).\n\n## 🔥 Updates\n* **June 21, 2026**: MiniMax-M3 Day0 Support! ([Tutorial](./doc/en/kt-kernel/MiniMax-M3-Tutorial.md))\n* **June 17, 2026**: GLM-5.2 Day0 Support! ([Tutorial](./doc/en/kt-kernel/GLM-5.2-Tutorial.md))\n* **May 6, 2026**: KTransformers at [GOSIM Paris 2026](https://paris2026.gosim.org/zh/schedule/) — "Agentic AI on Edge" track. We'll present KT's inference performance on consumer hardware.\n* **May 02, 2026**: DeepSeek-V4-Flash Support! ([Tutorial](./doc/en/DeepSeek-V4-Flash.md))\n* **Apr 30, 2026**: KTransformers v0.6.1 refreshes kt-kernel inference and SFT docs with separate [Inference](./kt-kernel/README.md) and [SFT Quick Start](./doc/en/SFT/KTransformers-Fine-Tuning_Quick-Start.md) entry points.\n* **Mar 26, 2026**: Support AVX2-only CPU backend for KT-Kernel inference. ([Tutorial](./doc/en/kt-kernel/AVX2-Tutorial.md))\n* **Feb 13, 2026**: MiniMax-M2.5 Day0 Support! ([Tutorial](./doc/en/MiniMax-M2.5.md))\n* **Feb 12, 2026**: GLM-5 Day0 Support! ([Tutorial](./doc/en/kt-kernel/GLM-5-Tutorial.md))\n* **Jan 27, 2026**: Kimi-K2.5 Day0 Support! ([Tutorial](./doc/en/Kimi-K2.5.md)) ([SFT Tutorial](./doc/en/SFT_Installation_Guide_KimiK2.5.md))\n* **Jan 22, 2026**: Support [CPU-GPU Expert Scheduling](./doc/en/kt-kernel/experts-sched-Tutorial.md), [Native BF16 and FP8 per channel Precision](./doc/en/kt-kernel/Native-Precision-Tutorial.md) and [AutoDL unified fine-tuning and inference](./doc/zh/【云端低价训推】%20KTransformers%
常见问题 (5)
故障排除如何修复 DeepSeek V4 Flash 在支持 AVX-512 但不支持 AVX512BF16 的 Xeon Cascade Lake 上返回乱码输出的问题?
这是 PR #2181 引入的回归问题:kt-kernel/operators/amx/fp4-moe.hpp 中的 prepare_decode_down_input() 即使在 __AVX512BF16__ 不可用时,也会使用优化的 MXFP4 解码路径。在非 BF16 CPU 上,down_ba_ 从未被填充,因此 down projection 会读取未初始化的内存并产生垃圾数据。
修复方法:更新到包含 PR fix(kt-kernel): restore MXFP4 decode fallback without AVX512 BF16 的构建版本,或者使用 __AVX512BF16__ 对优化路径进行门控:
void prepare_decode_down_input(int expert_idx, int qlen) {
#if defined(__AVX512BF16__)
if (qlen != 1 || config_.quant_config.group_size != 32 ||
config_.intermediate_size % 32 != 0) {
Base::prepare_decode_down_input(expert_idx, qlen);
return;
}
assert(down_ba_[expert_idx]->natural_order);
#else
Base::prepare_decode_down_input(expert_idx, qlen);
#endif
}
然后重新构建内核。这将为支持 AVX512F/VNNI 但缺少 AVX512BF16 的 CPU(例如 Xeon Platinum 8268/Cascade Lake)恢复基础回退路径。
故障排除使用 ktransformers 在 DeepSeek-V2-Lite 上运行 LoRA SFT 时,如何修复 MoELayer._compute_routing 中的 IndexError?
此问题出现在 ktransformers 0.6.4 中:当 PEFT/LoRA 将 DeepSeek MoE 的 gate 替换为 nn.Linear 后,_compute_routing 仍会进入 deepseek_gate 分支,并把原始 logits 当作 (topk_ids, topk_weights, aux_loss) 元组来处理。
在 kt_kernel/sft/layer.py 中应用以下单行修复:
# 修复前
if self.router_type == "deepseek_gate":
# 修复后
if self.router_type == "deepseek_gate" and self._original_router is None:
这样,被替换的 Linear 路由器将使用现有的 _original_router 路由路径,该路径会为 DeepSeek-V2-Lite 执行 softmax 打分和贪心 top-k 选择。
另外,请避免在 LLaMA-Factory 的 YAML 配置中使用 lora_target: all,因为它会把 MoE 路由器本身也包装进去。请使用显式的目标模块列表:
lora_target: q_proj,kv_a_proj_with_mqa,kv_b_proj,o_proj,gate_proj,up_proj,down_proj
应用该补丁并修改配置后,DeepSeek-V2-Lite 的 LoRA SFT 即可正常进行;该修复已通过 20 步训练运行和成功导出适配器得到验证。
故障排除为什么 GLM-4.5-Air 在使用 transformers-kt 5.x 时,输出会在约 4,000 个 token 之后出现退化、循环或乱码?又该如何修复 rope_theta 被读取为 10000 的问题?
模型的 config.json 在 rope_parameters 下存储了正确的值(1000000),但 transformers-kt 5.x 未暴露顶层的 rope_theta,因此加载器会回退到默认值 10000。错误的 RoPE 基频会导致困惑度在大约 4k 个 token 之后急剧飙升。
报告的受影响环境为 sglang-kt 0.7.0.post4、kt-kernel 0.7.0.post4 和 transformers-kt 5.6.0.post5。
修复 config/RoPE 初始化逻辑,使其读取嵌套值:
if getattr(config, "rope_parameters", None):
rope_theta = config.rope_parameters.get(
"rope_theta", getattr(config, "rope_theta", 10000)
)
else:
rope_theta = getattr(config, "rope_theta", 10000)
在构建 rotary embedding 时使用此 rope_theta,然后重启服务器。生效的值必须为 1000000,而不是 10000。
作为临时的本地变通方案,可以向模型的 config.json 添加顶层值:
import json, pathlib
p = pathlib.Path("/path/to/model/config.json")
c = json.loads(p.read_text())
c["rope_theta"] = c["rope_parameters"]["rope_theta"]
p.write_text(json.dumps(c, indent=2))
修复后,长上下文困惑度应保持大致平稳,而不是在 4096 及之后的位置急剧上升。
故障排除使用 kt_use_lora_experts 和 FSDP2 保存 LoRA Experts 时,如何修复 "Attempted to access the data pointer on an invalid python storage" 错误?
此问题影响 kt-kernel 0.6.4。在 FSDP2 下,LoRA-Expert 参数是 DTensor 分片,但 save_lora_experts_to_adapter 直接调用了 .data.cpu().clone()。这不会聚合各个分片,因此 safetensors 收到一个存储无效的张量并在训练结束后崩溃,导致 adapter_model.safetensors 中只剩下标准的 PEFT LoRA 权重。
请在 kt_kernel/sft/lora.py 约第 797–799 行附近打补丁,在保存前聚合 DTensor:
def _materialise_for_save(t):
try:
from torch.distributed.tensor import DTensor
except ImportError:
try:
from torch.distributed._tensor import DTensor
except ImportError:
DTensor = ()
if DTensor and isinstance(t, DTensor):
t = t.full_tensor() # collective: must run on every FSDP rank
return t.detach().cpu().clone()
state_dict[f"{base_key}.le_gate.weight"] = _materialise_for_save(expert.le_gate.weight)
state_dict[f"{base_key}.le_up.weight"] = _materialise_for_save(expert.le_up.weight)
state_dict[f"{base_key}.le_down.weight"] = _materialise_for_save(expert.le_down.weight)
不要只在 rank 0 上调用 full_tensor();它是一个分布式集合通信操作,必须由所有 rank 共同进入。你仍然可以对实际的 safetensors.torch.save_file 调用加以保护,使只有主进程写入检查点。
修复后,请验证 adapter_model.safetensors 包含 le_gate、le_up 和 le_down 张量,并且文件大于未启用 LoRA Experts 的运行结果。作为临时变通方案,可以禁用 kt_use_lora_experts,或者改用非 FSDP2/DDP 的配置。
故障排除如何修复 ktransformers FSDP2 LoRA SFT 梯度裁剪中出现的 'aten._foreach_mul_.Tensor: got mixed torch.Tensor and DTensor' 错误?
此问题出现在 ktransformers 0.6.4 与 FSDP2 一起使用时,因为 FSDP2 会将普通参数包装为 DTensor,而驻留在 CPU 上的 expert-LoRA 参数仍然是普通的 torch.Tensor。随后 HF Trainer 会将一个混合类型的列表传递给 _foreach_mul_。该问题在真实的梯度裁剪(max_grad_norm > 0)和 _get_grad_norm() 中都会发生,后者仅以 inf 调用裁剪用于日志记录,因此仅设置 max_grad_norm: 0.0 并不足够。
临时解决方案(禁用梯度裁剪):
1. 在训练/YAML 配置中设置:
max_grad_norm: 0.02. 在开始训练之前,对仅用于日志记录的梯度范数调用打补丁:
from transformers import Trainer
_orig_get_grad_norm = Trainer._get_grad_norm
def _safe_get_grad_norm(self, model, grad_norm=None):
try:
return _orig_get_grad_norm(self, model, grad_norm)
except RuntimeError as e:
if "DTensor" in str(e):
return None
raise
Trainer._get_grad_norm = _safe_get_grad_norm这样可以让 LoRA SFT 正常运行,但不会执行梯度裁剪,因此不适合用于生产级质量的训练。
正确的修复方法:在 FSDP2 激活时,将 ktransformers 的 expert-LoRA 参数注册为 replicated DTensor 参数,使 model.parameters() 在类型上保持同质。或者,将这些 expert-LoRA 参数从 Trainer/accelerate 的裁剪列表中排除,并将它们作为普通张量单独进行裁剪。这两种方法都能同时覆盖梯度裁剪和梯度范数日志记录这两个调用点,并恢复 max_grad_norm > 0 的功能。