首页
/ 在 Transformers 中使用 Ernie 4.5:百度 ERNIE-4.5-0.3B 架构解析、文本生成与源码级实践指南

在 Transformers 中使用 Ernie 4.5:百度 ERNIE-4.5-0.3B 架构解析、文本生成与源码级实践指南

2026-09-07 16:00:20作者:滕妙奇

导读

本文面向希望在 Hugging Face Transformers 框架中加载、运行并深入理解百度 Ernie 4.5 文本基础模型(非 MoE、约 0.3B 参数)的开发者。你将掌握 Ernie4_5 系列在 transformers 仓库中的接入位置、用 AutoTokenizer + AutoModelForCausalLM 完成对话式文本生成的标准流程、Ernie4_5Config 全部关键超参数的作用,以及该模型基于 Llama 核心、叠加 GQA、全维度 RoPE、RMSNorm 与多种注意力后端与并行方案的源码级架构事实。文中所有实现细节均可追溯到仓库内 configuration_ernie4_5.pymodeling_ernie4_5.py 等真实文件。

Ernie 4.5 模型族与本模型定位

Ernie 4.5 模型于 2025 年随百度 Ernie 4.5 模型族发布。该模型族包含多种不同的架构与参数规模;本文档介绍的 ernie4_5 特指面向文本的基础(base)模型、不包含混合专家(MoE)结构、总参数量约 0.3B 的变体,其核心主干采用标准的 Llama 解码器架构。

从仓库源码结构可以确认,ernie4_5 在 transformers 中与同族其他架构分开维护:文本 MoE 变体见 ernie4_5_moe.md,多模态 MoE 变体见 ernie4_5_vl_moe.md。在自动映射层中三者被分别注册为不同的 model_typeernie4_5 映射到 Ernie4_5Model / Ernie4_5ForCausalLM,而 ernie4_5_moeernie4_5_vl_moe 则各自指向独立的实现类(见 modeling_auto.pymodeling_auto.py),这意味着你可以通过 AutoModelForCausalLMAutoConfig 依据 Hub 上的 model_type 字段自动分派到正确实现。

从模块组织看,models/ernie4_5 目录下共有五个文件:

关键架构事实(源码可验证)

通过阅读 modular 源文件 modular_ernie4_5.py 可以看到,Ernie4_5 的实现大量复用了 Llama 与 Olmo 的既有模块:

  • Ernie4_5ForCausalLM 继承自 LlamaForCausalLM(modular 中以 class Ernie4_5ForCausalLM(LlamaForCausalLM) 定义,等价于 Ernie4_5PreTrainedModel + GenerationMixin 的实现);
  • Ernie4_5MLP 继承 LlamaMLP,但按 config.use_biasgate_proj / up_proj / down_proj 三个线性层显式传入偏置开关;
  • Ernie4_5Attention 继承 LlamaAttention,四个投影层同样遵循 use_bias,并固定 attention_dropout = 0.0
  • Ernie4_5RotaryEmbedding 复用 Olmo 的旋转位置编码方式;
  • 正式生成的 modeling_ernie4_5.py 头部声明“由 modular 文件自动生成”,若需改动应修改 modular 源文件,这正是 transformers 官方推荐的 modular 建模流程的实际案例。

也就是说:Ernie 4.5(0.3B 文本版)在架构上是一个“Llama 内核 + Ernie 4.5 特性”的组合,便于复用 Llama 生态中已经充分验证的 KV Cache、注意力后端与生成逻辑。

快速上手:对话文本生成

模型权重由百度官方发布在 Hugging Face Hub,标识符为 baidu/ERNIE-4.5-0.3B-PT(该 checkpoint 在配置类的 @auto_docstring 装饰器中也有引用,见 configuration_ernie4_5.py)。文档给出的标准用法如下:

from transformers import AutoModelForCausalLM, AutoTokenizer


model_name = "baidu/ERNIE-4.5-0.3B-PT"

# 加载 tokenizer 与模型(device_map="auto" 会自动放置到可用设备)
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map="auto",
)

# 准备对话消息
prompt = "Hey, are you conscious? Can you talk to me?"
messages = [{"role": "user", "content": prompt}]
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
)
model_inputs = tokenizer([text], add_special_tokens=False, return_tensors="pt").to(model.device)

# 执行文本补全
generated_ids = model.generate(
    **model_inputs,
    max_new_tokens=32,
)
output_ids = generated_ids[0][len(model_inputs.input_ids[0]):].tolist()

# 解码生成结果
generate_text = tokenizer.decode(output_ids, skip_special_tokens=True)

