Toolkit

Eliminamos Ollama: Unificación de Inferencia en TRT-LLM

Cómo migramos de una arquitectura dual Ollama + TRT-LLM a un único punto de inferencia, reduciendo 57 GB de memoria y 21°C de temperatura GPU.

Ulises González
Eliminamos Ollama: Unificación de Inferencia en TRT-LLM

Correr dos motores de inferencia LLM en paralelo sobre un mismo servidor parecía una solución pragmática hasta que dejó de serlo. Con la GPU a 71°C en idle, swap al 97% de capacidad y servicios systemd reiniciándose mutuamente, la arquitectura dual de nuestra DGX Spark se había convertido en un problema operativo que demandaba intervención inmediata.

Este artículo documenta la migración de una arquitectura dual (Ollama + TensorRT-LLM) a un único punto de inferencia unificado sobre TRT-LLM, el proceso de diagnóstico, las decisiones técnicas involucradas y los resultados medibles obtenidos.

Arquitectura antes y después

Arquitectura dual antes de la migración — Ollama + TRT-LLM compitiendo por 128 GB de memoria

Arquitectura unificada después de la migración — un solo motor TRT-LLM con watchdog térmico

El punto de partida: dos motores, un servidor

La DGX Spark de Rizoma — un sistema NVIDIA con chip GB10 Grace Blackwell y 128 GB de memoria unificada — servía como infraestructura de inferencia para cuatro productos: clasificación de leads, análisis de clima organizacional, generación de cursos educativos y un motor RAG con más de 200K documentos indexados.

El problema no era la capacidad del hardware, sino cómo la estábamos usando. La arquitectura había crecido orgánicamente en dos capas:

  • Ollama en el puerto 11434, sirviendo modelos GGUF como Qwen2.5:72B (47 GB) a través de su API nativa /api/generate
  • TensorRT-LLM en el puerto 8000, sirviendo Qwen3-14B-NVFP4 a través de la API OpenAI-compatible /v1/chat/completions

Cada producto llamaba al motor que se había configurado primero para su caso de uso. No había una decisión de arquitectura detrás — era acumulación de decisiones tácticas.

El diagnóstico: ¿por qué el servidor se ahogaba?

Los síntomas eran claros: GPU a 71°C con 96% de utilización en idle, swap consumido en 15.6 de 16 GB disponibles, y lentitud generalizada en todos los servicios. La causa raíz, sin embargo, no era obvia.

Servicios duplicados en dos capas de systemd

El descubrimiento crítico fue que existían servicios systemd en dos niveles:

  • Nivel sistema (/etc/systemd/system/): servicios heredados de configuraciones anteriores — un vLLM sirviendo Qwen-32B, otro sirviendo Qwen-7B, y un proxy RAG duplicado
  • Nivel usuario (~/.config/systemd/user/): la configuración activa — TRT-LLM, Milvus, el proxy RAG operativo y Ollama

Ambas capas se auto-reiniciaban al arranque del sistema. El resultado: Ollama cargaba Qwen2.5:72B (47 GB), TRT-LLM pre-alocaba su KV cache (86 GB), y los servicios de nivel sistema intentaban cargar modelos adicionales. La suma excedía los 119 GB disponibles, disparando swap thrashing continuo.

El cálculo de memoria que no cerraba

ComponenteMemoria requerida
Ollama (Qwen2.5:72B GGUF Q4)47 GB
TRT-LLM (Qwen3-14B-NVFP4 + KV cache)86 GB
Milvus (base vectorial)~8 GB
Sistema operativo + servicios~6 GB
Total demandado~147 GB
Disponible~119 GB

El déficit de 28 GB se resolvía con swap, lo que degradaba el rendimiento de toda la máquina.

La decisión: un solo motor, un solo modelo

La evaluación de alternativas fue directa. El criterio era: calidad de inferencia comparable a Qwen2.5:72B, velocidad superior, y consumo de memoria que dejara espacio para el resto del ecosistema.

ModeloMotorTamañoCalidad estimadaVelocidad
Qwen2.5:72BOllama (GGUF Q4)47 GBAltaLenta
Llama3.1:8bOllama (GGUF Q4)4.7 GBMediaRápida
Qwen3-14B-NVFP4TRT-LLM (NVFP4 nativo)~5 GB modelo + 86 GB KV cacheAlta (95-98% de FP16)Muy rápida

La elección fue Qwen3-14B-NVFP4 sobre TRT-LLM como motor único. Las razones:

  1. NVFP4 no es cuantización convencional. A diferencia de GGUF — que es cuantización post-entrenamiento ejecutada en CPU — NVFP4 es un formato de punto flotante de 4 bits nativo de los Tensor Cores Blackwell. Los benchmarks de NVIDIA reportan retención del 95-98% de la calidad FP16.
  2. KV cache pre-alocado. TRT-LLM reserva memoria para el cache de key-value al iniciar, eliminando la fragmentación dinámica que Ollama genera al cargar y descargar modelos bajo demanda.
  3. API OpenAI-compatible. Consolidar todos los clientes en una sola API (/v1/chat/completions) simplifica el mantenimiento y reduce el acoplamiento a proveedores específicos.
  4. Presupuesto de memoria. Con free_gpu_memory_fraction=0.85, TRT-LLM consume 86.5 GB dejando ~25 GB libres para Milvus y otros servicios — un margen que antes no existía.

La migración: ¿qué se cambió?

La migración se ejecutó en una sola sesión de trabajo. No fue un proyecto de semanas — fue un día intenso de diagnóstico, limpieza y verificación. Eso dice algo sobre la naturaleza del problema: la complejidad no estaba en la solución sino en la acumulación de decisiones tácticas que la precedieron.

