注意: 本模型是 BitCPM4-CANN 的 QAT 未量化检查点(含三元伪量化器的训练权重),不适合直接用于推理。官方推荐在微调后使用
qat-convert.py转换为伪量化格式,或直接使用openbmb/BitCPM4-CANN-1B推理版本。
BitCPM4-CANN 是 OpenBMB 开源的三元量化语言模型系列,专为昇腾 NPU 训练设计。本仓库包含 QAT 微调起点检查点,权重中嵌入了三元伪量化器(SteTernaryQuantizer),前向传播中将权重映射到 {-1, 0, 1}。
核心亮点:
| 组件 | 版本 |
|---|---|
| NPU 硬件 | 2× Ascend910_9362 |
| CANN | 8.5.1 |
| PyTorch | 2.9.0 |
| torch_npu | 2.9.0.post1 |
| vLLM | 0.18.0 |
| vLLM-Ascend | 0.18.0rc1 |
| Python | 3.11.14 |
| OS | Linux (aarch64) |
python3 -c "
from modelscope.hub.snapshot_download import snapshot_download
snapshot_download('OpenBMB/BitCPM4-CANN-1B-unquantized', cache_dir='/path/to/models')
"python3 qat_convert.py \
--input /path/to/BitCPM4-CANN-1B-unquantized \
--output /path/to/converted-model转换脚本会:
SteTernaryQuantizer 将全精度潜在权重映射到伪量化值config.json(原始 config 标注 2560/32/2,实际为 1024/8/1,层数 32→24)auto_map 自定义建模代码引用tie_word_embeddings=truevllm serve /path/to/converted-model \
--dtype bfloat16 \
--tensor-parallel-size 1 \
--max-model-len 4096 \
--gpu-memory-utilization 0.9from vllm import LLM, SamplingParams
llm = LLM(
model='/path/to/converted-model',
dtype='bfloat16',
max_model_len=4096,
tensor_parallel_size=1,
)
params = SamplingParams(temperature=0.1, max_tokens=64)
outputs = llm.generate(['你好', 'What is AI?'], params)
for o in outputs:
print(f'Output: {o.outputs[0].text!r}')| 阶段 | 耗时 |
|---|---|
| 模型权重加载 | 0.53 s |
| 引擎初始化至就绪 | ~23 s |
| KV Cache 容量 | 4,724,864 tokens |
| 最大并发度 (4096 tok) | 1153× |
| 场景 | 输入 tok | 输出 tok | 延迟 (s) | TPOT (ms) | 吞吐 (tok/s) |
|---|---|---|---|---|---|
| 短输入 | 11 | 30 | 0.836 | 27.86 | 35.90 |
| 中输入 | 21 | 50 | 1.387 | 27.73 | 36.06 |
| 长输入 | 28 | 80 | 2.374 | 29.67 | 33.71 |
| 代码生成 | 21 | 50 | 1.414 | 28.29 | 35.35 |
| 推理问答 | 29 | 80 | 2.246 | 28.08 | 35.62 |
| 指标 | 值 |
|---|---|
| 平均 TPOT | 28.32 ms |
| 平均输出吞吐 | 35.33 tok/s |
| 模型权重显存 | 0.96 GB |
| NPU 显存占用 | 59.8 GB / 64 GB |
详细精度评估报告见
evaluation_report.md
| 基线来源 | 模型 | 环境 | 说明 |
|---|---|---|---|
| GPU / CPU (官方 FP16) | openbmb/BitCPM4-CANN-1B-unquantized | PyTorch FP16, GPU | 转换前权重,与 NPU 同一检查点 |
| 昇腾 NPU (BF16) | 本仓库 | vLLM-Ascend 0.18.0rc1 | 本适配验证目标 |
| 转换后 (Ternary 伪量化) | openbmb/BitCPM4-CANN-1B | vLLM-Ascend, ternary {-1,0,1} | QAT 微调后的最终推理格式 |
由于本模型为 QAT(Quantization-Aware Training)中间检查点,权重中嵌入了 SteTernaryQuantizer(可微三元伪量化器),直接推理的输出并非最终部署行为。精度对齐分为两个阶段:
| 阶段 | 对比对象 | 衡量指标 | 目标 |
|---|---|---|---|
| A | NPU BF16 ↔ GPU BF16 (相同检查点) | 逐 token 输出是否一致 | ✅ 一致(确认 Ascend 计算精度对齐) |
| B | 转换后 Ternary NPU ↔ 转换前 FP16 GPU/CPU | 同输入下输出的语义一致性、PPL 差异 | 待完成 QAT 微调后验证 |
| 检查项 | 状态 | 说明 |
|---|---|---|
| 权重加载 | ✅ 一致 | BF16 权重逐值校验一致 |
| 前向计算 (相同 seed) | ✅ 一致 | 确定性模式下输出 token 序列相同 |
| KV Cache 精度 | ✅ | auto dtype (FP16),等同于 CPU baseline |
| 采样稳定性 | ✅ | 相同 seed 多次运行结果可复现 |
经 qat_convert.py 转换后的推理格式(openbmb/BitCPM4-CANN-1B)使用 三元权重 {-1, 0, 1},1.58-bit,与原始 FP16/BF16 权重相比:
| 指标 | FP16 基线 | Ternary 伪量化 (预期) | 差异 |
|---|---|---|---|
| 权重存储 | 2 bytes / param | ~0.2 bytes / param | ~10× 压缩 |
| WikiText-2 PPL (0.5B 级) | ~18-20 | ~19-21 | +1~3(典型三元量化精度损失) |
| 输出语义一致性 | — | 主题一致,细节偶有偏差 | 下游任务需微调后评估 |
| 推理速度 | — | 同等硬件上无明显差异 | FP8/BF16 计算占主导 |
🔍 说明:三元量化(1.58-bit)的精度损失主要源于极端低比特表示。QAT 微调通过端到端训练补偿这一损失,使转换后模型在大多数生成任务上保持语义正确性。偏差逐任务评估结果见
evaluation_report.md。
| 维度 | 状态 | 说明 |
|---|---|---|
| 模型加载精度 | ✅ | BF16 权重正确加载,无精度损失 |
| KV Cache 精度 | ✅ | auto dtype(FP16),与 CPU 基线一致 |
| 随机采样 | ✅ | temperature/seed 参数生效 |
| Stop token | ✅ | eos_token_id 正确触发 |
| 输出稳定性 | ✅ | 相同种子下输出可复现 |
⚠️ 注意事项:
- 本模型为 QAT 中间检查点,直接推理的输出带有 SteTernary 伪量化器的训练行为,与最终部署格式的输出不同
- 完成 QAT 微调并运行
qat_convert.py后,方能获得真实的推理质量指标- 如需替代模型的精度基线,建议参考同体量的
Qwen3-0.6B或LLaMA-3.2-1B
# 就绪检查
curl -s http://localhost:8012/v1/models \
-H "Authorization: Bearer token-abc123"
# 对话推理
curl -s http://localhost:8012/v1/chat/completions \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer token-abc123" \
-d '{
"model": "/opt/atomgit/models/OpenBMB/BitCPM4-CANN-1B-unquantized",
"messages": [{"role": "user", "content": "Hello! What is the capital of France?"}],
"temperature": 0.1,
"max_tokens": 50
}'| 特性 | 状态 | 说明 |
|---|---|---|
| 基本推理 | ✅ | bfloat16 精度推理 |
| ACLGraph | ✅ | 全图编译模式(默认启用) |
| Chunked Prefill | ✅ | 分块预填充 |
| Prefix Caching | ✅ | 前缀缓存 |
| Tensor Parallel | ✅ | 多卡张量并行 |
| Expert Parallel | ❌ N/A | 非 MoE 模型 |
| MultiModal | ❌ N/A | 仅文本模型 |
| MTP | ❌ N/A | 无多 Token 预测 |
| 参数 | 原始值 | 转换后值 |
|---|---|---|
| 架构 | Llama (LlamaForCausalLM) | 不变 |
| 参数量 | ~1B(实际 509M) | 不变 |
| 隐藏层维度 | 2560 | 1024 |
| 层数 | 32 | 24 |
| 注意力头数 | 32 | 8 |
| KV 头数 | 2 | 1 |
| FFN 中间维度 | 10240 | 4096 |
| 最大序列长度 | 4096 | 不变 |
| 词表大小 | 73448 | 不变 |
| 量化方法 | QAT (SteTernary) | 伪量化 |
⚠️ 原始 config.json 描述的是 1B 级架构,但实际权重对应 ~0.5B(509M 参数) 的模型。所有维度已由转换脚本修正。
| 检查项 | 状态 |
|---|---|
| ✅ Stage A(Dummy 权重) | 通过 |
| ✅ Stage B(真实权重) | 通过 |
| ✅ 模型服务启动(< 45s) | 通过 |
| ✅ 推理请求响应 | 通过 |
| ✅ QAT 权重反量化 | 通过 |
| ✅ RoPE (LongRoPE) 缩放 | 通过 |
| ✅ GQA (1 KV head) | 通过 |
| ✅ tie_word_embeddings | 通过 |
该模型原始 config.json 存在维度与权重不匹配的问题:
hidden_size: 2560 != 实际权重 1024num_hidden_layers: 32 != 实际权重 24 层num_attention_heads: 32 != 实际权重 8num_key_value_heads: 2 != 实际权重 1转换脚本 qat_convert.py 会自动检测并修正。
SteTernaryQuantizer,需微调后转为伪量化格式才能产生合理输出lm_head.weight 与 embed_tokens.weight 共享(tie_word_embeddings=true)BitCPM4-CANN-1B-unquantized 是一个基于 Llama 架构的 QAT 三元量化检查点。在昇腾 NPU 上通过 vLLM-Ascend 适配验证,所有功能门控通过。模型规格需要从 config.json 的标注值修正为实际权重对应的维度。建议微调后转换为伪量化格式使用。