我们已经用 Ollama 在本地运行了 Qwen3 0.6B。运行命令很简单,但只要开始寻找其他模型,很快就会遇到一连串陌生词:Model Card、checkpoint、BF16、Q4_K_M、Safetensors、GGUF 等等。
新概念比较多,有的表示模型托管平台,有的表示训练状态,有的描述数字精度,还有的只是保存权重的文件格式。
这篇文章从 Qwen 官方的 Hugging Face 模型页面出发,先看清一个模型仓库里有哪几类文件,再把这些新词逐个挂到对应的文件上,它们就不难理解了。
Hugging Face 到底是什么
Hugging Face Hub 可以理解成面向 AI 模型的 GitHub。开发者可以在上面发布模型仓库、保存文件版本、展示使用文档、声明许可证,也可以让 Transformers、Ollama 等工具下载这些文件。
一个模型页面最常用的两部分是:
- Model Card(模型卡):类似项目的 README,说明模型是谁训练的、能做什么、不能做什么、如何使用以及采用什么许可证。
- Files(文件):模型真正的交付物,包括权重、模型结构配置和 tokenizer 等。

打开 Qwen3 0.6B 的官方页面,右侧信息卡上有两个值得留意的字段:Model size 0.8B params 和 Tensor type BF16。
名字里写的是 0.6B,页面却统计出 0.8B。两个数都没错,只是数法不同:名字按模型逻辑上有多少个不重复的参数算,页面按权重文件里实际存了多少个数算。
BF16 是另一个维度的事,它表示权重保存时每个数字的精度,后面讲精度时再展开。
读懂模型卡
模型名称和参数量不能完整说明能力。模型卡通常还会写清楚:
- 这是 Base 模型、Instruct 模型还是 Chat 模型。
- 主要支持哪些语言和任务。
- 训练数据、评测结果和已知限制。
- 许可证是否允许自己的使用场景。
- 推荐使用哪个推理框架和提示词格式。

