ik_llama.cpp 中 THUDM GLM-4-MoE-100B-A10B 模型支持的技术评估与 MoE 架构实现指南
【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp
导读:本文基于 github-data/issues/597 中提出的功能请求,结合当前 ik_llama.cpp 仓库源码,系统梳理 GLM-4 系列 MoE 架构在本项目中的支持现状、实现原理与量化实践。读者将掌握glm4moe架构的推理图构建细节、专家门控与共享专家配置方式,以及如何将新 MoE 模型接入本项目的完整技术路径。
一、问题背景:一份针对 GLM-4-MoE-100B-A10B 的功能请求
2025-07-10,开发者ubergarm在 ik_llama.cpp 仓库提交了编号 #597 的功能请求,核心诉求是为智谱 AI(THUDM)尚未正式发布的GLM-4-MoE-100B-A10B模型架构提前做准备。
该 issue 的关键信息如下:
| 字段 | 内容 |
|---|---|
| 请求编号 | #597 |
| 提出者 | ubergarm |
| 状态 | 开放(Open) |
| 创建时间 | 2025-07-10 |
| 最后更新 | 2025-07-14 |
issue 中提到,THUDM 开发者zRzRzRzRzRzRzR正在 vLLM 项目中为该新架构添加支持,模型名称中的100B 代表总参数量、A10B 代表每次激活 10B 参数,这是一个"大而稀疏"的 MoE 定位,介于 32B 级别 GLM-4-0414 系列与更大规模模型之间。issue 发起人明确表示"如果看起来有前景,我会尝试在它准备好后为这个尺寸合适的 MoE 添加支持"。
社区成员arch-btw在 2025-07-14 补充提醒:GLM-4-MoE-100B-A10B这一名称可能只是占位符,并引用了 HuggingFace 上 THUDM 官方讨论区的截图佐证。这一提醒具有工程意义——在为未发布模型写死架构名与超参数之前,需要确认命名稳定性。
说明:该 issue 目前仍处于开放状态,仓库内尚无
GLM-4-MoE-100B-A10B专属实现。但 GLM-4 系列 MoE 的核心架构在本项目中已有完整实现与落地,这正是本文可以基于源码深入展开的部分。
二、仓库中的 GLM-4 系列架构支持现状
2.1 架构注册表:glm4与glm4moe
在 src/llama-arch.cpp 中,本项目注册了完整的 GLM 系架构名称:
{ LLM_ARCH_CHATGLM, "chatglm" }, { LLM_ARCH_GLM4, "glm4" }, { LLM_ARCH_GLM4_MOE, "glm4moe" },对应的枚举定义位于 src/llama-arch.h。这意味着:
glm4:对应 GLM-4 / GLM-4-0414 系列稠密模型(如 GLM-Z1-Rumination-32B-0414);glm4moe:对应 GLM-4 系 MoE 变体,即本文讨论的 GLM-4-MoE-100B-A10B 在架构层面的归属。
此外,仓库还注册了glm-dsa、glm5next等更新架构(见 src/llama-arch.cpp),说明本项目对 GLM 生态保持着持续的跟进节奏。
2.2 已有的 GLM-4-0414 支持历程
在等待 100B MoE 的同时,项目此前已通过 PR #333 和 #344 合入了对 GLM-4-0414 系列模型的支持。从 PR #333 的描述中可以确认以下事实:
- 该 PR 的目标是引入 piDack 在 llama.cpp 主线 PR#12957 中的改动,以支持
THUDM/glm-4-0414系列; - 发起人当时的实践意图是对 GLM-Z1-Rumination-32B-0414 做 imatrix 与量化,并尝试用"余弦相似度逐层重要性评分"来设计更低 PPL 的量化方案;
- 该 PR 明确标注"在 CUDA 后端不工作,在 CPU 后端可能工作",最终处于 Closed 状态——说明 GLM-4 系架构的落地过程中,后端兼容性是必须重点验证的一环。
这条历史线索对 issue #597 的参考价值在于:即便 GLM-4-MoE-100B-A10B 发布,其支持工作也应沿用"先验证转换脚本 → 再验证 CPU 后端 → 再扩展到 GPU 后端"的渐进路线。
三、glm4moe 架构的源码级实现剖析
3.1 推理图构建:build_glm4_moe
GLM-4 MoE 的完整前向计算图位于 src/graphs/build_glm4.cpp 的llm_build_context::build_glm4_moe()函数。从源码结构看,该实现包含以下关键环节:
1)位置编码与 RoPE 缓存
struct ggml_tensor * inp_pos = build_inp_pos(); auto rope_cache = model.split_mode != LLAMA_SPLIT_MODE_GRAPH && cparams.rope_cache && (rope_type == LLAMA_ROPE_TYPE_NEOX || rope_type == LLAMA_ROPE_TYPE_NORM) ? ggml_rope_cache(...) : nullptr;当满足拆分模式、RoPE 缓存启用且类型为 NEOX/NORM 时,预计算 RoPE 缓存以加速;否则在逐层前向中调用ggml_rope_ext动态计算。
2)自注意力:QKV 合并与多形态权重
auto [Qcur, Kcur, Vcur] = llm_build_mul_mat_qkv(gf, cur, model.layers[il].wqkv, model.layers[il].bqkv, model.layers[il].wqk, model.layers[il].bqk, model.layers[il].wq, model.layers[il].bq, ...);llm_build_mul_mat_qkv同时兼容合并 QKV(wqkv)、QK 合并(wqk)与分离 Q/K/V三种权重布局,这是 GLM-4 系列不同代际权重组织方式并存所必需的。
3)前导稠密层与 MoE 层分区
if ((uint32_t) il < hparams.n_layer_dense_lead) { // dense FFN cur = llm_build_ffn(..., LLM_FFN_SILU, LLM_FFN_PAR, ...); } else { cur = llm_build_std_moe_ffn(ctx0, lctx, model.layers[il].ffn_norm, ffn_inp, model.layers[il].ffn_gate_inp, model.layers[il].ffn_gate_inp_b, model.layers[il].ffn_up_exps, model.layers[il].ffn_up_exps_b, ... n_expert, n_expert_used, LLM_FFN_SILU, hparams.expert_weights_norm, true, hparams.expert_weights_scale, (llm_expert_gating_func_type) hparams.expert_gating_func, LLM_FFN_SILU, cb, il, gf, true, model.layers[il].ffn_up_gate_exps); }这是整个glm4moe架构的核心特征:模型前若干层(n_layer_dense_lead)使用稠密 FFN,其余层切换为专家混合(MoE)FFN。llm_build_std_moe_ffn支持共享专家(shared experts,ffn_*_shexp)与各专家独立的 up/gate/down 权重,并透传门控函数类型。
4)MTP(Multi-Token Prediction)支持
if (cparams.mtp_op_type != MTP_OP_NONE) { ggml_tensor * hidden_states_from_main_model = build_inp_mtp_states(hparams.n_embd); cur = build_glm4_moe_mtp(mtp_layer, hidden_states_from_main_model, n_embd_head, gf, inp_pos, rope_cache); }当启用 MTP 时,最后一层被保留给 NextN 预测头(n_transformer_layers = n_layer - hparams.nextn_predict_layers),主模型只处理前n_transformer_layers层,MTP 模块从主模型隐藏状态继续计算。
3.2 超参数加载与门控函数默认值
在 src/llama-hparams.cpp 中,LLM_ARCH_GLM4_MOE分支加载以下关键超参数:
ml.get_key(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp); // 专家 FFN 维度 ml.get_key(LLM_KV_EXPERT_COUNT, hparams.n_expert); // 专家总数 ml.get_key(LLM_KV_EXPERT_USED_COUNT, hparams.n_expert_used); // 每 token 激活专家数 ml.get_key(LLM_KV_EXPERT_SHARED_COUNT, hparams.n_expert_shared); // 共享专家数 ml.get_key(LLM_KV_LEADING_DENSE_BLOCK_COUNT, hparams.n_layer_dense_lead); // 前导稠密层数 ml.get_key(LLM_KV_EXPERT_WEIGHTS_SCALE, hparams.expert_weights_scale); ml.get_key(LLM_KV_EXPERT_WEIGHTS_NORM, hparams.expert_weights_norm, false); ml.get_key(LLM_KV_EXPERT_GATING_FUNC, hparams.expert_gating_func, false); if (hparams.expert_gating_func == 0) { hparams.expert_gating_func = LLM_EXPERT_GATING_FUNC_SIGMOID; // GLM4_MOE 默认 sigmoid 门控 }源码注释明确指出"GLM4_MOE uses sigmoid":当 GGUF 未写入门控函数类型(默认值 0)时,代码自动回退到LLM_EXPERT_GATING_FUNC_SIGMOID。这是 GLM-4 MoE 与多数使用 softmax 门控的 MoE 模型(如 Mixtral、DeepSeek)的重要区别,加载模型时不可忽视。
加载端在 src/llama-load-tensors.cpp 还做了防御性校验:
GGML_ASSERT(hparams.n_expert > 0 && "n_expert must be > 0 for GLM4_MOE MoE layers"); GGML_ASSERT(hparams.n_expert_used > 0 && "n_expert_used must be > 0 for GLM4_MOE MoE layers");若 GGUF 中专家数或激活专家数为 0,将直接触发断言失败,避免带病进入前向计算。
3.3 数值稳定性与 CUDA 图等特殊处理
GLM4 与 GLM4_MOE 架构在项目中受到多处"特殊照顾",这些处理对量化与推理精度影响显著:
- 半精度累加器的数值问题:在 src/llama-build-context.cpp、L1259-L1260、L2231-L2232 等多处,源码注释均写明"GLM4 and GLM4_MOE seem to have numerical issues with half-precision accumulators",因此在构建上下文时对这两类架构强制使用全精度累加路径;
- CUDA 图与 MTP 拆分:
GLM4_MOE与QWEN35一样被标记为可参与 MTP 的 CUDA 图拆分(见 src/llama-load-tensors.cpp),而 CUDA 图禁用条件中则明确排除了GLM4_MOE(见 src/llama.cpp); - 图拆分支持:在 src/llama-model.cpp 的 MoE 张量并行拆分列表中,
LLM_ARCH_GLM4_MOE被列入支持集合。
这些细节共同说明:glm4moe不是"能跑就行"的移植,而是针对该架构数值特性做了专项调优的成熟实现。
四、从 issue #597 到落地:新增 MoE 架构的接入路径
虽然GLM-4-MoE-100B-A10B尚未发布,但结合仓库现有结构与历史 PR,可以梳理出一条经过验证的接入路径,供后续支持工作参考:
第 1 步:确认架构命名与张量映射(llama-arch)在 src/llama-arch.cpp 注册架构字符串与张量名映射。若 100B MoE 与现有glm4moe张量布局一致,则可能无需新架构,直接复用glm4moe;若引入新权重(如新的门控或偏置),则需要扩展LLM_ARCH_*枚举与LLM_TENSOR_*映射。
第 2 步:验证 GGUF 转换脚本项目根目录的 convert_hf_to_gguf.py 是 HF → GGUF 的唯一入口。PR #333 的历史经验表明:转换脚本的 Python 改动需与 C++ 加载端同步合入,否则会出现"模型能下载、无法加载"的断档。转换时建议使用--outtype bf16并在大模型场景配合--split-max-size分片(参考 PR #333 中--split-max-size 35G的用法)。
第 3 步:校验超参数与门控函数对照 src/llama-hparams.cpp 确认n_expert、n_expert_used、n_expert_shared、n_layer_dense_lead等键在 GGUF 中存在;确认门控函数默认回退 sigmoid 的语义是否适用于 100B MoE(若官方采用不同门控,需显式写入expert_gating_func元数据)。
第 4 步:后端兼容性验证参考 PR #333 的教训——先验证 CPU 后端,再扩展 CUDA。重点检查glm4moe的半精度累加规避逻辑(src/llama-build-context.cpp)与 CUDA 图禁用条件是否在新模型上正确触发。
第 5 步:imatrix 与量化GLM-4 系在 ik_llama.cpp 中的主要实践场景是量化。可复用项目自带的 scripts/get-pg.sh、scripts/qnt-all.sh 等工作流,对 100B-A10B 这种"总参大、激活小"的模型,量化收益将非常显著(推理只接触 10B 激活参数对应的专家权重)。
五、GLM-4 MoE 的量化与部署要点
基于上述架构特征,针对 GLM-4-MoE-100B-A10B 这类模型,在 ik_llama.cpp 中部署时建议重点关注:
| 关注点 | 建议 | 依据 |
|---|---|---|
| 模型转换 | convert_hf_to_gguf.py --outtype bf16,大模型加分片 | convert_hf_to_gguf.py,PR #333 |
| 门控函数 | 确认 GGUF 中expert_gating_func;缺省按 sigmoid 处理 | src/llama-hparams.cpp |
| 前导稠密层 | 关注n_layer_dense_lead,稠密层占比影响量化策略 | src/graphs/build_glm4.cpp |
| 累加精度 | 保持全精度累加路径,勿用半精度累加器 | src/llama-build-context.cpp |
| 专家并行 | 利用 MoE 张量并行与图拆分特性 | src/llama-model.cpp |
| 推理验证 | 先 CPU 后 CUDA,逐层比对输出 | PR #333 历史经验 |
六、小结与展望
issue #597 提出时,GLM-4-MoE-100B-A10B尚处未发布状态,模型命名也可能只是占位符。但通过对当前仓库源码的分析可以确认:
- 架构基础已就绪:
glm4moe架构的推理图、超参数加载、门控回退、数值稳定性处理均已在 src/graphs/build_glm4.cpp 与 src/llama-hparams.cpp 中实现,GLM-4 系 MoE 的核心技术栈在本项目内是完整可用的; - 接入路径清晰:一旦模型正式发布,若其张量布局与现有
glm4moe兼容,理论上只需更新转换脚本与超参数即可支持;若不兼容,则需扩展架构注册与张量映射; - 量化价值明确:100B 总参 / 10B 激活的 MoE 形态,配合本项目对 GLM 系已有的量化实践(见 scripts/qnt-all.sh),是低资源部署大模型的理想目标。
从该 issue 的演进可以看到开源 MoE 支持工作的一般节奏:提前在 issue 中标记方向 → 模型发布后由转换脚本验证 → 逐步打通 CPU/CUDA 后端 → 最终沉淀为稳定的架构实现。对于关注 GLM 生态的开发者,当前即可基于glm4moe架构熟悉推理路径与量化工作流,待 100B-A10B 正式发布后快速落地。
【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考