这段代码的要点:

  1. apply_chat_template 再做 add_special_tokens=False 的二次分词。ERNIE 系列走的是 Llama 风格分词器,其对话格式需要先由模板把 messages 展开为带特殊 token 的纯文本,再编码为输入;若直接对原始 prompt 编码,会丢失 User: / Assistant: 的角色结构。
  2. 切片截取generated_ids[0][len(model_inputs.input_ids[0]):] 只保留新生成的 token,避免把输入 prompt 重复解码进结果。
  3. skip_special_tokens=True 会剔除 <|end_of_sentence|> 等特殊 token(详见下文词表说明)。

集成测试给出的预期输出

仓库中的慢速集成测试 test_modeling_ernie4_5.py 以几乎相同的调用方式对 baidu/ERNIE-4.5-0.3B-PTrevision="refs/pr/3")进行验证,并断言了确定性生成结果。测试还展示了更完整的配置:

tokenizer = AutoTokenizer.from_pretrained("baidu/ERNIE-4.5-0.3B-PT", revision="refs/pr/3")
model = Ernie4_5ForCausalLM.from_pretrained(
    "baidu/ERNIE-4.5-0.3B-PT",
    device_map="auto",
    dtype=torch.bfloat16,       # 显式使用 bf16 精度加载
)
  • 测试覆盖了 cudaxpu 两种后端(通过 Expectations 分别存放期望文本),说明该模型在 CUDA 与 Intel/XPU 加速卡上都应能复现一致输出;
  • 测试对同一 prompt 在 max_new_tokens=128, do_sample=False 下验证输出文本,可作为你本地跑通后核对行为是否一致的参照;
  • dtype=torch.bfloat16 是官方集成测试选用的默认加载精度。

关于 tokenizer 与对话模板的补充事实

官方 checkpoint 仓库本身已提供可直接使用的 HF tokenizer。若需要从 ERNIE 原生格式重建 HF fast tokenizer,可参考仓库内的 convert_ernie4_5_tokenizer.py,其要点包括:

  • 以 Llama 分词器为基础加载,设置 pad_token="<unk>"cls_token="<|begin_of_sentence|>"sep_token="<|end_of_sentence|>"mask_token="<mask:1>",并关闭自动加 BOS(add_bos_token=False);
  • 定义 model_max_length = 131072,与配置中的 max_position_embeddings=131072 保持一致;
  • 额外把 <mask:4> ~ <mask:7> 注册为特殊 token;
  • 内置一个 DEFAULT_CHAT_TEMPLATE:系统消息直接续写文本,用户消息加 User: 前缀,助手消息加 Assistant: 前缀并以 <|end_of_sentence|> 结尾,生成阶段再追加 Assistant: 作为生成起始。这也是 apply_chat_template 背后的具体模板逻辑。

该脚本通过 --repo_name(默认 baidu/ERNIE-4.5-0.3B-Base-PT)、--output_dir--push_to_hub 三个命令行参数控制源仓库、输出位置与是否直推 Hub。

深入理解 Ernie4_5Config:超参数全景

Ernie4_5Config 继承 PreTrainedConfigmodel_type = "ernie4_5"。以下默认值全部来自 configuration_ernie4_5.py,对应“0.3B 规模”的官方结构:

参数 默认值 含义与作用
vocab_size 103424 词表大小,embed_tokenslm_head 的输出维度
hidden_size 1024 隐藏层维度,所有注意力/MLP 投影的输入输出宽度
intermediate_size 3072 MLP 中间层宽度(约为 hidden_size 的 3 倍)
num_hidden_layers 18 解码器层数
num_attention_heads 16 Q 注意力头数
num_key_value_heads 2 KV 头数,小于 Q 头数即启用分组查询注意力(GQA)
hidden_act "silu" 激活函数,配合 SiLU 的 SwiGLU 型 MLP
max_position_embeddings 131072 最长序列 131072(128K),也是 RoPE 缓存上限
initializer_range 0.02 参数初始化标准差
rms_norm_eps 1e-5 RMSNorm 的分母 epsilon
use_cache True 是否缓存 past_key_values 以加速自回归生成
pad_token_id 0 <unk>/填充 token
bos_token_id 1 句首 token
eos_token_id 2 句尾 token <|end_of_sentence|>
tie_word_embeddings True 输入嵌入与 lm_head 权重绑定共享
head_dim 128 单头维度,独立于 hidden_size 显式给出(hidden 1024 / 16 头恰为 64,故 head_dim=128 说明 Ernie 4.5 的头宽并非由整除推导的默认值,必须显式配置)
use_bias False 所有线性投影(含 MLP 与注意力 q/k/v/o)是否加偏置,默认不加
rope_parameters None RoPE 参数(含 rope_typerope_theta 等),可由 Hub 配置注入
default_theta 500000.0 类属性:未显式给出 theta 时的默认 RoPE 基频
keys_to_ignore_at_inference ["past_key_values"] 推理时忽略的键

