vinpix commited on
Commit
8d289c9
Β·
verified Β·
1 Parent(s): 6a4c621

Update model card: TQ2_0 (CPU) + Q2_KT (GPU) unified card

Browse files
Files changed (1) hide show
  1. README.md +109 -121
README.md CHANGED
@@ -1,188 +1,176 @@
1
  ---
2
- quantized_by: vinpix
3
- base_model: prism-ml/Ternary-Bonsai-8B-gguf
4
  license: apache-2.0
5
- language:
6
- - en
7
- library_name: gguf
8
  tags:
9
- - gguf
10
- - llama.cpp
11
- - ternary
12
- - 1.58-bit
13
- - bitnet
14
- - cpu
15
- - qwen3
 
 
 
 
 
 
16
  pipeline_tag: text-generation
 
17
  ---
18
 
19
- <div align="center">
20
 
21
- # 🌳 Ternary-Bonsai-8B · TQ2_0 GGUF
22
 
23
- ### 1.58-bit ternary 8B that runs on **stock llama.cpp** β€” no fork required
24
 
25
- <p>
26
- <img src="https://img.shields.io/badge/format-GGUF-1f6feb?style=for-the-badge&logo=huggingface&logoColor=white" alt="GGUF">
27
- <img src="https://img.shields.io/badge/precision-ternary%20%7B%E2%88%921%2C0%2C%2B1%7D-8957e5?style=for-the-badge" alt="ternary">
28
- <img src="https://img.shields.io/badge/body-2.06%20bpw-2ea043?style=for-the-badge" alt="2.06 bpw">
29
- <img src="https://img.shields.io/badge/size-2.33%20GiB-e3b341?style=for-the-badge" alt="2.33 GiB">
30
- </p>
31
 
32
- <p>
33
- <img src="https://img.shields.io/badge/llama.cpp-mainline-000000?style=flat-square&logo=cplusplus" alt="llama.cpp">
34
- <img src="https://img.shields.io/badge/LM%20Studio-supported-4b32c3?style=flat-square" alt="LM Studio">
35
- <img src="https://img.shields.io/badge/Ollama-supported-000000?style=flat-square&logo=ollama" alt="Ollama">
36
- <img src="https://img.shields.io/badge/context-64K-0969da?style=flat-square" alt="64K context">
37
- <img src="https://img.shields.io/badge/license-Apache--2.0-750014?style=flat-square" alt="Apache-2.0">
38
- </p>
39
 
40
- <sub>A portable GGUF repack of <a href="https://huggingface.co/prism-ml/Ternary-Bonsai-8B-gguf"><b>PrismML Ternary-Bonsai-8B</b></a> Β· quantized by <b>vinpix</b></sub>
41
 
42
- </div>
 
 
43
 
44
  ---
45
 
46
- <div align="center">
47
 
48
- > **8B quality. 2.3 GB on disk. Runs on the llama.cpp you already have.**
 
49
 
50
- </div>
51
 
52
- Ternary-Bonsai-8B is an 8B **Qwen3-architecture** model whose linear weights are **ternary** β€” every weight is one of `{βˆ’1, 0, +1}` with a shared FP16 scale per group. This repack stores that ternary body in the **mainline `TQ2_0`** type so it loads on any current llama.cpp, **LM Studio** or **Ollama** with no fork and no special flags.
 
53
 