Capa de infraestructura

La limpieza de servicios systemd fue el primer paso:

  • Eliminación de 3 servicios duplicados a nivel sistema
  • Actualización del servicio TRT-LLM a nivel usuario para servir exclusivamente Qwen3-14B-NVFP4
  • Creación de un servicio watchdog (dgx-monitor.service) que monitorea temperatura y swap, matando el proceso LLM si la GPU alcanza 80°C o el swap supera el 15%
  • Redirección del Cloudflare Tunnel del puerto 11434 (Ollama) al 8000 (TRT-LLM)
  • Deshabilitación permanente de Ollama: systemctl stop ollama && systemctl disable ollama

Capa de aplicación

La migración de código fue relativamente contenida. Tres archivos TypeScript en el sitio corporativo y tres archivos Python en el servicio de generación de cursos necesitaron cambios. El patrón de migración fue consistente en todos los casos:

  • Endpoint: /api/generate/v1/chat/completions
  • Request body: {model, prompt, stream}{model, messages, max_tokens}
  • Response parsing: data.responsedata.choices[0].message.content
  • Parámetros: num_predictmax_tokens, options.temperaturetemperature a nivel raíz
  • Formato JSON: format: "json"response_format: { type: "json_object" }

Strip de thinking tags

Un detalle técnico que merece atención: Qwen3 genera tags <think>...</think> con su razonamiento interno antes de la respuesta final. Este patrón, común en modelos de razonamiento recientes (DeepSeek-R1, QwQ, entre otros), mejora la calidad de las respuestas al forzar al modelo a “pensar en voz alta” antes de responder. Pero el razonamiento interno no debería llegar al usuario final ni a los sistemas que parsean las respuestas.

El proxy RAG ya los eliminaba automáticamente. Pero las aplicaciones que llamaban directamente al motor de inferencia — el sitio web y el servicio de generación de cursos — recibían el bloque de pensamiento completo, lo que rompía el parsing de JSON y producía respuestas con texto inesperado.

La solución fue implementar un regex consistente en TypeScript y Python para todos los puntos de integración. Es una línea de código, pero su ausencia causa errores sutiles que son difíciles de diagnosticar porque la respuesta “funciona” — solo que viene precedida por texto que no debería estar ahí.

Resultados medidos

MétricaAntesDespuésCambio
Temperatura GPU (idle)71°C50°C-21°C
Utilización GPU (idle)96%0%-96 pp
Swap usado15.6 / 16 GB0.6 / 16 GB-96%
Modelos cargados simultáneamente2-31Consolidado
Puntos de inferencia21Unificado
Tiempo de carga del modelo~33s~5s-85%
APIs de integración distintas21Estandarizado

El volumen de código cambiado fue modesto: 6 archivos de aplicación (~160 líneas netas), 5 archivos de configuración systemd (~80 líneas) y 4 archivos de documentación actualizados.

Lecciones para equipos que corren inferencia local

La deuda técnica en infraestructura de IA es silenciosa. A diferencia de la deuda en código — que se manifiesta en bugs o lentitud de desarrollo — la deuda en infraestructura de inferencia se acumula como calor, swap y servicios fantasma. Si nadie audita los servicios systemd, nadie sabe que existen.

Ollama es excelente para prototipado, problemático para producción. Su modelo de carga dinámica de modelos es conveniente para experimentación, pero en un servidor de producción donde múltiples servicios comparten la misma GPU, la ausencia de reserva de memoria predecible es un riesgo operativo.

La API OpenAI-compatible se está convirtiendo en estándar de facto. Migrar de una API propietaria (Ollama) a una estandarizada no solo simplificó el código actual — reduce el costo de migración futura si decidimos cambiar de modelo o motor de inferencia.

Un watchdog térmico no es opcional. Hardware de inferencia en oficina (no en datacenter con refrigeración industrial) necesita protección activa. El servicio dgx-monitor que auto-mata el LLM a 80°C es seguro contra situaciones que, sin él, podrían dañar el hardware.

Conclusión

La migración de Ollama + TRT-LLM a TRT-LLM exclusivo no fue una decisión sobre cuál motor es “mejor” en abstracto. Fue una decisión de arquitectura operativa: un servidor con 128 GB de memoria no puede correr dos motores de inferencia en producción sin degradación. La unificación eliminó 57 GB de consumo innecesario, bajó la temperatura 21°C, y dejó un sistema que cualquier miembro del equipo puede entender y mantener.

Hay una tentación natural en los equipos técnicos de mantener múltiples opciones abiertas: “dejamos Ollama por si necesitamos probar otro modelo”, “conservamos el servicio de vLLM por si acaso”. En infraestructura de inferencia, esa optionalidad tiene un costo medible en temperatura, memoria y complejidad operativa. A veces la mejor decisión de arquitectura es eliminar las cosas que ya no justifican su presencia.

El costo de la migración fue un día de trabajo. El costo de no hacerla habría sido un servidor que eventualmente se degradara por sobrecalentamiento sostenido — o peor, que fallara en medio de una petición de producción sin que nadie entendiera por qué.


Referencias

  • NVIDIA. (2025). DGX Spark Technical Specifications. NVIDIA Developer Documentation.
  • NVIDIA. (2025). TensorRT-LLM: Optimizing LLM Inference. NVIDIA Technical Blog.
  • NVIDIA. (2025). Blackwell Architecture: NVFP4 Quantization. NVIDIA GPU Technology Conference.
  • Ollama. (2025). Ollama API Documentation. GitHub.
#inteligencia artificial#automatizacion#infraestructura ia