- Un modèle de langage de 28,9 millions de paramètres tourne sur un ESP32-S3 sans connexion à un serveur et affiche du texte sur un petit écran à environ 9 tokens par seconde
- Il utilise une architecture Per-Layer Embeddings : 25 millions des paramètres sont placés dans une mémoire flash lente, et seuls environ 6 lignes nécessaires par token, soit 450 octets, sont lues
- Le modèle fait 14,9 Mo en 4 bits ; le cœur de calcul utilisé à chaque token est placé dans 512 Ko de SRAM, la tête de sortie et la mémoire de travail dans 8 Mo de PSRAM, et la grande table d’embeddings dans 16 Mo de flash
- Entraîné sur TinyStories, il génère des histoires courtes et simples généralement cohérentes, mais n’est pas adapté aux questions-réponses, à l’exécution d’instructions, à l’écriture de code ni aux connaissances factuelles
- Il embarque environ 100 fois plus de paramètres qu’un modèle à 260 000 paramètres précédemment exécuté sur une puce similaire ; l’enjeu principal est moins la qualité de génération que l’architecture mémoire permettant de faire tenir un grand modèle sur une petite puce
Matériel et performances d’exécution
- Tout le traitement est effectué sur un seul ESP32-S3 d’environ 8 dollars, sans envoyer de données à un serveur
- Utilise 512 Ko de SRAM, 8 Mo de PSRAM et 16 Mo de flash
- Le débit global est d’environ 9,5 tok/s, et la vitesse de calcul pure d’environ 9,7 tok/s
- La taille du modèle 4 bits est de 14,9 Mo
- Sur un total de 28,9 millions de paramètres, 25 millions sont stockés dans une table de consultation en flash
Comment faire tenir le modèle dans une petite mémoire
- En général, l’ensemble du modèle doit être accessible depuis une mémoire rapide, mais la SRAM de l’ESP32-S3 ne fait que 512 Ko, ce qui ne permet d’accueillir que de très petits modèles
- Le projet exploite le fait que la plupart des paramètres se trouvent dans une table d’embeddings plutôt que dans la partie réellement calculée, et laisse cette table en flash
- À chaque token, seules environ 6 lignes nécessaires, soit environ 450 octets, sont lues
- Seule la petite partie chargée du calcul effectif est maintenue en mémoire rapide
- La majeure partie du modèle n’est pas chargée à l’exécution ; seules les parties nécessaires sont sélectionnées depuis la flash
- Les rôles mémoire sont répartis ainsi
- SRAM : cœur de calcul utilisé pour tous les tokens
- PSRAM : tête de sortie et mémoire de travail
- Flash : table de 25 millions de paramètres
Application des Per-Layer Embeddings
- Les Per-Layer Embeddings utilisés dans Gemma 3n et Gemma 4 de Google sont appliqués non pas à un téléphone ou à un GPU, mais à l’architecture mémoire d’un microcontrôleur
- D’après les vérifications du créateur du projet, il n’existe pas de précédent d’application de cette méthode à une puce aussi petite
Ce que le modèle peut faire, et ses limites
- Entraîné sur les courtes histoires synthétiques de TinyStories, il génère des histoires simples et conserve généralement une certaine cohérence
- Il ne sait pas répondre à des questions, exécuter des instructions, écrire du code ni fournir des connaissances factuelles
- Cette limite vient du petit cœur chargé de l’inférence, et la technique de placement mémoire n’améliore pas en soi les capacités de raisonnement
Code et données expérimentales
firmware/esp32_llm/README.mdcontient le firmware, le câblage et la procédure de flashagesrc/etexperiments/contiennent le code d’entraînement, d’ablation et de quantificationRESULTS.mdrécapitule la méthode complète, les expériences d’ablation et les mesures sur puce
Projets de base et historique
- TinyStories est un jeu de données de courtes histoires synthétiques conçu pour permettre même à de petits modèles d’apprendre à écrire de manière cohérente
- Les Per-Layer Embeddings de Google Gemma servent de base pour faire tenir un grand modèle sur une petite puce
- llama2.c d’Andrej Karpathy a influencé l’approche consistant à entraîner de petits modèles de langage et à les exécuter en C pur
- Le dépôt conserve aussi une erreur de calcul qui avait initialement gonflé le nombre de paramètres, ainsi que le processus de correction
- L’historique des commits et
RESULTS.mdpermettent de voir où les chiffres ont changé et pourquoi
- L’historique des commits et
1 commentaires
Commentaires sur Hacker News
Ce qu’on peut faire aujourd’hui avec des microcontrôleurs à 5 dollars est assez stupéfiant. Parmi les cartes Milk-V, la Duo dispose de jusqu’à 256 Mo de mémoire, d’un TPU 1TOPS@INT8, et peut même faire tourner Linux, donc j’en ai acheté cinq
GCC et Clang prennent entièrement en charge xTHeadVector, et avec les fonctions intrinsèques C, c’est compatible avec RVV 1.0 via de simples options en ligne de commande. Une grande partie du code manipulant des éléments 8 bits, comme
memcpy(),memset(),memcmp(),strlen(),strcpy()etstrcmp(), est compatible au niveau binaireQuand j’ai acheté la Duo 64 Mo, elle coûtait 3 dollars, puis les modèles 64 Mo, 256 Mo et 512 Mo étaient respectivement à 5, 7 et 10 dollars, mais les prix ont fortement augmenté cette année : https://arace.tech/products/milk-v-duo, https://arace.tech/products/milkv-duo-s
Il reste bien sûr des usages où un PIC de 4 Ko est la meilleure option, mais dans la plupart des cas, il ne faut pas agir comme s’il n’existait pas de meilleures alternatives
Les modèles de conversion voix-texte se rapprochent aussi de cette taille, et je me demande à quel point nous sommes proches de petits appareils capables de converser avec nous. On pourrait finir dans un monde où une brosse à dents donne des conseils d’hygiène bucco-dentaire, voire diffuse des pubs pour du dentifrice
En revanche, je ne veux pas vivre dans un monde où il faut aussi chercher un bloqueur de pub pour l’IA de sa brosse à dents
La technique d’embedding par couche a été utilisée de façon très astucieuse. Il existe aussi des modèles TTS pratiques d’environ 20 à 30 millions de paramètres, donc un ESP32 non connecté au réseau pourrait presque lire un texte à voix haute en temps réel
La PSRAM, la flash et les cartes SD n’ont pas individuellement une bande passante très élevée, mais en en pilotant plusieurs en parallèle, on peut atteindre un débit appréciable. Un matériel spécialisé de grande taille restera en tête en performance par watt, mais ce type de configuration reste attractif grâce à son faible coût initial et à sa montée en charge progressive
Au-delà des microcontrôleurs, je me demande quelle serait une option réaliste pour qu’un LLM local sur Raspberry Pi 4 ne mette pas 30 secondes à répondre
Faire tourner un LLM sur un appareil minuscule est impressionnant, mais je trouve encore plus marquante la méthode d’entraînement qui a produit ces poids
Je me demande si, avec de bons schémas d’accès, on ne pourrait pas exploiter la flash pour étendre cette approche à l’exécution de modèles bien plus grands sur CPU
L’ESP32-S3 est assez puissant, au point que je l’utilise actuellement pour du développement sur Raspberry Pi 4. L’un de ses deux ports USB prend en charge l’OTG, ce qui permet d’implémenter des fonctions qui coûteraient autrement plus de 100 dollars
Cela fonctionne actuellement avec tinyusb et pico-pio-usb, et j’expérimente aussi un portage Rust dans l’espoir d’obtenir de meilleures performances
Je me demande quel est le niveau de précision de ce modèle quantifié
Les performances à cette taille sont impressionnantes, et j’ai hâte de voir jusqu’où on peut aller sur les ordinateurs monocartes un peu plus puissants mentionnés dans le fil