54
- <table>
55
- <tr>
56
- <td>⚑</td><td><b>Tiny footprint</b><br><sub>2.33 GiB β€” fits in RAM on almost anything</sub></td>
57
- <td>πŸ”Œ</td><td><b>Zero setup</b><br><sub>Stock llama.cpp / LM Studio / Ollama</sub></td>
58
- </tr>
59
- <tr>
60
- <td>🎯</td><td><b>Lossless body repack</b><br><sub>Same {βˆ’1,0,+1} weights, just re-packed</sub></td>
61
- <td>πŸ“</td><td><b>64K native context</b><br><sub>No RoPE scaling tricks</sub></td>
62
- </tr>
63
- </table>
64
-
65
- > [!NOTE]
66
- > This repository redistributes and repacks the model. **All model capabilities come from PrismML.** See the [original model card](https://huggingface.co/prism-ml/Ternary-Bonsai-8B-gguf) for architecture, training and evaluations.
67
 
68
  ---
69
 
70
- ## πŸ“¦ Files
71
 
72
- <div align="center">
73
 
74
- | File | Body | Embed / Output | Body bpw | Size |
75
- |:---|:---:|:---:|:---:|:---:|
76
- | **[Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf](https://huggingface.co/vinpix/Bonsai-8B-TQ-GGUF/blob/main/Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf)** | `TQ2_0` ternary | `Q4_0` | 2.06 | ~2.33 GiB |
77
 
78
- </div>
79
 
80
- Everything except the **token-embedding** and **output (LM-head)** tensors is stored as native ternary `TQ2_0`. Those two tensors are **not** ternary in the source model β€” they hold higher-precision information β€” so they are kept in `Q4_0` to preserve it at a reasonable size.
81
 
82
- ---
 
 
 
83
 
84
- ## ⬇️ Download
85
 
86
- ```bash
87
- pip install -U "huggingface_hub[cli]"
88
-
89
- hf download vinpix/Bonsai-8B-TQ-GGUF \
90
- --include "Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf" \
91
- --local-dir ./
92
- ```
93
 
94
  ---
95
 
96
- ## πŸš€ Run
97
 
98
- <details open>
99
- <summary><b>llama.cpp</b></summary>
100
 
101
- ```bash
102
- llama-cli -m Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf \
103
- -p "The capital of France is" \
104
- -n 256 --temp 0.5 --top-p 0.85 --top-k 20
 
105
  ```
106
 
107
- OpenAI-compatible server:
108
 
109
- ```bash
110
- llama-server -m Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf -c 4096
111
  ```
112
- </details>
 
113
 
114
- <details>
115
- <summary><b>LM Studio / Ollama</b></summary>
116
 
117
- Point them at the `.gguf` file directly. No fork or extra flags are required.
118
- </details>
119
 
120
- <details>
121
- <summary><b>Recommended sampling & threads</b></summary>
122
 
123
- | Setting | Value |
124
- |:---|:---|
125
- | temperature | `0.5` |
126
- | top_p | `0.85` |
127
- | top_k | `20` |
128
- | threads (`-t`) | your **physical** core count |
129
 
130
- More threads than physical cores usually does not help and can hurt.
131
- </details>
132
 
133
- <details>
134
- <summary><b>Low-RAM tip β€” KV-cache quantization</b></summary>
 
135
 
136
- Shrink the KV cache at runtime for long contexts (does **not** modify the weights):
 
 
137
 
138
  ```bash
139
- llama-cli -m Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf \
140
- --cache-type-k q8_0 --cache-type-v q8_0 -p "..."
141
  ```
142
 
143
- `q8_0` cache is close to lossless; `q4_0` saves more memory at a small quality cost.
144
- </details>
145
 
146
- ---
 
 
147
 
148
- ## πŸ”¬ Format details
149
 
150
- `TQ2_0` packs **four ternary weights per byte** (2 bits each) with one scale per block. A weight is reconstructed as:
151
- w = q_ternary Γ— scale where q_ternary ∈ {βˆ’1, 0, +1}
152
 
153
- Because the source weights are already ternary, the body is a **re-packing of the same `{βˆ’1, 0, +1}` values β€” not a re-quantization of full-precision weights** β€” so it carries no additional accuracy loss. The embedding and LM-head are the only non-ternary weights in the source and are stored here in `Q4_0`.
154
 
155
- <details>
156
- <summary><b>Reproduce these files</b></summary>
 
 
157
 
158
- Produced from the PrismML F16 source with mainline llama.cpp:
159
 
160
- ```bash
161
- llama-quantize --token-embedding-type q4_0 --output-tensor-type q4_0 \
162
- Ternary-Bonsai-8B-F16.gguf \
163
- Bonsai-8B-TQ2_0-Q4out-llamacpp.gguf TQ2_0
164
- ```
165
- </details>
166
 
167
  ---
168
 
169
- ## ℹ️ Notes & limitations
 
 
 
 
 
 
170
 
171
- - This is a **re-quantization / re-pack**, not a re-train. All capabilities are inherited from [Ternary-Bonsai-8B](https://huggingface.co/prism-ml/Ternary-Bonsai-8B-gguf).
172
- - The body uses portable `TQ2_0` (group size 256). The official PrismML `Q2_0` (group size 128) is marginally more faithful to the original grouping but requires the [PrismML fork](https://github.com/PrismML-Eng/llama.cpp); this repack trades that for running on stock llama.cpp.
173
- - CPU inference of ternary models is **memory-bandwidth bound** β€” tokens/second depend on your system's memory bandwidth and core count, so throughput varies from machine to machine.
174
- - Native context length is **65,536 tokens** (RoPE base 1e6); no scaling applied.
175
 
176
  ---
177
 
178
- <div align="center">
179
 
180
- ### πŸ™ Credits
 
 
181
 
182
- **Model & all capabilities** β€” [Prism ML Β· Ternary-Bonsai-8B](https://huggingface.co/prism-ml/Ternary-Bonsai-8B-gguf) Β· [whitepaper](https://prismml.com)
183
- **Quantization / repack** β€” vinpix
184
- **License** β€” Apache-2.0 (inherited from the source model)
 
 
 
 
 
 
185
 
186
- <sub>⭐ If this repack is useful, a like on the repo helps others find it.</sub>
187
 
188
- </div>
 
1
  ---
 
 
2
  license: apache-2.0
3
+ base_model: prism-ml/Ternary-Bonsai-8B
 
 
4
  tags:
5
+ - gguf
6
+ - llama.cpp
7
+ - ternary
8
+ - 1.58-bit
9
+ - quantization
10
+ - q2_k
11
+ - tq2_0
12
+ - qwen3
13
+ - edge
14
+ - cpu
15
+ - vulkan
16
+ language:
17
+ - en
18
  pipeline_tag: text-generation
19
+ library_name: gguf
20
  ---
21
 
22
+ # Ternary-Bonsai-8B for llama.cpp
23
 
24
+ **GGUF builds of [PrismML's Ternary-Bonsai-8B](https://huggingface.co/prism-ml/Ternary-Bonsai-8B) for `llama.cpp`, covering both deployment targets: a native `TQ2_0` build for CPU, and a ternary-aware zero-exact `Q2_K` build for GPU and every k-quant runtime β€” at matching perplexity.**
25
 
26
+ Ternary-Bonsai is an end-to-end 1.58-bit model (weights in `{-1, 0, +1}`, trained with ternary QAT, no higher-precision escape hatches). It punches far above its size class, but on `llama.cpp` it runs into a practical wall: **the tight ternary format has no GPU kernel.** This repo provides both halves of the solution.
27
 
28
+ ## Files
 
 
 
 
 
29
 
30
+ | File | Format | BPW | Size | Backends | PPL (wikitext-2, 20x512) |
31
+ |---|---|---|---|---|---|
32
+ | `Bonsai-8B-TQ2_0.gguf` | native ternary | 2.06 | 2.50 GB | **CPU only** | 12.311 +/- 0.517 |
33
+ | `Bonsai-8B-Q2_KT.gguf` | ternary-aware `Q2_K` | 2.911 | 2.99 GB | **CPU - CUDA - Metal - Vulkan - ROCm - SYCL** | 12.299 +/- 0.516 |
 
 
 
34
 
35
+ Both decode to the same learned weights. They differ only in storage container, and therefore in which backends can run them and how fast.
36
 
37
+ > **TL;DR β€” which one?**
38
+ > **CPU box** -> `TQ2_0` (fewer bytes streamed, ~12-14 tok/s, smallest RAM).
39
+ > **GPU offload, or any runtime that only speaks k-quants** -> `Q2_KT`.
40
 
41
  ---
42
 
43
+ ## Why two files
44
 
45
+ ### `TQ2_0` β€” the native CPU format
46
+ `TQ2_0` is the tightest faithful ternary layout in `ggml` (~2.06 BPW). It is the right choice on CPU and it is what PrismML ships. Its one hard limit:
47
 
48
+ > **`TQ2_0` has no GPU kernel.** In current `llama.cpp` it implements a `vec_dot` for CPU only β€” no CUDA, Metal, or Vulkan path. `-ngl` silently keeps the ternary tensors on the host.
49
 
50
+ ### `Q2_KT` β€” the GPU-portable format
51
+ `Q2_K` is one of the most broadly supported quant types in the ecosystem β€” hand-written kernels for CUDA, Metal, Vulkan, ROCm, SYCL. Re-hosting the ternary weights inside a `Q2_K` container makes Bonsai portable everywhere `Q2_K` runs.
52
 
53
+ The catch: you **cannot** just run `llama-quantize ... Q2_K` on a ternary model. Doing so is actively harmful β€” for a reason worth explaining.
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  ---
56
 
57
+ ## The trap: naively quantizing a ternary model to `Q2_K`
58
 
59
+ `Q2_K` dequantizes each weight as
60
 
61
+ ```
62
+ w = d * (scale & 0xF) * q - dmin * (scale >> 4), q in {0, 1, 2, 3}
63
+ ```
64
 
65
+ The stock `Q2_K` quantizer (`make_qkx2_quants`) is an L2-optimal grid fitter for **continuous** FP16 distributions. Handed a ternary tensor whose values are exactly `{-s, 0, +s}`, it fits a 4-level grid over 3-level data and places the levels so the ternary **zero lands between grid points** β€” at `q ~ 1.5`, rounding to an offset of `+/-s/3`.
66
 
67
+ Measured directly on Bonsai-8B:
68
 
69
+ | Encoding | Sign accuracy vs. original ternary | Zero reconstruction |
70
+ |---|---|---|
71
+ | Stock `Q2_K` (`--pure`) | **33 %** | `-0.0095` (should be `0`) |
72
+ | **`Q2_KT` (this repo)** | **100 %** | `0.000000` (exact) |
73
 
74
+ A `--pure` `Q2_K` of a ternary model gets **two thirds of the signs wrong** and shifts every zero β€” in practice a degenerate model that loops single tokens. The stock pipeline masks this by *promoting* sensitive tensors (`attn_output`, `ffn_down`, `attn_v`) to `Q3_K`/`Q4_K`, inflating the file to ~3.18 BPW and only partially repairing the damage. That promotion is a workaround, not a fix.
75
 
76
+ `Q2_KT` fixes the encoding at the source.
 
 
 
 
 
 
77
 
78
  ---
79
 
80
+ ## How `Q2_KT` is built (ternary-aware, zero-exact)
81
 
82
+ The ternary structure admits an **exact** `Q2_K` encoding with no residual. For a group of magnitude `s`:
 
83
 
84
+ ```
85
+ scale nibble sc = 15
86
+ min nibble m = 15 (min-nibble == scale-nibble)
87
+ d = dmin = s / 15
88
+ q = t + 1 t in {-1, 0, +1} -> q in {0, 1, 2}
89
  ```
90
 
91
+ Substituting into the dequant:
92
 
 
 
93
  ```
94
+ w = d*15*q - dmin*15 = d*15*(q - 1) = s*(q - 1) = s*t <- exact ternary
95
+ ```
96
 
97
+ The `-1` bias falls out of the min term for free; the ternary zero (`t = 0 -> q = 1`) reconstructs to **exactly 0**; every non-zero to **exactly `+/-s`**. The only error is the FP16 storage of the single per-group scale β€” which `TQ2_0` also carries. Hence sign accuracy 100 % and PPL parity.
 
98
 
99
+ The `qs` nibbles are packed with the exact `ggml` `Q2_K` interleave (32-byte groups, stride-32 crumbs across 128-element spans), so the file is bit-compatible with the reference `dequantize_row_q2_K` **and** the SIMD `vec_dot_q2_K_q8_K` in the forward pass. Output projection and token embedding are kept at `Q4_0` (not ternary in the source).
 
100
 
101
+ > **Layout note.** `TQ2_0` and `Q2_K` `qs` streams share the *same* stride-32 / 128-span interleave. Matching `ggml`'s canonical order is the whole game: an encoding that is self-consistent with a hand-rolled unpacker but disagrees with the canonical order will pass every fidelity check against itself and still emit garbage in the forward pass, because `dequantize_row` and `vec_dot` both assume the canonical order. This build matches it.
 
102
 
103
+ ---
104
+
105
+ ## Usage
 
 
 
106
 
107
+ ### CPU (use `TQ2_0`)
 
108
 
109
+ ```bash
110
+ llama-cli -m Bonsai-8B-TQ2_0.gguf -p "The capital of France is" -n 64 -t 6
111
+ ```
112
 
113
+ Fastest on CPU and smallest RAM footprint. ~12-14 tok/s on a low-end Zen2 desktop (Ryzen 3 PRO 4350GE, dual-channel DDR4).
114
+
115
+ ### GPU offload (use `Q2_KT`)
116
 
117
  ```bash
118
+ llama-cli -m Bonsai-8B-Q2_KT.gguf -ngl 99 -p "The capital of France is" -n 64
 
119
  ```
120
 
121
+ Verified running fully offloaded on an AMD Radeon Vega iGPU via the Vulkan `RADV` backend. Because `Q2_K` has real GPU kernels, `-ngl 99` actually places the ternary body on the device β€” unlike `TQ2_0`, which would stay on the host.
 
122
 
123
+ ### Any GGUF loader / llama.cpp server
124
+
125
+ `Q2_KT` loads as an ordinary `Q2_K` model β€” no custom code, no patched runtime. Every existing loader already understands the container.
126
 
127
+ ---
128
 
129
+ ## Quality
 
130
 
131
+ Perplexity on `wikitext-2-raw` (test split, 20 chunks of 512 tokens, `-t 4`, identical harness):
132
 
133
+ | Model | Format | BPW | PPL (lower is better) |
134
+ |---|---|---|---|
135
+ | `Bonsai-8B-TQ2_0` | native ternary | 2.06 | 12.311 +/- 0.517 |
136
+ | `Bonsai-8B-Q2_KT` | ternary-aware `Q2_K` | 2.911 | **12.299 +/- 0.516** |
137
 
138
+ `Q2_KT` is **perplexity-neutral vs. the native ternary build** (delta within the +/-0.5 statistical error). You pay ~0.85 BPW over `TQ2_0` for universal backend support; you do **not** pay for it in quality β€” expected, since the encoding is lossless on the ternary levels.
139
 
140
+ For task benchmarks (MMLU-Redux, GSM8K, HumanEval+, IFEval, ...), see [PrismML's numbers](https://prismml.com/news/ternary-bonsai) for the base model β€” these files change the container, not the learned weights.
 
 
 
 
 
141
 
142
  ---
143
 
144
+ ## Technical notes & reproducibility
145
+
146
+ - **`Q2_KT` container:** 252 ternary body tensors -> pure `Q2_K` (zero-exact); `output` + `token_embd` -> `Q4_0`; 145 norms -> `F32`.
147
+ - **No tensor promotion.** Every ternary tensor is pure `Q2_K`; the zero-exact encoding makes the `Q3_K`/`Q4_K` promotion unnecessary β€” that is why `Q2_KT` is 2.91 BPW, not 3.18.
148
+ - **Bit-exactness:** validated against `ggml`'s reference `dequantize_row_q2_K` (100 % sign accuracy, max abs error 1e-5 from the FP16 scale) and end-to-end against the forward `vec_dot` (coherent generation, PPL parity).
149
+ - **Architecture:** Qwen3, 36 layers, `hidden 4096`, `FFN 12288`, GQA 32/8, full 65536-token context preserved in metadata.
150
+ - **Reproduce PPL:** `llama-perplexity -m <file> -f wiki.test.raw --chunks 20`.
151
 
152
+ ### A note for the llama.cpp community
153
+
154
+ The `+/-s/3` zero-error affects **any** end-to-end ternary model (Bonsai, BitNet, TriLM, ...) run through the stock `Q2_K` quantizer. A ternary-aware branch in `quantize_row_q2_K` β€” detect a block with <=3 symmetric levels, emit `d = dmin = s/15`, `sc = m`, `q = t+1` β€” would let the official pipeline produce zero-exact `Q2_K` for the whole class, without the promotion workaround. `Q2_KT` is a concrete demonstration that the encoding is exact and backend-portable. Contributions upstream welcome.
 
155
 
156
  ---
157
 
158
+ ## Attribution & license
159
 
160
+ - **Base model:** [Ternary-Bonsai-8B](https://huggingface.co/prism-ml/Ternary-Bonsai-8B) by **PrismML** (Babak Hassibi et al., Caltech). Ternary QAT, Qwen3 architecture, end-to-end 1.58-bit.
161
+ - **These files:** GGUF re-encodes for `llama.cpp`. `TQ2_0` is the native ternary layout; `Q2_KT` is a lossless-on-ternary `Q2_K` re-encode for backend portability. Learned weights unchanged.
162
+ - **License:** Apache 2.0, inherited from the base model.
163
 
164
+ ```bibtex
165
+ @techreport{ternarybonsai,
166
+ title = {Ternary Bonsai: 1.58-bit Language Models at 8B, 4B, and 1.7B Scale},
167
+ author = {Prism ML},
168
+ year = {2026},
169
+ month = {April},
170
+ url = {https://prismml.com}
171
+ }
172
+ ```
173
 
174
+ ---
175
 
176
+ *Community re-encodes, not affiliated with or endorsed by PrismML. Quality figures are measured on the specific files in this repository.*