- Published on
Ternary-Bonsai-27B 部署与调优指南
- Authors

- Name
- JiGu
- @crypto20x
模型简介
Ternary-Bonsai-27B 是 PrismML 推出的三值化(Ternary)大语言模型,基于 Qwen3.6-27B 架构(混合注意力 ~75% 线性 / ~25% 全注意力,SwiGLU MLP,RoPE,RMSNorm),支持 262K 上下文。
每个权重取值为 1,以 2-bit 存储 + FP16 分组缩放(每 128 权重共享一个 scale),实际信息密度仅 1.71 bits/weight,部署体积约 7.2 GB(理论极限 5.9 GB),相比 FP16 的 ~54 GB 缩小约 9.4 倍。
由于权重极度压缩,推理时几乎完全受内存带宽限制。在 AMD 395(256 GB/s 统一内存带宽)上,单模型理论极限约 35 token/s,实测约 20-30 token/s。Apple M5 Pro 实测约 26 token/s。
模型自带一个名为 DSpark 的轻量级草稿层(Drafter),配合推测解码(Speculative Decoding)可在 CUDA 平台实现约 1.8-2x 无损加速(代码/推理任务);在 AMD 平台上效果因算子优化程度而异。
重要:原版 llama.cpp 无法正确加载 Ternary-Bonsai 的三值化算子和 DSpark 架构,必须使用 PrismML 的特制分支(通过 Bonsai-demo 仓库获取)。
模型组件
| 组件 | 格式 | 大小 | 说明 |
|---|---|---|---|
| 主模型 | Q2_0_g128 (2-bit) | 7.17 GB | 必须常驻 |
| DSpark 草稿层 | Q4_1 | 1.95 GB | 可选,推测解码用 |
| DSpark 草稿层 | bf16(参考版) | 7.29 GB | 可选 |
| 视觉塔 mmproj | HQQ 4-bit (Q8_0 容器) | 0.63 GB | 可选,仅图像输入时加载 |
环境信息
| 项目 | 值 |
|---|---|
| 系统 | Linux x86_64 |
| 显卡 | AMD RX 395 (Vulkan/ROCm) |
| 显存 | 96 GB(统一内存) |
| 主模型 | Ternary-Bonsai-27B-Q2_0.gguf (~7.2 GB) |
| 草稿模型 | Ternary-Bonsai-27B-dspark-Q4_1.gguf (~1.95 GB) |
| llama.cpp 版本 | Prism 特制分支 |
1. 获取 Prism 分支 llama.cpp
Ternary-Bonsai 需要 PrismML 维护的特制 llama.cpp,官方推荐通过 Bonsai-demo 仓库获取:
git clone https://github.com/PrismML-Eng/Bonsai-demo.git
cd Bonsai-demo
./setup.sh
setup.sh 会自动编译并配置好支持 Ternary 算子和 DSpark 的 llama.cpp 二进制文件。
如果 27B 仓库为私有,下载模型需要设置
BONSAI_TOKEN(HuggingFace read-only token)。
多版本切换(推荐)
如果同时需要 Vulkan / ROCm / Prism 等多个版本,可以参考如下目录结构管理:
~/llama.cpp/
├── use-llama # 切换脚本
├── prism/ # Prism 特制分支(支持 Ternary + DSpark)
├── vulkan/ # 通用 Vulkan 版
└── rocm/ # ROCm 版
切换脚本 ~/llama.cpp/use-llama:
#!/bin/bash
LLAMA_HOME="$HOME/llama.cpp"
case "$1" in
prism)
export LLAMA_BACKEND="prism"
export LLAMA_PATH="$LLAMA_HOME/prism"
;;
vulkan)
export LLAMA_BACKEND="vulkan"
export LLAMA_PATH="$LLAMA_HOME/vulkan/b10079"
;;
rocm)
export LLAMA_BACKEND="rocm"
export LLAMA_PATH="$LLAMA_HOME/rocm/b10079"
;;
"")
if [ -n "$LLAMA_BACKEND" ]; then
echo "当前版本: $LLAMA_BACKEND ($LLAMA_PATH)"
else
echo "当前版本: 未激活"
echo "用法: source use-llama prism|vulkan|rocm"
fi
return 0 2>/dev/null || exit 0
;;
*)
echo "用法: source use-llama prism|vulkan|rocm"
return 1 2>/dev/null || exit 1
;;
esac
export PATH="$LLAMA_PATH:$PATH"
export LD_LIBRARY_PATH="$LLAMA_PATH:$LD_LIBRARY_PATH"
echo "llama.cpp ($LLAMA_BACKEND) 已激活"
chmod +x ~/llama.cpp/use-llama
使用方式:
source ~/llama.cpp/use-llama prism # 切换到 Prism 分支
source ~/llama.cpp/use-llama vulkan # 切换到 Vulkan 版
source ~/llama.cpp/use-llama # 查看当前版本
必须用
source执行,否则环境变量不会生效。
2. 下载模型文件
从 HuggingFace 仓库 prism-ml/Ternary-Bonsai-27B-gguf 下载:
mkdir -p ~/model-gguf
huggingface-cli download prism-ml/Ternary-Bonsai-27B-gguf \
Ternary-Bonsai-27B-Q2_0.gguf \
Ternary-Bonsai-27B-dspark-Q4_1.gguf \
--local-dir ~/model-gguf/
如果仓库为私有,需要先设置 token:
export HF_TOKEN="your_huggingface_read_only_token"
3. 启动服务
AMD 用户注意:DSpark 推测解码在 AMD 395 上实测为负优化,会显著降低速度。AMD 用户请直接使用方式一(单模型)。DSpark 仅在 NVIDIA CUDA 上有稳定的 1.8-2x 加速。
方式一:单模型(AMD 推荐)
source ~/llama.cpp/use-llama prism && \
llama-server \
--host 0.0.0.0 --port 8081 \
-m ~/model-gguf/Ternary-Bonsai-27B-Q2_0.gguf \
-ngl 999 \
-fa on \
-c 128000
AMD 395 实测速度约 20-30 tok/s,受限于 256 GB/s 内存带宽的物理极限。
方式二:使用 Bonsai-demo 脚本(CUDA 推荐)
官方推荐的启动方式,环境变量会自动处理所有参数:
cd Bonsai-demo
# 开启 DSpark 推测解码(仅 CUDA 有加速)
export BONSAI_SPECULATIVE=1
# 可选:开启 4-bit KV 缓存(显存紧张时)
# export BONSAI_KV4=1
./scripts/start_llama_server.sh
脚本会自动添加 -md <drafter> --spec-type draft-dspark --spec-draft-n-max 4 -ngld 999 -np 1,并将上下文提升到 16384。
方式三:手动 DSpark 命令(CUDA 专用)
source ~/llama.cpp/use-llama prism && \
llama-server \
--host 0.0.0.0 --port 8081 \
-m ~/model-gguf/Ternary-Bonsai-27B-Q2_0.gguf \
-md ~/model-gguf/Ternary-Bonsai-27B-dspark-Q4_1.gguf \
--spec-type draft-dspark \
--spec-draft-n-max 4 \
-ngl 999 -ngld 999 \
-fa on \
-c 16384 \
-np 1
参数一览
| 参数 | 说明 | 官方推荐值 |
|---|---|---|
-m | 主模型路径 | 必填 |
-md | 草稿模型路径(DSpark) | DSpark 时必填 |
--spec-type draft-dspark | 推测解码类型 | draft-dspark |
--spec-draft-n-max 4 | 每次推测最多生成 4 个 token(必须等于 DSpark 的 block_size) | 4 |
-ngl 999 | 主模型全部层 offload 到 GPU(官方用 999) | 999 |
-ngld 999 | 草稿模型全部层 offload 到 GPU | 999 |
-np 1 | 单 slot(DSpark 强制要求) | 1 |
-c 16384 | 上下文窗口(DSpark 模式下官方推荐 16384+) | 16384 |
-fa on | 开启 Flash Attention | on |
-ub 512 | Prompt 处理的 micro-batch size(需 ≤ -b,结合显存/内存带宽调优) | 512 |
4. 关键参数调优
--spec-draft-n-max 必须设为 4
这是最常见的踩坑点。DSpark 草稿模型的 block_size 固定为 4,如果不等于 4,启动时直接报错:
E srv load_model: draft-dspark: --spec-draft-n-max (3) must equal the drafter's block_size (4)
E srv llama_server: exiting due to model loading error
解决:始终显式指定 --spec-draft-n-max 4。
-ngl 用 999 而非 99
官方 AGENTS.md 和 SPECULATIVE.md 中统一使用 -ngl 999 / -ngld 999(而非 99),确保所有层都 offload 到 GPU。虽然 99 通常也够用(模型只有 64 层),但 999 是官方推荐的安全值。
-np 1:DSpark 强制单 slot
开启 DSpark 后,llama-server 被强制为单 slot 模式(一次只能处理一个请求)。这是因为推测解码会禁用跨请求的 prompt-cache 复用,每次请求都需要重新处理完整对话历史。
KV 缓存量化选择
官方文档明确指出:Q4_0 KV 缓存是内存工具,不是速度工具——decode 会比 FP16 KV 缓存略慢。
| 格式 | 每 token KV 大小 | 相对 FP16 | 说明 |
|---|---|---|---|
f16 | ~64 KiB | 1x | 默认,最快 |
q8_0 | ~32 KiB | ~2x | 近似无损 |
q4_0 | ~18 KiB | ~3.5x | 有损,decode 略慢 |
27B 的混合注意力架构(~75% 线性注意力)已经让 KV 缓存很小(只有 16/64 层使用全注意力),所以只有在非常长的上下文且显存紧张时才需要 Q4_0。
# 显存紧张时的配置(通过 Bonsai-demo 脚本)
export BONSAI_KV4=1
./scripts/start_llama_server.sh
# 或手动指定
-ctk q4_0 -ctv q4_0
AMD RX 395 上
iq4_nlKV 量化格式支持不佳,建议避开,使用q4_0或q8_0。
KV 缓存质量优化:Mean-centering Bias
4-bit KV 量化会对 K 缓存中非零均值的通道造成精度损失。官方提供了 make_kv_bias.sh 脚本来构建模型特定的校准偏差,可以零运行时成本修复大部分精度损失:
# 使用内置合成语料构建
./scripts/make_kv_bias.sh
# 或使用你自己的文本(推荐,更贴合实际使用场景)
./scripts/make_kv_bias.sh my_corpus.txt
构建完成后,BONSAI_KV4=1 启动时会自动加载偏差文件。
上下文长度 -c
| 上下文 | FP16 KV 大小 | Q4_0 KV 大小 | 说明 |
|---|---|---|---|
| 8K | ~0.5 GB | ~0.14 GB | DSpark 默认推荐起步 |
| 16K | ~1 GB | ~0.28 GB | DSpark 官方推荐 |
| 100K | ~6.3 GB | ~1.8 GB | 长对话 |
| 262K | ~16 GB | ~4.6 GB | 模型最大上下文 |
官方建议 DSpark 模式下
-c 16384+,因为模型通常会"思考" 1.5-2K token 后才输出可见回答,上下文太小会截断回答。
GPU Offload 覆盖
通过环境变量 BONSAI_NGL 可以覆盖 GPU 层数 offload:
# 强制 CPU-only(某些弱核显反而更慢时)
export BONSAI_NGL=0
# 强制全部 GPU
export BONSAI_NGL=999
官方提示:自动检测依赖的是已安装的工具链而非 GPU 能力。如果你的机器只有集成显卡和 Vulkan 驱动,自动检测会 offload 到 iGPU。对于 Strix Halo 这类强力 iGPU 确实有益,但弱 iGPU 反而建议
BONSAI_NGL=0走 CPU。
5. 性能参考
各平台速度参考
| 平台 | 单模型 | DSpark 加速 | 来源 |
|---|---|---|---|
| Apple M5 Pro | ~26 tok/s | 尚未优化,不推荐 | 官方 Model Card |
| AMD RX 395 | ~20-30 tok/s | 负优化,实测更慢 | 实测 |
| CUDA 数据中心 GPU | ~70 tok/s | ~135 tok/s(代码任务) | 官方 SPECULATIVE.md |
DSpark 在 AMD 395 上为负优化(实测结论)
官方明确标注 DSpark 为 highly experimental,且 "Apple Silicon (Metal) support will be improved in a later release, so do not expect a speedup on Macs yet"。AMD 平台同理。
AMD 395 实测结论:开启 DSpark 后速度显著下降,即使加上 -np 1 和 16384 上下文限制也没有改善。AMD 用户请直接关闭 DSpark,使用单模型运行。
原因分析:
1. Ternary 算子在 AMD 上未优化
单模型时速度受限于内存带宽,GPU 算力有富余。开启 DSpark 后 GPU 需要额外跑草稿模型,Ternary 的特殊算子在 AMD ROCm/Vulkan 上优化尚不完善,算力被草稿模型吃满。
2. 草稿模型接受率低
每次 API 响应的 timings 对象中包含 draft_n 和 draft_n_accepted。可以检查接受率:
curl -s http://localhost:8081/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"messages":[{"role":"user","content":"Implement quicksort in Python."}],"max_tokens":400}' \
| jq '.timings | {predicted_per_second, draft_n, draft_n_accepted}'
3. prompt-cache 被禁用
DSpark 模式下每次请求都会重新处理完整对话历史,长上下文时开销显著。
优化方案
| 方案 | 操作 | 效果 |
|---|---|---|
| 关闭 DSpark(AMD 首选) | 去掉 -md 和 --spec-type,去掉 -np 1 | AMD 395 最稳最快 |
| 降低 KV 缓存精度 | BONSAI_KV4=1 或 -ctk q4_0 -ctv q4_0 | 释放显存,但 decode 略慢 |
| 构建 KV bias | ./scripts/make_kv_bias.sh | 修复 Q4 KV 量化的精度损失 |
| 确保全层 GPU offload | -ngl 999 | 防止任何层留在 CPU |
| 开启 VGM High 模式 | AMD 驱动设置中将 VGM 设为 High | 提升显存吞吐量 |
6. API 调用与验证
基本调用
curl -s http://localhost:8081/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"messages":[{"role":"user","content":"你好"}],"max_tokens":100}'
验证 DSpark 是否生效
curl -s http://localhost:8081/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"messages":[{"role":"user","content":"Implement quicksort in Python."}],"max_tokens":400}' \
| jq '.timings | {predicted_per_second, draft_n, draft_n_accepted}'
draft_n缺失或为 0 → DSpark 未生效draft_n_accepted / draft_n→ 接受率,越高越好
CLI 单次推理
llama-speculative-simple \
-m ~/model-gguf/Ternary-Bonsai-27B-Q2_0.gguf \
-md ~/model-gguf/Ternary-Bonsai-27B-dspark-Q4_1.gguf \
--spec-type draft-dspark --spec-draft-n-max 4 \
-ngl 999 -ngld 999 -c 8192 -n 400 --temp 0 -e \
-p "<|im_start|>user\n你好<|im_end|>\n<|im_start|>assistant\n"
llama-speculative-simple是 Prism 分支自带的 CLI 推测解码工具(包含在预编译二进制中),运行结束会打印n_drafted/n_accept/ accept rate。
7. 常见问题
--spec-draft-n-max 报错
draft-dspark: --spec-draft-n-max (N) must equal the drafter's block_size (4)
解决:显式加 --spec-draft-n-max 4。
DSpark 静默失效
在 AMD 集成显卡上,如果显存不足,DSpark 可能因 OOM 被自动关闭,退回到普通 Decode 模式。
解决:加 BONSAI_KV4=1 或 -ctk q4_0 -ctv q4_0 压缩 KV 缓存,或缩短 -c 上下文长度。
速度远低于预期
排查清单:
- 确认用了 Prism 分支,而非原版 llama.cpp
- 确认
-ngl 999,没有层残留在 CPU - 确认 KV 量化格式避开了
iq4_nl(AMD 395 不兼容) - 确认 AMD 驱动中 VGM 设为 High
- 通过
timings中的draft_n判断 DSpark 是否生效 - 弱 iGPU 建议尝试
BONSAI_NGL=0走 CPU
DSpark 的代价
官方明确列出了 DSpark 的两个代价(这也是它默认关闭的原因):
- 跨请求 prompt-cache 复用被禁用:每次请求都要重新处理完整对话历史,多轮对话的首 token 延迟会增加
- 单 slot(
-np 1):一次只能处理一个请求
因此,Open WebUI 的 agentic demo 故意使用普通的 cached path,DSpark 只用于独立 chat server。