前面 19 课你听了一堆术语:GGUF、量化、KV Cache、上下文窗口、采样温度——这一课把它们全部落到一条命令上。我们要在自己的 Mac 上用 llama.cpp 下载一个 Qwen3.8-7B 的量化模型,跑通"命令行一次推理 → 起 HTTP 服务 → 用 curl 调 OpenAI 兼容接口"整条链路。这是整个 AI 基础板块唯一一页照着敲就能跑通的动手页,所有参数、命令、JSON 请求体都是真的,不杜撰。
这是"动手落地"页,建议边读边在终端跟着敲。没有 Mac 也没关系,Windows/Linux 命令几乎一样,照抄即可。
/completion 和 /v1/chat/completions;④ 根据自己机器内存算出能跑多大的模型。一句话:llama.cpp 是 Georgi Gerganov 用纯 C/C++ 写的推理引擎,它的本事是——不依赖 CUDA、不依赖 PyTorch,光靠 CPU(或 Apple Metal / Vulkan)就能把一个 GGUF 格式的模型文件跑起来。它不是训练框架,只做"推理"这一件事。
为什么它这么火?因为它把"跑大模型"的门槛从"租 A100"降到了"一台 MacBook"。量化后的 7B 模型才 4GB 出头,MacBook Air 都能跑。
main 和 server,2024 年底起改名为 llama-cli / llama-server,网上旧教程看到 main 别慌,就是它。)
| 参数 | 全称 / 单位 | 作用 | 常用值 |
|---|---|---|---|
-m | --model | 模型 .gguf 文件路径 | ./models/qwen3.8-7b-instruct-q4_k_m.gguf |
-c | --ctx-size(token 数) | 上下文窗口长度,决定能读多长的前文 | 4096 / 8192 / 32768 |
-ngl | --n-gpu-layers | 把多少层权重卸载到 GPU;99 = 全部 | Mac Metal 给 99;纯 CPU 给 0 |
-t | --threads | 用几个 CPU 线程做 Prefill | 8(按你核数,别超物理核) |
-p | --prompt | 输入给模型的提示词 | "你好,介绍一下你自己" |
-n | --n-predict(token 数) | 最多生成多少个 token 就停 | 256 / 512 |
--temp | temperature | 采样温度,0~2,越高越发散 | 写代码 0.2 / 聊天 0.7 / 脑暴 0.9 |
--top-p | nucleus sampling | 只在累计概率前 p 的词里挑,0~1 | 0.9 |
--repeat-penalty | 重复惩罚 | 对已出现过的词打折,防车轱辘话,1.0=不惩罚 | 1.05~1.15 |
--color | 彩色输出 | 命令行里把 user/assistant 染不同色 | 调试时加上 |
--mmproj | 多模态投影文件 | 跑视觉模型时指定 mmproj-f16.gguf | 见⑨.4 多模态段 |
--chat-template | 对话模板名 | server 模式下指定模板,否则乱码 | qwen3.8 / llama4 / chatml |
| 精度 | 每权重字节(约) | 7B 模型体积 | 质量损失 | 什么时候选 |
|---|---|---|---|---|
| F16 | 2.0 | ≈14 GB | 无 | 服务器上追求满血 |
| Q8_0 | 1.0 | ≈7.0 GB | 几乎无损 | 内存充裕、要稳 |
| Q4_K_M | 0.5~0.6 | ≈4.4 GB | 轻微 | 本地甜点,默认选它 |
| Q4_K_S | 0.45 | ≈3.8 GB | 略明显 | 内存紧张 |
| Q3_K_M | 0.38 | ≈3.1 GB | 能感到笨 | 16G 以下硬跑大模型 |
/v1/chat/completions 接 VS Code 插件。-c 8192 起步(要塞长上下文),--temp 0.2(要它照材料答,别自由发挥)。llama-cli -p "..." -f input.txt -n 256 循环,跑完即退。mmproj-f16.gguf,用 --image 传图。-m 路径写错(相对路径相对于你敲命令的当前目录,不是 .gguf 所在目录);② 文件没下全——HF 下载中断会留下半截 .gguf,大小不对。解法:用 ls -lh 核对体积是否和 HF 页面一致(4.4GB),不一致就重下。-c 给太大(比如 32768),KV Cache 爆内存;② -ngl 99 全卸到 GPU,但你显存不够。解法:先把 -c 降到 4096,-ngl 从 20 开始往上加,看哪一档能起来。--chat-template 没对。llama.cpp 不知道 Qwen3.8 的对话格式(<|im_start|>user...<|im_end|>),就会把你的问题当裸文本续写。解法:server 命令里加 --chat-template qwen3.8;cli 模式加 --interactive 让它自动套模板。--repeat-penalty 是 1.0(不惩罚)。解法:调到 1.1~1.15;同时把 --temp 降到 0.6 左右。惩罚太高(>1.3)会让它用词奇怪。--temp 压到 0.1~0.3,让它别发散。| 考法 | 出题形式 | 应对 |
|---|---|---|
| 选哪个量化 | 问本地甜点 | Q4_K_M |
| 参数含义 | 问 -ngl 99 | 全部层卸到 GPU |
| 接口区分 | 问 OpenAI 兼容端点 | /v1/chat/completions |
| 排错 | 问中文乱码原因 | chat-template 没对 |
真题基础1. 你在 Mac 上本地跑 7B 模型,默认应该选哪个量化版本?
真题中档2. llama-cli 命令里 -ngl 99 是什么意思?
真题中档3. 想用 OpenAI SDK 无缝切换到本地 llama-server,应该调哪个端点?
真题拔高4. llama-server 起来后,调中文对话模型出现乱码、不按对话格式回答,最可能原因是?
GGUF,认准 bartowski 等量化仓库 别从官网下 F16打开 huggingface.co,搜索框输 Qwen3.8-7B-Instruct GGUF。你会看到一堆仓库,优先选 bartowski/Qwen3.8-7B-Instruct-GGUF(社区最常用、更新及时、量化版本齐全)。点进去在 Files 标签里找文件名:
# 认准这个文件名(HF 上真实存在): qwen3.8-7b-instruct-q4_k_m.gguf # ≈ 4.4 GB,这就是我们要下的 qwen3.8-7b-instruct-q5_k_m.gguf # ≈ 5.2 GB,质量略高 qwen3.8-7b-instruct-q8_0.gguf # ≈ 7.0 GB,几乎无损
下载可以直接浏览器点文件名,也可以用 huggingface-cli:
pip install -U "huggingface_hub[cli]"
hf download bartowski/Qwen3.8-7B-Instruct-GGUF qwen3.8-7b-instruct-q4_k_m.gguf \
--local-dir ./models
# 1. 拉源码 git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp # 2. 编译(macOS 自动用 Metal,Apple Silicon 速度起飞) cmake -B build cmake --build build --config Release -j # 3. 编译完后,二进制在 build/bin/ 下: ls build/bin/llama-cli # 命令行推理 ls build/bin/llama-server # HTTP 服务
llama-xxxx-mac-universal.zip(或对应 Windows/Linux 包),解压后 bin/ 目录里就是编译好的 llama-cli、llama-server。新手强烈推荐这条,省掉 cmake 坑。把上一步下的 .gguf 放进 ./models/,然后敲这一条(整条可直接复制):
./build/bin/llama-cli \ -m ./models/qwen3.8-7b-instruct-q4_k_m.gguf \ -c 4096 \ -ngl 99 \ -t 8 \ -p "你好,请用三句话介绍你自己" \ -n 256 \ --temp 0.7 \ --top-p 0.9 \ --repeat-penalty 1.1 \ --color
| 参数 | 这里取的值 | 意思 |
|---|---|---|
-m | ./models/...q4_k_m.gguf | 模型权重文件路径,必须指对 |
-c 4096 | 4096 token | 上下文窗口,能读入的前文长度。越大越吃内存(KV Cache) |
-ngl 99 | 99 | 把 99 层 Transformer 全部卸载到 GPU(Metal)。7B 大约 28 层,给 99 = 全卸。纯 CPU 机给 0 |
-t 8 | 8 | Prefill 阶段用 8 个 CPU 线程。按你物理核数给,别超 |
-p "你好..." | 提示词 | 输入给模型的文本 |
-n 256 | 256 token | 最多生成 256 个 token 就停(大约 200 个汉字) |
--temp 0.7 | 0.7 | 聊天温度,0.7 是"自然但不乱编"的常用值 |
--top-p 0.9 | 0.9 | 只在概率累计前 90% 的词里采样,去掉冷门怪词 |
--repeat-penalty 1.1 | 1.1 | 对已出现过的词打 9 折,防重复 |
--color | 开 | 终端彩色打印,方便看 user/assistant 分界 |
llm_load_tensors: ...),然后输出你的 prompt,紧接着打印模型生成的中文回答。第一次加载约 5~15 秒(把 4.4GB 读进内存),之后逐 token 吐字。如果跑的是视觉语言模型(如 Qwen3.8-VL),你需要两个文件:主模型 .gguf + 投影文件 mmproj。投影文件把图片编码器输出对齐到语言模型的嵌入空间(原理见第18课)。
# 两个文件: qwen3.8-vl-7b-instruct-q4_k_m.gguf # 主权重 mmproj-f16.gguf # 投影层,单独下 # 命令里多两个参数: ./build/bin/llama-cli \ -m ./models/qwen3.8-vl-7b-instruct-q4_k_m.gguf \ --mmproj ./models/mmproj-f16.gguf \ -c 4096 -ngl 99 -t 8 \ --image ./path/to/cat.jpg \ -p "描述这张图里有什么" -n 256
--image,它就当纯文本模型跑,不报错。一次性跑 cli 每次都要重新加载模型(5~15 秒)。要反复调用,就起常驻服务:
./build/bin/llama-server \ -m ./models/qwen3.8-7b-instruct-q4_k_m.gguf \ -ngl 99 \ -c 8192 \ --port 8080 \ --host 127.0.0.1 \ --chat-template qwen3.8
<|im_start|>user...<|im_end|>),Llama 4 用 <|start_header_id|>user<|end_header_id|>。llama.cpp 默认不知道你加载的是哪家模型,不指定 --chat-template,它就把 messages 数组生硬拼接,模型看到一堆没有分隔符的文字,于是输出乱码、不按角色回答、中文串成一坨。Qwen3.8 就填 qwen3.8,Llama 4 填 llama4,ChatML 系填 chatml。看到 main: server is listening on 127.0.0.1:8080 就成功了。浏览器打开 http://127.0.0.1:8080 还有一个自带的网页聊天框可以先玩。
curl http://127.0.0.1:8080/completion \
-H "Content-Type: application/json" \
-d '{
"prompt": "用三句话解释什么是量化",
"n_predict": 256,
"temperature": 0.7,
"top_p": 0.9,
"repeat_penalty": 1.1,
"stream": false
}'
返回 JSON 里关键字段是 content(模型生成的文本)和 timings(速度统计,含 prompt eval / eval 每秒 token 数)。
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-7b-instruct",
"messages": [
{"role": "system", "content": "你是一个简洁的中文助手,回答不超过三句话。"},
{"role": "user", "content": "什么是 KV Cache?"}
],
"n_predict": 256,
"temperature": 0.3,
"stream": false
}'
这个接口的请求体和 OpenAI 官方 /v1/chat/completions 几乎一样——意味着你把 OpenAI SDK 的 base_url 改成 http://127.0.0.1:8080/v1、api_key 随便填,原有代码一行不改就能跑本地模型。
把上面请求体里 "stream": false 改成 true,服务器不再一次性返回完整 JSON,而是以 SSE(Server-Sent Events)格式逐块吐:
data: {"choices":[{"delta":{"content":"K"}}]}
data: {"choices":[{"delta":{"content":"V"}}]}
data: {"choices":[{"delta":{"content":" "}}]}
data: {"choices":[{"delta":{"content":"Cache"}}]}
data: {"choices":[{"delta":{"content":" 是"}}]}
data: [DONE]
前端每收到一段 data: 就把 choices[0].delta.content 追加到页面上——这就是"打字机效果"的来源(第22课专门讲流式)。
算例(7B Q4_K_M,-c 4096):权重 ≈ 4.4GB;KV Cache 在 FP16 下大约几百 MB(7B 大约 0.5~1GB),合计 ≈5~5.5GB。Mac 16G 跑它还剩一半内存给系统,很舒服。
| 模型规模 | Q4_K_M 权重 | +8K 上下文 KV Cache | 建议机器内存 | 16G Mac 能跑? | 32G Mac 能跑? |
|---|---|---|---|---|---|
| 3B | ≈2.0 GB | ≈0.3 GB | 8 GB | 轻松 | 轻松 |
| 7B | ≈4.4 GB | ≈0.8 GB | 16 GB | 可以(甜点) | 轻松 |
| 14B | ≈8.5 GB | ≈1.5 GB | 24 GB | 勉强(-c 降到 4K) | 可以 |
| 32B | ≈19 GB | ≈3.5 GB | 40 GB | 跑不动 | 勉强(-c 4K) |
| 任务类型 | --temp | --top-p | --repeat-penalty | 为什么 |
|---|---|---|---|---|
| 写代码 / 函数补全 | 0.1~0.3 | 0.9 | 1.05 | 要确定性,别让它自由发挥 |
| RAG 问答(照材料答) | 0.2~0.4 | 0.9 | 1.1 | 低温度照抄材料,少幻觉 |
| 日常聊天 / 写作 | 0.6~0.8 | 0.9 | 1.1 | 自然但不离谱 |
| 头脑风暴 / 起名 | 0.9~1.1 | 0.95 | 1.15 | 发散,要多样性 |
| 翻译 | 0.3 | 0.9 | 1.0 | 忠实原文,别润色过头 |
GGUF 关键词,认准 bartowski 这类量化仓库。-ngl 99 里的 99 是什么意思?-n(--n-predict),单位是 token。-n 256 = 最多生成 256 个 token。/v1/chat/completions,请求体里用 messages 数组。--chat-template qwen3.8 会怎样?data: 开头,内容是 JSON 片段 choices[0].delta.content,最后以 data: [DONE] 结束。前端每收到一段就追加到页面。--kv-cache-type q8_0,把 KV 也量化,省一半 KV 内存);④ 关掉其他占内存的程序。ollama run qwen3.8 自动拉文件、自动选 chat-template)。需要调底层参数(自定义 mmproj、改 KV 量化类型、试新模型架构)或看真实报错时,直接用 llama.cpp;日常不想管细节用 Ollama。| 天 | 任务 | 自检 |
|---|---|---|
| 第 1 天 | 读②③④,把流水线图默写一遍 | 说清 cli/server 分工 |
| 第 2 天 | 读⑨.1~9.3,下模型 + 跑通 llama-cli | 终端能吐出中文 |
| 第 3 天 | 读⑨.5~9.6,起 server + curl 两个接口 | 能看到 JSON 返回 |
| 第 4 天 | 读⑨.7~9.8 内存表和调优表,做中档 7-11 | 会算自己机器能跑多大 |
| 第 5 天 | 做⑦真题 4 题 + 基础 1-6 | 限时每题 2 分钟 |
| 第 6 天 | 做拔高 12-16,故意制造一个报错再排查 | 能自己定位乱码/OOM |
| 第 7 天 | 合上书口述完整命令和三句口诀 | 不看资料全敲对 |
-c 参数在调它;
第9课 显存与内存——⑨.7 的测算公式来源;
第12课 采样参数——--temp/--top-p/--repeat-penalty 的原理。