模型文件格式
一次模型发布不是一个文件——它是一个按引擎重新打包的检查点。本页绘制你本地真正会遇到的格式:llama.cpp 世界的 GGUF、PyTorch/HF 栈的 safetensors、引擎原生 GPU 量化、以及边缘运行时的 ONNX。先选引擎;格式随之而来。
GGUF:一个文件,一切都在里面
一个 .gguf 文件把模型权重、分词器词表、对话模板和逐张量元数据打进一个二进制。一次下载、零配置,所有说 GGUF 的应用跑同一个文件:llama.cpp 和 llama-server、Ollama、LM Studio、Jan、KoboldCpp。该格式支持内存映射,所以权重从磁盘逐页流式载入——启动快,OS 页缓存免费做缓存。
文件名解剖,逐字段,以 Qwen3-8B-Q4_K_M.gguf 为例:
| 字段 | 值 | 含义 |
|---|---|---|
Qwen3 |
家族 + 世代 | 引擎构建的架构;也是质量世代 |
8B |
尺寸档 | ~80 亿参数——你的显存预算以此为键 |
Q4_K_M |
量化标签 | 每权重 ~4.8 比特、K-quant “中等”混合——见 量化 |
.gguf |
容器 | 权重 + 分词器 + 对话模板 + 元数据,一个文件 |
不加载就检查任何 GGUF:
python gguf-py/gguf/scripts/gguf_dump.py model.gguf
general.architecture : qwen3
general.name : Qwen3 8B
qwen3.context_length : 32768
tokenizer.ggml.model : gpt2 (BPE)
tokenizer.chat_template : {%- ... a Jinja template ... %}
那个元数据块就是 GGUF 在五个不同应用里“开箱即用”的原因:引擎读架构、构图、加载分词器,聊天前端应用内嵌模板。不用翻配置、不用词表错配、不用单独下载分词器。
Safetensors:Hugging Face 的原住民
Safetensors 是一个刻意无聊的容器:一个 JSON 头(张量名、形状、dtype)接原始字节。它只存张量——没有可执行代码,不像盲目加载不安全的 pickle 味 .bin 检查点——并支持零拷贝 mmap,这就是 PyTorch 启动快的原因。Transformers、vLLM、SGLang、TRL 和整个微调生态原生说它。
因为它只存张量,一个能工作的模型是整个仓库目录:
model-00001-of-00004.safetensors ← 权重分片(每个 ~5 GB)
model-00002-of-00004.safetensors
model-00003-of-00004.safetensors
model-00004-of-00004.safetensors
model.safetensors.index.json ← 分片映射:张量名 → 分片文件
config.json ← 架构 + 超参数
generation_config.json ← 默认采样设置
tokenizer.json ← 分词器本身
tokenizer_config.json ← 对话模板住在这里
分片存在是因为一个 70B FP16 检查点约 140 GB——单文件没法管。用 vLLM 服务就要下载全部分片;safetensors 发布里没有“只要那个 4-bit 文件”的捷径。量化服务是单独的仓库(同一模型的 AWQ 或 GPTQ 变体)。
引擎原生 GPU 量化:AWQ、GPTQ、EXL2
这些格式为 GPU 推理服务器而存在,那里吞吐比文件便利更重要:
- AWQ——激活感知量化。校准提示词找出激活最依赖的那 ~1% 权重通道;它们获得受保护的缩放,其余全部降到 4-bit。4-bit 下近原始质量配快速内核;vLLM 的默认 4-bit 之选。
- GPTQ——经典 GPU 量化,源自最优脑量化:逐层量化,用尚未量化的权重补偿每层的误差。4-bit、仅 GPU 内核、至今遍布服务配置。
- EXL2——exllamav2 的格式,每权重可变比特。一个仓库可以坐在比如 4.65 bpw,靠混合 2–8 位张量让总量恰好落在你的显存上限之下。用于 Q4 装不下而 Q3 会痛的时候。
三者都需要校准数据和一次性转换运行,而且都不能在 CPU 上跑。
ONNX、MLX、原始 FP16/BF16
ONNX 是可移植计算图格式:一次导出 transformers 模型,任何 onnxruntime 能跑的地方都能跑——没有 CUDA 的 Windows 机器、手机、浏览器 WebGPU 演示。onnxruntime 还能把图量化到 INT8 给 CPU。你付出设置摩擦和常常峰值速度;你换来到没有 PyTorch 栈的机器的可移植性。边缘和嵌入式是它的主场,不是桌面聊天。
MLX 是 Apple 为 Apple Silicon 做的数组框架;mlx-community 组织把多数主要发布重新打包成 MLX 格式,含 4-bit 和 8-bit。在跑 mlx-lm 的 M 系列 Mac 上,那就是你的格式——见 Apple Silicon。
原始 FP16/BF16 检查点在你想要无损参照、微调基座或转换源时重要。BF16 保留 FP32 的 8 位指数范围并以此换尾数比特——训练上远比 FP16 稳定,同样每权重 2 字节。7–8B 模型 FP16/BF16 光权重就 ~16 GB,上下文还不算。
哪种格式配哪种引擎
| 引擎 / 栈 | 它吃的格式 | 备注 |
|---|---|---|
| llama.cpp、Ollama、LM Studio、Jan | GGUF | 单文件;CPU + GPU;全量化家族 |
| vLLM、TGI、SGLang | safetensors、AWQ、GPTQ | 服务器吞吐;GPU |
| exllamav2 / TabbyAPI | EXL2、GPTQ | 可变 bpw;GPU |
| transformers / PyTorch | safetensors | 训练、微调、研究 |
| onnxruntime | ONNX | 边缘、移动、浏览器 |
| mlx-lm | MLX | Apple Silicon |
混格式是经典的初学者错误:把 vLLM 指向 .gguf,或把 llama.cpp 指向 safetensors 分片。两者都不行——引擎要么报错,要么需要先做一次转换。
转换路径
从 Hugging Face 仓库到本地文件的标准路径是两步——把检查点转成 16-bit GGUF,再向下量化:
git clone https://github.com/ggerganov/llama.cpp
pip install -r llama.cpp/requirements.txt
# 1. 把 HF 检查点(safetensors)转换为 GGUF
python llama.cpp/convert_hf_to_gguf.py ./Qwen3-8B --outtype bf16 --outfile qwen3-8b-bf16.gguf
# 2. 量化到目标大小
llama-quantize qwen3-8b-bf16.gguf qwen3-8b-Q4_K_M.gguf Q4_K_M
实践中你很少自己转换:bartowski 和 mradermacher 这样的量化者在数小时内发布每个值得一提的发布的每种尺寸。自己转换的场合:私有微调、要 imatrix 校准的 I-quant、或需要非标准比特目标——细节在 量化。
嵌入模型——RAG 的检索半边——以相同格式发布:llama.cpp 嵌入端点用 GGUF,sentence-transformers 用 safetensors。与上面一切相同的规则:把格式匹配到你真正要跑的引擎。