28.9M 參數塞入 ESP32-S3:拆開 14.9MB 離線故事模型
3C 產品

28.9M 參數塞入 ESP32-S3:拆開 14.9MB 離線故事模型

圖片:via XDA Developers — https://www.xda-developers.com/someone-squeezed-a-289m-llm-onto-an-esp32-s3-and-so-can-you/
TechLab 編輯部(譯)·

靠 4-bit、flash 同 PLE 慳 RAM,但能力離 chatbot 好遠

有人成功喺 ESP32-S3 跑一個 28.9M 參數、14.9MB 嘅文字生成模型,仲可以完全離線逐個 token 寫英文故事。個數字望落幾誇張,不過拆開架構就會發現,佢冇將 28.9M 參數全部當成運算核心。大量容量其實係一張放喺 flash 嘅查表,真正每步都要落力計算嗰部分細好多。

28.9M 參數唔代表有 28.9M 參數嘅「腦」

呢個模型有 6 層、hidden size 96、4 個 attention heads,同埋 32,768 token 嘅詞彙表。項目作者嘅拆法係:大約 559K 參數屬於 dense core、約 3.1M 參數係輸入 embedding 同輸出 head,另外約 25M 參數就放喺 Per-Layer Embeddings 表。換句話講,模型做到幾多,主要受嗰 559K dense core 限制;總參數數目唔代表佢有幾接近 ChatGPT。

模型用 TinyStories dataset 訓練,入面係用幼兒程度詞彙寫成嘅合成英文短篇。呢類資料專門畀細模型學文法、人物同簡單情節,所以輸出睇落可以幾順,亦有機會記得故事角色;但呢種連貫唔等於具備廣泛知識。項目程式而家只會由寫死咗嘅 Once upon a time token 開始,greedy 生成 200 個 token,未有互動 tokenizer 或對話輸入。

項目示範動畫,畫面逐個 token 顯示 ESP32-S3 生成嘅英文故事

圖片:slvDev/esp32-ai

4-bit 點樣將模型壓入 16MB flash

項目用 group-wise symmetric int4 PTQ,每個權重只佔 4 bit,兩個權重可以塞入一個 byte;每組 128 個權重另存 fp16 scale,最後再用 ragged row 避免補位浪費。28.9M 個 4-bit 權重本身約佔 14.45MB,加埋 scales、norm 同格式資料,作者匯出嘅 model.bin14,912,332 bytes,放入 15,597,568-byte 自訂 partition 後剩返 685,236 bytes。

作者用兩個 seed 比較後話,量化會令所有版本嘅 perplexity 變差,不過 PLE 相對普通 baseline 嘅優勢仍然保留。呢批訓練、量化同 perplexity 數字全部出自項目作者,暫時未見第三方完整重跑。佢至少有公開訓練、量化、C runtime 同 host verifier,其他人有條件逐項核對,但現階段未適合當成獨立驗證過嘅 benchmark。

Espressif ESP32-S3-DevKitC-1 開發板產品圖

圖片:Espressif

Flash 查表先係今次最值得拆嘅部分

PLE 會為每個 token、每一層 decoder 準備另一組細 embedding。呢個模型大致係 32,768 token × 6 層 × 128 維,合計約 25M 參數。生成一個 token 時,每層只查相應嗰一行,所以每步大約讀 6 行、約 450 bytes,餘下成張表繼續留喺 memory-mapped flash。正確講法係 25M 參數查表,行數遠少過 25M。

概念源自 Google Gemma 3n 嘅 PLE:大型 embedding 可以放喺較慢儲存空間,逐層取出而家 token 用到嘅資料,再加落 transformer 狀態。搬到 ESP32-S3 後,flash 就變成容量大但慢嘅參數層。作者量到 6 次 flash random read 約花 0.12ms;完整 PLE path 每個 token 約 8.5ms,仍然快過掃描輸出 head 嘅 57.6ms。呢啲同樣係作者喺指定開發板量到嘅結果。

Google 圖解 Gemma 3n 總參數、有效參數同 PLE 分配方式

圖片:Google

PSRAM 負責接住輸出 head 同工作記憶體

14.9MB 模型會一直映射喺 flash,開機後程式就將量化輸出 head 解成 int8,約 2.53MB,放入 PSRAM;scratch buffers、logits 同 KV cache 亦用 PSRAM,配置完成後作者話仲有約 5.1MB 可用。559K dense core 設計上可以 4-bit 壓到約 273KB,但現有 firmware 實際仍然留佢喺 flash XIP,因為作者量到咁做已經夠快。呢點同「整個核心塞入 SRAM」嘅簡化講法有少少出入。

作者話,int8-staged head 配合 ESP32-S3 雙核心後,整體生成速度約 9.5 tok/s;淨計模型運算,每個 token 要 102.9ms,即 9.72 tok/s。速度睇落唔差,不過佢只跑固定 TinyStories 生成,冇 prompt prefill、對話管理、搜尋、工具調用同事實問答。項目作者自己亦講明,模型唔識答問題、跟指示、寫程式或者處理算術,定位係架構 proof of concept。

想跟住整,先睇清楚塊板

硬件要揀 16MB flash 加 8MB OPI PSRAM 嘅 ESP32-S3;Espressif 官方 DevKitC-1 對應型號係 N16R8V。常見 N8R8 雖然同樣有 8MB PSRAM,但 flash 只有 8MB,裝唔落 14.9MB 模型。淨睇商品標題寫「ESP32-S3」都唔夠,落單前要核對 module 絲印同 flash/PSRAM 容量。顯示屏可以唔裝;想跟原方案就可用 SH1106 或 SSD1306 I2C OLED,接 GPIO46 做 SCL、GPIO18 做 SDA。

軟件方面,先準備 Python 3.12、uv、Arduino CLI、esptool 同 Arduino ESP32 core 3.3.10。clone 項目後用 data/prepare.py --vocab 32768 準備 TinyStories,再照 clean_confirm.sh 入面嘅 deploy 參數訓練 PLE checkpoint,跟住跑 src/export.py 產生 model.bin 同 golden reference。先用 repo 嘅 host verifier 對 logits,確認 C runtime 同 PyTorch 對得上,最後先編譯 firmware、燒 app,再由 flash 地址 0x110000 寫入模型。

呢個 DIY 暫時未算插線即玩:repo 喺報道刊出時冇附上預訓練 checkpoint、model.bin 或正式 release,使用者要自行訓練同匯出;訓練時間亦會跟電腦硬件相差好遠。只想睇 serial output,可以將 USE_DISPLAY 設成 0,慳返 OLED library 同接線。玩開 Arduino、IoT 或機械人嘅人,最實用嘅收穫係點樣分配 flash、PSRAM 同 SRAM;下一步就睇有冇人獨立重跑,同項目會唔會補回可直接燒錄嘅模型檔。


參考來源

本文根據原文及公開資料整理;資料有出入時,以原文及官方資料為準。

分享:WhatsAppThreadsTelegramFacebook