¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Presupuesto y coste en tokens de un LLM

Después de esta lección: Puedo impedir que una función gaste de más, con un límite por usuario, un límite diario y un mensaje claro.

Lección de 60 min8 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Evita que una función gaste de más

Un presupuesto para una función con modelo convierte los tokens en dinero y rechaza la llamada que pasaría un límite. Importa porque el coste crece con el uso. Un usuario muy activo o un bucle pueden gastar un mes de presupuesto en una tarde.

Un modelo se factura por token y nadie ve la factura hasta fin de mes. Un límite en tu propio código es el único freno que actúa al instante.

Al final de esta lección

Nota

Puedo impedir que una función gaste de más, con un límite por usuario, un límite diario y un mensaje claro.

Palabras clave

PalabraQué significa
Tokenla unidad que un modelo lee y escribe, y en la que se factura
Lista de preciosel coste de un millón de tokens, de entrada y de salida
Límite por usuariolo máximo que una cuenta puede gastar en un día
Límite diariolo máximo que toda la función puede gastar en un día
Libro de cuentasel registro corriente de lo gastado
Rechazodevolver una llamada, con un motivo

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Convierte tokens en dinero

Un modelo tiene dos precios: uno para los tokens de entrada y otro para los de salida, normalmente por millón. Una llamada cuesta los tokens de entrada por el primer precio más los de salida por el segundo.

No uses decimales para el dinero. Cuenta en una unidad pequeña y entera. Aquí, euros por millón de tokens significa que cada token cuesta esos microeuros, así que las cuentas son enteras. Los precios de esta lección son inventados.

Ejemplo resuelto: dos llamadas

ModeloEntradaSalidaCuentaCoste
small, precios 1 y 4900300900 x 1 + 300 x 42100 microeuros
large, precios 10 y 40200100200 x 10 + 100 x 406000 microeuros

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Comprueba un límite antes de cobrar

Lleva un libro de cuentas: el total de cada usuario y el total del día. Antes de cobrar una llamada, compruébala. Recházala si lleva al usuario por encima de su límite, o al día por encima del suyo. Un total justo en el límite se permite.

Pregunta primero por el límite del usuario, porque su mensaje es más útil. Una llamada rechazada no se cobra. Y el rechazo dice por qué, con palabras que una persona pueda seguir.

Un error frecuente

Advertencia

Mucha gente cree que un límite solo sirve contra el abuso, y lo pone después del lanzamiento. Los costes también suben por un fallo, como un bucle de reintentos o un prompt largo enviado a todos. Fija los dos límites antes de que llegue el primer usuario.

Escribe el ayudante del modelo, parte 1

Comando
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

Comando
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 presupuesto, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' '// Una lista de precios inventada: euros por millón de tokens. Tokens por precio = microeuros.' 'const PRICE = { small: { in: 1, out: 4 }, large: { in: 10, out: 40 } };' 'const USER_LIMIT = 5000; // microeuros para un usuario en un día' 'const DAY_LIMIT = 8000; // microeuros para todos en un día' 'const spent = { user: new Map(), day: 0 };' 'function cost(model, inTokens, outTokens) {' '  return inTokens * PRICE[model].in + outTokens * PRICE[model].out;' '}' > budget3.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 presupuesto, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function check(user, price) {' '  const mine = spent.user.get(user) || 0;' '  if (mine + price > USER_LIMIT) return \"user\";' '  if (spent.day + price > DAY_LIMIT) return \"day\";' '  return \"ok\";' '}' 'function charge(user, price) {' '  spent.user.set(user, (spent.user.get(user) || 0) + price);' '  spent.day = spent.day + price;' '}' >> budget3.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 presupuesto, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function message(why, user) {' '  if (why === \"user\") return \"Hola \" + user + \", esta llamada te haría pasar tu cupo de hoy. Se renueva a medianoche.\";' '  return \"El asistente ha llegado a su límite diario para todos. Inténtalo mañana.\";' '}' 'async function demo() {' '  const prompt = \"Saluda en cinco palabras.\";' '  const reply = await ask([{ role: \"user\", content: prompt }], \"Hola, ¿en qué puedo ayudarte?\", 20);' '  const inT = reply.inTokens === null ? Math.ceil(prompt.length / 4) : reply.inTokens;' '  const outT = reply.outTokens === null ? Math.ceil(reply.text.length / 4) : reply.outTokens;' '  const how = reply.inTokens === null ? \"estimados\" : \"contados\";' '  console.log(\"Tu llamada: \" + inT + \" de entrada, \" + outT + \" de salida (\" + how + \"), \" + cost(\"small\", inT, outT) + \" microeuros\");' '}' >> budget3.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 presupuesto, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const calls = [' '  { user: \"lucia\", model: \"small\", in: 900, out: 300 },' '  { user: \"mateo\", model: \"small\", in: 1000, out: 500 },' '  { user: \"lucia\", model: \"large\", in: 200, out: 100 },' '  { user: \"carmen\", model: \"large\", in: 300, out: 50 },' '  { user: \"carmen\", model: \"small\", in: 500, out: 100 },' '  { user: \"pablo\", model: \"large\", in: 200, out: 50 },' '];' >> budget3.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 presupuesto, parte 5

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  await demo();' '  calls.forEach(function (c, at) {' '    const price = cost(c.model, c.in, c.out);' '    const why = check(c.user, price);' '    const label = \"#\" + (at + 1) + \" \" + c.user + \" \" + c.model + \" \" + price + \" microeuros: \";' '    if (why === \"ok\") { charge(c.user, price); console.log(label + \"ok\"); }' '    else console.log(label + message(why, c.user));' '  });' '  console.log(\"Gastado hoy: \" + spent.day + \" microeuros = \" + (spent.day / 1000000).toFixed(6) + \" euros\");' '}' 'main();' >> budget3.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 presupuesto

Comando
docker exec -w /home/node/project agent node budget3.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una salida posible

LíneaQué muestra
Tu llamada: 42 de entrada, 17 de salida (contados)...Tu propia llamada. Contada si la respuesta trae uso, estimada si no. Cambia en cada Run
#1 lucia small 2100 microeuros: okCobrada
#3 lucia large 6000 microeuros: Hola lucia...Rechazada por el límite del usuario, con un mensaje
#4 carmen large 5000 microeuros: El asistente...Rechazada por el límite diario
Gastado hoy: 6000 microeuros = 0.006000 eurosSolo cuentan las llamadas cobradas

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.