【免费下载链接】Ling-3.0-tiny-base
Ling-3.0-tiny-base 是蚂蚁集团 Ling 团队开源的混合线性 MoE 基础模型(总参 7.9B、每 token 仅激活 1.3B)。本文带你源码阅读它的 MoE 门控路由:group-limited TopK 分组选择与 noaux_tc 无辅助损失负载均衡具体是怎么实现的,帮助你快速看懂这份模型仓库的路由核心逻辑。
📦 模型速览:先看这份仓库里有什么
这个仓库是标准的 Hugging Face 格式模型检查点,核心文件一目了然:
| 文件 | 作用 |
|---|---|
| config.json | 模型超参数,路由相关配置都在这里 |
| configuration_bailing_moe_v3.py | 自定义 Config 类,定义路由参数默认值 |
| modeling_bailing_moe_v3.py | 完整模型实现,路由核心在BailingMoeV3Gate |
| model.safetensors.index.json | 权重分片索引,可看到每层的expert_bias |
关键规格(摘自 config.json 与 README.md):
- 专家规模:128 个路由专家 + 1 个共享专家(
num_experts: 128),每 token 只激活8 个路由专家(num_experts_per_tok: 8) - 层结构:24 层,每 4 层为一组,组内 3 层线性注意力 KDA + 1 层 Gated MLA(18 KDA + 6 MLA)
- Dense 层:
first_k_dense_replace: 1表示第 0 层用普通 Dense MLP,从第 1 层起才是 MoE - 路由配置:
n_group: 8、topk_group: 4、topk_method: "noaux_tc"、routed_scaling_factor: 2.5
一句话概括路由策略:128 个专家先分成 8 组,先选 4 个"组",再在组内精选 8 个"专家"——这就是本文主角 group-limited TopK。
🔍 路由全景:一个 token 是怎么被分派的
入口是 modeling_bailing_moe_v3.py 中的BailingMoeV3Gate类。每个 token 的隐状态会经过下面这条流水线:
- 打分:隐状态(fp32 精度,
router_dtype: "fp32")与路由权重矩阵做线性变换,得到 128 个 logits - 激活:用sigmoid而不是 softmax(
scoring_func: "sigmoid"),得到每个专家的原始得分 - 加偏置:原始得分 +
expert_bias(负载均衡用,详见下文) - 分组 TopK 选择:调用
group_limited_topk选出 8 个专家 - 归一化加权:选中的 sigmoid 得分做归一化,再乘以放大系数 2.5
scores = torch.sigmoid(logits.float()).type_as(logits) scores_for_routing = scores + self.expert_bias _, topk_idx = self.group_limited_topk(scores_for_routing)💡 注意一个细节:参与选专家的分数是"得分 + bias",而最终加权用的是不带 bias 的纯得分。bias 只影响"选谁",不影响"权重给多少",这正是 DeepSeek 风格路由的典型做法。
🧩 group-limited TopK:三步选出 8 个专家
核心实现在 group_limited_topk 方法,逻辑分三步,非常好懂:
第一步:128 个专家分成 8 组
n_group: 8,即每组 16 个专家。对每个 token,把 128 维得分 reshape 成(8, 16)的形状——相当于专家被"排队站好",按索引顺序 0~15 是第 0 组,16~31 是第 1 组,依此类推。
第二步:组内取前 2 名求和,选出最强的 4 组
对每组取组内得分最高的 2 个专家,把它们的得分相加,作为该组的"组得分";然后从 8 个组里挑出组得分最高的4 个组(topk_group: 4):
group_scores = scores.view(num_tokens, self.n_group, -1).topk(2, dim=-1)[0].sum(dim=-1) group_idx = torch.topk(group_scores, k=self.topk_group, dim=-1, sorted=False)[1]用"组内前 2 名之和"而不是"组内最高分"来衡量组实力,可以避免"某个组只有一个特别强的专家"导致的误判,让组间竞争更稳健。
第三步:在 4 个入围组里精选 8 个专家
把未入选组的 96 个专家得分置为-inf(掩码屏蔽),再对剩下的4 × 16 = 64个候选专家做全局 TopK,取前 8 名:
masked_scores = scores.masked_fill(~score_mask.bool(), float('-inf')) probs, top_indices = torch.topk(masked_scores, k=self.top_k, dim=-1)为什么要"先分组再选择"?直接对 128 个专家做 Top-8,容易选中挤在同一个区域的"同类专家",造成负载不均。分组限制(group-limited)强制选出的 8 个专家必须分散在至少 4 个组里,天然带来专家多样性,是 Mixtral 以来业界常用的路由设计。
⚖️ noaux_tc 是什么:不靠辅助损失也能负载均衡
传统 MoE 训练时要额外加一个负载均衡辅助损失(aux loss),惩罚"某些专家被过度使用"的现象。而 Ling 采用的是topk_method: "noaux_tc"(配置见 configuration_bailing_moe_v3.py),含义是:
- noaux:不加辅助损失,路由梯度完全来自主任务 loss,训练更稳定、超参更少
- tc(token choice / biased top-k):改用可学习的
expert_bias偏置做负载均衡——哪个专家最近接的 token 多了,就调低它的 bias,让它"自动退热"
在源码里对应的就是这行 buffer 注册(L360):
self.register_buffer("expert_bias", torch.zeros((self.num_experts)))打开 model.safetensors.index.json 可以看到,每一层 MoE 的 gate 下都保存了一份expert_bias权重(全文共出现 24 次,正好对应 24 层中参与 MoE 的路由门)。这份偏置是训练时学出来的"负载均衡记忆",推理时直接加载生效——所以这份开源检查点即使不训练,也能保持训练时均衡的路由行为。
另外 config.json 里的seq_aux: true是训练框架侧的标志位(序列级辅助策略),在这份只含推理实现的 transformers 代码中不参与前向计算,属于保留的训练配置。
📊 关键配置速查表
| 配置项 | 值 | 含义 |
|---|---|---|
| num_experts | 128 | 路由专家总数 |
| num_experts_per_tok | 8 | 每 token 激活的路由专家数 |
| n_group | 8 | 专家分组数(每组 16 个) |
| topk_group | 4 | 先入围的组数 |
| topk_method | noaux_tc | 无辅助损失 + bias 负载均衡 |
| routed_scaling_factor | 2.5 | 路由专家输出整体放大系数 |
| moe_router_enable_expert_bias | true | 启用 expert_bias 偏置 |
| router_dtype | fp32 | 路由计算精度 |
🛠 专家计算:训练与推理两条路径
选完专家后,BailingMoeV3SparseMoeBlock 负责实际计算,这里也做了工程上的双路径设计:
- 训练路径:用布尔索引逐专家分发 token,方便梯度回传
- 推理路径(
moe_infer):先把所有 token 按"专家编号排序"(argsort),每个专家一次性批量处理自己名下的 token,再按原顺序拼回——避免了逐 token 调用的碎片化开销,是典型的 token 重排加速技巧
最终输出 = 8 个路由专家加权求和× 2.5+ 1 个共享专家(shared_experts)的输出。共享专家对每个 token 都参与计算,承担"通用能力底座",让路由专家更专注分工。
🗺 动手读码路线图
如果你是第一次读这份源码,建议按这条线走:
- configuration_bailing_moe_v3.py:先看 MoE 配置段,建立参数概念
- BailingMoeV3Gate:约 60 行,本文的主角
- group_limited_topk:三步选择法的核心 20 行
- BailingMoeV3SparseMoeBlock.forward:看路由结果如何驱动专家计算
- Decoder 层的 Dense/MoE 切换:理解
first_k_dense_replace的生效位置
✅ 小结
Ling-3.0-tiny-base 的 MoE 路由可以用三个词总结:分组限流(group-limited TopK 保证专家多样性)、无辅助损失(noaux_tc 让训练更简单)、偏置负载均衡(expert_bias 把均衡信息固化进权重)。整套路由逻辑集中在BailingMoeV3Gate约 60 行代码里,即使你是 MoE 新手,配合本文的三步拆解也能快速读透。这个检查点同时适合继续预训练、微调与 MoE 系统研究,读完源码再上手实验,效果事半功倍。
【免费下载链接】Ling-3.0-tiny-base
相关推荐
如何读懂 Ling-3.0-flash-Fin 的 MoE 路由:group-limited top-k 的负载均衡指南
如何读懂 Ling 3.0 flash Fin 的 MoE 路由:group limited top k 的负载均衡指南 Ling 3.0 flash Fin
Ling-3.0-tiny-base-30T源码深度解析:BailingMoeV3的KDA、Gated MLA与MoE核心实现原理
Ling 3.0 tiny base 30T源码深度解析:BailingMoeV3的KDA、Gated MLA与MoE核心实现原理 Ling 3.0 tiny
Ling-3.0-flash-Fin-fp4 MoE路由源码解析:512专家、分组限制Top-8与Sigmoid门控的完整实现
Ling 3.0 flash Fin fp4 MoE路由源码解析:512专家、分组限制Top 8与Sigmoid门控的完整实现 Ling 3.0 flash F
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考