Bon marché par message, cher par problème
Un magasin ajoute une fonction de discussion. L’équipe annonce fièrement que chaque message coûte presque rien. La directrice pose une autre question : combien coûte la résolution d’un problème de client ?
Les deux chiffres peuvent être très éloignés. Montrer qu’une fonction vaut son coût, c’est choisir le bon.
À la fin de cette leçon
Remarque
Je peux montrer si une fonction d’IA vaut ce qu’elle coûte.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Coût par message | le coût total divisé par tous les messages |
| Coût par tâche résolue | le coût total divisé par les tâches réglées |
| Résolue | la personne a eu ce qu’il lui fallait |
| Référence | la façon de faire le travail avant la fonction |
| Coût caché | un coût réel qu’on laisse de côté |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Deux coûts qui ne sont pas les mêmes
Additionnez tout ce que la fonction a coûté. Divisez par le nombre de messages : vous obtenez un petit nombre. Divisez par le nombre de problèmes résolus : vous obtenez celui qui compte.
Les discussions non résolues coûtent aussi de l’argent. Le module 69 montre comment compter les jetons et chiffrer un appel. Ici, on reprend ces totaux.
Comparez avec la façon de faire d’avant
Un coût seul dit peu. Comparez-le avec la référence : combien coûtait le travail, et combien de temps prenait-il, avant la fonction ?
Comptez les coûts cachés, comme la personne qui prend le relais. Une fonction qui semble moins chère peut perdre une fois qu’on les compte.
Une erreur courante
Attention
Beaucoup pensent que le prix du modèle est tout le coût. Ce n’en est qu’une part. Une personne qui prend le relais et une discussion non résolue coûtent aussi. Divisez toujours le coût complet par les tâches vraiment résolues.
É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 calculateur de coût, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const PRIX = { entree: 300, sortie: 1500, humain: 2000000 };' 'const ECHANGES = [' ' { id: \"r1\", jetonsEntree: 1000, jetonsSortie: 200, resolu: true, relais: false },' ' { id: \"r2\", jetonsEntree: 2000, jetonsSortie: 500, resolu: true, relais: true },' ' { id: \"r3\", jetonsEntree: 1500, jetonsSortie: 100, resolu: false, relais: false },' ' { id: \"r4\", jetonsEntree: 500, jetonsSortie: 50, resolu: true, relais: false },' '];' > cout.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 calculateur de coût, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function coutAppel(e) {' ' return e.jetonsEntree * PRIX.entree + e.jetonsSortie * PRIX.sortie;' '}' 'function total() {' ' let somme = 0;' ' for (const e of ECHANGES) somme += coutAppel(e) + (e.relais ? PRIX.humain : 0);' ' return somme;' '}' >> cout.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 calculateur de coût, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const resolus = ECHANGES.filter(function (e) { return e.resolu; }).length;' ' console.log(\"total \" + total() + \" micro-centimes\");' ' console.log(\"par message \" + Math.floor(total() / ECHANGES.length));' ' console.log(\"par résolu \" + Math.floor(total() / resolus));' ' console.log(\"résolus \" + resolus + \" sur \" + ECHANGES.length);' ' const q = \"Écrivez une seule ligne courte qui dit qu’un coût par message peut sembler bas alors que le coût par problème résolu est élevé.\";' ' const reponse = await demander([{ role: \"user\", content: q }], \"Un coût par message bas peut cacher le coût des problèmes non résolus.\", 30);' ' console.log(\"verdict : \" + reponse.texte);' '}' 'main();' >> cout.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 calculateur de coût
docker exec -w /home/node/project agent node cout.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 |
|---|---|
| total 4775000 micro-centimes | Quatre appels plus une personne |
| par message 1193750 | Semble bas |
| par résolu 1591666 | Plus haut, car r3 n’a pas été résolu |
| résolus 3 sur 4 | Le nombre par lequel on divise |
| verdict : ... | Une phrase. Les mots changent à chaque Run |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.