Ce modèle tiendra-t-il sur mon ordinateur ?
La mémoire dont un modèle a besoin, c’est la place de ses nombres, plus celle du texte qu’il lit. Un petit calcul la donne avant tout téléchargement.
C’est important, car un modèle qui ne tient pas ne démarre pas. Une mauvaise estimation fait perdre un après-midi, et parfois le prix d’une machine plus grosse.
À la fin de cette leçon
Remarque
Je peux calculer la mémoire dont un modèle a besoin.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Paramètre | un nombre que le modèle a appris | |
| Poids | tous les paramètres réunis | |
| Précision | le nombre de bits qui gardent chaque nombre | 16 bits |
| Cache | la mémoire qui garde le texte lu jusqu’ici | |
| Gigaoctet (Go) | mille millions d’octets |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Les poids sont des paramètres fois des octets
Un modèle est surtout une très longue liste de nombres. Chaque nombre est un paramètre. Chaque paramètre est gardé sur un certain nombre de bits, et 8 bits font un octet.
Les poids prennent donc les paramètres fois les octets de chacun. Un modèle de 7 milliards de paramètres sur 16 bits (2 octets) demande 14 gigaoctets pour ses poids seuls.
Modèle A, poids seulement
| Précision | Octets chacun | Poids de 7 milliards |
|---|---|---|
| 32 bits | 4 | 28 Go |
| 16 bits | 2 | 14 Go |
| 8 bits | 1 | 7 Go |
| 4 bits | 0,5 | 3,5 Go |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un long texte ajoute un cache
Pendant qu’il lit, un modèle garde des notes sur chaque jeton vu. Ces notes forment le cache. Un jeton demande 2 fois les couches, fois la largeur, fois les octets.
Pour le Modèle A, cela fait 2 x 32 x 1024 x 2 = 131 072 octets par jeton. À 8 000 jetons, le cache pèse environ 1 Go. Le cache grandit avec le texte, les poids non.
Modèle A, cache selon la longueur du texte
| Jetons dans le texte | Cache |
|---|---|
| 1 000 | 0,13 Go |
| 8 000 | 1,05 Go |
| 32 000 | 4,19 Go |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur courante
Attention
Beaucoup pensent qu’un modèle de 16 Go à télécharger demande 16 Go pour tourner. Les poids ne sont qu’une partie. Le cache grandit avec le texte, et il faut garder de la mémoire en réserve. Ajoutez le cache, puis gardez un cinquième libre.
Écrire l’assistant du modèle, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Les jetons d’une réponse, ou null si elle n’en donne pas.' 'function compter(donnees, nom) {' ' return donnees.usage && typeof donnees.usage[nom] === \"number\" ? donnees.usage[nom] : null;' '}' > model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire l’assistant du modèle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function demander(messages, echantillon, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"statut \" + res.status);' ' const d = await res.json();' ' return { texte: d.choices[0].message.content, entree: compter(d, \"prompt_tokens\"), sortie: compter(d, \"completion_tokens\"), enregistre: false };' ' } catch (erreur) {' ' console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' ' return { texte: echantillon, entree: null, sortie: null, enregistre: true };' ' }' '}' 'module.exports = { demander };' >> model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le calcul de mémoire, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const modele = { milliards: 7, couches: 32, largeurKv: 1024 };' 'const BITS = [32, 16, 8, 4];' 'function poidsGo(bits) {' ' return modele.milliards * bits / 8;' '}' > mem.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le calcul de mémoire, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function cacheGo(jetons) {' ' const parJeton = 2 * modele.couches * modele.largeurKv * 2;' ' return parJeton * jetons / 1000000000;' '}' >> mem.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le calcul de mémoire, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' console.log(\"Modèle A : 7 milliards de paramètres, cache gardé sur 16 bits\");' ' for (const bits of BITS) {' ' const total = poidsGo(bits) + cacheGo(8000);' ' console.log(bits + \" bits : poids \" + poidsGo(bits) + \" Go, total \" + total.toFixed(2) + \" Go\");' ' }' ' console.log(\"Cache pour 1000 jetons : \" + cacheGo(1000).toFixed(2) + \" Go\");' ' console.log(\"Cache pour 32000 jetons : \" + cacheGo(32000).toFixed(2) + \" Go\");' >> mem.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le calcul de mémoire, partie 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' const q = \"En une phrase courte, pourquoi un texte plus long demande-t-il plus de mémoire ?\";' ' const echantillon = \"Chaque jeton du texte s’ajoute au cache que garde le modèle : un texte plus long donne un cache plus gros.\";' ' const reponse = await demander([{ role: \"user\", content: q }], echantillon, 60);' ' console.log(\"le modèle dit : \" + reponse.texte);' '}' 'main();' >> mem.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer le calcul de mémoire
docker exec -w /home/node/project agent node mem.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Rien n’est téléchargé
Ce labo n’a pas de carte graphique et ne garde aucun fichier de modèle. Le Modèle A est inventé, et chaque taille est un calcul. Le court appel au modèle du labo ne fait que formuler une phrase.
Si aucun modèle ne répond, le Run affiche d’abord Échantillon enregistré. Les calculs restent les mêmes.
Ce que le Run affiche
| Ligne | Ce qu’elle montre |
|---|---|
| 32 bits : poids 28 Go, total 29.05 Go | La taille pleine ne tient pas sur une petite machine |
| 4 bits : poids 3.5 Go, total 4.55 Go | Moins de bits, bien moins de mémoire |
| Cache pour 32000 jetons : 4.19 Go | Un long texte coûte vraiment |
| le modèle dit : ... | Une phrase. Les mots changent à chaque Run |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.