Qwen3 的模型卡就把这些交代得很清楚:支持思考模式与非思考模式、原生上下文多长、怎么开关思考输出。
当然,0.6B 毕竟是很小的模型,模型卡上宣传的推理、Agent 这些能力到底够不够用,还得拿自己的任务实测。
名称中的 Base 和 Instruct 的区别,LLM 和 Agent 的核心术语和原理里专门讲过:Base 模型是纯粹的文本补全模型,只会「接话」,一般用作继续预训练或微调的起点;Instruct 模型在它基础上做过指令对齐,会把你的输入当成问题来回答。
所以日常聊天要选 Instruct 或 Chat 版本。Qwen3 0.6B 的官方仓库带有对话模板并支持 conversational,Ollama 可以直接把用户消息组织成适合它的输入。
一个 LLM 由哪几类文件组成
切换到 Files 页签,可以看到模型仓库的实际内容。为了让文件列表在未来仍能复现,下面固定到 revision c1899de。主要文件包括:
LICENSE
README.md
config.json
generation_config.json
merges.txt
model.safetensors
tokenizer.json
tokenizer_config.json
vocab.json
文件不少,先做个分类,README.md 就是网页上展示的模型卡,LICENSE 记录授权条款,这两个是给人看的说明文件。
剩下的文件才是模型本体,可以归成三类:
| 文件类别 | 对应文件 | 作用 |
|---|---|---|
| 权重文件 | model.safetensors | 保存模型学到的所有参数 |
| 配置文件 | config.json、generation_config.json | 说明模型结构和默认生成配置 |
| tokenizer 文件 | tokenizer.json、tokenizer_config.json、merges.txt、vocab.json | 定义文字和 token 如何互相转换 |
所以「从 Hugging Face 下载模型」往往不是下载一个能双击运行的程序,而是下载这样一组文件,交给推理框架共同解释:权重提供模型学到的数字,配置说明如何搭建网络,tokenizer 负责在文字和 token 之间转换。
之前用 Ollama 在本地运行大模型时,ollama run 一条命令就把这些事全办了,所以你只看到一个对话框。下面挨个打开看看,它们各自装着什么。
权重文件:模型学到的参数
model.safetensors 有 1.50GB,比其他文件加起来还大得多,因为它保存了训练得到的全部参数,也就是模型权重。
权重是模型的本体,平时说「下载模型」,主要就是在下载它。这 1.50GB 的权重其实就是一块块张量(tensor)。
张量就是「多维数组」在机器学习里的叫法,每块都带一个形状(shape),说明张量有几个方向、每个方向多长,看几个例子:
shape tensor
1D [3] [0.1, 0.2, 0.3]
2D [2, 3] [[0.1, 0.2, 0.3],
[0.4, 0.5, 0.6]]
3D [2, 2, 3] [[[0.1, 0.2, 0.3],
[0.4, 0.5, 0.6]],
[[0.7, 0.8, 0.9],
[1.0, 1.1, 1.2]]]说白了张量就是多维数组,形状为 [3] 的张量就是长度为 3 的一维数组,形状为 [2,3] 的张量就是 2 行 3 列的二维数组(矩阵)。权重文件里基本都是一维和二维张量,三维以上要到成批处理数据时才常见。
明白了这个名词,来看 model.safetensors 文件。文件开头是一份清单,记着里面每个张量叫什么、形状多大,Qwen3 0.6B 一共列了 311 个,挑几个看看:
model.embed_tokens.weight [151936, 1024]
model.layers.0.self_attn.q_proj.weight [2048, 1024]
model.layers.0.mlp.gate_proj.weight [3072, 1024]
...
model.layers.27.mlp.down_proj.weight [1024, 3072]第一行 embed_tokens 就是 LLM 是怎么预测下一个 token 的 里讲过的 embedding 矩阵,形状 [151936, 1024] 说明它是个二维张量:151,936 行是词表容量,每个 token 占一行,每行 1,024 个数。
后面几行是注意力和前馈网络的权重,名字里的 layers.0、layers.27 是层号,这款模型一共 28 层。
清单后面才是正文,也就是每个张量的具体数字。把 embedding 矩阵铺开,大致长这样:
model.embed_tokens.weight [151936, 1024]
col 0 col 1 col 2 ... col 1023
row 0 -0.00928 0.03369 -0.07471 ... 0.01599
row 1 0.03198 0.02380 -0.05933 ... 0.00903
...
row 14990 -0.04517 0.00081 0.01868 ... -0.00952
...
row 151935 0.00604 0.01312 0.01904 ... 0.00568151,936 乘以 1,024 是 1.56 亿个数,每个数占 2 byte,光这一张表就占 311MB。多个张量累加起来,就凑出了 1.50GB。
模型「学到的东西」就是这样一堆二维矩阵,没有一个是人写的,全是靠训练时一步步调出来的。
如果模型的权重太大,还可能被拆成 model-00001-of-00004.safetensors 等多个分片,并由索引文件记录每个张量在哪个分片中。这些分片合起来才是一套完整的模型权重。
配置文件:模型结构的说明书
光有一大堆参数还不够,推理框架得知道怎么把这些数字组装成一个神经网络,这就是 config.json 的活儿。节选几行:
{
"num_hidden_layers": 28,
"num_attention_heads": 16,
"hidden_size": 1024,
"vocab_size": 151936,
"max_position_embeddings": 40960
}这几个数字在LLM 是怎么预测下一个 token 的里都照过面:
vocab_size 和 hidden_size 正是 embedding 矩阵的 151,936 行、1,024 列;num_attention_heads 是多头注意力的头数;num_hidden_layers 说明这样的层要叠 28 遍;max_position_embeddings 是位置编码能覆盖的最大 token 数,也就是上下文长度的上限。推理框架照着这些数字把骨架搭起来,再把权重文件里同名的矩阵填进去。
generation_config.json 管的是另一件事,生成文本时的默认采样参数,同样节选几行:
{
"temperature": 0.6,
"top_p": 0.95,
"top_k": 20
}这三个值应该眼熟,ollama show qwen3:0.6b 显示的就是它们,模型作者调好写在这里,转成 Ollama 用的格式时一起带了过去。你不指定采样参数时,用的就是这一套。
这两个都是很小的 JSON 文件,但少了它们,权重就只是一堆没法组装的数字。
tokenizer 文件:文字和 token 的转换
LLM 是怎么预测下一个 token 的里讲过,模型不直接处理文字,输入要先被切成 token,输出的 token 也要再拼回文字。
那篇文章拆过的两个文件就在这里:vocab.json 是词表,记着哪个 token 对应哪个编号;merges.txt 是 BPE 合并规则,一共 151,387 条,按训练时学到的先后顺序排列。
另外两个文件的角色不一样:
tokenizer.json可以理解成vocab.json和merges.txt的合并升级版:同样的词表和合并规则装进一个文件,再补上切分流程的其余规则,比如标点怎么预切分、有哪些特殊 token、token 怎么解码回文字。它是如今 tokenizer 库实际读的那个;vocab.json和merges.txt这两个老文件的内容跟它完全重合,留着是给旧版实现读的。tokenizer_config.json里没有完整词表,只有几 KB,记的是这个 tokenizer 该怎么用:结束符是哪个 token、最长支持多少 token,还有前面提过的对话模板——把「谁说了什么」拼成模型认识的格式,<|im_start|>、<|im_end|>这些标记就是在这里定义的。
它们加起来也就十几 MB,和权重文件完全不是一个量级。
其中的对话模板值得多说两句,它能解释一个常见疑问:模型只会一个接一个地续写 token,多轮对话和「思考过程」是怎么冒出来的?
答案全在那几个标记上。你问一句「1+1 等于几?」,tokenizer 会先按模板把它拼成这样,再交给模型:
<|im_start|>user
1+1 等于几?<|im_end|>
<|im_start|>assistant模型顺着这段文字往下续写,思考和回答一并吐出来,中间用标记隔开:
<think>
好的,用户问的是“1+1等于几?”。首先,我需要确定用户的问题类型。这是一个常见的数学问题……
</think>
1加上1等于2。这是一个基本的加法运算,无需额外步骤。如果你需要更多数学练习或帮助,请随时告诉我。<|im_end|>推理框架收到的就是这么一串连续文本,它按 </think> 切一刀,前半段作为思考内容,后半段作为正式回复,看到 <|im_end|> 就停止生成。
你在 API 响应里看到的「思考过程」和「正式回复」两个字段,就是这么分出来的。模型自己并不区分这两者,它只是在续写 token 而已。
拿用 Ollama 在本地运行大模型里用过的那个接口问同一个问题,看到的就是切好之后的样子:
curl --silent http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3:0.6b",
"messages": [{"role": "user", "content": "1+1 等于几?"}],
"stream": false
}' | jq '.choices[0]'本机实测返回:
{
"index": 0,
"message": {
"role": "assistant",
"reasoning": "好的,用户问的是“1+1等于几?”。首先,我需要确定用户的问题类型。这是一个常见的数学问题……",
"content": "1加上1等于2。这是一个基本的加法运算,无需额外步骤。如果你需要更多数学练习或帮助,请随时告诉我。"
},
"finish_reason": "stop"
}response 中 reasoning 字段是 <think> 和 </think> 之间的部分,content 是 </think> 之后的部分,finish_reason 为 stop 表示生成是撞上 <|im_end|> 正常结束的。
这套标记只是 Qwen 选的约定,换个模型可能完全不同。比如 DeepSeek-R1 用的是 <|User|> 和 <|Assistant|>。所以同一段对话喂给不同模型,拼出来的字符串并不一样,这也是每个模型仓库都得自带一份对话模板的原因。
其他术语
三类文件认全了,再回头看开头那串新词:checkpoint、BF16、Q4_K_M、Safetensors、GGUF。
它们看起来杂,其实都在描述权重文件,只是角度不同:
- checkpoint 说的是「这是哪个时刻保存下来的权重」。
- 精度和量化说的是「权重里的数字用多少 bit 表示」。
- Safetensors 和 GGUF 说的是「权重怎么装进文件里」。
checkpoint:权重存档
训练模型的过程要持续调整大量参数。为了防止中断后从头再来,训练程序会定期保存当时的状态,这份存档叫 checkpoint(检查点)。
一个完整的训练 checkpoint 可能包含:当前模型权重、优化器状态、已完成的训练步数等等信息。
有了这些内容,训练程序才能尽量从中断位置继续。
训练结束后发布的最终模型权重,也经常被简称为 checkpoint。它表达的是「模型在某个时刻的参数状态」,不是某一种固定的文件扩展名。
如果仓库中出现 checkpoint-1000、checkpoint-2000,通常表示训练到不同步数时保存的版本。
普通使用者一般应该选择作者明确发布的最终版本,而不是随便挑一个中间存档,因为中间存档可能训练不到位,效果不理想。
checkpoint 中的模型权重可以保存成 Safetensors 格式,也可以转换成 GGUF 格式。GGUF 是本地推理工具通用的格式,两种格式的区别后面会展开讲。
精度:每个参数用多少 bit
模型权重本质上是一大组数字,精度决定每个数字用多少 bit、采用什么数值表示。常见的有三种:
| 类型 | 每个参数常见占用 | 特点 |
|---|---|---|
| FP32 | 32 bit,也就是 4 byte | 精度高、占用大,常作为高精度基准 |
| FP16 | 16 bit,也就是 2 byte | 文件和显存约为 FP32 的一半,常用于训练和推理 |
| BF16 | 16 bit,也就是 2 byte | 位数与 FP16 相同,但数值范围更接近 FP32 |
前面算 embedding 表占 311MB 时,用的就是 BF16 的每个数 2 byte。同一套权重如果改用 FP32 保存,每个数变成 4 byte,整个文件就从 1.50GB 翻倍到 3GB 左右。
当然,这里只是计算权重文件的磁盘占用大小,真正加载到内存里跑起来还要加上上下文缓存、临时张量和推理程序本身的开销,内存占用会比模型文件大不少。
量化:让模型变小
量化把高精度数字近似成更低精度的表示,以减少文件和内存占用。它会把原本 16 bit 或 32 bit 的权重近似成 8 bit、4 bit。
位数降低后,最直接的好处是 权重文件更小,加载权重所需的内存也就更少,资源有限的机器(比如笔记本电脑)也能跑的起来。
至于推理速度是否能提升,要看硬件和推理引擎的支持情况,4 bit 量化不一定就比 8 bit 量化快。
代价是精度降低后的近似误差可能让回答质量下降。因为推理的本质其实就是大量的矩阵运算,如果权重矩阵中数字的精度降低,那么计算结果难免有偏差,体现出来的就是模型的回答质量下降,也就是我们常说的「降智」。

