Представяме Needle 2: отворен модел с 45 млн. параметъра за извикване на инструменти, който се доставя като 14 MB бинарен файл и изпълнява цяла сесия в 28 MB RAM
MarkTechPost·8 мин четене
Cactus Compute пусна Needle 2 — отворен модел с 45 милиона параметъра за извикване на инструменти, използване на устройства и структурирано извличане. Целият модел се доставя като един-единствен бинарен файл от 14 MB, който изпълнява пълна сесия с около 28 MB RAM. Теглата са обучени и внедрени при CQ2-bit чрез Cactus Quants, а моделът е вграден в собствения C++ енджин на компанията, така че няма нужда от инсталиране на runtime и от изтегляне при извеждане. Отчетената скорост на декодиране е 500 токена/секунда на Raspberry Pi 5, 400–1 500 токена/секунда на Meta Quest 3S и Apple Vision Pro и 300–700 токена/секунда на телефони под 200 щатски долара. Основната идея на дизайна е тясна и е формулирана ясно от екипа: преобразуването на неструктурирано изречение в типизиран функционален подпис не изисква познания за света и неограничена проза. Именно затова тук са достатъчни 45 милиона параметъра и моделът е насочен към хардуер без GPU и NPU.
Може ли да бъде внедрен?
Да, Needle 2 се доставя като готови бинарни файлове и статична библиотека за macOS, Linux (x86-64, ARM64, ARMv7, RISC-V, MIPS32el), Windows, Android, iOS/watchOS/tvOS и WebAssembly. От Cactus посочват, че Pebble вече изпълнява Needle локално в приложението Index 01 за офлайн гласови действия.
Кои компании: Всеки екип, който доставя фърмуер или приложения за устройства с ограничени ресурси. Стартъпи в ранен етап, разработващи носими устройства и IoT продукти, производители на потребителска електроника от средния пазар, екипи по роботика и големи производители на устройства, които се нуждаят от офлайн резервен вариант. SaaS екипите, ориентирани към облака, ще спечелят по-малко.
Индустрии: интелигентен дом, носими устройства, мобилни устройства от нисък клас, управление на функциите в купето на автомобили, сервизна роботика, търговски киоски и POS системи, рутери и IP камери, както и регулирани среди, в които аудиото не може да напуска устройството.
Приложения: преобразуване на глас в действие при устройства без екран, офлайн управление на уреди, извличане на полета от касови бележки и фактури, маркиране с enum стойности и локално маршрутизиране, което прехвърля заявката към облака само при ниска увереност.
Архитектура: Simple Attention Network
Needle 2 използва архитектура, която екипът на Cactus нарича Simple Attention Network. Тази схема заменя FFN с Hadamard MLP, запазва GQA вниманието, добавя engram key-value памет от хеширани n-грам таблици и използва многоканални хиперсвързвания. Мрежата има 27 слоя и ширина 512. Изследването, на което се основава, е публикувано в arXiv под заглавие A Controlled Study of Attention-Only Transformers.
Предварителното обучение е използвало собствен корпус от 115 милиарда токена, а дообучаването — 38 милиарда токена. Изследователският екип отбелязва, че LFM2.5-230M е предварително обучен върху 19 трилиона токена.
Needle 2 изразходва 70 MFLOPs на токен, като матричното умножение използва активно 35 милиона от общо 45 милиона параметъра. LFM2.5 230M изразходва 460, FunctionGemma 270M — 540, а Apple FM е близо до 6 000.
Енджин, граматика, извличане и увереност
Теглата никога не се декомпресират в RAM. 2-битовите кодове се разширяват във векторни регистри и се сливат в целочислени скаларни произведения, така че аритметичният път остава int8. Един бинарен файл анализира процесора при стартиране и избира ниво на ядрото: SDOT, NEON, AVX2, RISC-V vectors, wasm SIMD или скаларен режим.
Граматика на ниво байтове, компилирана от вашите JSON схеми, ограничава всеки генериран токен. Тъй като матчерът знае кои токени са допустими още преди появата на логитите, енджинът пропуска до 98% от проекцията на речника при структурни токени.
Вниманието използва плъзгащ се прозорец от 256 токена, а системният turn и декларациите на инструментите са фиксирани като KV sinks. Паметта остава близо до 28 MB независимо от дължината на разговора.
Декларирайте пет или по-малко инструмента и те се визуализират директно. При повече от пет контрастивна retrieval глава вгражда всяка схема веднъж, оценява заявката при всеки turn и допуска само петте най-добри. Невключените инструменти са недостъпни, а не просто малко вероятни.
Всеки отговор съдържа стойност confidence, която е минимумът между калибрирана post-hoc глава и вероятността при декодиране на токените за извикването. Заявките извън темата връщат празно извикване []. Договорът се основава на праг: изпълнявайте над него, а под него поискайте уточнение или прехвърлете заявката.
Оценяване
Екипът на Cactus оценява модела върху пет публични бенчмарка за извикване на функции чрез подредено строго точно съвпадение, при което името, редът на извикванията и всеки аргумент трябва да съвпадат. Needle 2 работи от край до край чрез доставения енджин при CQ2-bit с включено извличане; базовите модели работят с f16 под vLLM.
Бенчмарк
Needle 2 (CQ2)
LFM2.5 230M
FunctionGemma 270M
Apple FM
Mobile Actions (961)
63.7
69.1
64.0
57.6
DroidCall (200)
17.0
11.0
17.5
—
Seal-Tools in-domain (700)
32.6
26.9
16.3
—
Seal-Tools OOD (654)
28.7
17.0
15.6
—
BFCL v4 single-turn (3,641), overall
42.6
60.8
46.1
61.7
Needle 2 води и в двата сплита на Seal-Tools и постига 98.3% точност на имената на функциите в Mobile Actions. Моделът изостава при BFCL v4, което Cactus отдава на разпределението на данните: корпусът му е съставен от действия на потребителски устройства, а не от общи или корпоративни API. Делът на добре форматираните изходи сред 3 641-те реда на BFCL е 93.4. Екипът предварително посочва две асиметрии: базовите f16 модели са в по-благоприятна позиция, а специализацията на задачите е в полза на Needle.
Decode call</button>
<button class="n2-btn" id="n2-reset-g">Reset</button>
</div>
<div class="n2-term" id="n2-term"><span class="q">> dim the living room to 30</span></div>
<div class="n2-legend">
<span><i class="n2-swatch" style="background:var(--green)"></i>forced by grammar</span>
<span><i class="n2-swatch" style="background:var(--sand)"></i>value chosen by the model</span>
</div>
<div class="n2-meters">
<div class="n2-meter"><span>Vocab rows scored · structural</span><b id="n2-m1">0%</b></div>
<div class="n2-meter"><span>Structural bytes forced</span><b id="n2-m2">0</b></div>
</div>
</section>
<!-- 03 RETRIEVAL -->
<section class="n2-panel" role="tabpanel" data-p="2">
<h3 class="n2-h">Above five tools, only five ever reach the model</h3>
<p class="n2-p">Every schema is embedded once by a built-in contrastive head. Each turn scores the query and
admits the top five; the grammar is then rebuilt over that subset. An unselected tool is unreachable.</p>
<div class="n2-controls" role="group" aria-label="Choose a query">
<button class="n2-btn is-on" data-q="0">"dim the living room"</button>
<button class="n2-btn" data-q="1">"text Ada I'm late"</button>
<button class="n2-btn" data-q="2">"set it to 21 and play jazz"</button>
</div>
<p class="n2-lanehead">Declared catalogue — 12 tools</p>
<div class="n2-chips" id="n2-chips"></div>
<p class="n2-note">Illustrative simulation of the documented top-5 mechanism, not live model output.</p>
</section>
<!-- 04 CONFIDENCE -->
<section class="n2-panel" role="tabpanel" data-p="3">
<h3 class="n2-h">The failure mode is escalation, not wrong execution</h3>
<p class="n2-p"><code>confidence</code> is the minimum of a calibrated post-hoc head and the decoding
probability of the call tokens. You pick the threshold. Off-topic input returns the empty call
<code>[]</code> before any score applies.</p>
<input class="n2-slider" id="n2-slider" type="range" min="50" max="99" value="80" aria-label="Confidence threshold">
<p class="n2-thresh">Threshold: <b id="n2-tv">0.80</b> — act at or above, re-ask or route to a bigger model below.</p>
<div class="n2-rows" id="n2-rows"></div>
<p class="n2-note">0.94 is the value shown in the Cactus README response object; the rest are illustrative.</p>
</section>
<!-- 05 MEMORY -->
<section class="n2-panel" role="tabpanel" data-p="4">
<h3 class="n2-h">A ceiling, not a curve</h3>
<p class="n2-p">Attention runs a 256-token sliding window, and the system turn plus tool declarations are
pinned as KV sinks — so the one thing a tool-calling model must not forget cannot be evicted. Add turns
and watch what happens to each bar.</p>
<div class="n2-controls">
<button class="n2-btn is-on" id="n2-turn">+ Add a turn</button>
<button class="n2-btn" id="n2-reset-m">Reset conversation</button>
<span class="n2-btn" style="cursor:default" id="n2-turns">turns: 1</span>
</div>
<div class="n2-memgrid">
<div class="n2-membar">
<span class="n2-bar-l" style="color:var(--green)">Needle 2</span>
<div class="n2-memtrack">
<div class="n2-memfill pin" id="n2-pin" style="width:34%"></div>
<div class="n2-memfill win" id="n2-win" style="left:34%;width:24%"></div>
</div>
<span class="n2-bar-v" id="n2-memv">28.0 MB</span>
</div>
<div class="n2-membar">
<span class="n2-bar-l">Unbounded KV</span>
<div class="n2-memtrack"><div class="n2-memfill grow" id="n2-grow" style="width:22%"></div></div>
<span class="n2-bar-v" id="n2-growv">rising</span>
</div>
</div>
<p class="n2-note">Striped block = pinned tools and system facts (KV sinks). Solid block = the 256-token window.</p>
<p class="n2-overflow" id="n2-of"></p>
</section>
<div class="n2-foot">
<span class="n2-brand">Explainer by <b>Marktechpost</b></span>
<span>
<a href="https://github.com/cactus-compute/needle" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://huggingface.co/Cactus-Compute/needle2" target="_blank" rel="noopener">Hugging Face</a> ·
<a href="https://cactuscompute.com/needle" target="_blank" rel="noopener">Cactus</a> ·
<a href="https://arxiv.org/abs/2607.18363" target="_blank" rel="noopener">arXiv:2607.18363</a>
</span>
</div>
</div>
<script>
(function(){
var root=document.getElementById('n2-root');
var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
/* ---------- resize ---------- */
function post(){
try{ parent.postMessage({type:'n2-height', height: root.offsetHeight + 40}, '*'); }catch(e){}
}
var ro=window.ResizeObserver?new ResizeObserver(post):null; if(ro) ro.observe(root);
window.addEventListener('load',post); setTimeout(post,120); setTimeout(post,600);
/* ---------- tabs ---------- */
var tabs=[].slice.call(root.querySelectorAll('.n2-tab'));
var panels=[].slice.call(root.querySelectorAll('.n2-panel'));
tabs.forEach(function(t){
t.addEventListener('click',function(){
tabs.forEach(function(x){x.setAttribute('aria-selected','false')});
t.setAttribute('aria-selected','true');
panels.forEach(function(p){p.classList.remove('is-on')});
panels[+t.dataset.t].classList.add('is-on');
if(t.dataset.t==='0') drawBars(metric);
post();
});
});
/* ---------- 01 frontier ---------- */
var DATA={
params:{unit:'M params', note:'Общ брой параметри. Apple FM е приблизително 3B. Източник: таблицата на Cactus за изчисленията на токен.',
rows:[['Needle 2',45,'45M'],['LFM2.5 230M',230,'230M'],['FunctionGemma 270M',270,'270M'],['Apple FM',3000,'~3B']]},
flops:{unit:'MFLOPs/token', note:'2 FLOPs на операция за умножение и натрупване върху параметрите, активни за матрично умножение; embeddings са свързани, а термините за вниманието са изключени. Needle запазва 8M параметъра като събрана engram памет, което не изисква аритметични операции.',
rows:[['Needle 2',70,'70'],['LFM2.5 230M',460,'460'],['FunctionGemma 270M',540,'540'],['Apple FM',6000,'~6,000']]},
acc:{unit:'%', note:'Оценъчен сплит Mobile Actions, 961 реда, подредено строго точно съвпадение. Needle 2 при CQ2-bit с включено извличане; LFM2.5 и FunctionGemma при f16 под vLLM; Apple FM на устройството.',
rows:[['Needle 2',63.7,'63.7'],['LFM2.5 230M',69.1,'69.1'],['FunctionGemma 270M',64.0,'64.0'],['Apple FM',57.6,'57.6']]}
};
var metric='params', barsEl=document.getElementById('n2-bars'), noteEl=document.getElementById('n2-barnote');
function drawBars(m){
var d=DATA[m], max=Math.max.apply(null,d.rows.map(function(r){return r[1]}));
barsEl.innerHTML=d.rows.map(function(r){
return '<div class="n2-bar'+(r[0]==='Needle 2'?' is-hero':'')+'">'+
'<span class="n2-bar-l">'+r[0]+'</span>'+
'<div class="n2-bar-t"><div class="n2-bar-f"></div></div>'+
'<span class="n2-bar-v">'+r[2]+'</span></div>';
}).join('');
noteEl.textContent=d.note;
var fills=barsEl.querySelectorAll('.n2-bar-f');
d.rows.forEach(function(r,i){
var w=Math.max(2,(r[1]/max)*100);
if(reduce){fills[i].style.width=w+'%';}
else setTimeout(function(){fills[i].style.width=w+'%';},60*i+40);
});
post();
}
root.querySelectorAll('[data-m]').forEach(function(b){
b.addEventListener('click',function(){
root.querySelectorAll('[data-m]').forEach(function(x){x.classList.remove('is-on')});
b.classList.add('is-on'); metric=b.dataset.m; drawBars(metric);
});
});
drawBars('params');
/* ---------- 02 grammar ---------- */
var CALL=[
['{"name":"',1],['set_lights',0],['","arguments":{"room":"',1],['living room',0],
['","on":',1],['true',0],[',"brightness":',1],['30',0],['}}',1]
];
var term=document.getElementById('n2-term'), m1=document.getElementById('n2-m1'), m2=document.getElementById('n2-m2');
var timer=null;
function resetG(){
if(timer){clearInterval(timer);timer=null;}
term.innerHTML='<span class="q">> затъмни всекидневната до 30</span>';
m1.textContent='0%'; m2.textContent='0'; post();
}
document.getElementById('n2-reset-g').addEventListener('click',resetG);
document.getElementById('n2-decode').addEventListener('click',function(){
if(timer){clearInterval(timer);timer=null;}
var flat=[]; CALL.forEach(function(seg){
for(var i=0;i<seg[0].length;i++) flat.push([seg[0][i],seg[1]]);
});
term.innerHTML='<span class="q">> затъмни всекидневната до 30</span><br>';
var out=document.createElement('span'); term.appendChild(out);
var caret=document.createElement('span'); caret.className='n2-caret'; caret.textContent='_'; term.appendChild(caret);
var i=0, forced=0;
function step(){
if(i>=flat.length){ if(timer){clearInterval(timer);timer=null;} caret.remove();
m1.textContent='2%'; m2.textContent=forced; post(); return; }
var ch=flat[i][0], isF=flat[i][1];
var s=document.createElement('span'); s.className=isF?'n2-forced':'n2-free';
s.textContent=ch; out.appendChild(s);
if(isF) forced++;
var pct=Math.round(100-(forced/(i+1))*98);
m1.textContent=pct+'%'; m2.textContent=forced;
i++;
}
if(reduce){ while(i<flat.length) step(); }
else timer=setInterval(step,26);
});
/* ---------- 03 retrieval ---------- */
var TOOLS=['set_lights','play_music','send_message','set_thermostat','get_weather','set_timer',
'call_contact','navigate_to','take_photo','lock_door','add_calendar_event','control_tv'];
var PICKS=[[0,3,11,1,5],[2,6,10,0,4],[3,1,0,5,4]];
var chipsEl=document.getElementById('n2-chips');
chipsEl.innerHTML=TOOLS.map(function(t,i){return '<span class="n2-chip" data-i="'+i+'">'+t+'</span>'}).join('');
function retrieve(qi){
var sel=PICKS[qi];
[].slice.call(chipsEl.children).forEach(function(c,i){
c.classList.remove('is-sel','is-out');
var d=sel.indexOf(i)>-1?0:180;
setTimeout(function(){ c.classList.add(sel.indexOf(i)>-1?'is-sel':'is-out'); }, reduce?0:d);
});
}
root.querySelectorAll('[data-q]').forEach(function(b){
b.addEventListener('click',function(){
root.querySelectorAll('[data-q]').forEach(function(x){x.classList.remove('is-on')});
b.classList.add('is-on'); retrieve(+b.dataset.q);
});
});
retrieve(0);
/* ---------- 04 confidence ---------- */
var TURNS=[
['затъмни всекидневната до 30',0.94,false],
['направи го по-топло тук',0.81,false],
['постави онова върху другото',0.58,false],
['изпрати на Ада съобщение, че закъснявам',0.88,false],
['коя е столицата на Перу?',null,true]
];
var rowsEl=document.getElementById('n2-rows'), slider=document.getElementById('n2-slider'), tv=document.getElementById('n2-tv');
function renderRows(){
var th=(+slider.value)/100; tv.textContent=th.toFixed(2);
rowsEl.innerHTML=TURNS.map(function(t){
if(t[2]) return '<div class="n2-row ref"><span class="n2-row-q">'+t[0]+
'</span><span class="n2-row-c">[ ]</span><span class="n2-verdict v-ref">празно извикване</span></div>';
var ok=t[1]>=th;
return '<div class="n2-row '+(ok?'act':'esc')+'"><span class="n2-row-q">'+t[0]+
'</span><span class="n2-row-c">'+t[1].toFixed(2)+'</span><span class="n2-verdict '+
(ok?'v-act">изпълни':'v-esc">ескалирай')+'</span></div>';
}).join('');
post();
}
slider.addEventListener('input',renderRows); renderRows();
/* ---------- 05 memory ---------- */
var turns=1, gv=document.getElementById('n2-gv'), gf=document.getElementById('n2-gf');
var win=document.getElementById('n2-win'), grow=document.getElementById('n2-grow');
var memv=document.getElementById('n2-memv'), growv=document.getElementById('n2-growv');
var ofEl=document.getElementById('n2-of'), turnsEl=document.getElementById('n2-turns');
function renderMem(){
turnsEl.textContent='ходове: '+turns;
var w=Math.min(24, 12+turns*2.5);
win.style.width=w+'%';
memv.textContent='28.0 MB';
gf.style.width='78%'; gv.innerHTML='<b>28.0 MB</b> / твърд таван от 28 MB';
var g=Math.min(100, 18+turns*7);
grow.style.width=g+'%';
growv.textContent=(Math.round((18+turns*7)*0.62*10)/10)+' MB';
ofEl.textContent = g>=78 ? 'Неограниченият KV е преминал тавана от 28 MB. Needle 2 не се е променил.' : '';
post();
}
document.getElementById('n2-turn').addEventListener('click',function(){turns++;renderMem();});
document.getElementById('n2-reset-m').addEventListener('click',function(){turns=1;renderMem();});
renderMem();
})();
</script>
</body>
</html>
">
Основни изводи
Needle 2 е модел с 45 милиона параметъра за извикване на инструменти, разположен в бинарен файл от 14 MB и изпълняващ сесия с около 28 MB RAM.
CQ2-bit е включен още при предварителното обучение, а не е приложен post-hoc, така че внедреният модел е същият като обучения модел.
Моделът води при Seal-Tools in-domain (32.6) и out-of-domain (28.7), но изостава при BFCL v4 overall (42.6).
Плъзгащ се прозорец от 256 токена с фиксирани инструментални sinks превръща RAM в постоянен таван, а не в растяща крива.
Оценките за увереност и отказите чрез празно извикване превръщат ескалацията от периферното устройство към облака в изрично продуктово решение.