验证廉价硬件部署轻量级语言模型的可行性,为 IoT 和边缘计算 AI 应用开辟新方向。
微控制器只有很少的快速内存。ESP32-S3 提供 512KB 的 SRAM。通常整个模型必须可以从那里访问,这使你被限制只能用极小的模型,这就是为什么之前在这样的芯片上的模型只有 26 万个参数。
解决办法是完全停止将模型放在快速内存中。语言模型的大部分参数存储在嵌入表中,模型从中读取而不是计算。因此你可以将那个 2500 万行的表留在速度较慢的闪存中,每个 token 只提取需要的少数几行,大约 450 字节,而做实际工作的小部分保持在快速内存中。然后大模型运行的成本几乎为零,因为你永远不会加载它的大部分。它只是存放在闪存中,每次只被采样一点点。
这个想法是 Google 的 Per-Layer Embeddings,来自 Gemma 3n 和 Gemma 4。这里它运行在微控制器的内存布局上,而不是手机或 GPU。据我所知,没有人在这么小的芯片上尝试过。
SRAM (fast, tiny) the "thinking" core, used on every token
PSRAM (medium) the output head and working memory
FLASH (huge, slow) the 25M-param table, about 6 rows read per token (~450 B)
这个模型在 TinyStories 上训练,所以它写简短的、简单的故事,大多数时候保持连贯。它不会回答问题、遵循指令、编写代码或了解事实。这个限制来自做推理的模型的小部分,内存技巧不会改变这一点。这里有趣的是架构,将大模型放在小芯片上,而不是 2890 万参数的模型能说什么。
固件、接线和刷写步骤在 firmware/esp32_llm/README.md 中。训练、消融和量化代码在 src/ 和 experiments/ 中。完整的方法、消融实验和片上测量在 RESULTS.md 中记录。
TinyStories 是训练数据集:简短的合成故事,足够简单,使得小模型仍然可以学会连贯地写作(Ronen Eldan 和 Yuanzhi Li,微软研究院,arXiv:2305.07759)。另一半是 Per-Layer Embeddings,Google 从 Gemma 模型中的设计,这就是让大模型能够放在小芯片上的原因。
Andrej Karpathy 的 llama2.c 是为什么很多人(包括我)相信你可以训练一个微小的语言模型并在普通 C 中运行它。这是由此发展而来的。
我故意在仓库中保留了混乱的历史。这包括我在自己的参数计数中发现的一个 bug,它夸大了早期的数字,以及我修复后得到的更正结果。提交历史和 RESULTS.md 显示数字在哪里移动了以及为什么。