Un modello linguistico da 14,3 milioni di parametri gira interamente su un microcontrollore ESP32-S3 e prende ogni decisione di alto livello per un piccolo acquario virtuale di pesci: mangiare, nascondersi, esplorare, socializzare, riposare o fuggire. Il cervello è un file da 7,56 MB letto direttamente dalla flash, senza rete né cloud. Il tank vive su un display AMOLED da 1,8 pollici che si tiene in una mano. Quindi non serve alcun server, alcuna API, alcuna connessione: il pesce decide da solo, sul posto.
Il progetto dimostra che un modello distillato da circa 26 miliardi di parametri può girare su un microcontrollore da pochi dollari. Lo studente, chiamato pocket-tank, ha 14,3 milioni di parametri con dimensione 384, 8 layer e 8 head: circa 1.818 volte meno dell’insegnante. In fp32 peserebbe 57 MB, in 4 bit scende a 7,56 MB. Il vocabolario è di 58 token, un lessico a schema chiuso, contro i circa 262K token dell’insegnante.
Tre livelli separati compilati identici nel simulatore e nel firmware
L’architettura si divide in tre strati, tutti in common/ e compilati identici nel simulatore e nel firmware: lo strato riflessi (tank.c), il consulente LLM (llm/) e la progressione (progression.c). Lo strato riflessi gestisce fisica, sterzo, branco, gesti touch, alimentazione, economia della fame, vegetazione e alghe. Gira a ogni frame e non si blocca mai sul modello. Invece il consulente LLM è un motore di inferenza a 4 bit in stile llama2.c, con tokenizer a livello di parola e un encoder di stato condiviso.
Il modello gira sul secondo core dell’ESP32-S3 con prodotti scalari SIMD e attivazioni quantizzate in SRAM interna. I pesi sono mappati in memoria dalla flash e non vengono mai copiati. Perciò il tank resta fluido mentre il modello pensa. I pesci vengono ri-interrogati solo quando la loro situazione cambia in modo significativo: così quattro o sei pesci condividono un solo cervello.
- Ogni pesce descrive periodicamente la sua situazione al modello come una singola riga di testo: fame, energia, paura, chi è vicino, la sua personalità.
- Il modello completa la riga con un obiettivo e un’urgenza.
- Lo strato riflessi trasforma quell’obiettivo in movimento.
- Il modello campiona la propria distribuzione invece di prendere sempre la risposta più probabile.
- Quando le prime due scelte sono vicine il pesce esita visibilmente prima di impegnarsi.
- Non esistono euristiche di ripiego che sovrascrivono la decisione.
I numeri dell’addestramento raccontano la qualità della distillazione. Il modello è stato addestrato su 51.162 situazioni etichettate dall’insegnante. Lo studente sceglie l’obiettivo dell’insegnante nel 75% dei casi, mentre l’insegnante concorda con se stesso nell’82% dei casi. Un pesce affamato sceglie seek_food almeno l’89% delle volte, in tutte le personalità. Quindi la quantizzazione a 4 bit non ha distrutto il comportamento appreso.

La scheda, la partizione da 8 MB e i tempi misurati sul banco
Il firmware è basato su ESP-IDF v5.4 con PSRAM octal da 8 MB. La scheda target ha 16 MB di flash e 8 MB di PSRAM. Il modello vive in una partizione raw dedicata da 8 MB e va flashato una sola volta, all’indirizzo 0x290000. Sul lato hardware il progetto usa una Waveshare ESP32-S3-Touch-AMOLED-1.8 con ESP32-S3R8, display AMOLED 368×448, touch capacitivo, IMU, PMIC e RTC. La scheda con schermo e batteria costa in realtà circa 35 dollari.
Sulla scheda reale una decisione richiede circa 3,6 s a 12 token al secondo, con il tank renderizzato a 25-30 fps in parallelo sull’altro core. In emulazione QEMU una decisione richiede circa 2,3 s. Il tank parte con due avannotti e arriva fino a cinque pesci. Un pasto dura cinque o sei minuti da svegli. Tenere un dito sul vetro per tre secondi richiama i pesci che si fidano di te. Il prompt di reset scompare dopo venti secondi di silenzio.
Per chi vuole rifare il progetto, la catena software comprende ESP-IDF v5.4, un motore di inferenza a 4 bit in stile llama2.c, LVGL v9.2.2, SDL2, ESP Web Tools, gli script tools/make_installer.py e tools/director.py, e QEMU nella versione Espressif. Chi vuole orientarsi su una scheda con display integrato e grafica LVGL può guardare anche altre soluzioni del catalogo, ma il cuore del progetto resta la partizione raw da 8 MB e il motore a 4 bit. Il codice, gli script e la procedura di flash sono raccolti nel repository di codice del progetto.

Chi vuole replicare la parte di sensoristica può valutare un modulo IMU a 9 assi per aggiungere orientamento e movimento al tank, oppure un circuito RTC su bus I2C per tenere traccia del tempo anche a scheda spenta. Entrambi i componenti compaiono già nella scheda target, quindi il cablaggio resta coerente con il firmware esistente.
