Published on

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

Authors

模型简介

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_11.95 GB可选,推测解码用
DSpark 草稿层bf16(参考版)7.29 GB可选
视觉塔 mmprojHQQ 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_size4
-ngl 999主模型全部层 offload 到 GPU(官方用 999)999
-ngld 999草稿模型全部层 offload 到 GPU999
-np 1单 slot(DSpark 强制要求)1
-c 16384上下文窗口(DSpark 模式下官方推荐 16384+)16384
-fa on开启 Flash Attentionon
-ub 512Prompt 处理的 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 KiB1x默认,最快
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_nl KV 量化格式支持不佳,建议避开,使用 q4_0q8_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 GBDSpark 默认推荐起步
16K~1 GB~0.28 GBDSpark 官方推荐
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_ndraft_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 1AMD 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 上下文长度。

速度远低于预期

排查清单:

  1. 确认用了 Prism 分支,而非原版 llama.cpp
  2. 确认 -ngl 999,没有层残留在 CPU
  3. 确认 KV 量化格式避开了 iq4_nl(AMD 395 不兼容)
  4. 确认 AMD 驱动中 VGM 设为 High
  5. 通过 timings 中的 draft_n 判断 DSpark 是否生效
  6. 弱 iGPU 建议尝试 BONSAI_NGL=0 走 CPU

DSpark 的代价

官方明确列出了 DSpark 的两个代价(这也是它默认关闭的原因):

  1. 跨请求 prompt-cache 复用被禁用:每次请求都要重新处理完整对话历史,多轮对话的首 token 延迟会增加
  2. 单 slot(-np 1:一次只能处理一个请求

因此,Open WebUI 的 agentic demo 故意使用普通的 cached path,DSpark 只用于独立 chat server。