首页
/ Transformers 中的 Apertus:Swiss AI 8B 级大语言模型的架构解析与使用指南

Transformers 中的 Apertus:Swiss AI 8B 级大语言模型的架构解析与使用指南

2026-09-06 18:18:01作者:毕习沙Eudora

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 导出 ApertusConfigApertusModelApertusForCausalLMApertusForTokenClassificationApertusPreTrainedModel

建模代码头部注释明确说明 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_palpha_n(初始值均为 0.8,经 log-expm1 参数化保证正数域),以及 beta=0.5eps=-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_parametersRopeParameters 类型(也可传 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_plancolwise_gather_output_pp_plan 接收 hidden_states 输出 logits,同时 _fsdp_plankeep_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.pymodeling_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.pyApertusForCausalLM.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 层)、末端 normrotary_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 cacheuse_cacheDynamicCache 机制,配合 keys_to_ignore_at_inference 优化推理路径;
  • 输出捕获_can_record_outputs 声明可按 ApertusDecoderLayer/ApertusAttention 粒度捕获 hidden_statesattentions

测试体系:仓库如何验证 Apertus

模型级测试位于 tests/models/apertus/test_modeling_apertus.py,直接复用 tests/causal_lm_tester.py 提供的通用因果 LM 测试基座(CausalLMModelTester / CausalLMModelTest),这说明 Apertus 已完全纳入 Transformers 的公共测试契约。两个值得关注的细节:

  1. ApertusModelTester 强制将 attention_probs_dropout_prob 设为 0.0,代码注释解释:TP 反向测试中非零 dropout 会导致非 TP 与 TP 两次前向的 RNG 状态不一致,进而使 dropout mask 不同、loss 对不上——这是分布式训练测试的典型约束
  2. 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 并行方案。对开发者而言,无论是通过 pipelineAutoModelForCausalLM 快速上手,还是参考其 TP/PP 计划与 modular 源文件来定制新模型,Apertus 都是不可多得的完整范本。

进一步阅读与验证材料:

登录后查看全文
热门项目推荐
相关项目推荐