LLM in locale con Claude Code: Bonsai 2 27B su una GPU da 8 GB
Ternary Bonsai 2 27B di Prism ML in locale su una GPU da portatile da 8 GB con llama.cpp e Claude Code: installazione, insidie risolte e misure reali.

Far girare un LLM in locale da 27 miliardi di parametri su un portatile, fino a pochi mesi fa, significava rassegnarsi a una quantizzazione così aggressiva da rendere il modello poco più di una curiosità, oppure spostare metà dei pesi sulla CPU e accettare velocità da telescrivente. Con Ternary Bonsai 2 27B, rilasciato da Prism ML a metà settembre 2026, la promessa cambia di scala: un modello derivato da Qwen3.8-27B che pesa meno di 6 GB e che, secondo il produttore, conserva il 98,2% delle prestazioni della versione a piena precisione.
Ho voluto verificare quanto di quella promessa regga su hardware ordinario, e soprattutto se un modello del genere possa sostituire, almeno per una parte del lavoro, il modello remoto dietro Claude Code. Ne è uscita un'installazione che ha richiesto tre giorni di prove, un fork di llama.cpp, un template corretto a mano e un piccolo proxy scritto apposta. Questo articolo racconta il percorso con i numeri misurati sulla mia macchina, tenendo separate le dichiarazioni del produttore da ciò che ho osservato direttamente.
Cosa troverai: chi è Prism ML e come funzionano i pesi ternari di Bonsai 2 27B, perché oggi non si può usare Ollama, come installare il runtime corretto su WSL2 senza toccare il sistema, come collegare il modello a Claude Code evitando le sei insidie che ho incontrato e quali velocità aspettarsi realmente su una GPU da portatile con 8 GB di VRAM.
Prism ML, lo spin-off del Caltech che punta tutto sui pochi bit
Prism ML è uscita allo scoperto ad aprile 2026 come spin-off del California Institute of Technology. Il fondatore e CEO è Babak Hassibi, professore di ingegneria elettrica al Caltech, la cui ricerca sulla compressione delle reti neurali costituisce la base tecnologica dell'azienda; il Caltech detiene la proprietà intellettuale e Prism ML ne è licenziataria esclusiva. Il round iniziale, da circa 16,25 milioni di dollari, è stato guidato da Khosla Ventures con la partecipazione di Cerberus Capital e del Caltech Seed Fund (The Register).
La tesi industriale è dichiarata senza giri di parole: i modelli grandi non entrano negli smartphone e i data center faticano a sostenerne i costi energetici, quindi conviene misurare l'intelligenza per bit anziché per numero di parametri. Il primo prodotto è stato 1-bit Bonsai 8B, un modello a pesi binari da circa 1,15 GB; poco dopo è arrivata la famiglia Ternary Bonsai (1,7B, 4B e 8B), che sostituisce i pesi binari con pesi a tre valori e, secondo l'azienda, recupera in media cinque punti di benchmark al costo di circa 600 MB in più. È seguito un primo Bonsai 27B e infine, il 17 settembre 2026, Bonsai 2 27B, rilasciato con licenza Apache 2.0.
Aprile 2026
Prism ML esce dallo stealth con 1-bit Bonsai 8B e annuncia il finanziamento guidato da Khosla Ventures.
Aprile 2026
Segue la famiglia Ternary Bonsai (1,7B, 4B, 8B): pesi in {−1, 0, +1} su tutta la rete.
Luglio 2026
Primo Bonsai 27B, con una ritenzione dichiarata intorno al 95% del modello a piena precisione.
17 settembre 2026
Ternary Bonsai 2 27B su base Qwen3.8-27B: ritenzione dichiarata del 98,2%, file da 5,95 GB.
Ternary Bonsai 2 27B: cosa c'è dentro il file da 6 GB
Le informazioni che seguono provengono dalla model card su Hugging Face e dal whitepaper pubblicato nel repository Bonsai-demo; sono quindi dichiarazioni del produttore. L'architettura è quella di Qwen3.8-27B, lasciata invariata: 27,36 miliardi di parametri complessivi, di cui 24,35 nel backbone linguistico (64 blocchi), 2,54 fra embedding e LM head e 0,46 nella vision tower. L'attenzione è ibrida, circa tre quarti lineare e un quarto completa, il che produce una cache K/V sensibilmente più piccola di quella di un transformer classico di pari taglia; il contesto nativo dichiarato è di 262.000 token.
Pesi ternari con una scala ogni 128 valori
Ogni peso assume uno fra tre valori, −1, 0 oppure +1, e ogni gruppo di 128 pesi condivide un fattore di scala in FP16 (lo schema che Prism ML chiama «ternary g128»). Il risultato è di circa 1,75 bit per peso, applicato anche a embedding e LM head, cioè proprio ai componenti che molte quantizzazioni lasciano in precisione più alta per prudenza. Restano in precisione maggiore soltanto circa 26 milioni di parametri, relativi allo stato ricorrente dei layer lineari e alle normalizzazioni.
Il dettaglio meno evidente, e quello che più conta in fase di installazione, è la rotazione di Hadamard. Prima della ternarizzazione le matrici vengono ruotate a blocchi di 1024 elementi; la rotazione è incorporata nei pesi e il runtime deve applicare la trasformazione inversa alle attivazioni durante l'inferenza. Il file GGUF la dichiara nei metadati, ma un runtime che la ignora non produce un errore: produce testo privo di senso.
Secondo Prism ML, PTQ1_0 decodifica più rapidamente sulle schede Ada e sulla L4, mentre PQ2_0 è più veloce su H100, A100 e Blackwell, oltre che nell'elaborazione del prompt. Su una GPU da 8 GB la scelta è obbligata a prescindere dall'architettura: PQ2_0 non lascia spazio sufficiente alla cache, perciò ho usato PTQ1_0.
Il 98,2% e come leggerlo
Il dato di copertina è una media di 84,78 punti contro gli 86,32 del modello FP16 su 14 benchmark in thinking mode. Vale la pena sapere come è stato ottenuto: le valutazioni sono state eseguite con EvalScope e vLLM su GPU H100, non con llama.cpp e non su hardware consumer, e nessuno dei 14 benchmark è in italiano. La distribuzione per categoria è più istruttiva della media.
Codice e matematica restano praticamente intatti, mentre conoscenza generale e visione perdono qualche punto in più: è coerente con l'idea che la compressione sacrifichi prima la memoria enciclopedica e poi le capacità procedurali. Per un uso come agente di programmazione la lettura è incoraggiante, ma il calo nel tool calling, per quanto contenuto, riguarda proprio la capacità che Claude Code mette più sotto pressione.
Parametri consigliati da Prism ML in thinking mode: temperatura 1.0, top_p 0.95, top_k 20, min_p 0.05. Il livello di ragionamento predefinito del template è xhigh; medium è indicato per risposte più brevi, mentre low, per ammissione della documentazione, non riduce davvero il ragionamento.
Perché non si può usare Ollama (per ora)
Sul portatile avevo già Ollama, e la prima domanda è stata ovvia: perché non usare quello? La risposta sta nei formati. PTQ1_0 e PQ2_0 sono tipi di quantizzazione nuovi e, come riporta il file KNOWN_ISSUES ufficiale, né llama.cpp mainline né Ollama né LM Studio sono in grado di caricarli. Serve il fork di llama.cpp mantenuto da Prism ML, che contiene i kernel CUDA e Metal per i pesi ternari e l'applicazione della rotazione.
Ho verificato lo stato del supporto upstream al 6 ottobre 2026. La pull request #29077 che proponeva di aggiungere i due tipi a llama.cpp è stata chiusa in favore di una serie di contributi più piccoli; i maintainer hanno chiesto che sia Prism ML stessa a proporre il codice, e dal lato Prism ML è emersa la possibilità che i nuovi tipi restino nel fork, perché ogni tipo aggiunto al progetto principale aumenta il carico di manutenzione. Esistono fork di terze parti che riportano il supporto su mainline o su ik_llama.cpp, ma non li ho provati.
Attenzione al formato Q2_0. A differenza di PTQ1_0 e PQ2_0, llama.cpp mainline lo conosce e lo carica senza segnalare errori, ma non applica la rotazione di Hadamard: il risultato è un modello che sembra funzionare e invece genera testo senza senso. Se un runtime «generico» accetta un file Bonsai 2 senza lamentarsi, è il primo segnale che qualcosa non va.
La perdita, per fortuna, è minore di quanto sembri. Il vantaggio di Ollama per chi usa Claude Code è l'endpoint compatibile con l'API Anthropic, ma il llama-server del fork espone già /v1/messages e /v1/messages/count_tokens, quindi Claude Code può parlarci direttamente.
L'hardware: una GPU da portatile e un gigabyte che non c'è
La macchina è un Samsung Galaxy Book6 Ultra con Windows 11 e WSL2 (Ubuntu 24.04), equipaggiato con una GeForce RTX 5060 Laptop con 8 GB di VRAM, architettura Blackwell (compute capability 12.0). Dentro WSL non è installato alcun driver NVIDIA: la GPU è esposta dal driver Windows attraverso la libreria libcuda che WSL monta automaticamente.
La sorpresa vera è arrivata misurando la memoria disponibile. Degli 8150 MiB nominali, CUDA dentro WSL ne vede liberi soltanto circa 7085, perché il driver Windows in modalità WDDM riserva per sé circa un gigabyte. Il budget reale, quindi, è di 7 GB e non di 8, e ogni scelta successiva (formato del modello, dimensione del contesto, tipo di cache) discende da questo numero. La RAM di sistema, invece, è irrilevante: i pesi stanno interamente in VRAM.
Installazione del runtime senza toccare il sistema
L'obiettivo era un'installazione reversibile, confinata in una cartella e senza pacchetti di sistema. Non è stato necessario compilare nulla: il fork pubblica binari precompilati.
1. Binari del fork
Ho scaricato la release del fork fissata dagli script di Bonsai-demo, nella variante Linux con CUDA 12.8, verificando il checksum contro il digest pubblicato su GitHub. La scelta di CUDA 12.8 anziché 13.3 non è casuale: il KNOWN_ISSUES segnala crash delle build 13.3 su Linux, e la 12.8 include già il supporto a Blackwell (sm_120).
2. Librerie CUDA mancanti
I binari non includono libcudart e libcublas, e sul sistema non c'era un toolkit CUDA. Anziché installarlo, ho creato un ambiente virtuale con uv e vi ho installato i pacchetti pip ufficiali di NVIDIA, impostando LD_LIBRARY_PATH soltanto negli script di avvio.
3. Download del modello
Solo il file PTQ1_0, con revisione fissata e hash sha256 verificato contro quello pubblicato da Hugging Face. Niente FP16 da 54 GB, niente PQ2_0, niente proiettore per la visione.
4. Prova di caricamento
65 layer su 65 caricati in GPU e, nel log, la conferma di 402 pesi con rotazione di Hadamard incorporata: il segnale che il runtime Prism è attivo. Prima risposta coerente, in italiano.
Configurare llama-server su 7 GB di VRAM
Il server ascolta soltanto su 127.0.0.1, gestisce una conversazione alla volta e usa una cache dei prompt in RAM, utile quando un agente rimanda ogni volta lo stesso lungo prefisso. Due scelte meritano una spiegazione. La prima è la combinazione di offload totale con il fitting automatico disattivato: in questo modo, se il modello non entra, il server fallisce invece di ridurre in silenzio il contesto o di spostare layer sulla CPU. Lo script di avvio controlla inoltre nel log che tutti i 65 layer siano in GPU e si rifiuta di partire se la VRAM è già occupata, per esempio da un modello Ollama dimenticato in memoria.
La seconda riguarda la cache K/V, che a contesto pieno diventa la voce di memoria dominante. In FP16 occuperebbe 64 KiB per token, troppo per qualsiasi contesto utile; in q8_0 scende a 34 KiB per token e un contesto da 32K entra con circa 7,05 GB occupati, mentre a 64K si arriverebbe a 8,1 GB. Per raggiungere 64K ho usato q4_0 con il bias di mean-centering previsto dal fork, circa 18 KiB per token e 7,3 GB complessivi.
Il bias si calcola una sola volta con lo strumento llama-kv-mean-center su un piccolo corpus di calibrazione. Qui ho trovato una piccola discrepanza nella documentazione stessa: il README dello strumento nel fork indica di calibrare con la rotazione delle chiavi attiva (divergenza KL di 0,00111 contro 0,00149 senza), mentre lo script della demo la disattiva. Ho seguito l'indicazione del runtime.
L'opzione preserve_thinking: false evita che il template riproponga nella cronologia il ragionamento di tutti i turni precedenti, un comportamento noto che gonfia rapidamente il contesto. La temperatura a 0.6, più bassa del valore raccomandato, è una scelta mia che discende dai test di qualità descritti più avanti. Il server include anche una Web UI raggiungibile all'indirizzo locale, sufficiente per le prove senza installare Open WebUI o Docker.
Claude Code con un modello locale: le insidie una per una
Collegare Claude Code a un endpoint compatibile Anthropic richiede poche variabili d'ambiente, ma la documentazione è esplicita: Anthropic non supporta l'uso di Claude Code con modelli non-Claude attraverso alcun gateway. Funziona, senza garanzie, e all'avvio compare un avviso di modello non riconosciuto. Ho racchiuso tutto in uno script di avvio da lanciare nella cartella del progetto, che tiene la sessione locale completamente separata da quella abituale.
1. Senza token, Claude Code ignora l'endpoint locale
Impostare solo ANTHROPIC_BASE_URL non basta: se esiste un login claude.ai salvato, resta quello la credenziale attiva. Serve anche ANTHROPIC_AUTH_TOKEN, con un valore qualsiasi, perché la richiesta parta davvero verso il server locale. Le variabili sono definite solo nel processo lanciato dallo script, quindi non contaminano le altre sessioni.
2. Il prompt di sistema occupa metà del contesto
Con tutti i tool attivi, Claude Code invia 17.542 token prima ancora che l'utente scriva qualcosa, e su questa GPU l'elaborazione richiede 31 secondi. Limitando i tool a Bash, Read, Edit, Write, Glob, Grep e TodoWrite il prompt scende a 5.993 token e a 10 secondi. È la configurazione predefinita dello script.
3. La compattazione scatta troppo presto
Per un modello che non conosce, Claude Code assume una finestra di 200K token, quindi il contesto reale va dichiarato con CLAUDE_CODE_MAX_CONTEXT_TOKENS. La soglia di compattazione che ho osservato è pari alla finestra meno l'output massimo (8192) meno circa 13K di margine: a 32K scattava intorno a 11.500 token, cioè dopo appena 5K di lavoro effettivo. È il motivo principale per cui sono passato a 64K, dove la soglia sale a circa 44K.
4. Il template rifiuta i messaggi system a metà conversazione
Il template di Bonsai 2 accetta un solo messaggio system e solo in prima posizione; in caso contrario il server risponde con un errore HTTP 500 («System message must be at the beginning»), un problema documentato nel KNOWN_ISSUES. Claude Code però inserisce messaggi system anche a conversazione avviata. Ho risolto con un override locale del template, passato al server con --chat-template-file, che trasforma quei messaggi in un turno utente marcato come system-reminder; l'originale è conservato e la modifica riguarda una sola riga. L'ho verificato con richieste simulate, non ancora in una sessione interattiva lunga.
5. L'auto mode blocca ogni comando
Dalla versione 2.1.283 le sessioni interattive di Claude Code partono in auto mode. Il classificatore che valuta la sicurezza di ogni azione gira per impostazione predefinita su Claude Sonnet 5, ma la richiesta passa dallo stesso endpoint e quindi arriva a Bonsai, che non risponde nel formato atteso: ogni comando veniva negato con un messaggio di modello «temporaneamente non disponibile». La soluzione è disattivare l'auto mode nella configurazione separata, come previsto dalla documentazione sui permission mode. Del resto, un classificatore di sicurezza che coincide con il modello da sorvegliare non sarebbe una vera garanzia.
6. Il modello pensa sette minuti per ritoccare una card
Claude Code invia il livello di effort nel campo output_config.effort, ma l'endpoint Anthropic di llama-server lo scarta: dal sorgente risulta che inoltra soltanto temperatura, top_p, top_k, chat_template_kwargs e thinking. Con il livello xhigh del server, il modello ragionava dai cinque ai dieci minuti anche per modifiche banali. Ho scritto un piccolo proxy locale, avviato e chiuso insieme alla sessione, che traduce /effort in livello del template più un tetto ai token di ragionamento.
C'è un effetto collaterale da conoscere: entrare o uscire da xhigh cambia il prompt di sistema generato dal template, quindi la richiesta successiva rielabora da capo l'intero contesto. Il proxy, già che c'era, scrive in tempo reale su un file di log il ragionamento, le risposte e le chiamate ai tool, mentre uno script separato mostra la fase in corso (elaborazione del prompt o generazione) con i token al secondo. Vedere il modello pensare è il modo più rapido per capire se sta lavorando o se si è infilato in un ciclo. Infine, Claude Code non invia una temperatura propria, per cui vale quella impostata sul server.
Una lezione di sicurezza che vale per qualunque agente. Per avviare il server di sviluppo di un sito, il modello ha deciso da solo di leggere un file .env.local contenente un token API. Con un modello locale il dato non lascia la macchina, ma il comportamento sarebbe identico con un modello remoto: conviene negare esplicitamente la lettura dei file .env con permissions.deny, come nell'esempio sopra, oppure tenerli fuori dalla cartella di lavoro dell'agente.
Le misure: velocità, memoria e contesto lungo
Tutti i numeri di questa sezione sono stati misurati sulla RTX 5060 Laptop da 8 GB descritta sopra, con il file PTQ1_0 e Flash Attention attiva. Per la velocità ho usato llama-bench a diverse profondità di contesto.
Nel server reale, con prompt brevi, la generazione si attesta intorno ai 30 token al secondo. Il rallentamento con la profondità del contesto, però, è marcato: in un test a 64K con cache q4_0 ho elaborato un prompt di 62.078 token in 195 secondi (319 token al secondo) e la generazione è scesa a 6,1 token al secondo. La documentazione di Prism ML lo dice chiaramente, la cache q4_0 è uno strumento per risparmiare memoria e non per guadagnare velocità. Per confronto, il produttore dichiara per PTQ1_0 circa 91 token al secondo su RTX 4090 e circa 120 su RTX 5090 in generazione.
Sul fronte della memoria, la VRAM occupata è di 7,05 GB a 32K con cache q8_0 e di 7,3 GB a 64K con cache q4_0 e bias, a fronte dei circa 7,08 GB effettivamente disponibili per CUDA dentro WSL; i soli pesi occupano 5395 MiB. Il test dell'ago nel pagliaio, con un codice nascosto a metà di un testo lungo, è stato superato sia a 30.015 token effettivi (contesto da 32K) sia a 62.154 token (contesto da 64K).
Quanto costa comprimere la cache
Restava da capire se le compressioni della cache introdotte da me peggiorassero l'output. Ho confrontato la distribuzione dei token rispetto a una cache FP16, a parità di pesi, su testo italiano e su codice.
La conclusione è netta: le compressioni aggiunte alla cache non bastano a spiegare gli errori osservati nell'output, che vanno attribuiti al modello. Sul piano funzionale, il modello ha gestito correttamente l'italiano, una conversazione a tre turni con memoria del contesto e il tool calling con restituzione dei risultati; dentro Claude Code ha letto, creato e modificato file e lanciato le suite di test, superate in due prove con 7 test su 7 e 8 su 8.
La qualità dell'output nel lavoro reale
Ho sottoposto al modello otto compiti Python con nomi di variabili e funzioni in italiano, verificati da test nascosti scritti a mano; sei compiti sono stati completati in tutte e quattro le configurazioni. Il campione è piccolo e indica tendenze, non risultati statistici.
Nel lavoro reale dentro Claude Code, però, il quadro è diverso da quello che questi numeri lasciano intendere. Gli errori di lingua, così evidenti nei test, nell'uso quotidiano non si sono quasi mai presentati: le risposte nell'interfaccia erano pulite e prive di refusi. Non ho una spiegazione certa di questa differenza; è possibile che nei test il modello fosse condizionato dal testo stesso su cui doveva ragionare, fitto di identificatori in italiano, ma resta un'ipotesi che non ho verificato. Del resto, l'uso che avevo in mente per questo modello è esclusivamente la programmazione, e in quel contesto ciò che conta è la correttezza del codice; per la stessa ragione i valori attesi sbagliati nei test scritti dal modello mi preoccupano meno di quanto sembri.
Il codice prodotto, nel complesso, era utilizzabile così com'era. Su una modifica front-end dal perimetro molto ristretto, tuttavia, il risultato è stato tecnicamente corretto ma modesto sul piano della qualità, e soprattutto ha richiesto un tempo del tutto sproporzionato rispetto alla portata dell'intervento.
È proprio il tempo il limite che oggi mi impedisce di usarlo stabilmente nel lavoro di tutti i giorni. Il Galaxy Book6 Ultra non è un portatile economico, ma rientra nella fascia di macchine accessibili per un uso professionale: offre molta potenza, una buona autonomia e un ottimo schermo, ed è a mio giudizio uno dei Windows più completi in circolazione, soprattutto per chi è già abituato all'ecosistema Samsung. Anche su questo hardware, tuttavia, i livelli di ragionamento più alti, cioè quelli che producono l'output migliore, impongono attese enormi persino per piccole modifiche, e il modello tende a ragionare su sé stesso molto più di quanto il compito richieda.
Un router per decidere quanto ragionare
Una strada che vorrei sperimentare, ora che Claude Code si può estendere con le mod, è affiancare al modello un router che, prima dell'avvio della pipeline, valuti la richiesta e stabilisca il livello di effort da applicare. Una correzione di poche righe non avrebbe più bisogno di dieci minuti di ragionamento, mentre i compiti complessi continuerebbero a ricevere il budget pieno.
Il candidato più interessante per questo ruolo è Jev, presentato da TypeSafe AI a metà settembre 2026 come il primo dei cosiddetti «System One models». Non genera testo, ma restituisce decisioni tipizzate, per esempio la scelta fra un insieme di opzioni predefinite, accompagnate da un valore di confidenza e, secondo l'azienda, in tempi compresi fra 70 e 500 millisecondi. È esattamente il tipo di decisione che serve qui: letto il prompt, scegliere fra low, medium, high e xhigh. Jev è però un servizio proprietario in cloud, quindi il testo della richiesta lascerebbe la macchina; chi vuole restare interamente in locale può ripiegare su un modello di classificazione molto leggero eseguito accanto a Bonsai. Il proxy descritto sopra fa già metà del lavoro, perché traduce l'effort in un tetto ai token di ragionamento; quello che manca è la scelta automatica del livello.
Per chi ha senso un LLM in locale di questa taglia
Bonsai 2 27B su una GPU da 8 GB non sostituisce un modello di frontiera remoto, e chi si aspetta la stessa velocità resterà deluso già oltre i 30.000 token di contesto. Dimostra però un punto che fino a poco tempo fa era teorico: un modello da 27 miliardi di parametri, con capacità di ragionamento e di tool calling utilizzabili, può girare interamente sulla GPU di un portatile e pilotare un agente di programmazione completo. I limiti sono altrove, nella maturità dell'ecosistema: un fork obbligatorio, un template da correggere, un parametro di effort che si perde per strada e un client che non è progettato per questo uso.
Il caso d'uso più solido, a mio avviso, riguarda i progetti in cui il codice o i dati non possono uscire dalla macchina, per vincoli contrattuali o normativi, e i compiti ripetitivi e ben delimitati in cui la latenza conta meno della riservatezza. Per un'azienda che valuta l'adozione di agenti AI su codice proprietario, un'installazione locale come questa è anche un banco di prova economico per capire cosa delegare prima di affidarsi a un servizio esterno.
- GPU NVIDIA con almeno 8 GB di VRAM (in WSL considera circa 1 GB riservato da Windows)
- Binari del fork Prism ML di llama.cpp, nella build CUDA 12.8
- File GGUF PTQ1_0 verificato tramite checksum
- Cache q4_0 con bias di mean-centering per arrivare a 64K di contesto
- Override del template per i messaggi system a metà conversazione
- Configurazione di Claude Code separata, con auto mode disattivato e lettura dei file .env negata
- Tool ridotti e un tetto al ragionamento, tramite proxy, per tempi di risposta accettabili
Vuoi portare un agente AI sul tuo codice senza farlo uscire dall'azienda?
Progetto e configuro ambienti di sviluppo con agenti AI, locali o ibridi, partendo dai vincoli reali di riservatezza, hardware e budget. Se stai valutando questa strada, possiamo parlarne partendo dal tuo caso concreto.
Se vuoi approfondire il confronto fra gli agenti di programmazione remoti, trovi qui la mia analisi basata sull'uso quotidiano in produzione.
Grazie per aver letto questo articolo
Hai un progetto in mente?
Raccontami obiettivo e situazione attuale. Ti rispondo con domande mirate e una proposta per fasi.