深入解析 CPMAnt:Hugging Face Transformers 中的 10B 中文因果语言模型
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
CPMAnt 是由 OpenBMB 团队开源、并于 2023-04-12 贡献进 Hugging Face Transformers 的 10B 参数中文预训练语言模型,也是 CPM-Live 开放训练计划的第一个里程碑。本文以 docs/source/en/model_doc/cpmant.md(及其日文版 docs/source/ja/model_doc/cpmant.md)为骨架,结合仓库内 CpmAntConfig、CpmAntTokenizer、CpmAntModel / CpmAntForCausalLM 的源码实现,系统讲解 CPMAnt 的模型架构、分词器设计、配置项以及基于 Pipeline 和直接调用模型两种文本生成实战方案。
模型概览:CPM-Live 的第一个里程碑
CPM-Ant 是一个拥有 100 亿(10B)参数的开源中文预训练语言模型(PLM),它是 CPM-Live 实时训练流程产出的第一个里程碑模型。CPM-Live 项目以"持续学习、持续演进"为理念,其训练过程强调成本效益与环境友好。除了完整模型外,官方还针对不同硬件配置提供了多种压缩版本,以便在显存受限的环境中也能运行。
从评测角度看,CPMAnt 在CUGE 基准(中文生成与理解评测)的 delta tuning(增量微调)任务上取得了有竞争力的结果。在当前的 Transformers 仓库中,CPMAnt 相关代码位于 src/transformers/models/cpmant/ 目录,由四个文件组成:
| 文件 | 职责 |
|---|---|
| configuration_cpmant.py | CpmAntConfig配置类,定义模型超参数 |
| modeling_cpmant.py | CpmAntModel(基础模型)与CpmAntForCausalLM(因果语言建模头) |
| tokenization_cpmant.py | CpmAntTokenizer,基于 rjieba 分词 + byte-level BPE 的中文分词器 |
| init.py | 模块导出入口(采用_LazyModule惰性加载) |
对应的测试位于 tests/models/cpmant/,包括 test_modeling_cpmant.py 与 test_tokenization_cpmant.py,覆盖了模型前向推理、因果 LM 输出、简单/批量生成以及分词器行为等场景。
快速上手:两种文本生成方式
英文文档给出了两种使用 CPMAnt 生成中文文本的示例,官方 checkpoint 为openbmb/cpm-ant-10b。下面分别介绍。
方式一:使用 Pipeline(推荐快速体验)
Pipeline 封装了 tokenizer、模型与前处理/后处理逻辑,只需两行代码即可完成文本生成:
from transformers import pipeline pipe = pipeline( task="text-generation", model="openbmb/cpm-ant-10b", ) pipe("今天天气很好,")Pipeline 方式会自动加载 CPMAnt 的 tokenizer 与CpmAntForCausalLM模型,并执行标准的自回归解码。
方式二:直接使用 CpmAntForCausalLM
当需要更精细地控制生成参数(如max_new_tokens、device_map、采样策略)时,可以直接实例化模型类:
from transformers import CpmAntForCausalLM, CpmAntTokenizer tokenizer = CpmAntTokenizer.from_pretrained("openbmb/cpm-ant-10b") model = CpmAntForCausalLM.from_pretrained( "openbmb/cpm-ant-10b", device_map="auto", # 自动分配层到可用设备,缓解显存压力 ) input_ids = tokenizer("今天天气很好,", return_tensors="pt").to(model.device) output = model.generate(**input_ids, max_new_tokens=50) print(tokenizer.decode(output[0], skip_special_tokens=True))要点说明:
CpmAntTokenizer与CpmAntForCausalLM均通过from_pretrained("openbmb/cpm-ant-10b")加载,仓库源码 modeling_cpmant.py 的 docstring 中还给出了同样的生成示例,输出形如"今天天气不错,阳光明媚,我和妈妈一起去超市买东西……"的中文续写结果;device_map="auto"依赖accelerate库,可将模型各层自动分布到多 GPU/CPU 上,是运行 10B 量级模型时的常用手段;generate(**input_ids, max_new_tokens=50)指定最多新生成 50 个 token;skip_special_tokens=True在解码时剔除<s>、</s>等特殊 token。
CpmAntConfig:关键配置参数详解
configuration_cpmant.py 定义了CpmAntConfig,其model_type为"cpmant"。该类继承自PreTrainedConfig,所有字段均为类属性并带有默认值,因此可以直接CpmAntConfig()构造一个"cpm-ant-10b 风格"的配置,再传入CpmAntModel(configuration)初始化模型,或通过model.config回读配置。
核心超参数
| 参数 | 默认值 | 说明 |
|---|---|---|
vocab_size | 30720 | 词表大小 |
hidden_size | 4096 | 隐藏层维度 |
num_attention_heads | 32 | 注意力头数 |
dim_head | 128 | 每个注意力头的维度(hidden_size / num_attention_heads) |
dim_ff | 10240 | 前馈网络中间层维度 |
num_hidden_layers | 48 | Transformer 层数 |
dropout_p | 0.0 | 注意力与前馈层 dropout 概率 |
position_bias_num_buckets | 512 | 位置偏置的 bucket 数量 |
position_bias_max_distance | 2048 | 位置偏置的最大距离 |
eps | 1e-6 | RMS LayerNorm 的数值稳定性常数 |
init_std | 1.0 | 参数初始化标准差 |
prompt_types | 32 | prompt 类型数量 |
prompt_length | 32 | prompt 长度 |
segment_types | 32 | segment 类型数量 |
use_cache | True | 是否缓存 KV,加速自回归解码 |
tie_word_embeddings | True | 是否绑定输入输出嵌入 |
自定义配置示例
from transformers import CpmAntModel, CpmAntConfig # 初始化一个 cpm-ant-10b 风格的配置 configuration = CpmAntConfig() # 基于该配置初始化模型(随机权重,非预训练权重) model = CpmAntModel(configuration) # 读取模型配置 configuration = model.config也可以按需修改字段(例如减小层数或调整注意力头维度),构造适合自己显存的小规模模型用于实验。
架构剖析:从源码看 CPMAnt 的模型设计
modeling_cpmant.py 共 783 行,实现了完整的自回归解码器。其核心设计可以从以下几个组件理解。
1. RMS LayerNorm(CpmAntLayerNorm)
CPMAnt 使用Root Mean Square(RMS)Layer Normalization(参考论文 1910.07467),而不是标准的 LayerNorm。从源码 modeling_cpmant.py 可见其实现:在 float32 下计算激活的均方根,用torch.rsqrt(variance + eps)归一化后乘上可学习的权重,并做了 dtype 保持处理。该实现移除了均值中心化,在保证训练稳定的同时降低了计算开销。
2. 多头注意力(CpmAntAttention)
CpmAntAttention 采用标准的 Q/K/V 投影(project_q、project_k、project_v,均为无 bias 的线性层),将 query 与 key 做点积后除以sqrt(dim_head)缩放,然后加上位置偏置position_bias,再通过 attention mask 屏蔽非法区域(填充为-inf),经 softmax 后与 value 加权求和,最后经attention_out投影回原维度。它还支持传入past_key_values(Cache类型)实现 KV 缓存加速解码。
3. 门控前馈网络(CpmAntDenseGatedACT + CpmAntFeedForward)
FFN 采用门控激活结构:CpmAntDenseGatedACT 包含两条并行线性投影w_0、w_1,其中一条经过 GELU 激活后作为门控,与另一条逐元素相乘,再经w_out投影回hidden_size。这种门控设计(类似 SwiGLU 思路)是提升模型表达能力的常用手段。
4. 段位置编码(CpmAntSegmentPositionEmbedding)
CPMAnt 最具特色的设计之一是对位置与段落信息的统一建模。在 modeling_cpmant.py 中,relative_attention_bias参数的大小为segment_types * segment_types + position_bias_num_buckets行 ×num_attention_heads列,融合了两类信息:
- 段相对位置桶(segment-relative position bucket):通过
query_segment * num_segments + key_segment计算,编码 query 与 key 所属段落的关系; - 绝对位置桶(absolute position bucket):对相对位置差采用log 分桶策略——小距离用精确桶,大距离按
log(max_distance / max_exact)的对数比例分桶,从而在有限的 bucket 数量内覆盖到max_distance(2048)的长程距离。
当 query 与 key 属于同一段时使用绝对位置桶,否则使用段相对位置桶,最终经F.embedding得到形如(batch, num_heads, len_q, len_k)的偏置,直接加到注意力分数上。
5. 模型主体:CpmAntModel 与 CpmAntForCausalLM
CpmAntModel 的组成:
input_embedding:词嵌入,维度为vocab_size + prompt_types * prompt_length——为 prompt 预留了额外的嵌入槽位;segment_embedding:段嵌入,维度segment_types × hidden_size;position_bias:上述段位置编码模块;encoder:48 层CpmAntTransformerBlock(自注意力块 + FFN 块的残差堆叠)外加输出 LayerNorm。
在其forward中值得注意的细节(modeling_cpmant.py):
- 自动注入 prompt:当
past_key_values为空(首次前向)时,会在输入序列前面拼接一段长度为prompt_length(32)的特殊 prompt id(区间为[prompt_length*2 + vocab_size, prompt_length*3 + vocab_size)),用于让模型学习固定的引导模式; - 掩码策略:
_prepare_attention_mask构造的是双向可见(span 内)与因果可见(同一段内左到右)的复合掩码,同时屏蔽左侧 padding; - 输出裁剪:首轮前向后会把 prompt 部分从
hidden_states、attentions、hidden states 中裁掉,确保对外暴露的序列长度与用户输入一致; - KV 缓存:使用
DynamicCache(cache_utils.py)管理历史 key/value,解码阶段segment_states只取最后一帧,配合past_length完成增量计算。
CpmAntForCausalLM 在CpmAntModel之上叠加了一个lm_head(hidden_size → vocab_size的线性层,无 bias)。与一般"权重绑定"不同,由于 LM 头只是输入嵌入矩阵的一个切片,checkpoint 中单独保存了lm_head.weight(源码注释明确指出这一点)。该类继承GenerationMixin,可直接调用generate进行文本生成;其forward还支持labels参数计算交叉熵损失,用于微调训练,并且通过logits_to_keep只计算需要的 logits 以节省显存。
CpmAntTokenizer:rjieba 分词 + byte-level BPE
tokenization_cpmant.py 实现的CpmAntTokenizer面向中文场景做了专门设计,其分词流程为:rjieba 中文分词 → WordPiece 子词切分。
依赖与加载
分词器依赖rjieba(Python 的结巴分词绑定)。源码 tokenization_cpmant.py 通过requires_backends(self, ["rjieba"])强制校验,未安装时会报错提示。安装方式:
pip install rjieba特殊 token 体系
CpmAntTokenizer定义了一套面向文档/文本结构的中文特殊 token:
| 参数 | 默认值 | 含义 |
|---|---|---|
bod_token | <d> | 文档开始(beginning of document) |
eod_token | </d> | 文档结束(end of document) |
bos_token | <s> | 序列开始 |
eos_token | </s> | 序列结束 |
pad_token | <pad> | 填充 token |
unk_token | <unk> | 未知 token |
line_token | </n> | 换行 token |
space_token | </_> | 空格 token |
初始化时,分词器会将空格 token 映射为真实空格" "、换行 token 映射为"\n",再把这些"功能化"的 token 从 added tokens 中移除(tokenization_cpmant.py),因此" "与"\n"能直接被词表编码。其默认padding_side="left"(左填充),model_input_names = ["input_ids", "attention_mask"],与模型的注意力掩码设计相匹配。
分词流程
- 先用
rjieba.cut(text, False)将中文文本切分为词语; - 每个词语再交给
WordpieceTokenizer(tokenization_cpmant.py)按最长匹配在词表中切分为子词,找不到则回退到<unk>; - 解码时(
_decode)会自动过滤掉pad、eos、bostoken(tokenization_cpmant.py),convert_tokens_to_string直接以空字符串连接,还原出连续中文文本。
该分词器的行为在 test_tokenization_cpmant.py 中有系统测试覆盖。
模型验证:测试用例如何印证实现
tests/models/cpmant/test_modeling_cpmant.py 通过CpmAntModelTester构造小型 CPMAnt 模型,并利用ModelTesterMixin、PipelineTesterMixin进行了全面验证,其中与本文内容直接相关的用例包括:
test_cpmant_model:验证基础模型前向输出;test_cpmant_lm_head_model:验证带 LM 头的因果模型输出;test_inference_causal:验证因果 LM 的 logits 形状与数值;test_simple_generation/test_batch_generation:验证单条与批量generate文本生成。
这些测试印证了 CPMAnt 在仓库中已经实现为可直接用于推理与生成的完整因果语言模型,开发者可以参考它们了解模型的输入输出契约,或在自己环境中复现验证。
应用建议与注意事项
- 显存考量:CPMAnt 拥有 10B 参数,直接以 fp32 加载需要约 40GB 显存。实际使用建议:
- 使用
device_map="auto"自动分片; - 开启 8-bit / 4-bit 量化(如
load_in_8bit=True)或使用官方提供的压缩版本 checkpoint; - 生成时通过
max_new_tokens限制生成长度,并善用 KV 缓存(use_cache=True为默认)。
- 使用
- 运行环境:需安装
transformers、torch、rjieba;多设备分片还需accelerate。 - 中文续写场景:CPMAnt 适合中文开放式文本生成、对话与内容续写等任务;在 CUGE 基准的 delta tuning 任务上表现良好,也可在其上做 LoRA 等轻量微调。
- 模型规模:从配置看,48 层、32 头、
hidden_size=4096、dim_ff=10240的结构属于典型的"大模型"配置,适合有充足算力与显存资源的场景。
总结
CPMAnt 作为 CPM-Live 开放训练计划的首个成果,在 Transformers 仓库中提供了完整的配置、分词、建模与生成支持。其架构融合了 RMS LayerNorm、门控 FFN、段位置编码与 prompt 注入机制,分词器则以"rjieba + WordPiece"的组合服务于中文场景。无论是通过pipeline快速体验,还是借助CpmAntForCausalLM深度定制生成与微调,开发者都可以从 src/transformers/models/cpmant/ 出发,结合本文的配置说明与源码解析快速上手。
注:本文以仓库当前代码为准,模型权重与官方压缩版本请以 Hugging Face Hub 上
openbmb/cpm-ant-10b的实际文件为准;CUGE 基准与 CPM-Live 训练细节详见 OpenBMB 官方项目资料。
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考