4.3 INT4 模型的加载、运行与对话验证 4.1 和 4.2 走完了"算账、选型、转换、量化"四步,你手里应该已经有一个 Q4KM 的 GGUF 文件了。但很多新手到这一步反而卡住——文件有了,怎么让它真正"对话"起来?怎么确认量化后的模型没坏、质量还在可接受范围?这一节就把"从量化文件到可用对话服务"这最后一公里讲透,包括 llama.cpp 的加载参数怎么调、对话怎么验证、以及量化前后质量怎么对比。 我见过不少人在这一步翻车。最典型的是加载参数没调对,明明有 GPU 却跑在 CPU 上,慢得像乌龟;或者上下文长度开太大导致显存爆掉;又或者量化后模型"能跑但答非所问",却不知道是量化损失还是 prompt 写错了。这些坑都在这一节覆盖。 用 llama.
4.1 和 4.2 走完了"算账、选型、转换、量化"四步,你手里应该已经有一个 Q4_K_M 的 GGUF 文件了。但很多新手到这一步反而卡住——文件有了,怎么让它真正"对话"起来?怎么确认量化后的模型没坏、质量还在可接受范围?这一节就把"从量化文件到可用对话服务"这最后一公里讲透,包括 llama.cpp 的加载参数怎么调、对话怎么验证、以及量化前后质量怎么对比。
我见过不少人在这一步翻车。最典型的是加载参数没调对,明明有 GPU 却跑在 CPU 上,慢得像乌龟;或者上下文长度开太大导致显存爆掉;又或者量化后模型"能跑但答非所问",却不知道是量化损失还是 prompt 写错了。这些坑都在这一节覆盖。
4.2 节我们用 llama-quantize 得到了 Q4_K_M 文件,接下来用 llama-server(llama.cpp 自带的 HTTP 服务)加载它。最基础的启动命令:
./llama-server \ -m deepseek-v4-7b-Q4_K_M.gguf \ --host 0.0.0.0 --port 8080 \ -ngl 99 \ -c 4096
这里每个参数都有讲究,错一个就可能跑不起来或者性能很差。
-m 指定量化模型文件路径,没什么好说。-ngl 99 是关键参数之一——它表示把多少层网络 offload 到 GPU。99 是个"全量 offload"的惯用写法(模型层数一般几十层,写 99 表示全部放 GPU)。如果你漏了这个参数,默认是 0,也就是全部跑 CPU,那速度会让你怀疑人生。我帮人排查过好几次"为什么我的 INT4 模型比教程里慢 20 倍",根因都是忘了 -ngl。
-c 4096 设置上下文长度。这个值要根据你的显存余量来定,不是越大越好——上下文越长,KV Cache 占的显存越多。4.1 节算过显存账,权重之外的余量就是给 KV Cache 和激活用的。一个常见错误是直接 -c 32768 想开长上下文,结果显存不够直接 OOM。建议从 4096 起步,跑通后再根据显存占用逐步上调。
-ngl 不是只能写 99。当你的显存装不下全部层时,可以只 offload 一部分,剩下的留 CPU。这就是 llama.cpp 的"部分 offload"能力,也是它能在低配机器上跑起来的关键。
比如一张 8GB 显存的卡跑 14B 的 Q4_K_M(权重约 8GB,刚好或略超显存),全量 offload 会 OOM。这时可以 -ngl 24(假设模型 40 层,offload 24 层到 GPU,其余 16 层留 CPU),虽然慢一些但能跑。具体的层数要边调边看显存占用——启动时 llama.cpp 会打印每层的 offload 情况和显存占用,根据这个反馈调整。
判断 GPU 是否真的在工作,最简单的方法是启动后看 nvidia-smi。如果 GPU 利用率有波动说明在用,如果是 0 说明全跑 CPU 了(-ngl 没生效或写错了)。这个排查 5 秒钟就能做,但能省你几小时的迷茫。
模型加载成功不代表它工作正常。量化过程可能因为各种原因(校准问题、转换 bug、版本不匹配)导致模型质量退化甚至损坏。所以加载后第一步是做对话验证。
最简单的验证是用 llama-server 提供的 OpenAI 兼容接口发一个请求:
curl http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "messages": [{"role":"user","content":"用三句话介绍你自己"}] }'
观察返回结果,重点看几个信号。第一是模型是否"会说话"——如果返回乱码、重复、或者完全不相关的字符,说明量化文件可能损坏,需要重新量化。第二是响应是否连贯——让它做点需要推理的任务(简单数学、逻辑题),看它还能不能答对。INT4 量化对简单任务影响很小,但如果连"2+3 等于几"都答错,那不是正常量化损失,是模型坏了。
光靠几个主观对话判断质量不够严谨。更可靠的方法是测困惑度(Perplexity,PPL)——这是 3.1 节讲过的量化损失度量。llama.cpp 自带困惑度测量工具:
./llama-perplexity \ -m deepseek-v4-7b-Q4_K_M.gguf \ -f wiki.test.txt
用同一份测试文本,分别测原始 F16 模型和 INT4 量化模型的 PPL。正常情况下,Q4_K_M 的 PPL 相比 F16 上升不超过 5%(具体数值取决于模型和测试集)。如果 PPL 暴涨(比如上升 30% 以上),说明这次量化有问题——可能是校准集不合适、量化参数设错、或者模型本身不适合这个量化方法。
我建议每个新模型第一次量化后,都做一次 PPL 对比,建立基线。后续同样的模型同样的量化方法,就不用每次都测了。但换模型、换量化方法、换校准集时,一定要重新测。
量化主要目的是省显存,但顺带也会影响速度——INT4 的计算量比 F16 小,理论上更快,但实际还取决于实现。llama.cpp 提供了基准工具:
./llama-bench -m deepseek-v4-7b-Q4_K_M.gguf
它会输出 prompt 处理速度(prefill,token/s)和生成速度(decode,token/s)。对比 F16 的基准,你能清楚看到 INT4 在你的硬件上到底是变快还是变慢。一般来说,在显存带宽受限的卡上(比如消费级卡),INT4 因为搬运的数据量小,生成速度会明显提升;在算力受限的卡上,提升可能不明显。
值得测的两个指标是 ttft(首 token 延迟)和 tpot(每 token 生成时间)。ttft 主要由 prefill 速度和上下文长度决定,tpot 主要由 decode 速度决定。如果你的应用是交互式对话,ttft 影响用户等待感;如果是后台批处理,tpot 影响整体吞吐。根据你的场景关注不同指标。
手动敲一长串参数容易出错,建议把启动命令固化成脚本。我的习惯是写一个 serve.sh:
#!/bin/bash MODEL=${1:-deepseek-v4-7b-Q4_K_M.gguf} PORT=${2:-8080} CTX=${3:-4096} ./llama-server \ -m models/$MODEL \ --host 0.0.0.0 --port $PORT \ -ngl 99 \ -c $CTX \ --temp 0.7 \ --top-p 0.9
这样切换模型、端口、上下文长度只需改参数,不用重写命令。生产部署时,这个脚本还可以加上健康检查、日志重定向、自动重启等逻辑,但那些属于运维范畴了,这里先聚焦"跑起来"。
把量化文件变成可用对话服务,关键是调对加载参数——-ngl 决定 GPU 利用、-c 决定上下文与显存平衡。加载后要做对话验证确认模型没坏,用困惑度测量量化前后质量差异(正常 PPL 上升不超过 5%),用 llama-bench 量化性能收益。最后把启动命令固化成可复用脚本,减少人为出错。
下一节 4.4 讲运行过程中常见的报错和性能调优——那是"跑起来之后怎么跑得稳、跑得快"的问题。