🤗 Transformers 中的 dots.llm1(Dots1)模型:142B 稀疏 MoE 的架构解析与文本生成实战
dots.llm1(对应 Transformers 模型族 Dots1)是由 rednote-hilab 团队发布的 142B 参数混合专家(Mixture-of-Experts, MoE)大语言模型,每个 token 仅激活约 14B 参数。本文基于官方模型文档 dots1.md,结合仓库内模型源码与测试,系统讲解其架构要点、配置字段、并行策略,以及如何使用 Pipeline 或 AutoModelForCausalLM 完成文本生成。
模型背景与核心特性
dots.llm1 是一类"大参数、稀疏激活"的 MoE 模型,其核心设计目标是在保持较强推理/生成能力的同时显著压低训练与推理成本。官方模型文档给出的关键事实如下:
- 总参数量为 142B,每个 token 实际激活 14B 参数;
- 采用 top-6-of-128 路由专家选择(从 128 个路由专家中为每个 token 挑选 6 个),并额外叠加 2 个共享专家(shared experts);
- 官方在发布说明中给出的性能参照为 Qwen2.5-72B,即宣称以更低的激活/训练开销达到相当水平;
- 预训练阶段未使用任何合成数据(no synthetic data)。
模型发布于 2025 年,其模型卡与论文可在 Hugging Face 上以 rednote-hilab/dots.llm1.base 等检查点加载。需要注意的是,文档中"性能与 Qwen2.5-72B 相当""142B/14B 参数"等属于模型发布方的原始描述与仓库文档声明,读者应结合官方论文与评测自行验证。
从代码组织上看,Dots1 并非从零实现的独立模型,而是基于 Transformers 中已有成熟组件"拼装"出来的。通过查看 modular_dots1.py 可以看到其继承关系:
Dots1RMSNorm←Qwen3RMSNormDots1RotaryEmbedding、Dots1Attention←Qwen3RotaryEmbedding/Qwen3AttentionDots1MLP、Dots1TopkRouter、Dots1MoE、Dots1DecoderLayer←DeepseekV3对应组件Dots1Model←Qwen3Model;Dots1ForCausalLM←Qwen3ForCausalLM
这一"Qwen3 注意力骨架 + DeepSeek-V3 风格 MoE"的组合,直接决定了 Dots1 的推理行为,也是理解其"低激活成本"的关键:稀疏门控与分组 Top-k 路由逻辑来自 DeepSeek-V3 的 MoE 实现,而注意力、RoPE 位置编码与 RMSNorm 则沿用 Qwen3 的实现。
仓库采用 modular(模块化)开发流程,modeling_dots1.py 与 configuration_dots1.py 均由
modular_dots1.py自动生成,文件头有明确提示,直接修改生成文件会被 CI 覆盖。
快速上手:加载与文本生成
官方文档提供了两种完全等价的文本生成方式,模型检查点统一为 rednote-hilab/dots.llm1.base(基础版)。运行前请确保环境中已安装可用的 Transformers 版本,并有足够显存容纳权重。
方式一:通过 Pipeline
pipeline 封装了分词、前向推理与解码的全流程,适合快速验证与脚本化调用:
from transformers import pipeline
pipe = pipeline(
task="text-generation",
model="rednote-hilab/dots.llm1.base",
)
pipe("The advantage of mixture-of-experts models is")
task="text-generation" 会自动路由到仓库中与 Dots1ForCausalLM 对应的文本生成流水线(见 pipelines 目录),无需关心底层模型类。
方式二:通过 AutoModelForCausalLM 与 AutoTokenizer
这种方式暴露了更多控制点(如 device_map、解码参数),便于在自定义脚本中精细控制:
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("rednote-hilab/dots.llm1.base")
model = AutoModelForCausalLM.from_pretrained(
"rednote-hilab/dots.llm1.base",
device_map="auto",
)
input_ids = tokenizer("The advantage of mixture-of-experts models is", return_tensors="pt").to(model.device)
output = model.generate(**input_ids, max_new_tokens=50)
print(tokenizer.decode(output[0], skip_special_tokens=True))
要点说明:
device_map="auto"依赖accelerate,可自动把 142B 权重分配到多卡/混合设备上,这是单机加载大 MoE 模型的常规做法;- 通过
max_new_tokens控制生成长度,model.generate内部走 Transformers 统一的GenerationMixin解码循环; - 生成后使用
skip_special_tokens=True过滤掉 BOS/EOS 等特殊 token,使输出更干净。
检查点的两种可加载入口:AutoModelForCausalLM / AutoTokenizer 之所以能识别 dots.llm1,是因为该模型已注册进自动映射表——dots1 → Dots1Config / Dots1Model / Dots1ForCausalLM,参见 auto_mappings.py 与 modeling_auto.py 中的注册条目。因此无需显式 import Dots1ForCausalLM 也能按名字加载。
显式使用模型类
若想跳过 Auto 映射,也可直接 import:
from transformers import AutoTokenizer, Dots1Config, Dots1ForCausalLM
model = Dots1ForCausalLM.from_pretrained("rednote-hilab/dots.llm1.base")
tokenizer = AutoTokenizer.from_pretrained("rednote-hilab/dots.llm1.base")
集成测试中的用法参考
仓库的慢速集成测试给出了"完整加载 → 贪婪解码 → 断言文本"的可复现范式(见 test_modeling_dots1.py):
tokenizer = AutoTokenizer.from_pretrained("redmoe-ai-v1/dots.llm1.test", use_fast=False)
model = Dots1ForCausalLM.from_pretrained("redmoe-ai-v1/dots.llm1.test", device_map="auto")
input_ids = tokenizer.encode(prompt, return_tensors="pt").to(model.model.embed_tokens.weight.device)
# greedy generation outputs
generated_ids = model.generate(input_ids, max_new_tokens=20, do_sample=False)
text = tokenizer.decode(generated_ids[0], skip_special_tokens=True)
该测试类 Dots1ModelTest 继承自 CausalLMModelTest(覆盖标准的前向、梯度、缓存等一致性用例),其 tiny 版 tester Dots1ModelTester 用很小的配置(如 n_routed_experts=8、num_experts_per_tok=8)实例化模型,非常适合想快速验证代码逻辑、又不想下载 142B 权重的读者参考。
Dots1Config:关键配置字段详解
Dots1Config 继承自 PreTrainedConfig,model_type = "dots1",声明于 configuration_dots1.py。它既定义了 Dense 层(注意力/FFN)的超参数,也定义了 MoE 层的全部路由与专家参数。
通用与注意力相关字段
| 配置字段 | 默认值 | 含义 |
|---|---|---|
vocab_size |
152064 | 词表大小 |
hidden_size |
4608 | 隐藏层维度 |
num_hidden_layers |
62 | Transformer 层数 |
num_attention_heads |
32 | 注意力头数 |
num_key_value_heads |
32 | KV 头数(__post_init__ 中为 None 时回退到 num_attention_heads) |
intermediate_size |
10944 | Dense MLP 的中间维度 |
hidden_act |
"silu" | 激活函数(SiLU/Swish) |
attention_bias |
False | 注意力投影是否带偏置 |
attention_dropout |
0.0 | 注意力 dropout 比率 |
use_cache |
True | 生成时是否缓存 KV |
tie_word_embeddings |
False | 是否共享输入/输出词嵌入 |
initializer_range |
0.02 | 参数初始化标准差 |
rms_norm_eps |
1e-6 | RMSNorm 的 epsilon |
max_position_embeddings |
2048 | 预训练位置编码上限 |
rope_parameters |
None | RoPE 超参字典(rope_type、rope_theta 等) |
在 modeling_dots1.py 中可以看到对应实现细节:Dots1RMSNorm 在 fp32 下计算方差并做 rsqrt 归一化后乘回权重;Dots1RotaryEmbedding 依据 rope_parameters 中的 rope_type 决定走默认 compute_default_rope_parameters 还是其他 ROPE_INIT_FUNCTIONS,并可通过 @dynamic_rope_update 支持长上下文动态外推;注意力则注册进统一的 ALL_ATTENTION_FUNCTIONS,同一份代码可切换 eager / SDPA / FlashAttention 等多种实现(模型徽标中也标注了 SDPA 与 Tensor parallelism 支持)。
滑动窗口注意力(关键架构特征)
sliding_window: 4096 —— 滑动窗口大小;max_window_layers: 62 —— 从倒数第几层开始使用滑动窗口注意力;layer_types: 自动生成的分层注意力类型列表。
__post_init__ 中的逻辑决定了 Dots1 采用"分层注意力"(hybrid attention):前部层用 full_attention(全局注意力),后部 max_window_layers 层用 sliding_attention(局部窗口注意力)。规则为——当 sliding_window is not None 且层号 i >= max_window_layers 时该层标记为 sliding_attention,否则为 full_attention:
if self.layer_types is None:
self.layer_types = [
"sliding_attention"
if self.sliding_window is not None and i >= self.max_window_layers
else "full_attention"
for i in range(self.num_hidden_layers)
]
这一设计与推理时的 mask 构造直接相关:modeling_dots1.py 同时 import 了 create_causal_mask(全注意力因果掩码)与 create_sliding_window_causal_mask(滑动窗口因果掩码),前向时会按 layer_types 分发对应的掩码。从源码结构看,其注意力分层做法与 Qwen3、DeepSeek-V3 等近期稀疏注意力模型一脉相承,用于在超长序列上降低全局注意力的平方级开销。
MoE 路由与专家相关字段
| 配置字段 | 默认值 | 含义 |
|---|---|---|
n_routed_experts |
None | 路由专家总数(真实权重为 128) |
n_shared_experts |
None | 共享专家数(真实权重为 2) |
num_experts_per_tok |
None | 每个 token 激活的路由专家数(top-k,真实权重为 6) |
n_group |
1 | 路由专家分组数 |
topk_group |
1 | 参与路由的分组数(分组 Top-k 选择) |
norm_topk_prob |
False | 路由权重归一化方式开关 |
routed_scaling_factor |
1.0 | 路由 logits/权重缩放因子 |
first_k_dense_replace |
0 | 模型开头前 k 层用 Dense MLP 替换 MoE 层 |
moe_intermediate_size |
1408 | 每个专家的 FFN 中间维度 |
其中 attribute_map 将通用属性名 num_local_experts 映射到 n_routed_experts,便于其它模型代码(如分布式工具)复用。官方描述的 "top-6-of-128 + 2 shared" 实际对应配置 n_routed_experts=128、num_experts_per_tok=6、n_shared_experts=2——这些数值来自发布方检查点的真实权重文件,不在默认配置中硬编码(默认 None,表示必须由加载的 checkpoint 提供)。
这些字段的语义直接对应 DeepseekV3TopkRouter 与 DeepseekV3MoE 的实现逻辑(见 deepseek_v3/modeling_deepseek_v3.py):router 把专家分成若干组,先按分组得分选出 topk_group 组,再在组内选出 num_experts_per_tok 个专家;norm_topk_prob 决定路由权重是否做归一化,routed_scaling_factor 与 first_k_dense_replace 则分别控制路由强度的缩放以及"模型开头若干层仍保持稠密计算"的过渡设计。这也解释了为何 Dots1 的"有效参数量"远小于总参数量——每层只有少数专家真正参与前向。
并行策略字段
Dots1Config 内置了三组并行计划,用于张量并行(TP)、流水线并行(PP)与专家并行(EP):
base_model_tp_plan:将注意力q/k/v_proj标记为colwise、o_proj为rowwise,并把专家gate_up_proj标记为packed_colwise(专家 GEMM 融合)、down_proj为rowwise、专家整体为moe_tp_experts;base_model_pp_plan:定义了embed_tokens、layers、norm在各 PP stage 间的输入输出张量契约;base_model_ep_plan:将mlp.gate标为ep_router,把专家的两个投影标为grouped_gemm,即支持把不同专家分布到不同设备上、用分组 GEMM 批量计算。
结合模型文档顶部徽标中的 "Tensor parallelism" 标识,可以推断官方权重即为多卡并行部署做了完整规划;当用户使用 device_map="auto" 或借助 accelerate / 自定义并行工具加载时,这些计划可作为切分依据。
模型 API:Dots1Model 与 Dots1ForCausalLM
文档正文以 autodoc 形式收录了三个公开类,仓库中全部位于 modeling_dots1.py:
Dots1Config
配置类,上文已详解。也可直接以默认超参实例化一个"风格一致的随机初始化配置":
from transformers import Dots1Model, Dots1Config
configuration = Dots1Config()
configuration = model.config # 从已加载模型读取配置
Dots1Model
裸 Transformer 主干,输出 BaseModelOutputWithPast。其 forward 主要参数包括:
input_ids/inputs_embeds:token 序列或其对应的嵌入(二者传其一);attention_mask:注意力掩码;position_ids:位置 id;past_key_values:用于增量解码的 KV 缓存(Cache类型,如DynamicCache);use_cache:是否返回缓存。
Dots1ForCausalLM
在主干之上叠加 LM Head 用于因果语言建模,输出 CausalLMOutputWithPast。除继承主干参数外,关键参数为:
labels(形状(batch_size, sequence_length)):可选。用于计算掩码语言建模损失的标签;取值须在[0, ..., config.vocab_size]内,设为-100的 token 会被忽略(不计入损失);logits_to_keep:生成/训练时只保留末尾若干个位置的 logits,可显著减少显存与计算(默认 0,即返回全部位置)。
该类的 docstring 示例还展示了指令版检查点 dots1.llm1.inst 的对话式生成:
from transformers import AutoTokenizer, Dots1ForCausalLM
model = Dots1ForCausalLM.from_pretrained("rednote-hilab/dots1.llm1.inst")
tokenizer = AutoTokenizer.from_pretrained("rednote-hilab/dots1.llm1.inst")
prompt = "Hey, are you conscious? Can you talk to me?"
inputs = tokenizer(prompt, return_tensors="pt")
generate_ids = model.generate(inputs.input_ids, max_length=30)
tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
参考阅读与进一步探索
- 模型源码主体:modeling_dots1.py
- 配置定义:configuration_dots1.py
- 模块化源头(可读性更高、注释更少但结构清晰):modular_dots1.py
- 测试与可复现范例:test_modeling_dots1.py
- 自动映射注册:auto_mappings.py、modeling_auto.py
- 依赖的基座组件:qwen3/modeling_qwen3.py(RMSNorm/RoPE/Attention/Model)、deepseek_v3/modeling_deepseek_v3.py(MLP/TopkRouter/MoE/DecoderLayer)
小结
Dots1(dots.llm1)展示了 Transformers 生态中"组合式模型开发"的高效路径:通过 modular 机制将 Qwen3 的注意力骨架与 DeepSeek-V3 的分组稀疏 MoE 拼装为全新的 142B 参数模型。本文覆盖了官方文档的全部要点——背景特性、Pipeline 与 AutoModelForCausalLM 两套生成示例、Dots1Config 逐字段说明(MoE 路由、滑动窗口注意力、并行计划),并补充了对应源码与测试作为佐证。若要在自己的机器上实践,推荐先用 device_map="auto" 加载 rednote-hilab/dots.llm1.base 做短文本生成验证,再按需调整 max_new_tokens、采样策略与检查点(base / inst)。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00