/ 什么是系列
什么是Checkpoints
从大模型训练和推理两个视角解释 Checkpoint:它保存什么、为什么能断点续训、和模型权重及 .safetensors 的关系,以及它在 vLLM 部署中的角色。
在大模型语境里,Checkpoint 可以先理解成模型训练到某个时刻留下的一份状态快照。
一句话概括:
Checkpoint 把模型参数、训练进度和必要的运行状态保存下来,让后续可以继续训练、回滚版本、评估模型,或者把某个版本拿去部署推理。
这句话里有三个关键词:
- 状态快照:它不是抽象概念,而是落到磁盘上的一组文件。
- 可恢复:训练中断后,可以从最近的 checkpoint 接着跑,而不是从头开始。
- 可交付:推理部署时,加载的通常就是某个已经训练好或量化好的 checkpoint。
中文里有时会把 checkpoint 翻译成检查点、模型快照、模型权重文件。严格说,checkpoint 是更大的概念,权重只是其中最核心的一部分。
1. Checkpoint 到底是什么#
假设你在训练一个模型,参数会随着 step 不断变化:
step 0 初始参数
step 1000 参数更新了一部分
step 10000 参数进一步优化
step 50000 得到一个较好的模型状态如果在 step 50000 把当前模型保存下来,这个保存结果就可以叫一个 checkpoint。
完整训练 checkpoint 往往包含:
模型参数 weights
优化器状态 optimizer state
学习率调度器状态 lr scheduler state
当前训练步数 global step
随机数状态 random state
混合精度 scaler 状态
分布式训练相关状态其中最重要的是模型参数,也就是 weights。但如果目标是“完全恢复训练”,只保存 weights 通常不够,因为 optimizer、scheduler、随机数状态都会影响后续训练轨迹。
所以可以把 checkpoint 分成两种常见理解:
训练 checkpoint = 可恢复训练状态
推理 checkpoint = 可加载模型权重目录它们都叫 checkpoint,但关注点不一样。
2. 训练里的 Checkpoint:为了恢复状态#
在训练场景中,checkpoint 代表的是:
当前训练进度下,整个训练系统的一个可恢复状态。
大模型训练可能持续几天、几周甚至更久,中间任何环节都可能中断:
机器故障
显存 OOM
网络通信错误
训练任务被调度系统杀掉
代码 bug
集群维护如果没有 checkpoint,训练到第 10 天崩了,代价会非常高。有 checkpoint 后,就可以从最近保存点继续:
加载 checkpoint-50000
恢复 optimizer / scheduler / step
继续训练到 checkpoint-60000这就是常说的 resume training。
这里要注意:resume training 不是简单地“重新加载模型权重”。如果只恢复 weights,而不恢复 optimizer state,Adam 的一阶矩、二阶矩会丢失;如果不恢复 scheduler,学习率位置可能错掉;如果不恢复 global step,日志、保存策略、warmup 进度也可能错乱。
因此,训练 checkpoint 更像一次完整的“游戏存档”:不只保存角色属性,也保存当前关卡、背包、任务进度和随机状态。
3. 为什么训练要保存多个 Checkpoint#
训练过程中通常不会只保存最后一个版本,而是周期性保存:
checkpoint-10000
checkpoint-20000
checkpoint-30000
checkpoint-40000
checkpoint-50000这样做有三个直接价值。
第一,防止中断损失扩大。保存间隔越短,故障后需要重跑的 step 越少;但保存太频繁又会占用 I/O 和存储,所以需要权衡。
第二,方便选择最佳模型。训练不一定越久越好。可能训练 loss 还在下降,但验证集效果开始变差。这时 checkpoint-30000 可能比 checkpoint-50000 更适合发布。
第三,方便回滚和对比。如果某次数据、代码或超参数变更后模型行为变差,可以回到较早 checkpoint 做评估,定位问题从哪里开始出现。
所以,checkpoint 不只是容灾工具,也是模型版本管理工具。
4. 推理里的 Checkpoint:为了加载权重#
在推理场景中,checkpoint 通常主要指:
已经训练好、可以被推理框架加载的模型权重目录。
例如启动 vLLM:
vllm serve /data/models/Qwen3-32B-w8a8-sq/这里的 /data/models/Qwen3-32B-w8a8-sq/ 本质上就是一个推理 checkpoint 目录。
推理服务启动时大致会做:
读取 config.json
读取 tokenizer
加载模型权重 checkpoint
根据模型结构初始化参数
把权重搬到 GPU / NPU 显存中
创建 KV cache 管理器
开始接收请求和训练 checkpoint 不同,推理 checkpoint 通常不需要 optimizer state、scheduler state 或 mixed precision scaler。它更关注:
模型结构配置
模型权重
tokenizer
生成配置
量化配置所以在推理里,checkpoint 经常和这些词混用:
模型文件
模型权重
模型目录
部署版本
推理模型包5. 训练 Checkpoint 和推理 Checkpoint 的区别#
二者虽然都叫 checkpoint,但保存内容和使用目的不同。
| 场景 | Checkpoint 代表什么 | 是否包含优化器 | 主要用途 |
|---|---|---|---|
| 训练 | 训练过程的完整可恢复状态 | 通常包含 | 断点续训、回滚、继续训练 |
| 推理 | 训练好或量化好的模型权重目录 | 通常不包含 | 部署、加载模型、生成结果 |
训练 checkpoint 往往比推理 checkpoint 大很多。以 Adam 为例,除了模型参数本身,还要保存一阶矩、二阶矩等 optimizer state。对于大模型来说,完整训练 checkpoint 的体积可能是模型权重本身的数倍。
推理 checkpoint 则更像一个精简交付包。它保留让模型跑起来所需的权重、配置和 tokenizer,但不保留继续训练所需的全部状态。
6. Checkpoint 在模型生命周期里的作用#
大模型不是一次训练完就结束。实际链路里,checkpoint 会贯穿预训练、微调、对齐、量化和部署。
一个常见流程是:
Base checkpoint
↓
SFT 微调
↓
SFT checkpoint
↓
RLHF / DPO / 其他对齐方法
↓
Aligned checkpoint
↓
量化 / 压缩
↓
Inference checkpoint所以 checkpoint 是模型演进的中间产物,也是不同阶段之间的交接物。
例如你可以从一个基础模型开始:
通用大模型 checkpoint
↓
行业数据继续训练
↓
domain-specific checkpoint也可以从一个高精度权重转换出量化版本:
BF16 checkpoint
↓
W8A8 量化
↓
W8A8 checkpoint推理系统最终加载的,就是这个链路上某一个确定版本的 checkpoint。不同 checkpoint 即使模型结构相同,权重不同,模型行为也会不同。
7. Checkpoint 和模型目录是什么关系#
在 Hugging Face 生态里,一个推理可用的模型目录通常长这样:
Qwen3-32B/
├── config.json
├── generation_config.json
├── tokenizer.json
├── tokenizer_config.json
├── model-00001-of-00016.safetensors
├── model-00002-of-00016.safetensors
├── ...
└── model.safetensors.index.json可以这样理解这些文件:
| 文件 | 作用 |
|---|---|
config.json | 描述模型结构,例如层数、hidden size、head 数、rope 配置等 |
*.safetensors | 保存模型权重 tensor,是推理 checkpoint 的核心 |
tokenizer.json | 保存分词器规则和词表信息 |
generation_config.json | 保存默认生成参数 |
model.safetensors.index.json | 记录每个 tensor 位于哪个 shard 文件 |
严格区分一下:
checkpoint = 某一时刻保存下来的模型状态
weights = checkpoint 中最核心的模型参数部分
model directory = 包含权重、配置、tokenizer 的完整目录在日常部署里,大家会把整个模型目录称为一个 checkpoint,这是可以接受的工程简写。
8. .safetensors 是什么#
.safetensors 是一种专门用来保存深度学习张量权重的文件格式。现在 Hugging Face 生态里的大模型权重,很多都会用它保存。
一句话概括:
.safetensors 是一种比 pickle-based .bin、.pt、.pth 更安全,也更适合大模型分发和加载的权重格式。
它保存的是一个个 tensor,例如:
model.embed_tokens.weight
model.layers.0.self_attn.q_proj.weight
model.layers.0.self_attn.k_proj.weight
model.layers.0.mlp.gate_proj.weight
model.norm.weight
lm_head.weight每个 tensor 会有自己的名字、dtype、shape、数据偏移和原始二进制数据:
q_proj.weight: shape = [4096, 4096], dtype = BF16
k_proj.weight: shape = [1024, 4096], dtype = BF16
v_proj.weight: shape = [1024, 4096], dtype = BF16但 .safetensors 不是完整的 Python 模型对象。它通常不保存:
模型 Python 类定义
forward 逻辑
tokenizer 词表
config.json
generation_config.json
训练代码
推理代码所以单独拿到一个 .safetensors 文件,往往不能完整说明“这是什么模型”。它需要和 config.json、tokenizer、index file 等一起使用。
9. .safetensors 内部结构#
.safetensors 的文件结构很简单,可以简化成:
[8 bytes header length]
[JSON header]
[raw tensor data]第一段 8 字节记录 header 长度。第二段是 UTF-8 JSON header,描述每个 tensor 的 dtype、shape 和 data offsets。第三段是连续的权重二进制数据。
可以抽象成这样:
8 bytes:
header_size
JSON header:
{
"model.layers.0.self_attn.q_proj.weight": {
"dtype": "BF16",
"shape": [4096, 4096],
"data_offsets": [0, 33554432]
},
"model.layers.0.self_attn.k_proj.weight": {
"dtype": "BF16",
"shape": [1024, 4096],
"data_offsets": [33554432, 41943040]
}
}
raw tensor data:
一整块连续的二进制权重数据这个设计的好处是:加载器不需要执行 Python 反序列化逻辑,只要解析 header,再按 offset 读取对应二进制数据即可。
10. 为什么叫 Safe#
这里的 safe 主要指:
加载
.safetensors时不需要执行任意 Python 代码。
传统 PyTorch 权重文件,例如:
pytorch_model.bin
model.pt
model.pth很多底层依赖 Python pickle。pickle 的问题是,它不只保存数据,也可能携带对象反序列化逻辑。如果从不可信来源下载权重文件,加载 pickle-based 文件理论上存在执行恶意代码的风险。
.safetensors 的取舍更保守:只保存数值 tensor 和有限 metadata,不保存任意 Python 对象,不执行自定义反序列化代码。因此它更适合第三方模型分发和生产部署。
但 safe 不等于模型一定可信。它解决的是“加载文件时不要执行恶意代码”这个问题,不解决:
模型是否被投毒
模型输出是否安全
权重是否被篡改
license 是否合规
模型是否包含后门行为也就是说,.safetensors 是加载安全,不是内容安全,也不是版权保护或权重加密。
11. 为什么 .safetensors 适合大模型#
它适合大模型,主要有三个工程原因。
第一,更安全。不依赖 pickle,不执行 Python 对象反序列化逻辑,适合从模型仓库下载后直接加载。
第二,支持 lazy loading。加载器可以按需读取某些 tensor,而不是先把整个 checkpoint 反序列化成一个巨大的 Python 对象。对于几十 GB 甚至上百 GB 的模型,这一点很重要。
第三,更适合分片加载。大模型通常会被切成多个 shard,再通过 index file 记录每个 tensor 位于哪个 shard:
model.layers.0.self_attn.q_proj.weight -> model-00001-of-00016.safetensors
model.layers.20.mlp.down_proj.weight -> model-00007-of-00016.safetensors
lm_head.weight -> model-00016-of-00016.safetensors这对 tensor parallel、pipeline parallel、多卡加载和推理框架权重分发都很友好。
可以把 .safetensors 和传统 PyTorch 文件做个对比:
| 对比项 | .safetensors | .bin/.pt/.pth |
|---|---|---|
| 常见用途 | 模型权重分发、推理加载 | PyTorch 权重、训练 checkpoint |
| 是否依赖 pickle | 否 | 通常是 |
| 加载时是否可能执行代码 | 通常不会 | 存在风险 |
| 是否支持 lazy loading | 支持较好 | 较弱 |
| 是否保存任意 Python 对象 | 不支持 | 支持 |
| 适合大模型分片 | 很适合 | 可以,但不如 safetensors 清晰 |
所以 .safetensors 的核心取舍是:牺牲任意对象序列化能力,换取更简单、更安全、更适合大模型加载的权重格式。
12. 为什么会有很多个 .safetensors 文件#
因为模型太大。
一个 32B 模型如果用 BF16 保存,粗略估算就是:
32B 参数 * 2 bytes ~= 64 GB单个文件太大,不方便下载、上传、校验和加载,所以通常会切成多个 shard:
model-00001-of-00016.safetensors
model-00002-of-00016.safetensors
...
model-00016-of-00016.safetensors这些 shard 不是 16 个不同模型,而是同一个模型的权重被拆成了 16 份。一般不能只下载其中一个,而是要完整下载:
所有 .safetensors 分片
model.safetensors.index.json
config.json
tokenizer 相关文件否则加载时很容易遇到:
missing weight
cannot find tensor
cannot find model weights
index references missing shard13. 分布式训练里的 Checkpoint#
分布式训练里,checkpoint 还会更复杂。
大模型参数、梯度和 optimizer state 可能被切到不同 rank 上:
TP shard
PP shard
DP shard
ZeRO optimizer shard
FSDP shard这意味着某个 rank 保存的文件,可能只是完整训练状态的一部分。恢复训练时,框架需要根据并行策略重新组合或重新分发这些 shard。
例如 ZeRO / FSDP 训练中,每张卡可能只保存自己负责的参数 shard 和 optimizer shard。这样可以降低单卡内存和存储压力,但也带来两个问题:
- checkpoint 文件数量更多,目录结构更复杂。
- 更换 world size、并行策略或框架版本时,恢复和转换成本更高。
所以在大规模训练里,checkpoint 不只是“保存一下文件”,而是训练系统设计的一部分。保存频率、异步写盘、分片格式、对象存储、校验、清理策略都会影响训练稳定性和集群效率。
14. Checkpoint 和 KV Cache 不是一回事#
推理里很容易把 checkpoint、KV cache、prefix cache 混在一起。它们不是同一种东西。
| 名称 | 含义 | 生命周期 |
|---|---|---|
| Checkpoint | 模型权重快照或模型目录 | 长期保存,用于加载模型 |
| KV cache | 推理过程中保存的 attention Key / Value | 请求级或会话级,动态产生 |
| Prefix cache | 已计算前缀的 KV 复用 | 推理优化缓存 |
| Activation checkpointing | 训练省显存技术 | 不是模型保存文件 |
在 vLLM 这类推理系统里,可以这样理解:
服务启动时:加载 checkpoint,模型参数固定在显存中
请求进来后:prefill 阶段产生 KV cache
decode 阶段:复用并更新 KV cacheCheckpoint 是模型本身。KV cache 是模型处理某次请求时产生的中间状态。前者长期存在,后者动态产生。
15. Activation Checkpointing 又是什么#
还有一个容易混淆的概念叫:
activation checkpointing
gradient checkpointing它和保存模型 checkpoint 不是一回事。
Activation checkpointing 是一种训练省显存技术。正常训练时,前向传播会保存大量 activation,反向传播时直接使用。activation checkpointing 的思路是:
前向时少保存一些 activation
反向时重新计算一部分 activation
用计算时间换显存空间它的作用是降低显存占用,让训练更大的模型或更大的 batch size 成为可能。代价是训练速度会变慢。
所以它名字里也有 checkpoint,但不是把模型保存到磁盘,而是在训练计算图里选择性保存中间激活。
16. 在 vLLM 推理里怎么理解 Checkpoint#
如果你看到这样的命令:
vllm serve /data/models/Qwen3-32B-w8a8-sq/可以把它理解成:
加载一个已经训练好或量化好的推理 checkpointvLLM 要做的事情大致是:
1. 读取 checkpoint 权重和 config
2. 根据 config 构建模型结构
3. 加载 tokenizer 和 generation config
4. 将权重加载到设备显存
5. 按 tensor parallel / pipeline parallel 切分权重
6. 处理量化权重的加载和 kernel 路径
7. 创建 KV cache 管理器
8. 接收请求并执行 prefill / decode在这个链路里,checkpoint 本身通常不变。推理优化更多发生在这些地方:
权重加载方式
权重分片方式
量化格式
算子实现
KV cache 管理
调度策略
并行通信也就是说,checkpoint 是推理系统的输入资产;vLLM、TGI、SGLang 这类 serving 框架的工作,是把这个资产高效加载、切分、调度并执行起来。
17. 和 GGUF、ONNX、TensorRT Engine 的区别#
.safetensors 不是唯一的模型格式。不同格式服务于不同生态和阶段。
| 格式 | 主要生态 | 典型用途 |
|---|---|---|
.safetensors | Hugging Face / Transformers / vLLM / TGI / SGLang | 保存标准模型权重 |
.gguf | llama.cpp | 本地 CPU / GPU 轻量推理,常见于量化模型 |
.bin/.pt/.pth | PyTorch | 训练、保存 PyTorch 对象或权重 |
.onnx | ONNX Runtime | 跨框架推理图 |
.engine | TensorRT | 已编译优化后的推理引擎 |
.safetensors 更像通用权重存储格式;GGUF 更偏 llama.cpp 推理生态;ONNX 更偏跨框架计算图;TensorRT engine 则是已经针对特定硬件和 shape 编译优化后的产物。
18. 简单读取 .safetensors#
如果想看一个 .safetensors 文件里有哪些 tensor,可以用 safetensors Python 包:
from safetensors import safe_open
path = "model-00001-of-00016.safetensors"
with safe_open(path, framework="pt", device="cpu") as f:
print("metadata:", f.metadata())
for name in f.keys():
tensor = f.get_tensor(name)
print(name, tensor.shape, tensor.dtype)如果只想看 keys,可以这样:
from safetensors import safe_open
with safe_open("model.safetensors", framework="pt", device="cpu") as f:
for key in f.keys():
print(key)保存一个简单的 .safetensors 文件:
import torch
from safetensors.torch import save_file
tensors = {
"linear.weight": torch.randn(4096, 4096, dtype=torch.float16),
"linear.bias": torch.randn(4096, dtype=torch.float16),
}
save_file(tensors, "model.safetensors")这类代码适合做权重检查、格式转换和模型目录排查。但真正的大模型加载,通常交给 Transformers、vLLM 或训练框架的 model loader 处理。
19. 常见误区#
误区一:Checkpoint 就等于 .safetensors#
不准确。
Checkpoint 是概念,.safetensors 是保存 checkpoint 权重的一种文件格式。一个完整推理 checkpoint 目录通常还需要 config.json、tokenizer、index file 和生成配置。
误区二:.safetensors 是模型结构文件#
不是。
.safetensors 主要保存权重 tensor。模型结构通常由 config.json 和框架里的模型实现决定。
误区三:.safetensors 一定是量化模型#
不是。
.safetensors 只是存储格式,可以保存 FP32、FP16、BF16、INT8、FP8、W4A16、W8A8 等不同 dtype 或量化权重。具体是不是量化模型,要看 config.json、quantization_config、目录名和加载器逻辑。
误区四:.safetensors 可以防止模型被盗#
不能。
它不是加密格式。只要别人拿到文件,就可以读取里面的权重 tensor。safe 指的是反序列化加载更安全,不是访问控制、防逆向或版权保护。
误区五:.safetensors 一定让推理 token/s 更快#
不一定。
它更直接影响的是模型启动加载、权重分发和多卡加载阶段。真正 decode 阶段的 token/s 主要取决于 attention kernel、GEMM、KV cache 管理、调度策略、显存带宽、通信性能和量化 kernel。
20. 总结一句话#
Checkpoint 是大模型在某个阶段留下的状态资产:训练时它用于恢复和继续优化,推理时它用于加载权重和部署服务。
如果再把 .safetensors 放进来,可以这样记:
checkpoint 是概念;
weights 是 checkpoint 中最核心的参数;
.safetensors 是保存 weights 的主流安全文件格式;
model directory 是 config、tokenizer、weights 和 index 的完整交付目录。在 AI Infra 里,checkpoint 连接了训练、微调、评估、量化、部署和推理优化。训练系统关心它能不能快速、稳定、完整地保存和恢复;推理系统关心它能不能安全、高效、正确地加载到设备上。
所以,理解 checkpoint,不只是知道“模型权重在哪里”,更是在理解大模型从训练到上线之间最重要的交付边界。
参考资料#
- Hugging Face, Safetensors: https://huggingface.co/docs/safetensors/en/index
- Safetensors GitHub, Format and implementation: https://github.com/huggingface/safetensors
- PyTorch Foundation, Safetensors: https://pytorch.org/projects/safetensors/
- Hugging Face Transformers, Big model loading and sharded checkpoints: https://huggingface.co/docs/transformers/v4.44.2/big_models
- Hugging Face TGI, Safetensors: https://huggingface.co/docs/text-generation-inference/conceptual/safetensors
- vLLM, Loading model weights with fastsafetensors: https://docs.vllm.ai/en/stable/models/extensions/fastsafetensor/