BookinglyTech News
Inteligencia artificial

Ollama descarga el modelo a los cinco minutos y tu cron paga la recarga en frío

Un desarrollador instrumentó 1.180 peticiones durante 24 horas y encontró 214 cargas de modelo. El keep_alive por defecto son cinco minutos, y no siempre funciona como dice la documentación.

3 min de lecturaDev.to0 vistas

Ollama trae un valor por defecto que no aparece en ninguna demo: si pasan cinco minutos sin tráfico, el runner se apaga y los pesos del modelo salen de la VRAM. La siguiente petición los vuelve a leer de disco, reasigna memoria y solo entonces empieza a generar. Un desarrollador puso un cronómetro a cada petición durante 24 horas y le salieron 1.180 peticiones con 214 cargas de modelo. El primer token tardaba 11,4 segundos en frío contra 0,9 en caliente.

Su montaje: una máquina con 16 GB de VRAM y los modelos en NVMe. llama3.1:8b para chat (unos 4,9 GB), qwen2.5-coder:14b como ayudante de código (unos 9 GB) y nomic-embed-text para embeddings (274 MB). Tres clientes: una interfaz de chat manual, un cron que resume notas cada diez minutos y un indexador RAG. Ese cron es la clave: se dispara cada diez minutos contra un timeout de cinco. Nunca, ni una sola vez, encontró el modelo caliente.

El 18,1% de las peticiones eran frías, y eso arrastró la mediana hasta los 3,1 segundos. El histograma de tiempos al primer token no era una campana: eran dos picos, uno en 0,9 y otro en 11,4, sin nada en medio. Cuando la distribución tiene esa forma, el problema no es un modelo lento, es un estado binario: cargado o no cargado.

Dos formas de que keep_alive no haga nada

La primera trampa está en el endpoint compatible con OpenAI. Pasar keep_alive en el cuerpo de la petición a /v1/chat/completions no tuvo ningún efecto en su versión. keep_alive es un concepto de Ollama, no de OpenAI, y la capa de compatibilidad lo descarta. El endpoint nativo /api/chat sí lo respeta. Se comprueba en treinta segundos: se manda una petición, se ejecuta ollama ps y se mira la columna UNTIL. Si marca cinco minutos desde ahora, el valor se ignoró, digan lo que digan los documentos de esa compilación.

La segunda trampa es keep_alive: -1, que significa "no descargues nunca". Con dos modelos que no caben juntos en 16 GB, eso no elimina el problema, lo mueve. Las cargas bajaron de 214 a unas 60 al día, pero la latencia empeoró: el modelo de 14B dejó de tener una asignación completa en GPU y acabó con parte de las capas en CPU. La generación cayó de 42 a 6 tokens por segundo.

El arreglo no tiene gracia

La solución fue aburrida. OLLAMA_KEEP_ALIVE=24h como variable de entorno del servidor, un modelo residente por GPU y los embeddings movidos a una instancia de Ollama aparte, solo con CPU. Las cargas pasaron de 214 al día a 9.

Para medir lo propio hay dos comandos: ollama ps para ver qué está residente ahora mismo, y un grep sobre el log del servidor buscando la línea que aparece una vez por carga. En systemd sería journalctl -u ollama --since "24 hours ago" | grep -ci "llama runner started". El texto del log cambia entre versiones, así que conviene identificar la línea a mano antes de contar.

El detalle que importa: estos valores son de una máquina concreta con 16 GB de VRAM. En un portátil con tráfico esporádico, los cinco minutos por defecto son razonables. En cualquier cosa con peticiones en ráfaga, ese mismo valor garantiza que se pague la lectura de disco una y otra vez.