配置中的两个类级细节值得注意:

  1. use_bias 是唯一被单独写入 docstring 的差异化参数:默认 False,即全部投影都不带偏置项——这是区别于许多开源 Llama 变体(部分实现线性层带 bias)的关键行为。若想复现自定义实验可显式打开。
  2. rope_parameters 作为 RopeParameters 对象接收 rope_typerope_thetaErnie4_5RotaryEmbedding.__init__ 中通过 config.rope_parameters["rope_type"] 决定采用默认 RoPE 还是其他高级类型(如 dynamic rope),见 modeling_ernie4_5.py;默认基频即上表 default_theta = 500000,这一远超常见 10000 的基频与 128K 超长上下文直接相关。

__post_init__ 中还会做两项补齐:若 num_key_value_heads is None 则回退为等于 num_attention_heads(退化为 MHA);若 head_dim 未给出则由 hidden_size // num_attention_heads 推算(见 configuration_ernie4_5.py)。

通过 AutoConfig 读取与修改配置

Ernie4_5Config 已注册进自动映射,可这样直接构造或加载:

from transformers import AutoConfig, Ernie4_5Model, Ernie4_5Config

# 直接以默认参数(0.3B 风格)构造
configuration = Ernie4_5Config()
# 从已发布 checkpoint 读取配置
# configuration = AutoConfig.from_pretrained("baidu/ERNIE-4.5-0.3B-PT")

# 由配置初始化一个随机权重模型(用于自定义实验/继续预训练)
model = Ernie4_5Model(configuration)

# 再次取出配置核对
configuration = model.config

源码级架构拆解:从模块复用走向完整链路

逐层结构与前向流程

modeling_ernie4_5.py 定义,模型自底向上为:

  1. Ernie4_5RMSNormmodeling_ernie4_5.py):T5 风格 RMSNorm 实现——先将隐藏态提升到 float32 计算方差、rsqrt 归一化后再乘可学习 weight 并回落到原 dtype;被 @use_kernel_forward_from_hub("RMSNorm") 装饰,允许从 Hub 拉取替换内核。
  2. Ernie4_5Attentionmodeling_ernie4_5.py):多头注意力。num_key_value_groups = num_attention_heads // num_key_value_heads(默认 16/2=8),缩放因子 scaling = head_dim ** -0.5is_causal = True。q/k/v/o 四投影均由 use_bias 控制;attention_dropout=0
  3. Ernie4_5MLPmodeling_ernie4_5.py):SwiGLU 结构 down_proj(act_fn(gate_proj(x)) * up_proj(x)),激活取自 ACT2FN[config.hidden_act](默认 silu)。
  4. Ernie4_5DecoderLayermodeling_ernie4_5.py):标准 pre-norm 残差解码层——input_layernorm → 自注意力 → 残差相加 → post_attention_layernorm → MLP → 残差相加。该类继承 GradientCheckpointingLayer,天然支持梯度检查点。
  5. Ernie4_5Modelmodeling_ernie4_5.py):词嵌入(nn.Embedding,以 pad_token_id 为 padding_idx)→ 循环 num_hidden_layers 个解码层 → 末端 norm,再配合全局 rotary_emb;前向内部通过 create_causal_mask 生成因果掩码,用 DynamicCache 管理 KV 缓存,返回 BaseModelOutputWithPast
  6. Ernie4_5ForCausalLMmodeling_ernie4_5.py):在 Ernie4_5Model 之上叠加无偏置的 lm_head(hidden → vocab),forward 支持 labels 计算因果语言建模损失,logits_to_keep 控制只对末尾若干位置投影以节省计算。其 _tied_weights_keys 声明 lm_head.weightmodel.embed_tokens.weight 绑定共享,与配置 tie_word_embeddings=True 一致。

Ernie 4.5 特有的 RoPE:全维度 + 全精度

