# llama.cpp 2026 前沿大模型部署手册

> 版本基准：llama.cpp v0.9.0（2026-11-04）　·　文档核验：2026-11-06
> 参数与命令取自仓库官方文档 `docs/` 与 `tools/server/README.md`（含自动生成的参数表）。

---

## 目录

- [00 导读](#00-导读)
- [01 2026 的部署格局](#01-2026-的部署格局)
- [02 显存预算与 KV 计算](#02-显存预算与-kv-计算)
- [03 架构与参数作用点](#03-架构与参数作用点)
- [04 核心参数详解](#04-核心参数详解)
- [05 并行策略选型](#05-并行策略选型)
- [06 逐模型实战配置](#06-逐模型实战配置)
- [07 调优方法论](#07-调优方法论)
- [08 生产化与排错](#08-生产化与排错)
- [09 附录](#09-附录)

---

## 00 导读

### llama.cpp 的定位

llama.cpp 是一个**纯 C/C++ 的 LLM 推理实现**，基于 ggml 张量库，零 Python 依赖，可编译到几乎任何平台：x86、ARM、Apple Silicon、CUDA、ROCm、Vulkan、SYCL、Metal、甚至浏览器（WASM）。

2026 年它的定位非常清晰：

**它不是用来跑万亿 MoE 的**。1.6T 的模型即便量化到 2-bit 也要几百 GB，llama.cpp 的多卡能力（pipeline / experimental tensor parallel）撑不住这个量级。

**它的真正价值在三处**：

| 场景 | 为什么选它 |
| :-- | :-- |
| **本地 / 边缘部署** | 单机、单卡、甚至 CPU，无 Python 环境，一个二进制文件 |
| **极致量化** | 支持 1.5–8 bit 的几十种量化格式，让 70B 跑在 24GB 显卡上 |
| **快速验证与原型** | `-hf user/repo` 一条命令拉模型就跑，无需写代码 |

**2026 年的一个新变化**：llama.cpp 的 speculative decoding 能力大幅增强，已经支持 **EAGLE-3、MTP、DFlash、DSpark、n-gram 系**（`ngram-simple` / `ngram-map-k` / `ngram-map-k4v` / `ngram-mod` / `ngram-cache`）。这让它在小模型 + 低延迟场景下的竞争力明显提升。

### 数据基准

| 组件 | 基线 |
| :-- | :-- |
| llama.cpp | v0.9.0（2026-11-04） |
| 模型格式 | GGUF |
| 后端 | CPU / CUDA 12 / CUDA 13 / ROCm / MUSA / SYCL / Vulkan / Metal / CANN |
| Python | 仅转换脚本需要 |

### 三个必须先建立的心智模型

**① GGUF 是唯一格式。**

llama.cpp 只认 GGUF。HF 上的 safetensors 必须先转：

```bash
python convert_hf_to_gguf.py <hf-model-dir> --outtype bf16 --outfile model.gguf
```

或者直接下社区已转好的：

```bash
# 直接从 HF 拉，自动选量化
llama-cli -hf ggml-org/gemma-3-1b-it-GGUF
```

**② `-ngl`（GPU layers）是最重要的参数。**

它决定「多少层放进显存」。放不下的层会跑在 CPU 上——**速度会掉一到两个数量级**。所以 `-ngl` 的目标永远是「能放多少放多少」。

新版本的默认值是 `auto`，配合 `--fit on`（默认开启）会自动按显存调整未设置的参数。

**③ 多卡是「流水」不是「张量」。**

`--split-mode layer`（默认）是**流水并行**：每卡持有一段连续的层，KV 跟着层走。这种方式**通信量最小**，但需要足够多的 token 才能填满流水线。

`--split-mode tensor` 是**实验性的张量并行**，能降低延迟，但对互联带宽敏感，且限制很多（KV 必须是 f16/bf16/f32，`--fit` 不支持）。

---

## 01 2026 的部署格局

### llama.cpp 能跑什么、不能跑什么

**能跑（官方生态支持良好）**：

| 模型族 | 说明 |
| :-- | :-- |
| Llama 3.x / 4 | 最成熟 |
| Qwen 2.5 / 3 | 支持完善 |
| Gemma 3 / 4 | 官方有 GGUF 仓库 |
| gpt-oss 20b / 120b | 官方支持 |
| Mistral / Mixtral | 支持 |
| DeepSeek 蒸馏版 | 支持 |
| Phi / Granite / Command-R | 支持 |

**不建议跑**：

| 模型 | 原因 |
| :-- | :-- |
| DeepSeek-V4（1.6T） | 量化后仍数百 GB，多卡能力不足 |
| Kimi-K3（2.8T） | 同上 |
| Qwen3.5-397B | 即便 2-bit 也约 100 GB，需 4×A100，不划算 |
| GLM-5（744B） | 边界情况，2-bit 约 190 GB |
| MiniMax-M3（427B） | 边界情况 |

**边界判断经验**：

```
量化后大小 ≈ 参数量 × bits / 8
```

| 模型规模 | 4-bit 大小 | 2-bit 大小 | 可行性 |
| :-- | --: | --: | :-- |
| 7B | 3.5 GB | 1.8 GB | ✅ 单卡/CPU |
| 32B | 16 GB | 8 GB | ✅ 单张 24GB |
| 70B | 35 GB | 18 GB | ✅ 单张 48GB / 双卡 |
| 120B（gpt-oss，MXFP4） | — | ~63 GB | ✅ 单张 80GB |
| 235B | 118 GB | 59 GB | ⚠️ 多卡 |
| 397B | 199 GB | 99 GB | ⚠️ 4–8 卡 |
| 744B | 372 GB | 186 GB | ❌ 不推荐 |
| 1.6T | 800 GB | 400 GB | ❌ 不可行 |

> **实际可用性还要打折**：除权重外还要 KV Cache 和计算缓冲。上表的 2-bit 数字是理论下限。

### 2026 年 llama.cpp 的能力增长

**Speculative decoding 的方法矩阵**（来自 `docs/speculative.md`）：

| 方法 | `--spec-type` 值 | 需要 draft 模型 | 说明 |
| :-- | :-- | :-- | :-- |
| Draft model | `draft-simple` | ✅ | 最经典，小模型起草 |
| EAGLE-3 | `draft-eagle3` | ✅ | 读取目标模型 hidden states，接受率更高 |
| MTP | `draft-mtp` | ✅ | 目标模型自带 MTP 头 |
| DFlash | `draft-dflash` | ✅ | 块扩散，一次前向产出整块草稿 |
| DSpark | `draft-dspark` | ✅ | DeepSeek 系的融合草稿模块 |
| N-gram (simple) | `ngram-simple` | ❌ | 零额外模型 |
| N-gram (map-k) | `ngram-map-k` | ❌ | 基于哈希表 |
| N-gram (map-k4v) | `ngram-map-k4v` | ❌ | 变体 |
| N-gram (mod) | `ngram-mod` | ❌ | 模运算索引 |
| N-gram (cache) | `ngram-cache` | ❌ | 缓存式 |

**可以混用**：带 draft 模型的方法可以与不带 draft 模型的方法组合。

---

## 02 显存预算与 KV 计算

### 显存划分

```
┌────────────────────────────────────────────────────┐
│  Weights（-ngl 层在 GPU，其余在 CPU）│ KV │ Compute │
└────────────────────────────────────────────────────┘
```

llama.cpp 的显存管理和其它框架最大的不同：**权重可以部分放 CPU**。

```
-ngl N     → 前 N 层放 GPU
-ngl 999   → 全部放 GPU（等价于 all）
-ngl auto  → 自动（默认）
```

**关键**：放不下的层走 CPU，每 token 都要通过 PCIe 传输权重/激活。速度会掉 10–100 倍。所以：

> **`-ngl` 的目标不是「刚好装下」，而是「尽量多放」。**
> 如果 40 层里有 36 层能放 GPU，不要满足于 36——试试能不能通过降 `-c`（上下文）或 `-ctk q8_0` 挤出第 37 层。

### `--fit` 自动适配

`--fit on`（默认）会自动调整**未显式设置**的参数来适配设备内存。

```bash
# 什么都没设，让它自己算
llama-server -m model.gguf
```

> **`--fit` 与 `--split-mode tensor` 不兼容**。用 tensor 模式时需要手动设 `--ctx-size`。

### KV Cache 计算

```
KV_bytes_per_token = 2 × n_layers × n_kv_heads × head_dim × kv_dtype_bytes
```

`n_kv_heads` 由架构决定：MHA 等于 `n_heads`，GQA 等于 `n_heads / g`，MQA 等于 1。三者公式相同，只是取值不同。

llama.cpp 的 KV 精度用 `-ctk`（K）和 `-ctv`（V）分别控制：

| 值 | 字节 | 说明 |
| :-- | --: | :-- |
| `f32` | 4 | 最高精度 |
| `f16` | 2 | **默认** |
| `bf16` | 2 | 与 f16 同大小 |
| `q8_0` | ~1.06 | 8-bit 量化，几乎无损 |
| `q5_1` | ~0.75 | 5-bit |
| `q5_0` | ~0.69 | |
| `q4_1` | ~0.63 | |
| `q4_0` | ~0.56 | |
| `iq4_nl` | ~0.56 | |

**实践建议**：

- **`-ctk q8_0 -ctv q8_0`** 是最划算的一档：省一半显存，精度损失极小
- **不要只量化 K 或只量化 V**：通常两个一起
- **`-ctv` 量化要求开 Flash Attention**（`-fa on`）

### 量化的收益

权重侧：

| 量化 | bits/权重 | 70B 模型大小 | 相对质量 |
| :-- | --: | --: | :-- |
| F16 / BF16 | 16 | 140 GB | 基准 |
| Q8_0 | 8.5 | 75 GB | 几乎无损 |
| Q6_K | 6.6 | 58 GB | 极小损失 |
| **Q5_K_M** | 5.7 | 50 GB | 很小损失 |
| **Q4_K_M** | 4.8 | 42 GB | **最常用平衡点** |
| Q3_K_M | 3.9 | 34 GB | 可感知损失 |
| Q2_K | 3.0 | 26 GB | 明显损失 |
| IQ1_S | ~1.6 | 14 GB | 仅极限场景 |

> **Q4_K_M 是社区公认的性价比拐点**。再往下质量下降明显快于体积下降。

### 怎么估算总显存

```
总显存 ≈ 权重(量化后) + KV(ctx × per_token) + 计算缓冲(约 1–2 GB)
```

例：Llama-3.3-70B，Q4_K_M，32K 上下文，q8_0 KV

```
权重:  42 GB
KV:    2 × 80 × 8 × 128 × 1.06 ≈ 174 KiB/token × 32768 ≈ 5.4 GB
缓冲:  ~1.5 GB
总计:  ≈ 49 GB  → 需要 2× 24GB 或 1× 48GB
```

---

## 03 架构与参数作用点

### llama-server 的组件

```
┌──────────────────────────────────────────────┐
│  httplib（HTTP 层）                            │
│  · OpenAI 兼容：chat/completions, responses   │
│  · Anthropic Messages API                     │
│  · /v1/embeddings, /rerank                    │
│  · /metrics, /slots, /props                   │
│  · Web UI                                     │
└───────────────────┬──────────────────────────┘
                    ▼
┌──────────────────────────────────────────────┐
│  server-context（多 slot 管理）                 │
│  · -np 个 slot，每个 slot 一条独立对话           │
│  · slot 可保存/恢复 KV（--slot-save-path）      │
└───────────────────┬──────────────────────────┘
                    ▼
┌──────────────────────────────────────────────┐
│  llama_context（批处理与采样）                   │
│  · continuous batching（-cb，默认开）           │
│  · logical batch (-b) / physical batch (-ub)   │
│  · speculative decoding                        │
└───────────────────┬──────────────────────────┘
                    ▼
┌──────────────────────────────────────────────┐
│  libllama + ggml（计算图）                      │
│  · 后端：CPU / CUDA / ROCm / Metal / Vulkan    │
│  · 层分配：-ngl / --n-cpu-moe                  │
└──────────────────────────────────────────────┘
```

### 一次请求的路径

```
① HTTP 接入     /v1/chat/completions
                  ↓
② 模板渲染      Jinja（--jinja，默认开）
                  ↓  --chat-template-kwargs
③ slot 分配     -np 个 slot 中找一个空的
                  ↓  --parallel
④ 分词          内置 tokenizer（GGUF 里带）
                  ↓
⑤ 批处理        continuous batching
                  ↓  -b / -ub
⑥ 推理          层在 GPU / CPU 之间切分
                  ↓  -ngl / --n-cpu-moe
⑦ 采样 + 推测   可选 speculative
                  ↓  --spec-type
⑧ 输出          流式 / 全量
                  ↓  --reasoning-format
```

### 两个 batch 参数的区别

这是 llama.cpp 特有的概念，容易混淆：

| 参数 | 名称 | 含义 |
| :-- | :-- | :-- |
| `-b, --batch-size` | **逻辑**批大小 | 一次 prompt 处理最多多少个 token（默认 2048） |
| `-ub, --ubatch-size` | **物理**批大小 | 单个计算图里最多多少个 token（默认 512） |

关系：逻辑批会被拆成多个物理批依次计算。

- `-b` 影响**吞吐**（一次能吃多长的 prompt）
- `-ub` 影响**显存峰值**（单个计算图多大）
- 显存不够时，优先降 `-ub`

---

## 04 核心参数详解

### 4.1 模型与上下文

| 参数 | 默认 | 说明 |
| :-- | :-- | :-- |
| `-m, --model` | — | GGUF 文件路径 |
| `-hf <user>/<repo>[:quant]` | — | 直接从 HF 拉取并选择量化 |
| `-mu, --model-url` | — | 从 URL 拉取 |
| `-md, --model-draft` | — | 草稿模型路径（投机解码） |
| `-mm, --mmproj` | — | 多模态投影器路径 |
| `--alias` | — | API 里显示的模型名（逗号分隔多个） |
| `-c, --ctx-size` | 0（从模型读） | 上下文长度 |
| `-n, --predict` | -1（无限） | 最大生成 token 数 |
| `--keep` | 0 | 保留 prompt 开头的多少 token（-1 = 全部） |
| `--rope-scaling` | 模型默认 | `none` / `linear` / `yarn` |
| `--rope-scale` | — | 缩放倍数 |
| `--rope-freq-base` | — | RoPE 基频 |

### 4.2 GPU 与内存

| 参数 | 默认 | 说明 |
| :-- | :-- | :-- |
| `-ngl, --gpu-layers` | `auto` | **最重要的参数**：放 GPU 的层数。可用 `999` 或 `all` |
| `-sm, --split-mode` | `layer` | `none` / `layer` / `row`（废弃）/ `tensor`（实验） |
| `-ts, --tensor-split` | 自动 | 各卡分配比例，如 `3,1` 表示 75% / 25% |
| `-mg, --main-gpu` | 0 | 主 GPU（`split-mode none` 时选卡） |
| `-dev, --device` | 自动 | 限定设备，如 `CUDA1` |
| `--list-devices` | — | 列出可用设备与显存 |
| `--n-cpu-moe N` | 0 | **把前 N 层的 MoE 专家权重放 CPU** |
| `--n-cpu-ffn N` | 0 | 把前 N 层的稠密 FFN 权重放 CPU |
| `--moe-cache-mib N` | 0 | MoE 专家在 CPU 的 GPU 缓存大小（MiB） |
| `-fit, --fit` | `on` | 自动适配未设置的参数到设备内存 |
| `--mlock` | 关 | 锁定内存，防止换出 |
| `--no-mmap` | 关（即默认 mmap） | 禁用内存映射 |

> **`--n-cpu-moe` 是 2026 年 llama.cpp 最有价值的参数之一**。MoE 模型的专家权重占用巨大但每次只激活少量，把它放 CPU 只传激活的那部分，比把整层放 CPU 高效得多。这让 120B–235B 的 MoE 模型在单机上变得可行。

### 4.3 KV Cache

| 参数 | 默认 | 说明 |
| :-- | :-- | :-- |
| `-ctk, --cache-type-k` | `f16` | K 的精度：`f32`/`f16`/`bf16`/`q8_0`/`q4_0`/`q4_1`/`iq4_nl`/`q5_0`/`q5_1` |
| `-ctv, --cache-type-v` | `f16` | V 的精度，同上 |
| `-fa, --flash-attn` | `auto` | `on` / `off` / `auto` |
| `--swa-full` | 关 | 用全尺寸 SWA cache |
| `--slot-save-path` | 关闭 | slot KV 的保存路径 |

> **`-ctv` 量化必须开 Flash Attention**。设了 `-ctv q8_0` 但 `-fa off` 会报错。

### 4.4 批处理与并行

| 参数 | 默认 | 说明 |
| :-- | :-- | :-- |
| `-b, --batch-size` | 2048 | 逻辑批大小 |
| `-ub, --ubatch-size` | 512 | 物理批大小（显存峰值由它决定） |
| `-np, --parallel` | -1（自动） | slot 数，即并发对话数 |
| `-cb, --cont-batching` | **开启** | 连续批处理 |
| `-t, --threads` | -1（自动） | 生成阶段的 CPU 线程数 |
| `-tb, --threads-batch` | 同 `-t` | 批处理/prompt 阶段的线程数 |
| `-C, --cpu-mask` | — | CPU 亲和性掩码（十六进制） |
| `-Cr, --cpu-range` | — | CPU 范围，如 `0-7` |
| `--cpu-strict` | 0 | 严格 CPU 放置 |
| `--prio` | 0 | 进程优先级：-1 低 / 0 普通 / 1 中 / 2 高 / 3 实时 |
| `--poll` | 50 | 轮询级别 0–100 |

### 4.5 服务

| 参数 | 默认 | 说明 |
| :-- | :-- | :-- |
| `--host` | `127.0.0.1` | 监听地址 |
| `--port` | **9931** | 端口 |
| `--api-key` | 无 | API 密钥（逗号分隔多个） |
| `--api-key-file` | — | 密钥文件，一行一个，`#` 开头为注释 |
| `--metrics` | 关闭 | Prometheus 指标端点 |
| `--slots` | — | slot 监控端点 |
| `--props` | 关闭 | 允许 POST /props 改全局属性 |
| `--path` | — | 静态文件目录（Web UI） |
| `--timeout` | 3600 | 读写超时（秒） |
| `--media-path` | 关闭 | 本地媒体文件目录 |
| `--models-dir` | — | 模型目录（支持动态加载多模型） |
| `--jinja` | **开启** | 用 Jinja 模板引擎 |
| `--chat-template-kwargs` | — | 传给模板的 JSON 参数 |
| `--reasoning-format` | — | `none` / `deepseek` / `deepseek-legacy` |
| `--tool-server` | — | 内置工具服务（如 `demo`） |

> **默认端口是 9931**，不是 8000 也不是 30000。这个很容易踩。

### 4.6 采样

| 参数 | 默认 |
| :-- | :-- |
| `--temp` | 0.80 |
| `--top-k` | 40（0 = 关闭） |
| `--top-p` | 0.95（1.0 = 关闭） |
| `--min-p` | — |

### 4.7 投机解码

| 参数 | 说明 |
| :-- | :-- |
| `--spec-type` | 逗号分隔的方法列表 |
| `--model-draft` / `-md` | 草稿模型路径 |
| `--spec-draft-n-max` | 最大草稿 token 数 |
| `--target-model-dir` | 转换 EAGLE-3 / DFlash 时指定目标模型 |

---

## 05 并行策略选型

<!-- engine-topologies:start -->
### 本引擎的推理拓扑与 KV 存放

> layer 是按层放置，tensor 是实验性权重/KV 切分，不是路由专家 EP。这里不画不存在对应配置的 TEP/DEP；-ngl 和 CPU offload 也不是 EP。

#### llama.cpp · layer：按层放置

配置要点：`--split-mode layer -ngl all`（机制示例，须满足模型与硬件约束）。

![llama.cpp · layer：按层放置](assets/topologies/llamacpp/topology-1.svg)

层数是示意；KV 跟随所属层，不能将其标成 GQA 的 KV-head TP 分片。

#### llama.cpp · tensor：实验性切分

配置要点：`--split-mode tensor -fa on -ctk f16 -ctv f16`（机制示例，须满足模型与硬件约束）。

![llama.cpp · tensor：实验性切分](assets/topologies/llamacpp/topology-2.svg)

按所引官方文档：tensor 为实验特性；KV 类型与 --fit 等限制以目标构建为准。

#### llama.cpp · MoE 专家留 CPU

配置要点：`--n-cpu-moe N；可选 --moe-cache-mib`（机制示例，须满足模型与硬件约束）。

![llama.cpp · MoE 专家留 CPU](assets/topologies/llamacpp/topology-3.svg)

不把 vLLM/SGLang 的 TEP、DEP、共享专家布局套用到 llama.cpp。

官方依据：[llama.cpp](https://github.com/ggml-org/llama.cpp/blob/master/docs/multi-gpu.md)。
<!-- engine-topologies:end -->


### 三种 split mode

| 模式 | 机制 | 何时用 | 限制 |
| :-- | :-- | :-- | :-- |
| `none` | 单卡，`--main-gpu` 选卡 | 显式限制在单卡 | — |
| **`layer`**（默认） | **流水并行**：每卡持连续的一段层，KV 跟着层走 | 默认选择；要更大显存 + 快 prefill；能容忍慢互联 | — |
| `row` | 旧的行切分 TP | **已废弃，勿用** | 性能差 |
| `tensor` | 实验性 TP：权重和 KV 都切 | 要低延迟；快互联（NVLink） | KV 必须 f16/bf16/f32；`--fit` 不支持；FA 必须开 |

### 流水 vs 张量的本质差异

官方文档讲得很清楚：

> Pipeline-parallel runs different layers on different GPUs and processes tokens sequentially through the pipeline. This minimizes data transfers between GPUs but requires many tokens to scale well. Tensor-parallel splits each layer across GPUs and does multiple cross-GPU reductions per layer. This enables parallelizing any workload but is much more bottlenecked by the GPU interconnect speed. **Pipeline-parallel maximizes batch throughput; tensor-parallel minimizes latency.**

翻译成决策规则：

```
你的目标是？
├─ 吞吐（离线批处理、多用户）→ --split-mode layer（默认）
└─ 延迟（单用户交互）→ --split-mode tensor（需 NVLink）
```

### 分配比例

```bash
# 两张卡显存不同：第一张 3 份，第二张 1 份
llama-server -m model.gguf -ts 3,1

# 等价写法（比例归一化）
llama-server -m model.gguf -ts 75,25
```

比例按 `--device` 的顺序对应。

### MoE 的 CPU 卸载策略

这是 llama.cpp 在 MoE 上的独门技巧。

**传统做法**：`-ngl` 放不下的层整层放 CPU。但 MoE 层的专家权重占绝大部分，而每次只激活 top-k 个。

**llama.cpp 的做法**：

```bash
# 把前 N 层的 MoE 专家权重放 CPU，注意力/共享专家留在 GPU
llama-server -m model.gguf --n-cpu-moe 20

# 给 CPU 上的 MoE 专家一个 GPU 缓存
llama-server -m model.gguf --n-cpu-moe 20 --moe-cache-mib 2048
```

稠密模型用 `--n-cpu-ffn`：

```bash
llama-server -m model.gguf --n-cpu-ffn 10
```

> **效果**：让 120B 级 MoE 在单张 24–48GB 显卡上可跑。这是 llama.cpp 相对其它框架的独特优势。

---

## 06 逐模型实战配置

### 6.1 快速上手：一条命令

```bash
# 从 HF 直接拉（自动选量化）
llama-cli -hf ggml-org/gemma-3-1b-it-GGUF

# 服务化
llama-server -hf ggml-org/gemma-3-1b-it-GGUF
```

### 6.2 gpt-oss-120b（推荐的重点模型）

117B 总参 / 5.1B 激活，原生 MXFP4，量化后约 63 GB。

**单张 80GB 卡**：

```bash
llama-server \
  -m gpt-oss-120b-mxfp4.gguf \
  -ngl 999 \
  -c 131072 \
  -fa on \
  -ctk q8_0 -ctv q8_0 \
  --jinja \
  --reasoning-format deepseek \
  --host 0.0.0.0 --port 8000 \
  --alias gpt-oss-120b
```

**单张 48GB 卡（用 MoE 卸载）**：

```bash
llama-server \
  -m gpt-oss-120b-mxfp4.gguf \
  -ngl 999 \
  --n-cpu-moe 16 \
  --moe-cache-mib 4096 \
  -c 32768 \
  -fa on
```

**双卡（流水）**：

```bash
llama-server \
  -m gpt-oss-120b-mxfp4.gguf \
  -ngl 999 \
  -sm layer \
  -c 65536 \
  -fa on
```

**工具调用**：

```bash
llama-server \
  -m gpt-oss-120b-mxfp4.gguf \
  -ngl 999 \
  --jinja \
  --tool-server demo
```

> gpt-oss 用 harmony chat 格式，`--jinja` 会从 GGUF 元数据里读模板。

**验证**：

```bash
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-oss-120b",
    "messages": [{"role":"user","content":"Explain eigenvalues briefly."}],
    "max_tokens": 256
  }'
```

### 6.3 Llama-3.3-70B

70B 稠密，Q4_K_M 约 42 GB。

**单张 48GB（如 RTX 6000 Ada / A6000）**：

```bash
llama-server \
  -m Llama-3.3-70B-Instruct-Q4_K_M.gguf \
  -ngl 999 \
  -c 32768 \
  -fa on \
  -ctk q8_0 -ctv q8_0 \
  -b 2048 -ub 512
```

**双卡 24GB（流水）**：

```bash
llama-server \
  -m Llama-3.3-70B-Instruct-Q4_K_M.gguf \
  -ngl 999 \
  -sm layer \
  -ts 1,1 \
  -c 16384 \
  -fa on \
  -ctk q8_0 -ctv q8_0
```

**纯 CPU（64GB 内存，慢但可用）**：

```bash
llama-server \
  -m Llama-3.3-70B-Instruct-Q4_K_M.gguf \
  -ngl 0 \
  -t 32 \
  -c 8192
```

> CPU 上 70B Q4 大约 2–4 tok/s（取决于 CPU）。只适合离线/实验。

### 6.4 Qwen3 系列

```bash
# Qwen3-32B，单张 24GB
llama-server \
  -m Qwen3-32B-Q4_K_M.gguf \
  -ngl 999 \
  -c 32768 \
  -fa on \
  -ctk q8_0 -ctv q8_0 \
  --jinja

# Qwen3-30B-A3B（MoE），用 CPU 卸载跑在 16GB 卡上
llama-server \
  -m Qwen3-30B-A3B-Q4_K_M.gguf \
  -ngl 999 \
  --n-cpu-moe 24 \
  -c 32768 \
  -fa on
```

### 6.5 投机解码实战

#### EAGLE-3

```bash
# 1) 转换草稿模型（必须指定目标模型以继承 tokenizer）
python convert_hf_to_gguf.py AngelSlim/Qwen3-4B_eagle3 \
  --target-model-dir Qwen/Qwen3-4B \
  --outtype bf16 \
  --outfile Qwen3-4B-eagle3.gguf

# 2) 启动
llama-server \
  -m Qwen3-4B.gguf \
  -md Qwen3-4B-eagle3.gguf \
  --spec-type draft-eagle3
```

**官方支持的 EAGLE-3 草稿模型**（部分）：

- `yuhuili/EAGLE3-LLaMA3.1-Instruct-8B`
- `yuhuili/EAGLE3-LLaMA3.3-Instruct-70B`
- `AngelSlim/Qwen3-{1.7B,4B,8B,14B,32B}_eagle3`
- `Tengyunw/qwen3_8b_eagle3`
- `Tengyunw/qwen3_30b_moe_eagle3`
- `RedHatAI/gpt-oss-20b-speculator.eagle3`
- `lmsys/EAGLE3-gpt-oss-120b-bf16`
- `nvidia/gpt-oss-120b-Eagle3-long-context`

#### DFlash

```bash
python convert_hf_to_gguf.py z-lab/Qwen3-4B-DFlash \
  --target-model-dir Qwen/Qwen3-4B \
  --outtype bf16 \
  --outfile Qwen3-4B-DFlash.gguf

llama-server \
  -m Qwen3-4B.gguf \
  -md Qwen3-4B-DFlash.gguf \
  --spec-type draft-dflash \
  --spec-draft-n-max 15 \
  -fa on --jinja
```

#### N-gram（零额外模型）

```bash
llama-server \
  -m model.gguf \
  -ngl 999 \
  --spec-type ngram-simple
```

> 适合代码补全、模板化输出这类**重复性强**的场景。对自由文本收益有限。

#### 混用

```bash
# 同时用 draft 模型 + n-gram
llama-server \
  -m model.gguf \
  -md draft.gguf \
  --spec-type draft-simple,ngram-simple
```

### 6.6 多模态

```bash
llama-server \
  -m model.gguf \
  --mmproj mmproj-model-f16.gguf \
  -ngl 999 \
  -c 8192
```

> `-hf` 拉取时，如果仓库里有 mmproj，会自动关联。

### 6.7 配置速查

| 场景 | 关键参数 |
| :-- | :-- |
| 单卡尽量跑满 | `-ngl 999 -fa on -ctk q8_0 -ctv q8_0` |
| 显存不够 | `--n-cpu-moe N`（MoE）/ `--n-cpu-ffn N`（稠密）/ 降 `-c` / 降 `-ub` |
| 多卡吞吐 | `-sm layer -ts 1,1`（默认） |
| 多卡低延迟 | `-sm tensor` + `-fa on` + 非量化 KV |
| 多用户 | `-np 4` + `-cb`（默认开） |
| 低延迟单用户 | `--spec-type draft-eagle3` |
| 代码补全 | `--spec-type ngram-simple` |
| 生产 API | `--api-key xxx --metrics --host 0.0.0.0` |

---

## 07 调优方法论

### 先定位瓶颈

| 现象 | 瓶颈 | 检查 |
| :-- | :-- | :-- |
| 生成慢（< 5 tok/s）但 GPU 利用率低 | 层在 CPU 上 | 看启动日志的 `offloaded N/M layers to GPU` |
| prefill 慢 | `-b` 太小 / `-ub` 太小 | 提高 `-b`（与显存权衡） |
| 显存刚好卡住 | KV 太大 | `-ctk q8_0 -ctv q8_0`；降 `-c` |
| 多用户时变慢 | slot 太少 | 提高 `-np` |
| 延迟抖动 | 调度开销 | 降 `-np`；考虑 `--prio 2` |

### 按顺序调

**第一步：确保层都在 GPU**

看启动日志：

```
load_tensors: offloaded 41/41 layers to GPU
```

如果是 `offloaded 35/41 layers`，说明 6 层在 CPU——这是最大的性能杀手。

解决：降 `-c`、量化 KV、用 `--n-cpu-moe`（MoE）。

**第二步：量化 KV**

```bash
-ctk q8_0 -ctv q8_0 -fa on
```

省一半 KV 显存，精度几乎无损。

**第三步：调 `-b` / `-ub`**

- `-b 2048` 是默认，长 prompt 场景可提到 4096
- `-ub 512` 是默认，显存紧可降到 256 或 128
- 提高 `-b` 提升 prefill 吞吐；提高 `-ub` 提升单批效率但增显存

**第四步：调线程（CPU 推理时）**

```bash
-t $(nproc)          # 生成阶段
-tb $(nproc)         # prompt 阶段
```

> 一般设为物理核数。**超线程核心不计入**，设成逻辑核数反而变慢。

CPU 亲和性：

```bash
-Cr 0-31             # 限定在前 32 个核
--cpu-strict 1
```

**第五步：投机解码**

- 交互场景：EAGLE-3 收益最大
- 代码/模板：n-gram
- 有一定成本（额外显存放 draft 模型），要权衡

### 按场景的配方

| 场景 | 配置 |
| :-- | :-- |
| **本地单用户聊天** | `-ngl 999 -fa on -ctk q8_0 -ctv q8_0 -np 1 --spec-type draft-eagle3` |
| **本地多用户 API** | `-ngl 999 -np 8 -cb -b 4096 --host 0.0.0.0 --api-key xxx` |
| **离线批处理** | `-ngl 999 -b 8192 -ub 1024 -np 1`（大 batch 吞吐优先） |
| **CPU 部署** | `-ngl 0 -t <物理核数> -c 4096 -ctk q8_0` |
| **边缘设备** | `-ngl 999 -c 4096 -ctk q4_0 -ctv q4_0`（极致省显存） |
| **MoE 大模型单卡** | `-ngl 999 --n-cpu-moe N --moe-cache-mib 4096` |

### 性能观测

```bash
# 内置性能计时
--perf

# Prometheus
--metrics
curl http://localhost:9931/metrics
```

llama.cpp 的日志会打印每个请求的：
- prompt eval time（prefill）
- eval time（decode）
- tokens per second

这是最直接的调优依据。

---

## 08 生产化与排错

### 8.1 容器

官方提供多个镜像：

| 镜像 | 内容 |
| :-- | :-- |
| `ghcr.io/ggml-org/llama.cpp:server` | 仅 llama-server |
| `ghcr.io/ggml-org/llama.cpp:server-cuda` | CUDA 12 |
| `ghcr.io/ggml-org/llama.cpp:server-cuda13` | CUDA 13 |
| `ghcr.io/ggml-org/llama.cpp:server-rocm` | ROCm |
| `ghcr.io/ggml-org/llama.cpp:server-musa` | MUSA |
| `ghcr.io/ggml-org/llama.cpp:server-intel` | SYCL |
| `ghcr.io/ggml-org/llama.cpp:full` | 含转换与量化工具 |
| `ghcr.io/ggml-org/llama.cpp:light` | 仅 CLI |

```bash
docker run -d \
  --gpus all \
  --name llama-server \
  -p 8000:8000 \
  -v /models:/models \
  ghcr.io/ggml-org/llama.cpp:server-cuda13 \
  -m /models/model.gguf \
  -ngl 999 \
  -c 32768 \
  -fa on \
  --host 0.0.0.0 --port 8000 \
  --api-key your-secret-key \
  --metrics
```

### 8.2 端点

| 端点 | 说明 |
| :-- | :-- |
| `/v1/chat/completions` | OpenAI 兼容对话 |
| `/v1/completions` | 补全 |
| `/v1/responses` | Responses API |
| `/v1/embeddings` | 向量 |
| `/v1/models` | 模型列表 |
| `/rerank` | 重排序 |
| `/health` | 健康检查 |
| `/metrics` | Prometheus（需 `--metrics`） |
| `/slots` | slot 状态（需 `--slots`） |
| `/props` | 全局属性（需 `--props` 才能改） |
| `/` | Web UI |

**支持 Anthropic Messages API**，可直接接 Claude Code：

```bash
llama-server -m model.gguf -ngl 999 --jinja --host 0.0.0.0 --port 8000

ANTHROPIC_BASE_URL=http://localhost:8000 \
ANTHROPIC_AUTH_TOKEN=dummy \
claude
```

### 8.3 故障排查

| 现象 | 原因 | 处理 |
| :-- | :-- | :-- |
| 速度只有几 tok/s | 层被 offload 到 CPU | 看日志 `offloaded N/M`；降 `-c`；量化 KV；`--n-cpu-moe` |
| 启动 OOM | 层数 × 权重 + KV 超了 | 降 `-ngl`；降 `-c`；降 `-ub` |
| `-ctv q8_0` 报错 | 没开 Flash Attention | 加 `-fa on` |
| `tensor` 模式报错 | KV 是量化格式 / `--fit` 开着 | `-ctk f16 -ctv f16`；`--fit off` |
| 模型加载失败 | GGUF 版本不匹配 | 重新转换或升级 llama.cpp |
| 中文乱码 / 分词异常 | tokenizer 缺失 | 确认 GGUF 内含 tokenizer |
| 工具调用不生效 | 模板不支持 | 加 `--jinja`；检查 `--chat-template-kwargs` |
| 推理内容混在 content | `--reasoning-format` 未设 | 设 `deepseek` 或 `deepseek-legacy` |
| 多用户时排队 | `-np` 太小 | 提高 `-np`（代价是每个 slot 的上下文变小） |
| 端口连不上 | 默认 9931 | 检查 `--port` |
| 多模态报错 | mmproj 未加载 | 加 `--mmproj` |

### 8.4 安全

- **默认只监听 127.0.0.1**：要对外必须显式 `--host 0.0.0.0`
- **默认无鉴权**：务必设 `--api-key` 或 `--api-key-file`
- `--media-path` 会暴露本地文件读取，只在可信环境开
- `--props` 允许运行时改配置，生产环境慎开

---

## 09 附录

### A. 参数速查

| 参数 | 一句话 |
| :-- | :-- |
| `-m` | 模型路径 |
| `-hf` | 从 HF 直接拉 |
| `-ngl` | **放 GPU 的层数，最重要的参数** |
| `-c` | 上下文长度 |
| `-fa` | Flash Attention |
| `-ctk` / `-ctv` | K/V 的 KV Cache 精度 |
| `-b` / `-ub` | 逻辑 / 物理批大小 |
| `-np` | slot 数（并发对话） |
| `-cb` | 连续批处理（默认开） |
| `-sm` | split mode：`layer` / `tensor` / `none` |
| `-ts` | 各卡分配比例 |
| `--n-cpu-moe` | MoE 专家放 CPU 的层数 |
| `--n-cpu-ffn` | 稠密 FFN 放 CPU 的层数 |
| `--moe-cache-mib` | CPU 专家在 GPU 的缓存 |
| `--fit` | 自动适配内存（默认 on） |
| `-t` / `-tb` | 生成 / 批处理线程数 |
| `--jinja` | Jinja 模板（默认开） |
| `--spec-type` | 投机解码方法 |
| `-md` | 草稿模型 |
| `--reasoning-format` | 推理内容格式 |
| `--api-key` | 鉴权 |
| `--metrics` | Prometheus |
| `--port` | 端口（默认 9931） |

### B. 环境变量

| 变量 | 作用 |
| :-- | :-- |
| `LLAMA_ARG_*` | 所有参数都有对应的环境变量形式（见参数表） |
| `LLAMA_API_KEY` | 等价 `--api-key` |
| `CUDA_VISIBLE_DEVICES` | 控制可见 GPU |
| `MODEL_ENDPOINT` | 指定 HF 兼容的模型源 |
| `LLAMA_ARG_N_GPU_LAYERS` | 等价 `-ngl` |

### C. 量化格式选择指南

| 格式 | 用途 |
| :-- | :-- |
| `Q8_0` | 几乎无损，体积大 |
| `Q6_K` | 高保真 |
| **`Q5_K_M`** | 高质量 |
| **`Q4_K_M`** | **默认推荐，性价比最佳** |
| `Q4_0` | 更快但质量略低 |
| `Q3_K_M` | 显存极度受限 |
| `Q2_K` | 仅极限场景 |
| `IQ4_XS` / `IQ3_XS` | i-quant，同体积下质量更好但更慢 |
| `IQ1_S` / `IQ2_XXS` | 极端压缩，质量明显下降 |

### D. 来源

| 来源 | 用途 |
| :-- | :-- |
| github.com/ggml-org/llama.cpp/tools/server/README.md | server 全部参数（自动生成） |
| .../docs/multi-gpu.md | 多卡 split mode 与配方 |
| .../docs/speculative.md | 投机解码方法矩阵 |
| .../docs/models.md | 模型获取与量化 |
| .../docs/docker.md | 镜像列表 |
| .../docs/function-calling.md | 工具调用 |
| .../docs/multimodal.md | 多模态 |
| github releases | 版本核验 |

---

*本文档基于 2026-11-06 可获取的公开资料整理。llama.cpp 的参数表由代码自动生成，迭代频繁；具体参数的默认值请以 `llama-server --help` 输出为准。*
