Tencent Hunyuan-A13B 混元 MoE 模型支持全记录:从 ik_llama.cpp issue 561 到源码实现与量化实战 📅 发布时间:2026/9/19 9:46:36 👁 浏览次数: Tencent Hunyuan-A13B 混元 MoE 模型支持全记录从 ik_llama.cpp issue 561 到源码实现与量化实战【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp导读本文以 ik_llama.cpp 仓库中 issue 561「Feature Request: Tencent Hunyuan-A13B model support」 为主线完整还原腾讯混元 Hunyuan-A13B80B 总参数 / 13B 激活参数的稀疏 MoE 模型从社区请求、上游移植、调试修复到最终合入PR #565的全过程。读者可以借此了解该模型在 ik_llama.cpp 中的hunyuan-moe架构实现注意力、共享专家、路由专家的计算图与张量布局、官方实现与 llama.cpp 生态的差异top-k 路由容量机制、chat 模板、tokenizer并直接获得可用于实际部署的 llama-server 启动参数、imatrix 校准与 IQ4_K 量化配方以及针对该模型「过度调优」特性的采样参数建议。一、请求背景为什么 Hunyuan-A13B「正中 ik_llama.cpp 下怀」issue #561 由用户Downtown-Case于 2025-06-27 提出核心诉求非常明确80B/13B active MoEbenchmark 表现良好。看起来正中 ik_llama.cpp 的下怀——即像 DeepSeek 那样的专家卸载expert offloading。该模型的特点在请求中被概括为自定义架构基于经典的 GQAGrouped Query Attention多头注意力配合 NTK rope scaling整体没有太多「异国情调」的组件稀疏 MoE 规模总参数 80B单 token 激活约 13B 参数属于典型的「大底座 小激活」结构非常适合内存/显存有限如 32GB RAM 24GB VRAM 组合的单机混合推理场景。这一诉求与 ik_llama.cpp 的核心定位高度契合仓库的 README 明确定位为 llama.cpp 的 fork重点在于更好的量化格式与更高的推理性能其中面向 MoE 模型的内存优化专家卸载、按需张量加载正是其特色能力。二、支持落地的关键历程2025-06-27 至 2025-07-122.1 上游状态主线 PR 尚未就绪issue 提出时上游 ggml-org/llama.cpp 已有对应的 PR#14425但ubergarm实测后反馈上游分支还处于 WIP 状态在其上运行 bf16 版本时ik_llama.cpp 更早地在词表加载阶段就报错退出llama_model_loader: - type f32: 161 tensors llama_model_loader: - type bf16: 321 tensors llama_model_load: error loading model: error loading model vocabulary: invalid character llama_load_model_from_file: failed to load model即模型权重张量可以解析但词表vocabulary解析出现非法字符直接导致模型加载失败。这是 Hunyuan-A13B 落地过程中遇到的第一个实质性障碍。2.2 PR #565基于主线的移植与混合推理实测ubergarm于 2025-06-30 提交 PR #565「add hunyuan moe support for 561」PR 描述中说明移植基础是上游 llama.cpp#14425未合并上游的 Python 转换脚本沿用主线 convert 脚本在hybrid CUDA CPU环境下用 bf16 权重完成测试。该 PR 提供的实际部署示例注意其中的专家卸载与 KV 缓存量化参数model/mnt/raid/models/ubergarm/Hunyuan-A13B-Instruct-GGUF/Hunyuan-A13B-Instruct-BF16-00001-of-00004.gguf ./build/bin/llama-server \ --model $model \ --alias ubergarm/Hunyuan-A13B-Instruct-bf16 \ -fa \ -ctk q8_0 -ctv q8_0 \ -c 8192 \ --temp 0.6 \ --presence-penalty 0.7 \ --min-p 0.1 \ -ts 48,48 \ -ngl 16 \ --threads 24 \ --host 127.0.0.1 \ --port 8080关键参数解读参数含义说明-fa开启 Flash Attention对 Hunyuan-A13B 而言几乎必需作者实测不开启 FA 时 perplexity 出现很大的异常数值详见下文-ctk q8_0 -ctv q8_0K/V 缓存量化为 q8_0降低长上下文下的缓存显存占用社区实测q8_0/q5_1缓存在 60K 上下文内依然流畅-c 8192上下文长度演示配置为 8K实际可调至 64K~128K-ts 48,48双卡张量切分比例两路 GPU 各承担一半张量作者为双路 CPU/双卡环境-ngl 16卸载 16 层到 GPU与-ts配合实现混合推理-ngl 99可尝试全量卸载--temp 0.6 --presence-penalty 0.7 --min-p 0.1采样参数社区实测该模型对采样极度敏感需压制温度并加 presence penalty 防循环2.3 三个关键修复点在 PR 讨论与 issue 跟进中围绕该模型暴露了三个技术难点恰好对应 Hunyuan 官方实现与 llama.cpp 生态的三处差异① chat 模板中的多余|startoftext|腾讯官方修复了模型 chat 模板上游 PR #14584对应补丁是删除llama_chat_apply_template_internal中add_ass分支里多余的|startoftext|拼接。ubergarm将该补丁移植到 PR #565 后模型行为得到改善perplexity 数值本身基本持平但生成行为明显更正常。② tokenizer 的「hunyuan」预处理词表加载失败invalid character问题的根源在 tokenizer 侧。在 ik_llama.cpp 中词表构建逻辑专门为 Hunyuan 增加了tokenizer_pre hunyuan与hunyuan-dense的预处理分支见 src/llama-vocab.cpp这也是该模型与普通 BPE/SPM 模型的一个隐性差异点。③ 官方「top-k 路由容量机制」未实现 → PPL 异常issue 中引用了一条上游 PR 评论指出腾讯在modeling_hunyuan.py中实现了一个「特殊」的路由逻辑跟踪每个专家的使用量超过容量的专家会被降优先级de-prioritized导致不同 token 实际使用的专家数量不均、甚至某些 token 不路由到任何专家。该机制「极其难以在 llama.cpp 中重新实现」且官方实现仍按固定专家数计算因此被认为是一处「弄巧成拙」的设计。ubergarm对照官方 PyTorch 参考实现后确认该容量路由机制确实没有在build_moe_ffn()中实现这直接导致 Instruct 版 bf16 权重出现异常高的 perplexity# Instruct 版未实现容量机制CPU 16 线程 -fa -fmoe -rtr Final estimate: PPL 524.7090 /- 5.70049 # 对照未打补丁、CUDA 运行 # PPL 522.7473 /- 5.68072 # Pretrain 基础版同一份代码无 Instruct 的过度调优 Final estimate: PPL 5.2880 /- 0.03236从源码结构看ik_llama.cpp 的build_hunyuan_moe()走的是标准 MoE FFN 路径llm_build_std_moe_ffn固定n_expert_used个专家 共享专家因此与官方训练时的动态容量路由存在行为偏差——这正是 Instruct 版 PPL 异常的原因而 Pretrain 版不受影响。这也是社区建议「用 Pretrain 与 Instruct merge 后再用」的出发点。2.4 合入2025-07-01项目维护者ikawrakow在代码评审中指出此前 GLM4 PR 中曾遇到Vcurreshape 问题Hunyuan 同样需要删除该行这很可能是「开 FA 与不开 FA 结果差异」的根源2025-07-09PR #565 获APPROVED并合入2025-07-12issue #561 由ikawrakow以「Closed via #565」关闭。三、源码视角hunyuan-moe 架构在 ik_llama.cpp 中的实现3.1 架构注册与模型识别架构在 src/llama-arch.cpp 中注册为{ LLM_ARCH_HUNYUAN_MOE, hunyuan-moe },在 src/llama-hparams.cpp 的超参数解析中该架构读取n_ff_exp路由专家 FFN 长度、n_ff_shexp共享专家 FFN 长度与 RMS norm epsilon并按层数识别模型规格case LLM_ARCH_HUNYUAN_MOE: { ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps); ml.get_key(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp); ml.get_key(LLM_KV_EXPERT_SHARED_FEED_FORWARD_LENGTH, hparams.n_ff_shexp); switch (hparams.n_layer) { case 32: model.type e_model::MODEL_80B_A13B; break; default: model.type e_model::MODEL_UNKNOWN; } } break;即 32 层对应80B.A13B80B 总参、13B 激活与 PR #565 实测输出一致llm_load_print_meta: model type 80B.A13B llm_load_print_meta: model params 80.393 B3.2 计算图标准注意力 共享专家 MoE核心前向计算图位于 src/graphs/build_hunyuan.cpp 的build_hunyuan_moe()注意力每层调用build_std_attention使用n_embd_head_v作为头部维度并断言n_embd_head n_rotkq_scale 1/sqrt(n_embd_head)MoE FFN调用llm_build_std_moe_ffn传入路由矩阵ffn_gate_inp、路由专家ffn_up/gate/down_exps、共享专家ffn_up/gate/down_shexp注释说明共享专家没有 bias使用 SiLU 激活与 softmax 门控结尾lctx.cvec.apply_to推理时的控制向量应用、build_output输出层。从该实现可以推断Hunyuan-A13B 的每一层都包含1 个共享专家shared expert 64 个路由专家routed experts每个 token 固定激活若干路由专家n_expert_used并同时经过共享专家——这与 PR #565 的量化配方注释# 1x Shared Expert、# 64x Routed Experts完全一致。3.3 张量布局GQA 与每头 norm张量创建位于 src/llama-load-tensors.cpp 的create_hunyuan_tensors()每层包含layer.attn_norm // RMS norm layer.wq // {n_embd, n_embd_head_k * n_head} layer.wk // {n_embd, n_embd_k_gqa} ← GQA 投影 layer.wv // {n_embd, n_embd_v_gqa} ← GQA 投影 layer.wo // {n_embd_head_k * n_head, n_embd} layer.attn_k_norm // 每头 K norm layer.attn_q_norm // 每头 Q norm layer.ffn_norm layer.ffn_gate_inp // {n_embd, n_expert} // 64 个路由专家ffn_gate_exps / ffn_up_exps / ffn_down_exps layer.ffn_gate_shexp / ffn_up_shexp / ffn_down_shexp // 共享专家宽度 n_ff_shexpwk/wv使用 GQA 压缩维度n_embd_k_gqa/n_embd_v_gqa而非满维度的n_head从源码层面印证了 issue 中「good old GQA」的描述attn_q_norm/attn_k_norm则对应每头归一化per-head norm设计。3.4 chat 模板与 tokenizerchat 模板在 src/llama.cpp 中实现LLM_CHAT_TEMPLATE_HUNYUAN_MOE规则为角色拼接格式system|startoftext| 内容 |extra_4|assistant|startoftext| 内容 |eos|其他user|startoftext| 内容 |extra_0|tokenizer 侧则在 src/llama-vocab.cpp 增加hunyuan/hunyuan-dense预处理分支。这两个文件正是「词汇表加载失败」与「生成时标签混乱」两处问题的修复落点。四、实测观察一个「过度调优」的模型Downtown-Case在 3090/DDR5 环境q8_0/q5_1 KV 缓存、60K 上下文实测后给出详细反馈这些观察对该模型的日常使用极具参考价值不接受裸补全raw completion也不喜欢跳过 thinking 块非常频繁且自信地写错/think结束标签即使在低温度下也会出错think/answer 标签都不是独立 token由多个 token 组成采样时更容易出错极易进入循环温度 1、topK 10 下稍有偏差就复读对句中部分 token 表现出「超自信」的概率分布这在其他模型上少见但综合能力确实聪明长上下文理解测试表现良好。结论是该模型对采样与 chat/think 模板高度敏感必须把采样参数「调准」才能稳定输出。推荐从--temp 0.6 --presence-penalty 0.7 --min-p 0.1这类偏保守的组合起步。五、量化与 imatrix 实战配方5.1 imatrix 校准PR #565 中作者强调该模型跑 imatrix 必须加-fa否则会出现很大的异常数值。实测命令./build/bin/llama-imatrix \ --verbosity 1 \ --layer-similarity \ -m /mnt/raid/models/ubergarm/Hunyuan-A13B-Instruct-GGUF/Hunyuan-A13B-Instruct-BF16-00001-of-00004.gguf \ -f imatrix-calibration-corpus.txt \ -o imatrix-Hunyuan-A13B-Instruct-BF16.dat \ -fa \ --ctx-size 512 \ -ts 48,48 \ -ngl 18 \ --threads 24注意imatrix.dat 不可在 Pretrain 与 Instruct 之间混用社区讨论明确建议只复用公式、不复用数据文件llama_chat_apply_template_internal()不参与 imatrix 计算因此 chat 模板补丁不影响校准数据。5.2 IQ4_K 分层量化配方PR #565 作者发布的首个实验性量化model ftype IQ4_K - 4.5 bpw80.393B 参数48.581 GiB采用了按张量职责分级量化的策略可作为同类 MoE 模型的参考模板# 注意力 blk\..*\.attn_k.*iq6_k blk\..*\.attn_v.*iq6_k blk\..*\.attn_q.*iq5_k blk\..*\.attn_o.*iq5_k # 1x 共享专家 blk\..*\.ffn_(gate|up)_shexp.*iq6_k blk\..*\.ffn_(down)_shexp.*iq5_k # 64x 路由专家 blk\..*\.ffn_(gate|up)_exps.*iq5_k blk\..*\.ffn_(down)_exps.*iq4_k # Token 嵌入 token_embd\.weightiq4_k思路清晰KV 投影与共享专家保留较高精度iq6_k路由专家的 down 投影承载更多参数可以压到 iq4_k最终整体落在 4.5 bpw 附近。该量化后的运行方式与 bf16 相同./build/bin/llama-server \ --model Hunyuan-A13B-Instruct-IQ4_K.gguf \ -fa \ -ctk q8_0 -ctv q8_0 \ -c 524288 \ --temp 0.6 \ --presence-penalty 0.7 \ --min-p 0.1 \ -ts 48,48 \ -ngl 99 \ --parallel 8 \ --threads 1 \ --host 127.0.0.1 \ --port 8080六、混合推理围绕 MoE 专家的 offload 选项issue 讨论中ikawrakow给出了一条重要工程经验直接关系到 Hunyuan-A13B 这类「大底座小激活」模型的混合推理配置解码token generation阶段永远不要把放在 RAM 里的张量卸载到 GPU 计算这太慢了而 prompt 处理阶段几乎所有专家都会分到至少几个 token所以「跳过无 token 专家不卸载」的逻辑在 PP 阶段几乎零加速却徒增复杂度。结合 docs/parameters.md 中相关参数实战中可用的混合推理工具有-ngl N卸载前 N 层到 GPU与-ts张量切分配合-otoverride-tensor用正则表达式覆盖张量存放位置例如\.ffn_.*_exps\.CPU可把全部专家留在 CPU、只把注意力层放 GPU参数说明反向例-ot blk.(?:[0-9]|[1-7][0-9]|[8][0-7]).ffn._exps.CPU按层号批量指定专家回 RAM-ooaeoffload-only-active-experts当专家张量在 CPU、调度器按批拷贝到 GPU 计算时只搬运被激活的专家减少RAM - VRAM数据搬运。该选项对「激活专家数远小于总专家数」的模型收益明显如 GPT-OSS-120BHunyuan-A13B64 选少量专家同样是理想目标参数说明-sm graph多 GPU 时按计算图切分张量与计算对稠密与 MoE 模型都极为有效参数说明-fmoe融合 MoE 的ffn_up与ffn_gate计算以加速 MoE 模型参数说明。另外需特别警惕 README.md 中的警告混合 CPU/GPU 推理 MoE 模型且部分专家留在 CPU 时不要使用-rtrrun-time repack因为 k-quantsK2_K、Q3_K~Q6_K 等没有 CUDA 行交错实现-rtr会把留在 RAM 的张量强制重排为行交错格式导致这些矩阵乘法永远在 CPU 上执行反而拖慢 prompt 处理速度。Hunyuan 的 iq4/iq5/iq6_k 专家权重恰恰属于此类。七、SER 与「可变专家数」的关系issue 讨论中曾设想能否利用腾讯官方「按容量降级专家」的行为跳过某些 token 不需要的专家来加速ikawrakow的回应指出ik_llama.cpp 不存在「可变专家数」的问题因为 SERSmart Expert Reduction见 README.md 中 PR 239 的记录已经解决了相关需求。SER 是 ik_llama.cpp 为加速 DeepSeek 等模型推理而实现的智能专家裁剪技术后续在 README.md 的更新日志中还能看到其 CPUPR 415与 CUDAPR 416侧的修复记录。简而言之Hunyuan-A13B 官方训练时的容量路由属于「训练时特性」推理侧无法也不必要精确复刻ik_llama.cpp 以固定专家数 SER 的方案即可获得稳定性能。八、总结与进一步阅读Hunyuan-A13B 是 ik_llama.cpp 在 MoE 模型支持上的又一次典型落地社区提出诉求#561→ 基于上游移植PR #565→ 解决 tokenizer 词表、chat 模板、FA 一致性三个工程问题 → 合入主分支。目前hunyuan-moe架构已完整存在于仓库中包括架构注册src/llama-arch.cpp超参数识别MODEL_80B_A13Bsrc/llama-hparams.cpp计算图实现src/graphs/build_hunyuan.cpp张量加载src/llama-load-tensors.cppchat 模板src/llama.cpptokenizer 预处理src/llama-vocab.cpp需要强调的是Instruct 版因官方容量路由未实现而 PPL 偏高500Pretrain 版表现正常PPL ≈ 5.3Instruct 版对采样与模板极其敏感部署时应从保守采样参数低温度 presence penalty min-p开始并配合-fa、-fmoe与适合自身硬件的-ngl/-ts/-ot/-ooae混合卸载组合才能获得「funky but usable」的稳定体验。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考