- 1 - Con un modelo local no pagas euros, pagas vatios.
- 2 - Qué se mide y qué no.
- 3 - Y la columna no se puede sumar.
- 4 - El hallazgo: el rendimiento no predice el consumo.
- 5 - Cargar el modelo es medio tiempo y una décima parte de la energía.
- 6 - El fallo silencioso que casi nos pasa por encima.
- 7 - Cuándo esto te sirve.
- 8 - Cómo se activa.
- 9 - Los límites, dichos antes de que los descubras tú.
- 10 - Un efecto lateral muy útil.
Con un modelo local no pagas euros, pagas vatios.
Hay una respuesta muy repetida cuando alguien se queja de lo que le cuesta un agente: móntalo en local y deja de pagar.
Es cierto a medias. Dejas de pagar al proveedor. No dejas de pagar.
Cuando el modelo corre en tu máquina, estimate_cost_usd devuelve null, porque efectivamente nadie te está facturando. Pero el coste no ha desaparecido: se ha transformado. Ahora lo pagas en vatios, en calor, en tiempo de tu propia GPU y en la vida útil de un hardware que compraste tú.
Y eso también se puede medir.
Qué se mide y qué no.
Con un modelo local, OxideGate publica cuatro campos por petición:
| Campo | Qué es |
|---|---|
energy_wh | Energía bruta consumida durante la ventana de la petición |
energy_idle_wh | El reposo de esa misma ventana, publicado aparte |
power_peak_w | Pico de potencia alcanzado |
energy_samples | Cuántas muestras sostienen el número |
En el panel de terminal aparece como una columna, Wh_net, justo al lado de la de dólares. Medido sobre un modelo de 7.000 millones de parámetros ya caliente: 79,1 mWh por 200 tokens.
Fíjate en un detalle de diseño que dice bastante del proyecto: el reposo se publica al lado, no restado.
La tentación es obvia. Restas el idle de la bruta y das un número limpio de “energía neta de esta petición”. Queda mucho mejor en una tabla. Pero la atribución no es limpia —tu GPU estaba haciendo otras cosas, el reposo no es constante, la ventana no empieza y acaba donde tú crees— y un número ya cocinado fingiría una precisión que no existe.
Así que salen los dos, y resta quien quiera restar, sabiendo lo que está haciendo.
Y la columna no se puede sumar.
Esta es la limitación que más nos costó aceptar, y está fijada en un test para que nadie la rompa por accidente.
El campo dice “lo que gastó la máquina mientras esta petición estuvo abierta”. No dice “lo que costó esta petición”. Y la diferencia importa en cuanto hay concurrencia: dos peticiones solapadas reclaman los mismos vatios. Sumar la columna cuenta esa energía dos veces.
Repartirla entre peticiones solapadas es imposible con los datos que se pueden capturar desde fuera. No es un pendiente: es un no se puede, declarado como tal, con su leyenda en el propio panel.
Podríamos haber inventado un reparto proporcional al tiempo. Habría sido plausible, habría quedado bien y habría sido falso.
El hallazgo: el rendimiento no predice el consumo.
Aquí está el número que hizo que este capítulo mereciera existir.
Comparamos dos modelos locales a través del proxy, mismo prompt y con el número de tokens a generar fijado para igualar la carga:
| Velocidad | Energía | |
|---|---|---|
| Modelo de 3B frente al de 7B | 1,82× más rápido | 2,89× más barato |
Los dos números no coinciden. Y esa discrepancia es justamente el resultado.
Si hubieras estimado el ahorro de energía a partir de la velocidad —que es lo que hace todo el mundo, porque es lo único que se ve— habrías dicho “ahorra 1,8 veces”. La realidad es 2,89. Te habrías equivocado en un 60%.
El motivo es que son dos factores independientes multiplicándose: el modelo pequeño tarda 1,72× menos y además dibuja 1,68× menos potencia mientras tanto. Menos tiempo por menos vatios.
La conclusión práctica: los tokens por segundo no son un proxy del consumo energético. Si te importa la energía, mídela. No la deduzcas del rendimiento.
Cargar el modelo es medio tiempo y una décima parte de la energía.
El segundo hallazgo salió de una decisión técnica que parecía menor: soportar el dialecto nativo de Ollama, y no solo su endpoint compatible con OpenAI.
El endpoint compatible publica contadores de tokens y tira el reparto interno del tiempo. El dialecto nativo publica tres campos que ese otro pierde: tiempo de carga, tiempo de evaluación del prompt y tiempo de generación.
Con esos tres campos, medimos una petición fría:
Carga del modelo ████████████████████████████ 54% del tiempo
███ 11% de la energía
43 W de media
Generación ████████████████████████ 46% del tiempo
█████████████████████████ 89% de la energía
~189 W de media
Cargar mueve memoria. No calcula. Por eso ocupa más de la mitad del reloj y apenas una décima parte de los vatios.
Y esa distancia entre tiempo y energía es, otra vez, la razón de que una de las dos cifras no sirva para deducir la otra.
Una nota de honestidad: esta medición corrigió una afirmación anterior de este mismo proyecto, que decía que cargar costaba 2,5 veces más. Estaba mal. Se retractó, se documentó la retractación y el número nuevo lleva la medición que lo sostiene. Un proyecto de medición que no retracta sus propios errores no está midiendo, está defendiendo una posición.
El fallo silencioso que casi nos pasa por encima.
Merece la pena contarlo porque es la clase de error que no da la cara.
El escáner que lee las respuestas en streaming exigía el prefijo data: en cada línea, porque es lo que hace el formato de eventos servidor que usan los proveedores remotos.
El dialecto nativo de Ollama no usa ese formato: usa NDJSON, un objeto JSON por línea, sin prefijo.
Contra ese dialecto, el escáner habría publicado cero tokens, en silencio. Sin error, sin aviso, sin nada raro en el panel. Una columna de ceros que parecería un modelo que no responde en lugar de un medidor que no sabe leer.
Es el mismo principio que atraviesa todo el proyecto, esta vez en su versión más incómoda: un cero y un dato ausente no son lo mismo, y confundirlos es peor que no medir, porque un cero se cree.
Cuándo esto te sirve.
Escenarios concretos donde medir energía cambia una decisión:
- Elegir tamaño de modelo para una tarea repetitiva. Si vas a correr miles de inferencias, la diferencia entre un 3B y un 7B no es solo velocidad. Mide las dos cosas.
- Decidir entre local y API. La comparación honesta no es “gratis contra de pago”: es tu coste eléctrico y tu amortización de hardware contra la factura del proveedor. Ahora tienes el primer término.
- Dimensionar hardware. El panel de potencia en vivo enseña vatios, uso de GPU, temperatura y VRAM, con la aguja sobre el límite de la tarjeta, y con reposo y pico juntos. Sin el reposo no puedes restar nada; sin el pico, un número de vatios no te dice si vas holgado.
- Justificar una decisión de infraestructura. Un número medido de tu propia máquina pesa más en una conversación que una tabla de un fabricante.
Cómo se activa.
El muestreo de potencia se enciende solo si detecta nvidia-smi. Se apaga con:
OXIDEGATE_POWER_SAMPLING=off
Y cuando está apagado, energy_wh pasa a null. No a cero.
Para dirigir el tráfico al motor local:
OXIDEGATE_OLLAMA_API_BASE=http://127.0.0.1:11434
Las rutas del dialecto nativo, que son las que publican el reparto de tiempo y la energía, son POST /api/generate y POST /api/chat.
Los límites, dichos antes de que los descubras tú.
- Solo Linux con NVIDIA. El muestreo va contra
nvidia-smi. RAPL para la CPU no está. En macOS,powermetricstampoco. Se declara en vez de dejar que el campo salganullsin que nadie sepa por qué. - Solo con upstream local. Con un proveedor remoto el campo es
nulla propósito: muestrear tu GPU mientras responde un servidor a miles de kilómetros mide el consumo de tu escritorio, no el de la petición. - Solo energía de GPU. La CPU consume mientras tanto y no está contada.
- Nunca euros. El precio del kWh lo pone quien lee, no el medidor. Las tarifas eléctricas varían por país, por contrato y por hora del día.
Un efecto lateral muy útil.
Y termino con algo que no era el objetivo y resultó ser de lo más práctico del proyecto.
Si puedes medir contra un modelo local, puedes medir el peaje de un harness sin gastar cuota de nadie.
El bloque de instrucciones, los esquemas de herramientas y el listado de skills los inyecta el harness, no el modelo. Medir esa petición contra un modelo pequeño en local mide exactamente lo mismo que medirla contra uno de pago.
Sin cuenta. Sin red. Sin gastar un céntimo. Y reproducible por cualquiera que quiera comprobar los números de los capítulos anteriores en su propia máquina.
Eso convierte un banco de pruebas caro en uno gratuito, y es la diferencia entre “confía en mis números” y “compruébalos tú”.
En el siguiente capítulo dejamos el proxy y pasamos a la primera lente que lee sus datos: cuánto pesa exactamente cada servidor MCP en cada una de tus peticiones.
¿Listo para hacer crecer tu negocio?
Analicemos tu proyecto y definamos la estrategia perfecta para alcanzar tus objetivos
Solicitar consultoría gratuita