Barato por mensaje, caro por problema
Saber si una función compensa es comparar lo que cuesta con lo que resuelve. Importa porque dos cifras de coste pueden estar muy lejos una de otra.
Una tienda de ropa en línea añade un chat. El equipo presume de que cada mensaje cuesta casi nada. La gerente pregunta otra cosa: ¿cuánto cuesta resolver el problema de una clienta?
Al final de esta lección
Nota
Puedo mostrar si una función de IA compensa lo que cuesta.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Coste por mensaje | el coste total entre todos los mensajes |
| Coste por tarea resuelta | el coste total entre las tareas resueltas |
| Resuelta | la persona obtuvo lo que necesitaba |
| Punto de partida | cómo se hacía el trabajo antes de la función |
| Coste oculto | un coste real que se deja fuera |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Dos costes que no son lo mismo
Suma todo lo que costó la función. Si divides entre el número de mensajes, sale una cifra pequeña. Si divides entre los problemas resueltos, sale la cifra que importa.
Las conversaciones sin resolver también cuestan dinero. El módulo 69 enseña a contar tokens y poner precio a una llamada. Aquí usamos esos totales.
Compara con cómo se hacía antes
Un coste solo dice poco. Compáralo con el punto de partida: ¿cuánto costaba y cuánto se tardaba antes de la función?
Cuenta los costes ocultos, como la persona que toma el relevo. Una función que parece más barata puede perder cuando se cuentan.
Un error frecuente
Advertencia
Mucha gente cree que el precio del modelo es todo el coste. Es solo una parte. Una persona que toma el relevo y una conversación sin resolver también cuestan. Divide siempre el coste total entre las tareas que de verdad se resolvieron.
Escribe el ayudante del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el ayudante del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, 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(\"estado \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el calculador de costes, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const PRICE = { inCost: 300, outCost: 1500, human: 2000000 };' 'const RUNS = [' ' { id: \"r1\", tokensIn: 1000, tokensOut: 200, resolved: true, handed: false },' ' { id: \"r2\", tokensIn: 2000, tokensOut: 500, resolved: true, handed: true },' ' { id: \"r3\", tokensIn: 1500, tokensOut: 100, resolved: false, handed: false },' ' { id: \"r4\", tokensIn: 500, tokensOut: 50, resolved: true, handed: false },' '];' > worth.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el calculador de costes, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function callCost(r) {' ' return r.tokensIn * PRICE.inCost + r.tokensOut * PRICE.outCost;' '}' 'function total() {' ' let sum = 0;' ' for (const r of RUNS) sum += callCost(r) + (r.handed ? PRICE.human : 0);' ' return sum;' '}' >> worth.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el calculador de costes, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const resolved = RUNS.filter(function (r) { return r.resolved; }).length;' ' console.log(\"total \" + total() + \" micro-euros\");' ' console.log(\"por mensaje \" + Math.floor(total() / RUNS.length));' ' console.log(\"por tarea resuelta \" + Math.floor(total() / resolved));' ' console.log(\"resueltas \" + resolved + \" de \" + RUNS.length);' ' const msg = \"Escribe una frase corta que diga que un coste por mensaje puede parecer bajo mientras el coste por problema resuelto es alto.\";' ' const reply = await ask([{ role: \"user\", content: msg }], \"Un coste bajo por mensaje puede esconder el coste de los problemas sin resolver.\", 30);' ' console.log(\"veredicto: \" + reply.text);' '}' 'main();' >> worth.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta el calculador de costes
docker exec -w /home/node/project agent node worth.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué imprime el Run
| Línea | Qué muestra |
|---|---|
| total 4775000 micro-euros | Cuatro llamadas más una persona |
| por mensaje 1193750 | Parece bajo |
| por tarea resuelta 1591666 | Más alto, porque r3 no se resolvió |
| resueltas 3 de 4 | La cifra entre la que dividimos |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.