Transformers 中的 Apertus:Swiss AI 8B 级大语言模型的架构解析与使用指南
Apertus 是瑞士人工智能计划(Swiss AI Initiative)发布的开源大语言模型家族,于 2025-08-28 贡献并入 🤗 Transformers。本文以官方模型文档 docs/source/en/model_doc/apertus.md 为主体,结合仓库中的配置、建模与测试源码,逐层拆解 Apertus 的架构设计、配置参数、并行方案与实战用法,帮助读者快速完成加载、推理、微调与二次开发。
Apertus 是什么:来自 Swiss AI Initiative 的开源 LLM 家族
官方模型文档给出的定位非常简洁:Apertus 是瑞士人工智能计划(Swiss AI Initiative,详见其官网 swiss-ai.org 的公开介绍)推出的一族大语言模型(LLM)。它是一个纯 Decoder-only 的因果语言模型家族,在代码仓库中体现为 model_type = "apertus" 的完整实现,源码位于 src/transformers/models/apertus/,共包含 4 个文件:
| 文件 | 职责 |
|---|---|
| configuration_apertus.py | ApertusConfig,模型超参定义与默认值 |
| modeling_apertus.py | 前向计算实现(由 modular 生成) |
| modular_apertus.py | 模块化源文件,真正体现继承与定制关系 |
__init__.py |
导出 ApertusConfig、ApertusModel、ApertusForCausalLM、ApertusForTokenClassification、ApertusPreTrainedModel |
建模代码头部注释明确说明 modeling_apertus.py 是由 modular_apertus.py 自动生成的扁平化文件(CI 强制二者一致),因此任何架构改动都应作用于 modular 源文件而非生成文件——这是理解该目录组织方式的关键。
官方文档首页还标注了 Apertus 支持的能力徽章:FlashAttention、SDPA(PyTorch scaled dot-product attention)、Tensor parallelism(张量并行)。这些能力在源码中都有对应证据(见下文 ApertusPreTrainedModel 的支持标志与并行计划配置)。
架构深度解析:基于 Llama 的"少而精"定制
从 modular 源文件可以最清晰地看到 Apertus 的血统:modular_apertus.py 顶层直接复用了两个既有实现——LlamaAttention / LlamaDecoderLayer / LlamaModel / LlamaForCausalLM / LlamaRMSNorm / LlamaRotaryEmbedding(来自 ..llama.modeling_llama)以及 NemotronMLP(来自 ..nemotron.modeling_nemotron)。这意味着 Apertus 本质上是一个 LLaMA 系架构,再叠加三处关键定制,其中前两处在 modular 中通过继承覆写完成:
定制点 1:Q/K 头部 RMSNorm(per-head normalization)
标准 LLaMA 在 Q/K 投影之后直接施加 RoPE,而 ApertusAttention 在 q_proj/k_proj 之后、RoPE 之前对每个注意力头额外做了一次 RMSNorm:
self.q_norm = ApertusRMSNorm(self.head_dim, config.rms_norm_eps)
self.k_norm = ApertusRMSNorm(self.head_dim, config.rms_norm_eps)
# forward 中:
query_states = self.q_norm(query_states)
key_states = self.k_norm(key_states)
该逻辑见 modeling_apertus.py。注意 Q/K 归一化作用于每个头的 head_dim(由 config.hidden_size // config.num_attention_heads 推导,8B 配置下为 128),而非整个 hidden_size。
定制点 2:双前置 RMSNorm 的残差结构(pre-norm 残差)
与 LLaMA 的 input_layernorm + post_attention_layernorm 布线不同,ApertusDecoderLayer 只保留两个 前置(pre-norm) RMSNorm:attention_layernorm 归一化后进注意力、feedforward_layernorm 归一化后进 MLP,随后各自做残差相加:
residual = hidden_states
hidden_states = self.attention_layernorm(hidden_states)
hidden_states, _ = self.self_attn(hidden_states, ...)
hidden_states = residual + hidden_states # 注意力残差
residual = hidden_states
hidden_states = self.feedforward_layernorm(hidden_states)
hidden_states = self.mlp(hidden_states)
hidden_states = residual + hidden_states # MLP 残差
该结构在 modular 中通过 del self.input_layernorm; del self.post_attention_layernorm 显式删除 LLaMA 父类组件后重建(见 modular_apertus.py 与生成文件 modeling_apertus.py)。
定制点 3:xIELU 激活 + 非门控 MLP
Apertus 的 MLP 选择了一个非常规激活函数 xIELU。仓库在 activations.py 中实现了 XIELUActivation(类文档标注其方法出自 arXiv:2411.13010 对应的工作)。ApertusMLP 的默认配置为 hidden_act="xielu",实例化时携带可学习参数:
self.act_fn = ACT2CLS"xielu" # 使用可学习 alpha_p/alpha_n 的 xIELU
def forward(self, x):
return self.down_proj(self.act_fn(self.up_proj(x))) # 单分支、无 gate 投影
从 XIELUActivation.__init__ 可以看到其参数化细节:可学习的 alpha_p、alpha_n(初始值均为 0.8,经 log-expm1 参数化保证正数域),以及 beta=0.5、eps=-1e-6 等常量 Buffer。实现上有"锦上添花"的加速路径——若用户环境安装了 nickjbrowning/XIELU 的 CUDA wheel,则优先调用 CUDA kernel,否则回退到 Python 实现并给出一次性警告(源码注释原话,见 activations.py)。整个 MLP 是 down_proj(act(up_proj(x))) 的单分支形式,不包含 LLaMA 的 gate_proj 门控结构。
RoPE:复用 LLaMA-3 长上下文缩放
ApertusConfig.__post_init__ 在未显式指定时会填入一组默认 RoPE 参数(见 configuration_apertus.py):
self.rope_parameters = {
"rope_type": "llama3",
"rope_theta": 12000000.0,
"factor": 8.0,
"original_max_position_embeddings": 8192,
"low_freq_factor": 1.0,
"high_freq_factor": 4.0,
}
结合 max_position_embeddings = 65536(64K)可以推断:Apertus 以约 8K 的原始训练长度为基础,通过 LLaMA-3 风格的低/高频分段插值 RoPE(θ=1200 万、factor=8)将上下文能力扩展至 64K。旋转位置编码实现在 ApertusRotaryEmbedding 中完成,其 rope_theta=12000000 同时也被定义为 default_theta 类常量。forward 中强制在 fp32 下计算 cos/sin 并施加 attention_scaling,体现了数值稳定性考虑。
注意力后端:eager / SDPA / FlashAttention / FlexAttention 可插拔
ApertusAttention 通过 ALL_ATTENTION_FUNCTIONS.get_interface(...) 统一分发注意力实现(modeling_apertus.py),与仓库新一代 attention-backend 机制对齐。基类声明了完整的能力矩阵:
_supports_flash_attn = True
_supports_sdpa = True
_supports_flex_attn = True
_supports_attention_backend = True
_can_compile_fullgraph = True
对应的 eager 参考实现 eager_attention_forward 在 softmax 前显式 repeat_kv 扩展 KV 头,并在 fp32 下计算 softmax 后转回原 dtype,以提升数值稳定性(modeling_apertus.py)。
ApertusConfig 配置详解:8B 默认值与关键参数
ApertusConfig 继承自 PreTrainedConfig,以类型注解字段 + strict 校验的方式声明默认值。从配置类默认值(configuration_apertus.py)可以得到 Apertus-8B 的完整超参画像:
| 参数 | 默认值 | 说明 |
|---|---|---|
vocab_size |
131072 | 词表大小(约 128K,对应较大规模的 tokenizer) |
hidden_size |
4096 | 隐藏层维度 |
intermediate_size |
14336 | FFN 中间维度(约 3.5×hidden) |
num_hidden_layers |
32 | Decoder 层数 |
num_attention_heads |
32 | 注意力头数 |
num_key_value_heads |
None | 若为 None 则在 __post_init__ 中取 num_attention_heads(即默认 MHA,可配置为 GQA) |
hidden_act |
"xielu" |
xIELU 激活 |
max_position_embeddings |
65536 | 最大位置数(64K) |
initializer_range |
0.02 | 参数初始化标准差 |
rms_norm_eps |
1e-5 | RMSNorm 的 eps |
use_cache |
True | 推理缓存(KV cache)开关 |
pad_token_id / bos_token_id / eos_token_id |
3 / 1 / 2 | 特殊 token id |
tie_word_embeddings |
False | 默认不捆绑输入/输出词嵌入 |
attention_bias |
False | 各投影层不带 bias |
attention_dropout |
0.0 | 注意力 dropout |
此外还声明了 keys_to_ignore_at_inference = ["past_key_values"](推理时忽略键)与 default_theta = 12000000.0。配置类 docstring 里的标准用法如下:
from transformers import ApertusModel, ApertusConfig
# 初始化一个 Apertus-8B 风格的配置
configuration = ApertusConfig()
# 用配置构建模型
model = ApertusModel(configuration)
# 读取模型配置
configuration = model.config
rope_parameters 是 RopeParameters 类型(也可传 dict),__post_init__ 中的两条推导规则值得注意:其一是 num_key_value_heads=None 时自动对齐 num_attention_heads;其二是 rope_parameters=None 时自动填入上文那组 LLaMA-3 长上下文插值参数。这意味着新建 ApertusConfig() 即得到开箱可用的完整配置。
并行计划:TP / PP / FSDP 的默认布局
Apertus 是少数在配置层内置完整张量并行(TP)与流水线并行(PP)切分计划的模型之一(configuration_apertus.py):
base_model_tp_plan = {
"layers.*.self_attn.q_proj": "colwise", # Q/K/V 按列切分
"layers.*.self_attn.k_proj": "colwise",
"layers.*.self_attn.v_proj": "colwise",
"layers.*.self_attn.q_norm": "replicated_with_grad_allreduce", # 头级 Norm 复制 + 梯度全归约
"layers.*.self_attn.k_norm": "replicated_with_grad_allreduce",
"layers.*.self_attn.o_proj": "rowwise", # 输出投影按行切分
"layers.*.mlp.up_proj": "colwise",
"layers.*.mlp.down_proj": "rowwise",
}
base_model_pp_plan = {
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
"norm": (["hidden_states"], ["hidden_states"]),
}
读法很直观:colwise/rowwise 表明列/行并行切分策略;q_norm/k_norm 这类细粒度模块被标为 replicated_with_grad_allreduce(各 rank 复制一份并在反向时做全归约),这与"Q/K 头级归一化"的定制架构是配套的——TP 后每个 rank 持有部分头,复制归一化参数更利于稳定性。
在 ApertusForCausalLM 上还有与语言模型头相关的补充计划:lm_head 的 _tp_plan 为 colwise_gather_output、_pp_plan 接收 hidden_states 输出 logits,同时 _fsdp_plan 为 keep_full_weight(不切分 lm_head 权重),见 modeling_apertus.py。这些字段说明 Apertus 对 Tensor parallelism / Pipeline parallelism / FSDP 三种分布式范式都做了开箱配置,与官方徽章中的 "Tensor parallelism" 遥相呼应。
快速开始:官方推荐的三种加载方式
模型文档(apertus.md)以 swiss-ai/Apertus-8B 为例展示了生成式用法。文档同时声明了 Pipeline、AutoModel 与命令行三种入口——其中命令行示例在原文档中标注为 "Coming soon"(尚未落地),因此下文完整展开前两种可直接运行的 Python 方式。
方式一:pipeline 一行调用
最简路径使用 text-generation 管线,适合快速冒烟测试:
from transformers import pipeline
pipe = pipeline(
task="text-generation",
model="swiss-ai/Apertus-8B",
device=0, # 指定 GPU
)
pipe("Plants create energy through a process known as")
方式二:AutoModel + AutoTokenizer(可控性最高)
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("swiss-ai/Apertus-8B")
model = AutoModelForCausalLM.from_pretrained(
"swiss-ai/Apertus-8B",
device_map="auto", # 自动设备映射
attn_implementation="sdpa", # 显式选择 SDPA 注意力后端
)
input_ids = tokenizer("Plants create energy through a process known as", return_tensors="pt").to(model.device)
output = model.generate(**input_ids)
print(tokenizer.decode(output[0], skip_special_tokens=True))
AutoModelForCausalLM.from_pretrained 之所以能自动解析为 ApertusForCausalLM,依赖仓库的自动注册表:auto_mappings.py 与 modeling_auto.py 中登记了 ("apertus", "ApertusConfig" / "ApertusModel" / "ApertusForCausalLM" / "ApertusForTokenClassification") 四组映射(见 src/transformers/models/auto/auto_mappings.py)。若不依赖 Auto 类,也可直接导入具名类:
from transformers import ApertusForCausalLM, AutoTokenizer
model = ApertusForCausalLM.from_pretrained("swiss-ai/Apertus-8B-Instruct-2509")
tokenizer = AutoTokenizer.from_pretrained("swiss-ai/Apertus-8B-Instruct-2509")
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)
这段具名用法直接取自 modeling_apertus.py 中 ApertusForCausalLM.forward 的 docstring 示例。仓库标注的默认检查点名为 swiss-ai/Apertus-8B-Instruct-2509(出现在配置类与 docstring 的 @auto_docstring(checkpoint=...) 装饰器中),与文档示例中的 swiss-ai/Apertus-8B 同属该模型家族。
任务入口:三个公开模型的职责划分
除 ApertusConfig 外,文档以 autodoc 形式公开了三个模型类,它们的源码分工如下:
ApertusModel:裸 Transformer 主干(无任务头)。内部由embed_tokens词嵌入、ApertusDecoderLayer堆叠(nn.ModuleList,共 32 层)、末端norm与rotary_emb组成;forward中通过create_causal_mask构造因果掩码、以DynamicCache承载 KV cache,输出BaseModelOutputWithPast。主干代码见 modeling_apertus.py。ApertusForCausalLM:叠加lm_head(无 bias 的hidden_size → vocab_size线性层)的因果语言建模头,混入GenerationMixin获得generate()能力;forward支持labels计算 CE 损失,并以logits_to_keep参数只对必要的尾部 token 计算 logits,降低生成阶段开销;默认不捆绑词嵌入(tie_word_embeddings=False)。见 modeling_apertus.py。ApertusForTokenClassification:继承GenericForTokenClassification+ApertusPreTrainedModel的组合实现(modeling_apertus.py),用于词级分类任务(如 NER)。它与因果 LM 头共用同一个 Apertus 主干。
训练与推理工程化特性
除前述注意力后端外,基类还开启了多项工程特性(modeling_apertus.py):
- 梯度检查点:
supports_gradient_checkpointing = True,且ApertusDecoderLayer继承GradientCheckpointingLayer基础设施,可用model.gradient_checkpointing_enable()以显存换算力; - 全图编译:
_can_compile_fullgraph = True,可配合torch.compile进行训练/推理优化(测试套件中对应test_torch_compile_for_training用例); - KV cache:
use_cache与DynamicCache机制,配合keys_to_ignore_at_inference优化推理路径; - 输出捕获:
_can_record_outputs声明可按ApertusDecoderLayer/ApertusAttention粒度捕获hidden_states与attentions。
测试体系:仓库如何验证 Apertus
模型级测试位于 tests/models/apertus/test_modeling_apertus.py,直接复用 tests/causal_lm_tester.py 提供的通用因果 LM 测试基座(CausalLMModelTester / CausalLMModelTest),这说明 Apertus 已完全纳入 Transformers 的公共测试契约。两个值得关注的细节:
ApertusModelTester强制将attention_probs_dropout_prob设为0.0,代码注释解释:TP 反向测试中非零 dropout 会导致非 TP 与 TP 两次前向的 RNG 状态不一致,进而使 dropout mask 不同、loss 对不上——这是分布式训练测试的典型约束;model_split_percents = [0.5, 0.7, 0.8],注释说明为避开 causal_mask buffer 的边界用例而在 CPU offload 测试中使用 0.8 而非默认 0.9。
测试文件的文件头注释也再次印证了架构出处:"本实现基于 HuggingFace 的 LLaMA 实现,Swiss AI 在训练时做了细微的架构调整"(即上文所述三处定制)。
小结
Apertus 代表了 Transformers 中一类典型的"继承优先、覆盖精修"的模型集成范式:以 LLaMA 的成熟骨架为基础,通过 modular 机制做定向架构创新——Q/K 头级 RMSNorm、双前置归一化的残差布线、xIELU 可学习激活与 LLaMA-3 式 64K 长上下文 RoPE,同时原生集成 SDPA/FlashAttention/FlexAttention 与 TP/PP/FSDP 并行方案。对开发者而言,无论是通过 pipeline、AutoModelForCausalLM 快速上手,还是参考其 TP/PP 计划与 modular 源文件来定制新模型,Apertus 都是不可多得的完整范本。
进一步阅读与验证材料:
- 模型官方文档:docs/source/en/model_doc/apertus.md
- 配置与默认值:src/transformers/models/apertus/configuration_apertus.py
- 前向实现(生成文件):src/transformers/models/apertus/modeling_apertus.py
- 架构继承关系(modular 源):src/transformers/models/apertus/modular_apertus.py
- xIELU 激活实现:src/transformers/activations.py
- 自动类注册:src/transformers/models/auto/modeling_auto.py
- 模型测试:tests/models/apertus/test_modeling_apertus.py
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 StartedRust0624
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