PrismML has released Ternary Bonsai 2 27B, a ternary-weight version of Qwen3.8 27B. The language model occupies 5.93 GB, against 53.80 GB in FP16. PrismML reports that it keeps 98.2% of the parent model’s average across 20 benchmarks. The model accepts text and images and supports a 262K-token context. PrismML demos it driving Cline coding agents and computer use on an RTX 5090. It arrives 2 months after the first Bonsai 27B, whose ternary variant retained about 95%.
Is it deployable? Yes. The Apache 2.0 weights run today on a 16 GB laptop or a single 24 GB GPU. You need PrismML’s llama.cpp fork or its MLX runtime.
What is Ternary Bonsai 2 27B?
The model keeps the Qwen3.8 27B architecture unchanged. It has 27.36B parameters. That splits into a 24.35B language backbone, 2.54B in embeddings and LM head, and a 0.47B vision tower. The backbone uses hybrid attention, with about 75% linear-attention and 25% full-attention layers.
Ternary weights cover embeddings, attention projections, MLP projections and the LM head. Only 26.2M parameters, or 0.0976%, stay in higher precision. Those are the recurrent state path and normalization weights. In GGUF, the vision tower ships separately as a 0.63 GB file, loaded only for image input.
How Does the Ternary Format Work?
Each weight takes 1 of 3 values: -1, 0 or +1. Every group of 128 weights shares 1 FP16 scale. A ternary value carries log2(3), or about 1.585 bits. Adding 16 scale bits per 128 weights gives 1.71 bits per weight. Counting the high-precision tensors brings the model to 1.72.
Real kernels need a packed layout, so the whitepaper describes 2 GGUF packings. PTQ1_0 packs trits densely at 1.76 bits per weight and 5.93 GB. PQ2_0 stores each trit in a 2-bit slot at 7.25 GB, which is cheaper to unpack.
Weights are also stored in a rotated basis. PrismML applies a blockwise Hadamard rotation with block size 1,024 before ternary assignment. The runtime applies the matching transform to activations before each multiply. The whitepaper cites SpinQuant for this idea. PrismML does not publish how it assigns the ternary values.
<section class="panel" data-p="1">
<h3>Every weight becomes -1, 0 or +1</h3>
<p class="lede">Below is 1 group of 128 weights. Bonsai 2 stores each weight as 1 of 3 values. The whole group shares 1 FP16 scale. Press the button to see the group collapse.</p>
<div class="row">
<button class="btn" id="ternBtn">Ternarize this group</button>
<button class="btn ghost" id="ternNew">New weights</button>
</div>
<div class="card">
<div class="grid" id="grid" aria-label="Grid of 128 weights"></div>
<div class="legend" id="legend"></div>
</div>
<div class="stats">
<div class="stat"><div class="k">Shared scale s</div><div class="v" id="tScale">n/a</div></div>
<div class="stat"><div class="k">Count of -1 / 0 / +1</div><div class="v" id="tCount" style="font-size:17px;line-height:31px">n/a</div></div>
<div class="stat"><div class="k">Bits for this group</div><div class="v" id="tBits">2,048</div></div>
<div class="stat"><div class="k">Bits per weight</div><div class="v" id="tBpw">16.00</div></div>
</div>
<div class="row" style="margin-top:16px"><span class="lab" style="min-width:0">What if the group size changed?</span>
<input type="range" id="gRange" min="0" max="3" step="1" value="2" aria-label="Group size">
<span id="gOut" style="font-size:13px;font-weight:600"></span>
</div>
<div class="eq" id="eq"></div>
<p class="note"><b>Illustrative.</b> The storage math is from the whitepaper: log2(3) plus 16 scale bits shared by 128 weights. The rounding rule in this demo is a simple threshold. PrismML has not published how it assigns ternary values. Bonsai 2 ships with a group size of 128.</p>
</section>
<section class="panel" data-p="2">
<h3>A fixed rotation runs before every multiply</h3>
<p class="lede">Bonsai 2 stores its weights in a rotated basis. The runtime applies a sign flip and a Walsh-Hadamard transform to activations. This demo runs that same transform on 16 values. Click any bar to move the outlier.</p>
<div class="row">
<button class="btn" id="rotBtn">Rotate</button>
<button class="btn ghost" id="rotNew">New vector</button>
</div>
<div class="card"><div class="bars" id="bars"></div></div>
<div class="stats">
<div class="stat"><div class="k">Largest value</div><div class="v" id="rPeak"></div></div>
<div class="stat"><div class="k">Peak vs typical (RMS)</div><div class="v"><span id="rPar"></span><small>x</small></div></div>
<div class="stat"><div class="k">Energy (sum of squares)</div><div class="v" id="rEn"></div></div>
<div class="stat"><div class="k">State</div><div class="v" id="rState" style="font-size:17px;line-height:31px"></div></div>
</div>
<p class="note"><b>Real math, small scale.</b> The rotation is orthogonal, so energy stays identical while the peak spreads across all positions. Bonsai 2 uses blocks of 1,024, not 16. The rotation is folded into stored weights offline and adds no bits. The whitepaper cites SpinQuant for this approach and lists rotation overhead as a remaining batch-1 cost.</p>
</section>
<section class="panel" data-p="3">
<h3>Where quality holds and where it drops</h3>
<p class="lede">Pick a capability. Scores are thinking mode at xhigh reasoning effort, all measured by PrismML on the same harness.</p>
<div class="row" id="catRow"></div>
<div class="card" id="scoreCard"></div>
<p class="note" id="scoreNote"></p>
</section>
<section class="panel" data-p="4">
<h3>Watch the measured decode speed</h3>
<p class="lede">Choose hardware and a packing. The stream below emits tokens at the measured TG128 rate for 3 seconds. Each square is 1 token.</p>
<div class="row">
<select id="hwSel" aria-label="Hardware"></select>
<button class="chip" id="pkA" aria-pressed="true">PQ2_0, 7.25 GB</button>
<button class="chip" id="pkB" aria-pressed="false">PTQ1_0, 5.93 GB</button>
</div>
<div class="row">
<button class="btn" id="runBtn">Generate for 3 seconds</button>
<span class="clock" id="clock">0 tokens, 0.0 s</span>
</div>
<div class="stream" id="stream" aria-live="off"></div>
<div class="stats">
<div class="stat"><div class="k">Decode, TG128</div><div class="v"><span id="vTg"></span><small>tok/s</small></div></div>
<div class="stat"><div class="k">Prefill, PP512</div><div class="v"><span id="vPp"></span><small>tok/s</small></div></div>
<div class="stat"><div class="k">Energy per token</div><div class="v"><span id="vE"></span><small id="vEu">mWh</small></div></div>
<div class="stat"><div class="k">Faster packing here</div><div class="v" id="vWin" style="font-size:17px;line-height:31px"></div></div>
</div>
<p class="note" id="spNote"></p>
</section>
<div class="pn">
<button class="btn ghost" id="prev">Back</button>
<span class="pos" id="pos"></span>
<button class="btn" id="next">Next</button>
</div>
<div class="foot">
<span>Data: <a href="https://github.com/PrismML-Eng/Bonsai-demo/blob/main/bonsai-2-27b-whitepaper.pdf" target="_blank" rel="noopener">PrismML whitepaper</a>, measured Sep 16, 2026. Checked Sep 18, 2026.</span>
<span class="mtp">Built by Marktechpost</span>
</div>
</div>
<script>
(function(){
var $=function(s){return document.querySelector(s)},$$=function(s){return [].slice.call(document.querySelectorAll(s))};
var root=$(‘#root’),RM=window.matchMedia&&matchMedia(‘(prefers-reduced-motion:reduce)’).matches;
function postH(){try{parent.postMessage({__mtpH:root.offsetHeight+40},’*’)}catch(e){}}
function count(el,to,dec,dur){
var from=parseFloat(String(el.textContent).replace(/,/g,”));if(isNaN(from))from=0;
if(RM){el.textContent=to.toFixed(dec);return}
var t0=null;dur=dur||700;
function f(t){if(!t0)t0=t;var p=Math.min(1,(t-t0)/dur),e=1-Math.pow(1-p,3);el.textContent=(from+(to-from)*e).toFixed(dec);if(p<1)requestAnimationFrame(f)}
requestAnimationFrame(f);
}
function chip(txt,on,fn){var b=document.createElement(‘button’);b.className=’chip’;b.textContent=txt;b.setAttribute(‘aria-pressed’,on?’true’:’false’);b.addEventListener(‘click’,fn);return b}
function press(row,b){[].forEach.call(row.querySelectorAll(‘.chip’),function(c){c.setAttribute(‘aria-pressed’,c===b?’true’:’false’)})}
/* ———- tabs ———- */
var cur=0,N=5,names=[‘Size’,’Three values’,’Rotation’,’Scores’,’Speed’];
function go(i){
cur=Math.max(0,Math.min(N-1,i));
$$(‘.steps button’).forEach(function(b,k){b.setAttribute(‘aria-selected’,k===cur?’true’:’false’)});
$$(‘.panel’).forEach(function(p,k){p.classList.toggle(‘on’,k===cur)});
$(‘#prev’).disabled=cur===0;$(‘#next’).disabled=cur===N-1;
$(‘#pos’).textContent=’Step ‘+(cur+1)+’ of ‘+N+’: ‘+names[cur];
if(cur===0)renderSize();if(cur===3)renderScore();if(cur===4)renderSpeed();
postH();setTimeout(postH,420);
}
$$(‘.steps button’).forEach(function(b){b.addEventListener(‘click’,function(){go(+b.getAttribute(‘data-i’))})});
$(‘#prev’).addEventListener(‘click’,function(){go(cur-1)});
$(‘#next’).addEventListener(‘click’,function(){go(cur+1)});
/* ———- 1 size (whitepaper Tables 3, 7) ———- */
var FMT=[
{n:’FP16 baseline’,gb:53.80,bpw:’16.0′,avg:’85.4′},
{n:’IQ2_XXS, conventional 2-bit’,gb:7.3,bpw:’2.2′,avg:’75.2′},
{n:’Bonsai 2 PQ2_0′,gb:7.25,bpw:’2.16′,avg:’83.9′},
{n:’Bonsai 2 PTQ1_0′,gb:5.93,bpw:’1.76′,avg:’83.9′}];
var DEV=[{n:’Laptop, 16 GB’,gb:16},{n:’RTX 4090, 24 GB’,gb:24},{n:’RTX 5090, 32 GB’,gb:32},{n:’H100, 80 GB’,gb:80}];
var fi=3,di=0;
FMT.forEach(function(f,k){var b=chip(f.n,k===fi,function(){fi=k;press($(‘#fmtRow’),b);renderSize()});$(‘#fmtRow’).appendChild(b)});
DEV.forEach(function(d,k){var b=chip(d.n,k===di,function(){di=k;press($(‘#devRow’),b);renderSize()});$(‘#devRow’).appendChild(b)});
function renderSize(){
var f=FMT[fi],d=DEV[di],r=f.gb/d.gb,over=r>1,fill=$(‘#memFill’),tag=$(‘#memTag’),v=$(‘#memVerdict’);
fill.style.width=(Math.min(1,r)*100)+’%’;fill.classList.toggle(‘over’,over);
tag.textContent=f.gb.toFixed(2)+’ GB of weights’;
var out=!over&&(fill.parentNode.clientWidth*r)<(tag.offsetWidth+24);
tag.classList.toggle(‘dark’,out);
tag.style.left=out?’calc(‘+(r*100)+’% + 10px)’:’12px’;
$(‘#memMax’).textContent=d.gb+’ GB’;
if(over){v.className=’verdict no’;v.textContent=’Does not fit. The weights alone need ‘+(f.gb-d.gb).toFixed(1)+’ GB more than this device has.’}
else{v.className=’verdict ok’;v.textContent=’Fits. Weights take ‘+Math.round(r*100)+’% of memory, leaving ‘+(d.gb-f.gb).toFixed(1)+’ GB for KV cache, activations and the runtime.’}
count($(‘#sGb’),f.gb,2);$(‘#sBpw’).textContent=f.bpw;count($(‘#sRed’),53.80/f.gb,1);$(‘#sAvg’).textContent=f.avg;
postH();
}
/* ———- 2 ternary ———- */
var W=[],isT=false,grid=$(‘#grid’);
function randn(){var u=0,v=0;while(!u)u=Math.random();while(!v)v=Math.random();return Math.sqrt(-2*Math.log(u))*Math.cos(2*Math.PI*v)}
function mix(a,b,t){return ‘rgb(‘+[0,1,2].map(function(i){return Math.round(a[i]+(b[i]-a[i])*t)}).join(‘,’)+’)’}
var CN=[155,133,136],CZ=[245,243,239],CP=[44,49,56];
function colFP(w){var t=Math.max(-1,Math.min(1,w/2.2));return t<0?mix(CZ,CN,-t):mix(CZ,CP,t)}
function colT(t){return t<0?’rgb(155,133,136)’:t>0?’rgb(44,49,56)’:’rgb(245,243,239)’}
for(var i=0;i<128;i++){var c=document.createElement(‘div’);c.className=’cell’;grid.appendChild(c)}
var cells=$$(‘.cell’);
function legend(){
$(‘#legend’).innerHTML=isT
?'<span><i style="background:rgb(155,133,136)"></i>-1</span><span><i style="background:rgb(245,243,239)"></i>0</span><span><i style="background:rgb(44,49,56)"></i>+1</span><span>Each cell now needs about 1.585 bits.</span>’
:'<span><i style="background:linear-gradient(90deg,rgb(155,133,136),rgb(245,243,239),rgb(44,49,56));width:54px"></i>negative to positive, 16 bits each</span>’;
}
function newW(){W=[];for(var i=0;i<128;i++)W.push(randn());isT=false;paintFP()}
function paintFP(){
cells.forEach(function(c,i){c.style.transitionDelay=’0ms’;c.style.backgroundColor=colFP(W[i])});
$(‘#tScale’).textContent=’n/a’;$(‘#tCount’).textContent=’n/a’;$(‘#tBits’).textContent=’2,048′;$(‘#tBpw’).textContent=’16.00′;
$(‘#ternBtn’).textContent=’Ternarize this group’;legend();
}
function ternarize(){
var m=0;W.forEach(function(w){m+=Math.abs(w)});m/=128;var th=0.7*m,s=0,k=0,cn=[0,0,0];
var T=W.map(function(w){var t=Math.abs(w)>th?(w>0?1:-1):0;if(t){s+=Math.abs(w);k++}cn[t+1]++;return t});
s=k?s/k:0;isT=true;
cells.forEach(function(c,i){
var d=RM?0:(i%16)*18+Math.floor(i/16)*28;c.style.transitionDelay=d+’ms’;c.style.backgroundColor=colT(T[i]);
if(!RM){setTimeout(function(){c.classList.add(‘pop’)},d);setTimeout(function(){c.classList.remove(‘pop’)},d+220)}
});
$(‘#tScale’).textContent=s.toFixed(3);$(‘#tCount’).textContent=cn[0]+’ / ‘+cn[1]+’ / ‘+cn[2];
var bits=128*Math.log(3)/Math.LN2+16;
$(‘#tBits’).textContent=’2048′;count($(‘#tBits’),bits,1,900);$(‘#tBpw’).textContent=’16.00′;count($(‘#tBpw’),bits/128,2,900);
$(‘#ternBtn’).textContent=’Back to FP16′;legend();
}
$(‘#ternBtn’).addEventListener(‘click’,function(){if(isT){isT=false;paintFP()}else ternarize()});
$(‘#ternNew’).addEventListener(‘click’,newW);
var GS=[32,64,128,256];
function renderEq(){
var g=GS[+$(‘#gRange’).value],b=Math.log(3)/Math.LN2+16/g;
$(‘#gOut’).textContent=’g = ‘+g+(g===128?’ (shipped)’:”);
$(‘#eq’).innerHTML=’bits per weight = log2(3) + 16 / <em>’+g+'</em> = 1.585 + ‘+(16/g).toFixed(3)+’ = <em>’+b.toFixed(2)+'</em> FP16 / this = <em>’+(16/b).toFixed(1)+’x</em>’;
}
$(‘#gRange’).addEventListener(‘input’,renderEq);
/* ———- 3 rotation ———- */
var X=[],S=[],hot=5,rot=false,bars=$(‘#bars’),SC=3.2;
for(var j=0;j<16;j++){(function(j){var w=document.createElement(‘div’);w.className=’bw’;w.title=’Put the outlier here’;var b=document.createElement(‘div’);b.className=’bar’;w.appendChild(b);
w.addEventListener(‘click’,function(){hot=j;mkVec(false)});bars.appendChild(w)})(j)}
function mkVec(newNoise){
if(newNoise||!X.base){X.base=[];S=[];for(var i=0;i<16;i++){X.base.push(randn()*0.16);S.push(Math.random()<.5?-1:1)}}
rot=false;draw();
}
function fwht(a){a=a.slice();for(var h=1;h<16;h*=2)for(var i=0;i<16;i+=h*2)for(var k=i;k<i+h;k++){var x=a[k],y=a[k+h];a[k]=x+y;a[k+h]=x-y}return a.map(function(v){return v/4})}
function vec(){var v=X.base.slice();v[hot]=3.0;return v}
function draw(){
var v=vec(),o=rot?fwht(v.map(function(x,i){return x*S[i]})):v,pk=0,en=0;
[].forEach.call(bars.children,function(w,i){
var b=w.firstChild,val=o[i],h=Math.min(50,Math.abs(val)/SC*50);pk=Math.max(pk,Math.abs(val));en+=val*val;
b.style.height=h+’%’;
if(val>=0){b.style.bottom=’50%’;b.style.top=’auto’}else{b.style.top=’50%’;b.style.bottom=’auto’}
b.className=’bar’+(val<0?’ neg’:”)+(!rot&&i===hot?’ hot’:”);
});
var rms=Math.sqrt(en/16);
count($(‘#rPeak’),pk,2);count($(‘#rPar’),pk/rms,1);$(‘#rEn’).textContent=en.toFixed(2);
$(‘#rState’).textContent=rot?’Rotated’:’Original’;$(‘#rotBtn’).textContent=rot?’Undo rotation’:’Rotate’;
}
$(‘#rotBtn’).addEventListener(‘click’,function(){rot=!rot;draw()});
$(‘#rotNew’).addEventListener(‘click’,function(){hot=Math.floor(Math.random()*16);mkVec(true)});
/* ———- 4 scores (whitepaper Tables 7, 8 and Section 4) ———- */
var CAT=[
{n:’Overall’,rows:[[‘Qwen3.6 27B, FP16’,83.6],[‘Qwen3.8 27B, FP16’,85.4],[‘Qwen3.8 27B IQ2_XXS, 7.3 GB’,75.2,’iq’],[‘Ternary Bonsai 2 27B, 5.93 GB’,83.9,’me’]],base:85.4,me:83.9,note:’Average of 20 benchmarks. The conventional IQ2_XXS build is 1.23x larger than Bonsai 2 and scores 8.7 points lower.’},
{n:’Knowledge and reasoning’,rows:[[‘Qwen3.6 27B’,84.71],[‘Qwen3.8 27B’,86.66],[‘Ternary Bonsai 2 27B’,83.95,’me’]],base:86.66,me:83.95,note:’MMLU-Redux, GPQA Diamond, AA-LCR. This is one of the 2 largest gaps in the suite.’},
{n:’Math’,rows:[[‘Qwen3.6 27B’,94.64],[‘Qwen3.8 27B’,97.06],[‘Ternary Bonsai 2 27B’,96.57,’me’]],base:97.06,me:96.57,note:’AIME26, AIME25, GSM8K, MATH-500. Bonsai 2 scores 95.83 on AIME26, above the FP16 baseline at 94.58.’},
{n:’Coding’,rows:[[‘Qwen3.6 27B’,82.57],[‘Qwen3.8 27B’,82.17],[‘Ternary Bonsai 2 27B’,81.58,’me’]],base:82.17,me:81.58,note:’HumanEval+, LiveCodeBench v6, MBPP+, BigCodeBench. LiveCodeBench v6: 90.07 vs 90.05 for FP16.’},
{n:’Agentic and tool calling’,rows:[[‘Qwen3.6 27B’,80.05],[‘Qwen3.8 27B’,79.74],[‘Ternary Bonsai 2 27B’,77.57,’me’]],base:79.74,me:77.57,note:’tau2-Bench and BFCL v3. tau2-Bench reaches 80.22, up from 73.6 in the first Bonsai 27B release.’},
{n:’Instruction following’,rows:[[‘Qwen3.6 27B’,74.53],[‘Qwen3.8 27B’,81.25],[‘Ternary Bonsai 2 27B’,82.66,’me’]],base:81.25,me:82.66,note:’IFEval and IFBench. The only category where the ternary model edges past its FP16 parent.’},
{n:’Vision’,rows:[[‘Qwen3.6 27B’,79.82],[‘Qwen3.8 27B’,81.64],[‘Ternary Bonsai 2 27B’,78.59,’me’]],base:81.64,me:78.59,note:’CharXiv, A-OKVQA, OmniDocBench v1.6, RealWorldQA, OCRBench v2. The lowest retention of the 6 categories.’},
{n:’Long-horizon agents’,groups:[{t:’Terminal-Bench 2.1′,rows:[[‘Qwen3.8 27B’,69.7],[‘Ternary Bonsai 2 27B’,52.8,’me’]]},{t:’SWE-bench Verified’,rows:[[‘Qwen3.8 27B’,80.6],[‘Ternary Bonsai 2 27B’,60.8,’me’]]}],base:80.6,me:60.8,retLabel:’of FP16 kept on SWE-bench Verified (75.8% on Terminal-Bench 2.1)’,note:’These 2 benchmarks sit outside the 20-benchmark average. Retention here is about three quarters, far below the 98.2% headline.’}
];
var ci=0;
CAT.forEach(function(c,k){var b=chip(c.n,k===ci,function(){ci=k;press($(‘#catRow’),b);renderScore()});$(‘#catRow’).appendChild(b)});
function rowsHTML(rows){return rows.map(function(r){return ‘<div class="srow ‘+(r[2]||”)+’"><div class="n">’+r[0]+'</div><div class="t"><div class="f" data-w="’+r[1]+’"></div></div><div class="s">’+r[1]+'</div></div>’}).join(”)}
function renderScore(){
var c=CAT[ci],h=”;
if(c.groups)c.groups.forEach(function(g){h+='<div class="sub">’+g.t+'</div>’+rowsHTML(g.rows)});else h=rowsHTML(c.rows);
h+='<div class="ret"><div class="big"><span id="retN">0.0</span>%</div><span>’+(c.retLabel||’of Qwen3.8 27B FP16 retained’)+'</span></div>’;
$(‘#scoreCard’).innerHTML=h;$(‘#scoreNote’).textContent=c.note;
var fs=$$(‘#scoreCard .f’);
setTimeout(function(){fs.forEach(function(f,i){f.style.transitionDelay=(RM?0:i*90)+’ms’;f.style.width=f.getAttribute(‘data-w’)+’%’})},30);
count($(‘#retN’),c.me/c.base*100,1,900);postH();
}
/* ———- 5 speed (whitepaper Tables 5, 6) ———- */
var HW=[
[‘RTX 5090 (32 GB)’,[142.5,4121,0.582],[134.4,1901,0.609]],
[‘RTX PRO 6000 Blackwell’,[140.6,4520,0.637],[136.8,2290,0.642]],
[‘H200 SXM (141 GB)’,[118.0,2818,0.708],[89.5,1216,0.814]],
[‘B200 (180 GB)’,[117.1,3112,0.830],[91.9,1406,1.019]],
[‘H100 NVL (94 GB)’,[106.4,2484,0.541],[81.6,1098,0.647]],
[‘H100 SXM (80 GB)’,[103.2,2467,0.584],[77.3,1097,0.706]],
[‘RTX 4090 (24 GB)’,[90.9,3134,0.714],[96.7,1634,0.682]],
[‘RTX 6000 Ada (48 GB)’,[84.8,2430,0.731],[92.0,1627,0.701]],
[‘L40S (48 GB)’,[74.6,2827,0.812],[82.8,1601,0.743]],
[‘A100 SXM (80 GB)’,[74.0,1328,0.776],[54.6,703,0.932]],
[‘L4 (24 GB, 72 W)’,[29.7,778,0.629],[32.1,468,0.585]],
[‘MacBook, M5 Max (Metal)’,[46.8,765,null],null],
[‘MacBook, M5 Pro (Metal)’,[27.7,397,null],[27.1,369,null]],
[‘MacBook, M4 Pro (Metal)’,[18.0,125,null],null]];
var hi=0,pk=0,raf=0;
HW.forEach(function(h,k){var o=document.createElement(‘option’);o.value=k;o.textContent=h[0];$(‘#hwSel’).appendChild(o)});
$(‘#hwSel’).addEventListener(‘change’,function(){hi=+this.value;if(!HW[hi][2])pk=0;renderSpeed()});
$(‘#pkA’).addEventListener(‘click’,function(){pk=0;renderSpeed()});
$(‘#pkB’).addEventListener(‘click’,function(){if(HW[hi][2]){pk=1;renderSpeed()}});
function stop(){if(raf)cancelAnimationFrame(raf);raf=0;$(‘#runBtn’).disabled=false}
function renderSpeed(){
stop();var h=HW[hi],d=h[pk+1];
$(‘#pkA’).setAttribute(‘aria-pressed’,pk===0?’true’:’false’);$(‘#pkB’).setAttribute(‘aria-pressed’,pk===1?’true’:’false’);
$(‘#pkB’).disabled=!h[2];$(‘#pkB’).style.opacity=h[2]?1:.4;
count($(‘#vTg’),d[0],1);count($(‘#vPp’),d[1],0);
if(d[2]==null){$(‘#vE’).textContent=’n/a’;$(‘#vEu’).textContent=”}else{$(‘#vE’).textContent=d[2].toFixed(3);$(‘#vEu’).textContent=’mWh’}
$(‘#vWin’).textContent=!h[2]?’PQ2_0 only’:(h[1][0]>=h[2][0]?’PQ2_0′:’PTQ1_0′);
var n=’Batch size 1, depth 0, no vision tower, llama.cpp with PrismML kernels. ‘;
if(hi>=11)n+=’Apple rows carry no energy figure because powermetrics excludes DRAM power. ‘;
if(hi===13)n+=’The M4 Pro figures come from the earlier pre-rotation build. ‘;
if(hi===11||hi===13)n+=’Only PQ2_0 is reported for this laptop. ‘;
$(‘#spNote’).textContent=n+’PTQ1_0 wins on Ada cards and the L4. PQ2_0 wins on Blackwell, Hopper, Ampere and Apple silicon.’;
$(‘#stream’).innerHTML=”;$(‘#clock’).textContent=’0 tokens, 0.0 s’;postH();
}
$(‘#runBtn’).addEventListener(‘click’,function(){
stop();var rate=HW[hi][pk+1][0],st=$(‘#stream’),made=0,t0=null,DUR=3;st.innerHTML=”;
if(RM){var tot=Math.floor(rate*DUR),fr=document.createDocumentFragment();for(var i=0;i<tot;i++){var t=document.createElement(‘i’);t.className=’tok’;fr.appendChild(t)}st.appendChild(fr);$(‘#clock’).textContent=tot+’ tokens, 3.0 s’;postH();return}
$(‘#runBtn’).disabled=true;
function f(ts){if(!t0)t0=ts;var el=Math.min(DUR,(ts-t0)/1000),want=Math.floor(el*rate),fr=document.createDocumentFragment();
while(made<want){var t=document.createElement(‘i’);t.className=’tok’;fr.appendChild(t);made++}
st.appendChild(fr);$(‘#clock’).textContent=made+’ tokens, ‘+el.toFixed(1)+’ s’;
if(el<DUR)raf=requestAnimationFrame(f);else{raf=0;$(‘#runBtn’).disabled=false;postH()}}
raf=requestAnimationFrame(f);
});
/* ———- init ———- */
newW();renderEq();mkVec(true);go(0);
window.addEventListener(‘load’,postH);window.addEventListener(‘resize’,postH);
if(window.ResizeObserver)new ResizeObserver(postH).observe(root);
})();
</script>
</body>
</html>
” style=”width:100%;border:0;height:600px;display:block;overflow:hidden” loading=”lazy” title=”How Ternary Bonsai 2 27B fits a 27B model in 5.93 GB”>
How Does It Score Against Qwen3.8 27B?
PrismML evaluated all models in thinking mode with EvalScope and vLLM on H100 GPUs.
| Capability | Qwen3.6 27B | Qwen3.8 27B | Ternary Bonsai 2 27B | Retention |
|---|---|---|---|---|
| Knowledge and reasoning | 84.71 | 86.66 | 83.95 | 96.9% |
| Math | 94.64 | 97.06 | 96.57 | 99.5% |
| Coding | 82.57 | 82.17 | 81.58 | 99.3% |
| Agentic and tool calling | 80.05 | 79.74 | 77.57 | 97.3% |
| Instruction following | 74.53 | 81.25 | 82.66 | 101.7% |
| Vision | 79.82 | 81.64 | 78.59 | 96.3% |
| Overall (20) | 83.6 | 85.4 | 83.9 | 98.2% |
The comparison with conventional quantization is the sharper result. An IQ2_XXS build of Qwen3.8 27B averages 75.2 at 7.3 GB. On AIME26 it scores 78.6, while Bonsai 2 scores 95.83. On LiveCodeBench v6 the gap is 70.05 versus 90.07.
Where Does It Still Lose Quality?
The 98.2% figure is an average, and the losses are uneven. Vision retains 96.3% and knowledge and reasoning retains 96.9%.
Long-horizon agent work drops further. Bonsai 2 scores 52.8 on Terminal-Bench 2.1, against 69.7 for Qwen3.8 27B. On SWE-bench Verified it scores 60.8 against 80.6. That is about 75% retention, and both sit outside the 20-benchmark average.
Reasoning effort matters too. At medium effort the model averages 79.3, against 82.6 for the FP16 baseline. Low effort is not supported. All results are PrismML’s own and have not been independently reproduced.
How Fast is It on Real Hardware?
Figures are batch size 1 decode on PrismML’s custom kernels, measured September 16, 2026. An RTX 5090 reaches 142.5 tokens per second at 0.582 mWh per token. An RTX 4090 reaches 96.7 with PTQ1_0, and a 72 W L4 reaches 32.1. On Apple laptops, an M5 Max reaches 46.8 and an M5 Pro reaches 27.7.
Neither packing wins everywhere. PTQ1_0 is faster on Ada-generation cards and the L4. PQ2_0 is faster on Blackwell, Hopper, Ampere and Apple silicon, and at prompt processing everywhere.
PrismML research team also claims 40% better energy efficiency than a full-precision 8B model.
How Do You Run It?
The GGUF files need PrismML’s llama.cpp fork. Stock llama.cpp rejects the PTQ1_0 and PQ2_0 types. The Bonsai-demo repo is the supported path. Run ./setup.sh, then ./scripts/start_llama_server.sh for chat, vision and tools at localhost:8080.
Mac users can take the MLX pack, which needs its bundled loader. A WebGPU demo runs the model inside a browser.
Key Takeaways
- 5.93 GB language model, about 9.1x smaller than the 53.80 GB FP16 baseline.
- 83.9 average on 20 benchmarks, versus 85.4 for Qwen3.8 27B in FP16.
- 142.5 tokens per second on an RTX 5090 and 46.8 on an M5 Max.
- Long-horizon agent benchmarks keep only about 75% of full-precision scores.
- Stock llama.cpp cannot load these files. PrismML’s fork is required.
Check out the Whitepaper, Model weights, GitHub repo, Docs, WebGPU demo and announcement on X. All credit goes to the researcher of this project. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post PrismML Releases Ternary Bonsai 2 27B: A 5.9 GB Apache 2.0 Model Retaining 98.2% of Qwen3.8 27B Performance appeared first on MarkTechPost.