上图 model 那一行末尾的 quantization Q4_K_M,就是一种以 4 bit 为主的量化方案。
Hugging Face 官方仓库里的 BF16 权重文件是 1.50GB,而这个 Q4_K_M 模型包只有 523MB。
理论上 4 bit 量化后的权重大小应该是 16 bit 权重大小的 1/4,但实际 523MB 比 1.50GB 的 1/4 要大。因为量化要额外记录缩放数据,且部分张量需要保留更高精度,所以实际会比 1/4 大一些。
Q4_0、Q4_K_M、Q8_0 是不同的量化方案,名字里能看出大致位数和算法。具体好不好用,要看发布者的说明,最好在自己的任务和硬件上实测。
Safetensors 和 GGUF
最后两个词,回答的是「权重和配套元数据如何组织进文件」。
Safetensors 是专门保存张量的格式,重点是安全和快速。早年常见的 .bin 权重用 Python pickle 序列化,加载时可能执行文件里夹带的代码;Safetensors 文件里只有张量数据和一份描述它们的清单,加载时不会执行任何东西,读取也更高效。
Hugging Face Transformers 生态经常用它保存原始或微调后的权重;模型结构和 tokenizer 通常仍放在单独的 JSON 文件中和权重文件分开存储。
GGUF 是本地推理生态常见的二进制格式。
它不仅保存张量数据,还能把模型架构、tokenizer 等标准化元数据放进同一个文件,并支持多种量化类型,相当于把运行大模型所需的所有文件打包成一个文件。
llama.cpp、LM Studio、Ollama 等本地推理工具可以直接加载 GGUF 文件进行推理,这也是 GGUF 格式经常和「本地运行模型」一起出现的原因。
总结
一个 LLM 模型仓库里最重要的是三类文件:权重保存模型学到的参数,配置说明网络结构,tokenizer 负责文字和 token 的转换。
剩下的新词都在描述权重:checkpoint 是某个训练时刻的权重存档,FP16、BF16 和各种量化方案描述权重里的数字如何表示,Safetensors 与 GGUF 则描述权重如何保存在文件里。
总结成一张表格:
| 术语 | 它解决的问题 | 例子 |
|---|---|---|
| Hugging Face Hub | 模型发布和版本管理 | 模型页、Model Card、License |
| checkpoint | 保存的是哪个训练时刻的模型或训练状态 | checkpoint-2000、最终权重 |
| 精度和量化 | 权重参数中的数字如何表示 | BF16、FP16、Q4_0、Q4_K_M |
| 文件格式 | 权重参数和元数据如何保存 | Safetensors、GGUF |
这几层概念可以自由组合:一套 BF16 模型权重可以以 Safetensors 格式保存,也可以转换为 GGUF,再量化成 Q4_0 或 Q4_K_M,由推理引擎加载运行。
理解这些层次后,再看到 7B · Q4_K_M · GGUF 这种标签,就能理解:这个模型大约有 70 亿参数,权重采用 4 bit 为主的量化方案,并被组织成适合本地推理工具读取的 GGUF 文件。
不过,模型文件自己不会回答问题。接下来可以继续阅读动手跑通 LLM 推理的全流程,用 Transformers 把配置、权重和 tokenizer 加载进 Python,亲眼看看它们怎样变成一次完整的模型回答。