文章目录
-
- 前言
- [1 懒人首选:Ollama 三分钟跑起来](#1 懒人首选:Ollama 三分钟跑起来)
-
- [1.1 三条命令体验本地模型](#1.1 三条命令体验本地模型)
- [1.2 还能开成HTTP接口用](#1.2 还能开成HTTP接口用)
- [2 程序员硬核玩法:transformers 手搓运行](#2 程序员硬核玩法:transformers 手搓运行)
-
- [2.1 先装依赖,再加载模型](#2.1 先装依赖,再加载模型)
- [2.2 手写多轮对话逻辑](#2.2 手写多轮对话逻辑)
- [2.3 内存的猫腻:mmap是什么](#2.3 内存的猫腻:mmap是什么)
- [3 量化到底是个啥原理](#3 量化到底是个啥原理)
-
- [3.1 常见的模型存储格式](#3.1 常见的模型存储格式)
- [3.2 通用量化精度有哪些](#3.2 通用量化精度有哪些)
- [3.3 GGUF的黑科技:K-Quant方法](#3.3 GGUF的黑科技:K-Quant方法)
- [3.4 新硬件专属精度](#3.4 新硬件专属精度)
- [4 transformers也能量化:torchao实战](#4 transformers也能量化:torchao实战)
-
- [4.1 加载时直接量化](#4.1 加载时直接量化)
- [4.2 加载后再量化?没必要](#4.2 加载后再量化?没必要)
- [5 llama.cpp 与 GGUF 量化实战](#5 llama.cpp 与 GGUF 量化实战)
-
- [5.1 Safetensors转GGUF](#5.1 Safetensors转GGUF)
- [5.2 量化到不同精度,效果差多少](#5.2 量化到不同精度,效果差多少)

P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看, 传送门https://blog.csdn.net/HHX_01
前言
很多人刚接触本地大模型,第一反应都是"这玩意儿怎么这么大?"
几百MB起步,动辄几十GB,没点硬件家底真不敢随便下。
其实不用慌,咱们有量化这招,既能把模型体积压下来,还能尽量保住智商。今天就从最简单的一键部署,到手搓代码,再到量化原理,给大家唠明白。
1 懒人首选:Ollama 三分钟跑起来
要说本地部署最省心的工具,Ollama称第二没人敢称第一。不用管什么环境依赖,不用调一堆参数,敲几条命令就能完事。
1.1 三条命令体验本地模型
咱们拿最小的Qwen3:0.6B举例子,这模型小到什么程度?老电脑都能轻松跑,就当练手了。
第一步先装Ollama本体,官网直接下安装包就行。然后开命令行,敲pull命令下载模型:
# 下载模型到本地
ollama pull qwen3:0.6b
列出本地下载的模型
ollama list
输出结果
NAME ID SIZE MODIFIED
qwen3:0.6b 7df6b6e09427 522 MB 50 seconds ago
查看模型详情
ollama show qwen3:0.6b
你看,下好的模型默认是Q4_K_M量化的,才500多MB,上下文窗口有40K,日常聊天完全够用。
接下来直接run就能跑:
# 运行模型
ollama run qwen3:0.6b
运行之后直接进入对话模式,就跟你用网页版聊天一样,输入/bye就退出。
这里吐槽一句,0.6B的小模型是真的"实在",你问它问题,它连自己的思考过程都念给你听,主打一个坦诚,心里藏不住一点事儿。
1.2 还能开成HTTP接口用
光在命令行聊天哪够,咱们还能把它开成服务,当成本地API调用。敲个serve命令就启动了,默认端口11434:
# 开启本地模型HTTP服务
ollama serve
启动之后,就能发POST请求调用了,比如用PowerShell测试一下:
Invoke-RestMethod -Uri "http://localhost:11434/api/chat" -Method Post -Body '{"model":"qwen3:0.6b","messages":[{"role":"user","content":"你好"}],"stream":false}' -ContentType "application/json"
返回的结果很标准,模型、回复内容、耗时都给你列得清清楚楚。
而且它还兼容OpenAI的接口格式,base_url填http://localhost:11434/v1/,api_key随便填个ollama就行。
不过友情提示,0.6B的小模型就别拿来跑Agent了。我试过,人家DeepSeek V4 Flash能精准列项目文件,它倒好,直接把工具使用说明全文念出来了,主打一个"我知道工具怎么用,但我就是不用",纯纯的工具说明书复读机。
2 程序员硬核玩法:transformers 手搓运行
要是光用工具不过瘾,想自己写代码控制模型,那肯定得用transformers。Python生态的老大哥了,可玩性拉满。
2.1 先装依赖,再加载模型
首先得装几个必备的库,torch、transformers、accelerate,都是AI圈的老熟人了:
# torch为PyTorch,最流行的深度学习框架库
pip install torch
transformers是Hugging Face的大模型工具库
pip install transformers
transformers的可选依赖,用于自动适配不同硬件
pip install accelerate
模型咱们下原版的Safetensors格式,BF16精度,大概1.4GB,比Ollama的量化版大不少。
加载代码特别简单,两行完事:
from transformers import AutoModelForCausalLM, AutoTokenizer
模型目录
MODEL_DIR = "./Qwen3-0.6B"
加载分词器
tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR)
加载模型:Auto 根据 config.json 自动识别架构
model = AutoModelForCausalLM.from_pretrained(
MODEL_DIR,
torch_dtype="auto", # 按模型配置自动选择精度
device_map="auto", # 自动分配到可用设备
)
print(tokenizer)
print(model)
运行之后你会看到分词器和模型结构,Qwen3用的还是Qwen2的分词方案,28层解码器,结构很清晰。
加载速度也挺快,毕竟模型小,要是换个7B的,那可有得等,泡杯茶的功夫都不一定加载完。
2.2 手写多轮对话逻辑
模型加载好了,咱们写个循环实现多轮聊天,原理一点都不复杂:
# 对话历史列表
messages = []
while True:
# 读取用户输入,输入 exit 退出循环
user_input = input("\n你:")
# 去除字符串首尾空白
if user_input.strip() == "exit":
break
# 把用户消息加入历史对话中
messages.append({"role": "user", "content": user_input})
# 将历史对话按 Qwen3 模板转为纯文本
text = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True, return_tensors="pt"
)
# 将文本编码为输入TokenID的列表
model_inputs = tokenizer(text, return_tensors="pt")
# 最多生成 512 个新 token
outputs = model.generate(**model_inputs, max_new_tokens=512)
# 解码出新增部分,跳过特殊 token
response = tokenizer.decode(
outputs[0][len(model_inputs["input_ids"][0]):], skip_special_tokens=True
)
# 把模型回复加入历史
messages.append({"role": "assistant", "content": response})
print("模型:" + response)
说白了就是把历史对话攒起来,拼成模型认识的格式,喂给模型生成回复,再把回复加回去循环。
这里面最容易踩坑的就是对话模板,每个模型的格式都不一样,错一个符号模型都可能胡言乱语。就跟不同地方的人听方言似的,你说普通话它能懂,你说方言它就懵了。
2.3 内存的猫腻:mmap是什么
不知道你有没有发现,刚加载模型的时候,看任务管理器内存占得并不多。
0.6B的模型BF16按理说怎么也得1.2GB以上,结果一看才三百多MB,这是怎么回事?
这就是mmap技术在搞鬼,简单说就是模型没全加载进内存,只给你映射了个地址。用到哪部分才加载哪部分,跟外卖似的,你点了才给你送,不是全给你摆桌上。
你一开始聊天,内存就蹭蹭往上涨,硬盘也开始读,就是这个原因。
想看看真实内存占用?简单,把参数全克隆到内存里就行:
for p in model.parameters():
p.data = p.data.clone()
跑完再看,内存直接干到1.5GB左右,这才是模型的真实饭量。之前那都是虚的,玩的是数字游戏。
3 量化到底是个啥原理
聊了这么久量化,到底什么是量化?
说白了就是压缩,把原来32位、16位存的数字,用更少的位数存,尽量让数值差不太多。就像把图片从无损PNG压成JPG,体积小了,肉眼看差别不大。
3.1 常见的模型存储格式
先说说模型文件都有啥格式,不同格式对应不同的工具,别下错了用不了:
| 存储格式 | 对应框架 | 使用场景 |
|---|---|---|
| Safetensors | transformers | 最常用的格式 |
| GGUF | llama.cpp | Ollama等工具使用 |
| ONNX | ONNX Runtime | 跨平台部署使用 |
| .pt .pth .bin | PyTorch | 训练中使用 |
| .ckpt .pb | TensorFlow | 训练中使用 |
简单总结下:
Safetensors就是纯权重数据,得配配置文件、分词器一起用,属于散装套餐;
GGUF是个全家桶,分词器、模板、配置全塞一个文件里,分发特别方便;
ONNX连模型结构都包含了,直接就能跑,就是不包含分词那些周边东西。
3.2 通用量化精度有哪些
最基础的就是FP32、FP16,原汁原味的浮点数,精度高,但体积大,属于贵族配置。
想省空间,就得用整数量化,比如INT8、INT4,用整数加公共缩放因子来表示浮点数。
GGUF格式还有自己专属的Q8、Q4,原理差不多,就是缩放因子的共享方式不一样。就像合租房子,有的人是几个人平摊房租,有的人是按房间大小算,本质都是为了省钱。
3.3 GGUF的黑科技:K-Quant方法
说到GGUF,就不得不提K-Quant量化,这可是llama.cpp的绝活。
它把256个参数分成一个超级块,里面再分8个子块,两级缩放因子,既省空间又尽量保精度。简单说就是大总管管小队长,小队长管小兵,分级管理,比一刀切的量化聪明多了。
这种格式命名就是QX_K,比如Q4_K,就是4位量化。后面还能加后缀:
- _S:只给极少数关键参数提精度,极致省空间
- _M:更多参数用高精度,平衡之选
- _L:绝大多数层都用高精度,追求画质
咱们平时用Q4_K_M就够了,平衡体积和精度,性价比之王,闭眼冲都不会错。
3.4 新硬件专属精度
还有些精度是靠硬件指令集加速的,比如BF16,跟FP16都是16位,但结构不一样。
BF16就是FP32砍了一半尾数,数值范围跟FP32一样,训练的时候不容易溢出,属于训练界的网红格式。
还有FP8、MXFP8这些,都是给新显卡准备的,硬件直接算,速度飞快。咱们普通CPU用户看看就行,暂时还用不上,凑个热闹就行。
4 transformers也能量化:torchao实战
别以为只有GGUF能量化,transformers也能玩量化,用torchao就行,官方出品,兼容性拉满。
4.1 加载时直接量化
在加载模型的时候就指定量化配置,一步到位,省得后面折腾:
from transformers import AutoModelForCausalLM, AutoTokenizer, TorchAoConfig
from torchao.quantization import Int8WeightOnlyConfig, quantize_, PerGroup
模型目录
MODEL_DIR = "./Qwen3-0.6B"
加载分词器
tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR)
创建量化配置,128个参数共享一个缩放因子
quant_config = Int8WeightOnlyConfig(granularity=PerGroup(128))
包装成transformers可识别的格式
quantization_config = TorchAoConfig(quant_type=quant_config)
加载模型
model = AutoModelForCausalLM.from_pretrained(
MODEL_DIR,
torch_dtype="auto",
device_map="auto",
quantization_config=quantization_config, # 指定量化配置
)
量化完之后,内存占用直接降到0.9GB,差不多砍了一半,效果还是很明显的。
不过有一说一,CPU上跑INT8反而更慢,因为得先转成浮点数再算,多了一步。就像你看压缩文件,得先解压才能看,自然费点时间。有GPU的话就不一样了,加速很明显。
量化好的模型还能直接存成文件,下次直接加载,不用每次都量化一遍:
# 模型保存目录
SAVE_MODEL_DIR = "./Qwen3-0.6B-int8"
保存量化模型
model.save_pretrained(SAVE_MODEL_DIR)
保存分词器
tokenizer.save_pretrained(SAVE_MODEL_DIR)
4.2 加载后再量化?没必要
也有人说,我先加载模型再量化行不行?
行是行,但真心不推荐。模型都已经以高精度加载进内存了,再量化纯属脱裤子放屁,既费时间又多占内存。
我实测过,先加载再量化,峰值内存干到2.2GB,完了才慢慢降下来,纯纯浪费性能。有那功夫,不如直接加载的时候就指定量化。
5 llama.cpp 与 GGUF 量化实战
要说玩GGUF和量化,还得看llama.cpp,C++写的推理框架,性能拉满,Ollama底层就是用的它。
5.1 Safetensors转GGUF
首先得把原版模型转成GGUF格式,需要用到llama.cpp里的转换脚本。
先把项目clone下来,建个虚拟环境装依赖,避免把全局Python搞乱,这都是玩Python的基本操作了:
# clone llama.cpp项目
git clone https://github.com/ggml-org/llama.cpp
创建Python局部虚拟环境
python -m venv python-llama-venv
激活局部虚拟环境
python-llama-venv\Scripts\activate
安装依赖
pip install -r requirements\requirements-convert_hf_to_gguf.txt
然后运行转换脚本,就能输出GGUF文件了:
# 转换格式,输出GGUF文件
python convert_hf_to_gguf.py E:\llm\Qwen3-0.6B --outfile E:\llm\Qwen3-0.6B-model.gguf
转换完默认是BF16精度,1.5GB左右,一个文件包含所有东西,特别方便。
转好的GGUF可以直接导入Ollama用,建个Modelfile写路径就行:
FROM E:\llm\Qwen3-0.6B-model.gguf
然后ollama create一下就能用了,跟官方模型一模一样,毫无违和感。
5.2 量化到不同精度,效果差多少
有了BF16的GGUF,咱们就能量化成各种精度了,用自带的llama-quantize工具:
# 量化成Q8_0精度
.\llama-quantize.exe E:\llm\Qwen3-0.6B-model.gguf E:\llm\Qwen3-0.6B-q8-model.gguf Q8_0
我测了几个不同精度的体积和内存占用,给大家做个参考:
| 量化精度 | 位数 | 模型文件大小 | 实际运行内存 |
|---|---|---|---|
| BF16 | 16位 | 1.4GB | 1.9GB |
| Q8_0 | 8位 | 767MB | 1.29GB |
| Q4_K_M | 4位为主 | 461MB | 980MB |
| Q2_K | 2位 | 331MB | 850MB |
说下实际体验:
Q8_0跟原版几乎没区别,基本感知不到,属于追求品质的选择;
Q4_K_M日常聊天没问题,简单推理也能对付,性价比最高,大部分人选这个就够;
Q2_K就别碰了,输出跟乱码似的,模型直接智商清零,属于能跑但没用系列。就像压缩视频,压到一定程度,画面全是马赛克,就没法看了。
总结一下,想省事就用Ollama,想二次开发就用transformers,想极致性能就用llama.cpp。
量化的话,普通用户Q4_K_M闭眼冲,内存够就Q8,追求极致就原版BF16。
别盲目追求大模型、高精度,适合自己电脑的才是最好的。毕竟,能流畅跑起来的模型,才是有用的模型。
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/HHX_01