Comment prévoir ce que coûte une fonction
Le coût d’une fonction d’IA est le nombre d’appels que vous payez fois le prix d’un appel. Un cache réduit le premier nombre, car une question répétée est servie depuis la mémoire.
Le module sur le coût, le traçage et la fiabilité montre comment faire une clé de cache et quand la faire expirer. Cette leçon va plus loin : elle compte les succès sur une semaine de trafic et prévoit un mois.
À la fin de cette leçon
Remarque
Je peux prévoir ce que coûtera une fonction et ce qu’un cache économisera.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Cache | une réserve de réponses déjà payées | |
| Succès | une requête servie depuis le cache | |
| Défaut | une requête que le cache ne sait pas servir, donc vous payez | |
| Taux de succès | le pourcentage de requêtes qui sont des succès | 50 |
| Expiration | la durée pendant laquelle une réponse stockée reste utilisable | |
| Prévision | un calcul qui annonce l’avenir d’après le passé |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Ce que coûte un appel
Un appel coûte ses jetons d’entrée fois le prix d’entrée, plus ses jetons de sortie fois le prix de sortie. La sortie coûte en général plus cher.
Pour garder des nombres entiers, comptez en unités. Une unité vaut un millionième d’euro. Les prix de cette leçon sont inventés.
Exemple détaillé : un appel
| Partie | Jetons | Prix par jeton | Unités |
|---|---|---|---|
| Entrée | 120 | 3 | 360 |
| Sortie | 80 | 15 | 1200 |
| Un appel | 200 | 1560 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur courante
Attention
Beaucoup pensent qu’un cache économise autant pour chaque fonction. Il n’économise que ce que les questions répétées permettent. Une fonction où personne ne pose deux fois la même question n’économise presque rien.
Rejouer le trafic dans un cache
Pour mesurer un taux de succès, rejouez des requêtes réelles ou tirées d’une graine. Numérotez-les depuis 0. Une requête est un succès si la même question a été stockée il y a moins de requêtes que la durée fixée.
Un succès ne renouvelle pas la réponse stockée. Elle expire sur sa propre horloge : une question populaire reçoit donc une réponse fraîche quand son temps est écoulé.
Exemple détaillé : une durée de 3
| Numéro de requête | Question | Stockée au numéro | Résultat |
|---|---|---|---|
| 0 | a | Rien | Défaut, on stocke à 0 |
| 1 | a | 0 | Succès, 1 est sous 3 |
| 2 | b | Rien | Défaut, on stocke à 2 |
| 3 | a | 0 | Défaut, 3 n’est pas sous 3, on stocke à 3 |
| 4 | a | 3 | Succès |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Prévoir un mois à partir d’une semaine
Additionnez une semaine de requêtes. Un mois fait environ 30 jours : les requêtes du mois valent la semaine fois 30, divisée par 7.
Vous ne payez que les défauts. Multipliez par 100 moins le taux de succès, divisez par 100, puis multipliez par le coût d’un appel.
Exemple détaillé : une semaine de 835 requêtes
| Étape | Calcul | Résultat |
|---|---|---|
| Total de la semaine | 120 + 135 + 150 + 160 + 170 + 60 + 40 | 835 |
| Requêtes du mois | 835 fois 30 divisé par 7 | 3578 |
| Appels payés à 50 pour cent | 3578 fois 50 divisé par 100 | 1789 |
| Coût en unités | 1789 fois 1560 | 2790840 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
É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 script de cache, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'function suivant(graine) { return (graine * 75 + 74) % 65537; }' 'const table = [0, 0, 0, 1, 1, 2, 3, 4, 5, 6];' 'function trafic(graine, nombre) {' ' const sortie = [];' ' for (let i = 0; i < nombre; i++) { graine = suivant(graine); sortie.push(\"q\" + table[graine % 10]); }' ' return sortie;' '}' > cache.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 script de cache, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function rejouer(requetes, duree) {' ' const stocke = {};' ' let succes = 0;' ' requetes.forEach(function (cle, i) {' ' if (cle in stocke && i - stocke[cle] < duree) succes = succes + 1;' ' else stocke[cle] = i;' ' });' ' return succes;' '}' 'const semaine = [120, 135, 150, 160, 170, 60, 40];' 'const parAppel = 120 * 3 + 80 * 15;' >> cache.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 script de cache, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const requetes = trafic(7, 40);' ' console.log(\"8 premières : \" + requetes.slice(0, 8).join(\" \"));' ' for (const duree of [5, 10, 20]) {' ' const succes = rejouer(requetes, duree);' ' const pour = Math.floor(succes * 100 / 40);' ' const mois = Math.floor(semaine.reduce(function (a, b) { return a + b; }, 0) * 30 / 7);' ' const payes = Math.floor(mois * (100 - pour) / 100);' ' console.log(\"durée \" + duree + \" : \" + succes + \" succès, \" + pour + \" pour cent, le mois paie \" + payes + \" appels, \" + payes * parAppel + \" unités\");' ' }' >> cache.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 script de cache, partie 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' const reponse = await demander([{ role: \"user\", content: \"En une phrase courte, pourquoi un cache peut-il rendre une fonction moins chère ?\" }], \"Une question répétée est servie depuis la mémoire, donc aucun nouvel appel n’est payé.\", 60);' ' console.log(\"le modèle dit : \" + reponse.texte);' ' console.log(\"jetons en sortie : \" + (reponse.sortie === null ? \"non fournis\" : reponse.sortie));' '}' 'main();' >> cache.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 rejeu du cache
docker exec -w /home/node/project agent node cache.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.
Ce que le Run affiche
| Ligne | Ce qu’elle montre |
|---|---|
| 8 premières : q6 q6 q0 q2 q0 q0 q5 q0 | Le trafic tiré de la graine, le même pour tous |
| durée 5 : 16 succès, 40 pour cent | Une expiration courte donne moins de succès |
| durée 20 : 27 succès, 67 pour cent | Une expiration longue donne plus de succès et une facture plus petite |
| le modèle dit : ... | Une phrase du labo. Un échantillon enregistré si aucun modèle ne répond |
| jetons en sortie : ... | Le compte que la réponse annonce, ou non fournis |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.