Ernie 4.5 的旋转位置编码在源码中体现了两处与“教科书版”的差异,是理解其长上下文能力的关键:

  • 全维度旋转apply_rotary_pos_emb 中先对 cos/sin 执行 cos[..., : cos.shape[-1] // 2].repeat_interleave(2, dim=-1),将“半维度”形式的旋转矩阵展开为与 q/k 对齐的“全维度交织”形式,再与 rotate_half 配合完成旋转——代码注释明确标注这是 “glm rope style (with full dim)”;
  • 全精度计算:q、k 与 cos、sin 均被 .float() 提升后相乘,最终才回落到 original_dtype,避免低精度下旋转数值漂移;RoPE 生成侧(Ernie4_5RotaryEmbedding.forward)同样用 maybe_autocast(... enabled=False) 强制 float32 计算 cos/sin(见 modeling_ernie4_5.pymodeling_ernie4_5.py)。

注意力后端、训练与并行特性(能力矩阵)

Ernie4_5PreTrainedModel 上声明了一组能力标记(见 modeling_ernie4_5.py):

  • _supports_flash_attn = True_supports_sdpa = True_supports_flex_attn = True:FlashAttention、PyTorch SDPA 与 Flex Attention 后端全部可用(对应模型文档页顶部的 FlashAttention / SDPA 徽章);启用方式为 model = AutoModelForCausalLM.from_pretrained(..., attn_implementation="flash_attention_2")"sdpa"
  • supports_gradient_checkpointing = True:支持梯度检查点训练;
  • _can_compile_fullgraph = True:支持 torch.compile;
  • 注意力函数通过 ALL_ATTENTION_FUNCTIONS.get_interface(...)config._attn_implementation 分发,默认的 eager 实现见 eager_attention_forwardmodeling_ernie4_5.py),其中 softmax 强制 float32 后回落——与上文全精度偏好一脉相承。

在并行维度,Ernie 4.5 是标准的“一条龙式”模型文件示例:

  • 张量并行(TP)在配置类内置 base_model_tp_plan(见 configuration_ernie4_5.py):q/k/v 与 MLP 的 gate/up 投影按 colwise 切分,o 与 down 投影按 rowwise 归约;Ernie4_5ForCausalLM 额外定义 _tp_plan = {"lm_head": "colwise_gather_output"}
  • 流水线并行(PP)由 base_model_pp_plan_pp_plan 描述各阶段输入输出;
  • FSDP 通过 _fsdp_plan = {"lm_head": "keep_full_weight"} 指定权重保持策略。

测试覆盖与工程验证

单测侧,Ernie4_5ModelTester / Ernie4_5ModelTest 复用了通用的因果语言模型测试基类 CausalLMModelTester / CausalLMModelTest(见 test_modeling_ernie4_5.py),可自动获得包括前向、GQA 缓存、torch.compile、CPU offload 等在内的大批量通用用例;同时测试类显式把 model_split_percents 调整为 [0.5, 0.7, 0.8](原注释说明是为规避因果掩码 buffer 的边界情况,将默认 0.9 下调为 0.8)。若你在自己的机器上验证该模型,可直接运行:

python -m pytest tests/models/ernie4_5/test_modeling_ernie4_5.py -k "not slow"

常见问题与实操提示

  • Q:为什么示例中要对同一个 prompt 先 apply_chat_template 再分词? ERNIE 的生成模板需要完整展开 system / user / assistant 三种角色标记。用 tokenize=False 得到模板文本后,再以 add_special_tokens=False 编码,可避免重复插入 BOS;解码侧 skip_special_tokens=True 负责清理 <|end_of_sentence|> 等 token。

  • Q:Ernie 4.5 支持多长的上下文? 配置 max_position_embeddings=131072(128K token),配合 rope_theta=500000 的大基频。注意 RoPE 默认外推能力有限,若需超过训练长度请结合 rope_type(dynamic rope 等)策略使用;模型卡文档页顶部也仅标注了 FlashAttention、SDPA 与张量并行支持,未承诺任何上下文扩展性能。

  • Q:为什么 num_key_value_heads=2num_attention_heads=16 这是标准的 GQA 设计:8 组 Q 共享 1 个 KV 头,在保证效果接近 MHA 的同时显著减少 KV 缓存显存占用,对 128K 超长生成尤为重要。

  • Q:能否本地加载而不依赖网络? 可以。首次执行 from_pretrained 会把权重缓存到本地,之后可离线使用;也可在受控环境中先预下载模型与 tokenizer 再离线加载。

  • Q:训练/微调该模型应如何设置? Ernie4_5ForCausalLM.forward 支持传入 labels 直接返回语言建模损失(modeling_ernie4_5.py),可配合 transformers TrainerTrainingArguments 使用;训练侧建议开启梯度检查点,并可自由切换 SDPA / FlashAttention 后端。

小结

本文以百度 Ernie 4.5 0.3B 文本基础模型为主线,从官方使用代码出发,先后覆盖了:模型族内部 ernie4_5 与 MoE/多模态变体的定位差异;AutoModelForCausalLM + apply_chat_template 的对话生成标准范式及其集成测试佐证;Ernie4_5Config 全部关键超参数表与两处容易被忽略的设计(use_biashead_dim/rope_theta);以及从 modular 建模、Llama 模块复用、GQA + 全维度全精度 RoPE、三后端注意力到 TP/PP/FSDP 并行方案的整体源码事实。需要进一步扩展细节时,可直接研读同族的 Ernie 4.5 MoeErnie 4.5 VL MoE,或对照其底层 Llama 主干文档 Llama

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389