{"id":613,"date":"2026-09-08T17:11:21","date_gmt":"2026-09-08T16:11:21","guid":{"rendered":"https:\/\/www.darifer.net\/?p=613"},"modified":"2026-09-08T17:55:00","modified_gmt":"2026-09-08T16:55:00","slug":"como-desplegar-y-servir-llms-con-vllm","status":"publish","type":"post","link":"https:\/\/www.darifer.net\/index.php\/2026\/09\/08\/como-desplegar-y-servir-llms-con-vllm\/","title":{"rendered":"C\u00f3mo desplegar y servir LLMs con vLLM"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Una gu\u00eda pr\u00e1ctica con Docker, GPU NVIDIA y una API compatible con OpenAI<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hola a tod@s,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hoy voy a hablar de inteligencia artificial aplicada a infraestructura. En esta ocasi\u00f3n vamos a desplegar un LLM con vLLM, uno de los motores de inferencia m\u00e1s utilizados cuando necesitamos servir modelos con buen rendimiento y exponerlos mediante una API compatible con OpenAI.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Despu\u00e9s de comentarle a un compa\u00f1ero de la comunidad que iba mi proximo art\u00edculo me hizo la siguiente pregunta:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u00bfPor qu\u00e9 utilizar modelos de IA locales?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ejecutar modelos de inteligencia artificial dentro nuestra organizaci\u00f3n nos permite mantener el control sobre la informaci\u00f3n, evitar que nuestro c\u00f3digo fuente, documentaci\u00f3n o configuraciones corporativas se env\u00eden a servicios externos y garantizar que los datos permanezcan bajo la gobernanza de la empresa. Adem\u00e1s, nos proporciona una plataforma propia para desarrollo asistido por IA, con costes predecibles, independencia de proveedores externos y capacidad de adaptaci\u00f3n a las necesidades espec\u00edficas de la organizaci\u00f3n. En mi caso, hoy voy a utilizar el Dell Pro Max GB10 nos permite alojar modelos avanzados como Qwen3-Coder, ofreci\u00e9ndonos una experiencia similar a <strong>GitHub Copilot<\/strong> mientras se preservan la privacidad, la seguridad y la soberan\u00eda de los datos. La integraci\u00f3n se realiza mediante vLLM, que expone una API compatible con OpenAI para ser consumida por herramientas de desarrollo y automatizaci\u00f3n y otra cosa tener en cuenta que si necesitamos esto para una organizaci\u00f3n grande ya ir\u00edamos a otra tecnologia, otra plataforma que hablaremos m\u00e1s adelante.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La idea del art\u00edculo es muy pr\u00e1ctica. Partiremos de equipo Dell Pro Max GB10 con Linux con una GPU NVIDIA, ejecutaremos vLLM dentro de Docker, descargaremos un modelo desde Hugging Face y comprobaremos que podemos enviar una conversaci\u00f3n al endpoint \/v1\/chat\/completions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aunque la referencia utiliza DGX Spark, el flujo base resulta \u00fatil en otros servidores Linux con GPU NVIDIA. Lo que cambia entre plataformas es la capacidad de memoria, el soporte del modelo y algunos par\u00e1metros de lanzamiento.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Importante:<\/strong> probad primero este procedimiento en laboratorio. La publicaci\u00f3n de un modelo implica consumo de GPU, descarga de varios gigabytes, aceptaci\u00f3n de licencias y exposici\u00f3n de un servicio HTTP que debe protegerse antes de utilizarlo en producci\u00f3n.<\/p>\n<\/blockquote>\n\n\n\n<h1 class=\"wp-block-heading\">Qu\u00e9 vamos a conseguir<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Comprobar que Docker puede acceder a la GPU NVIDIA.<\/li>\n\n\n\n<li>Preparar las variables del modelo, la imagen y la longitud m\u00e1xima de contexto.<\/li>\n\n\n\n<li>Arrancar vLLM en segundo plano y publicar el puerto 8000.<\/li>\n\n\n\n<li>Validar el estado del servicio y revisar sus logs.<\/li>\n\n\n\n<li>Consumir una API compatible con OpenAI mediante curl.<\/li>\n\n\n\n<li>Aplicar recomendaciones b\u00e1sicas de seguridad, capacidad y operaci\u00f3n.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Qu\u00e9 es vLLM y por qu\u00e9 utilizarlo<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">vLLM es un motor de inferencia y serving para modelos de lenguaje. Su objetivo no es entrenar el modelo, sino cargar sus pesos, gestionar la memoria disponible y atender peticiones de generaci\u00f3n de texto de forma eficiente. Para un equipo de sistemas, podemos verlo como la capa que convierte un modelo almacenado en un servicio consumible por aplicaciones.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dos caracter\u00edsticas resultan especialmente interesantes: el procesamiento continuo de solicitudes para aprovechar mejor la GPU y la API compatible con OpenAI, que simplifica la integraci\u00f3n con clientes y aplicaciones que ya entienden ese formato.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Componente<\/strong><\/td><td><strong>Funci\u00f3n<\/strong><\/td><\/tr><tr><td>Hugging Face Hub<\/td><td>Repositorio de Modelo de IA.<\/td><\/tr><tr><td>Docker<\/td><td>A\u00edsla dependencias y facilita repetir el despliegue.<\/td><\/tr><tr><td>NVIDIA Container Toolkit<\/td><td>Permite que el contenedor utilice la GPU del host.<\/td><\/tr><tr><td>vLLM<\/td><td>Carga el modelo y atiende solicitudes de inferencia.<\/td><\/tr><tr><td>API compatible con OpenAI<\/td><td>Ofrece endpoints conocidos para chat y generaci\u00f3n.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Arquitectura del laboratorio<\/h1>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"484\" height=\"323\" src=\"https:\/\/www.darifer.net\/wp-content\/uploads\/2026\/09\/image.jpeg\" alt=\"\" class=\"wp-image-614\" style=\"width:394px;height:auto\" srcset=\"https:\/\/www.darifer.net\/wp-content\/uploads\/2026\/09\/image.jpeg 484w, https:\/\/www.darifer.net\/wp-content\/uploads\/2026\/09\/image-300x200.jpeg 300w\" sizes=\"auto, (max-width: 484px) 100vw, 484px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En el ejemplo publicaremos el puerto 8000 del contenedor. La cach\u00e9 de Hugging Face se monta desde el host para no descargar de nuevo el modelo cada vez que recreemos el contenedor.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Requisitos previos<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Host Linux compatible y actualizado. El flujo containerizado de la gu\u00eda de NVIDIA no aplica actualmente a Windows nativo ni a WSL.<\/li>\n\n\n\n<li>GPU NVIDIA con memoria suficiente para el modelo seleccionado.<\/li>\n\n\n\n<li>Driver NVIDIA funcional y comando nvidia-smi operativo.<\/li>\n\n\n\n<li>Docker Engine y NVIDIA Container Toolkit configurados.<\/li>\n\n\n\n<li>Espacio en disco para la imagen, la cach\u00e9 y los pesos del modelo.<\/li>\n\n\n\n<li>Cuenta y token de Hugging Face si el modelo es privado o requiere aceptar condiciones de acceso.<\/li>\n\n\n\n<li>Conectividad saliente hacia el registro de contenedores y Hugging Face Hub.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Decisi\u00f3n cr\u00edtica:<\/strong> el modelo debe caber en la memoria disponible teniendo en cuenta pesos, KV cache y sobrecarga del runtime. No seleccion\u00e9is un modelo solo por el n\u00famero de par\u00e1metros.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Paso 1. Validar Docker y el acceso a la GPU<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Abrimos una terminal en el host Linux y comprobamos primero el driver:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">nvidia-smi<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A continuaci\u00f3n validamos Docker:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker ps<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si aparece un error de permisos y nuestra pol\u00edtica nos permite administrar Docker sin sudo, a\u00f1adimos el usuario al grupo docker y actualizamos la sesi\u00f3n de grupo:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">sudo usermod -aG docker $USER<br>newgrp docker<br>docker ps<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Seguridad:<\/strong> pertenecer al grupo docker concede privilegios elevados sobre el host. Limitad esta pertenencia a cuentas administrativas y revisadla peri\u00f3dicamente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por \u00faltimo, podemos realizar una comprobaci\u00f3n espec\u00edfica del runtime NVIDIA con una imagen CUDA disponible en vuestro registro autorizado. La versi\u00f3n de la imagen debe ser compatible con el driver instalado:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker run &#8211;rm &#8211;gpus all &lt;imagen-cuda-autorizada&gt; nvidia-smi<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Paso 2. Elegir el modelo y preparar variables<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Antes de arrancar el servicio debemos conocer el identificador del modelo en Hugging Face y revisar la configuraci\u00f3n recomendada para nuestro hardware. Para modelos gated o privados necesitaremos un token con los permisos m\u00ednimos necesarios.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">export HF_TOKEN=\u00bbhf_reemplazar_por_un_token_seguro\u00bb<br>export MODEL_HANDLE=\u00bb&lt;organizacion\/modelo&gt;\u00bb<br>export VLLM_IMAGE=\u00bbvllm\/vllm-openai:latest\u00bb<br>export MAX_MODEL_LEN=8192<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Descargamos la imagen de vLLM:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker pull \u00ab$VLLM_IMAGE\u00bb<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sobre la versi\u00f3n latest:<\/strong> es c\u00f3moda para laboratorio, pero en producci\u00f3n conviene fijar una etiqueta o digest validado. As\u00ed evitamos cambios inesperados al recrear el servicio.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sobre MAX_MODEL_LEN:<\/strong> este valor representa el m\u00e1ximo de tokens de prompt m\u00e1s salida por solicitud. Un contexto mayor reserva m\u00e1s memoria para la KV cache. Empezad con un valor alineado con vuestro caso de uso y aumentadlo despu\u00e9s de medir.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Paso 3. Arrancar el servidor vLLM<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Lanzamos el contenedor en segundo plano. El siguiente comando es una base razonable para un modelo que cabe en una sola GPU o en las GPU visibles del nodo:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker run -d \\<br>&nbsp; &#8211;name vllm-server \\<br>&nbsp; &#8211;gpus all \\<br>&nbsp; &#8211;ipc host \\<br>&nbsp; &#8211;ulimit memlock=-1 \\<br>&nbsp; &#8211;ulimit stack=67108864 \\<br>&nbsp; &#8211;entrypoint \u00ab\u00bb \\<br>&nbsp; -p 8000:8000 \\<br>&nbsp; -e HF_TOKEN=\u00bb$HF_TOKEN\u00bb \\<br>&nbsp; -v \u00ab$HOME\/.cache\/huggingface\/hub:\/root\/.cache\/huggingface\/hub\u00bb \\<br>&nbsp; \u00ab$VLLM_IMAGE\u00bb \\<br>&nbsp; vllm serve \u00ab$MODEL_HANDLE\u00bb \\<br>&nbsp;&nbsp;&nbsp; &#8211;max-model-len \u00ab$MAX_MODEL_LEN\u00bb \\<br>&nbsp;&nbsp;&nbsp; &#8211;gpu-memory-utilization 0.8<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Par\u00e1metro<\/strong><\/td><td><strong>Qu\u00e9 controla<\/strong><\/td><td><strong>Recomendaci\u00f3n inicial<\/strong><\/td><\/tr><tr><td>&#8211;gpus all<\/td><td>GPU disponibles para el contenedor.<\/td><td>Restringir dispositivos si el host es compartido.<\/td><\/tr><tr><td>&#8211;ipc host<\/td><td>Memoria compartida del host.<\/td><td>\u00datil para cargas de IA. Evaluar el aislamiento requerido.<\/td><\/tr><tr><td>-p 8000:8000<\/td><td>Publicaci\u00f3n del servicio HTTP.<\/td><td>En producci\u00f3n, enlazar a red privada o a un proxy.<\/td><\/tr><tr><td>&#8211;max-model-len<\/td><td>Contexto m\u00e1ximo por solicitud.<\/td><td>No sobredimensionar sin medir memoria.<\/td><\/tr><tr><td>&#8211;gpu-memory-utilization 0.8<\/td><td>Fracci\u00f3n de memoria GPU que puede usar vLLM.<\/td><td>Deja margen inicial para estabilizar el laboratorio.<\/td><\/tr><tr><td>Montaje de cach\u00e9<\/td><td>Persistencia de descargas del Hub.<\/td><td>Proteger el directorio y controlar su crecimiento.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En un equipo dedicado puede ser posible aumentar gpu-memory-utilization hacia 0.9 o 0.95, pero no existe un valor universal. Debemos vigilar errores de memoria, concurrencia y tama\u00f1o de contexto. En DGX Spark existe memoria unificada y la presi\u00f3n de memoria requiere atenci\u00f3n espec\u00edfica. En DGX Station, NVIDIA indica consideraciones particulares para seleccionar la GPU GB300.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Paso 4. Supervisar el arranque<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">La primera ejecuci\u00f3n puede tardar m\u00e1s porque debe descargar el modelo. Seguimos los logs del contenedor:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker logs -f vllm-server<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Buscamos el progreso de descarga, la carga de pesos y el mensaje Application startup complete. Tambi\u00e9n podemos esperar al endpoint de salud:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">timeout 900 bash -c &#8216;until curl -sf http:\/\/localhost:8000\/health &gt;\/dev\/null 2&gt;&amp;1; do sleep 10; done&#8217; \\<br>&nbsp; || { echo &#8216;El servidor no ha arrancado&#8217;; docker logs vllm-server | tail -50; exit 1; }<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Resultado esperado:<\/strong> curl debe devolver c\u00f3digo HTTP satisfactorio y el contenedor debe permanecer en estado Up.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker ps &#8211;filter name=vllm-server<br>curl -i http:\/\/localhost:8000\/health<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Paso 5. Probar la API compatible con OpenAI<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez operativo el servicio, enviamos una conversaci\u00f3n de prueba. El nombre del modelo debe coincidir con MODEL_HANDLE:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">curl http:\/\/localhost:8000\/v1\/chat\/completions \\<br>&nbsp; -H &#8216;Content-Type: application\/json&#8217; \\<br>&nbsp; -d &#8216;{<br>&nbsp;&nbsp;&nbsp; \u00abmodel\u00bb: \u00ab&#8216;\u00bb$MODEL_HANDLE\u00bb&#8216;\u00bb,<br>&nbsp;&nbsp;&nbsp; \u00abmessages\u00bb: [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {\u00abrole\u00bb: \u00absystem\u00bb, \u00abcontent\u00bb: \u00abResponde en espa\u00f1ol y de forma concisa.\u00bb},<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {\u00abrole\u00bb: \u00abuser\u00bb, \u00abcontent\u00bb: \u00abExplica qu\u00e9 es la virtualizaci\u00f3n.\u00bb}<br>&nbsp;&nbsp;&nbsp; ],<br>&nbsp;&nbsp;&nbsp; \u00abmax_tokens\u00bb: 512,<br>&nbsp;&nbsp;&nbsp; \u00abtemperature\u00bb: 0.2<br>&nbsp; }&#8217;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La respuesta deber\u00eda incluir un array choices y el texto generado dentro de message.content. Si el modelo utiliza razonamiento interno o un parser espec\u00edfico, una cuota de max_tokens demasiado baja puede terminar con finish_reason igual a length y sin respuesta final \u00fatil.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Paso 6. Integrarlo desde Python<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Una ventaja de la compatibilidad con OpenAI es que podemos reutilizar clientes existentes apuntando base_url al servidor local. El valor de api_key puede ser un texto de laboratorio si no hemos configurado autenticaci\u00f3n delante del servicio:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">from openai import OpenAI<br><br>client = OpenAI(<br>&nbsp;&nbsp;&nbsp; base_url=\u00bbhttp:\/\/servidor-vllm:8000\/v1&#8243;,<br>&nbsp;&nbsp;&nbsp; api_key=\u00bblaboratorio\u00bb<br>)<br><br>respuesta = client.chat.completions.create(<br>&nbsp;&nbsp;&nbsp; model=\u00bb&lt;organizacion\/modelo&gt;\u00bb,<br>&nbsp;&nbsp;&nbsp; messages=[<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {\u00abrole\u00bb: \u00abuser\u00bb, \u00abcontent\u00bb: \u00abResume las ventajas de Azure Local.\u00bb}<br>&nbsp;&nbsp;&nbsp; ],<br>&nbsp;&nbsp;&nbsp; max_tokens=300,<br>&nbsp;&nbsp;&nbsp; temperature=0.2<br>)<br><br>print(respuesta.choices[0].message.content)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Producci\u00f3n:<\/strong> no expong\u00e1is vLLM directamente a Internet sin autenticaci\u00f3n, TLS, control de acceso, l\u00edmites de consumo y registro de actividad. Situadlo detr\u00e1s de un reverse proxy, API gateway o balanceador adecuado.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Validar capacidad y rendimiento<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Que una petici\u00f3n funcione no significa que el servicio est\u00e9 dimensionado. Debemos medir al menos latencia hasta el primer token, velocidad de generaci\u00f3n, concurrencia, uso de memoria GPU y tasa de errores. Tambi\u00e9n conviene probar el tama\u00f1o de prompt real y no solo una pregunta corta.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>M\u00e9trica<\/strong><\/td><td><strong>Por qu\u00e9 importa<\/strong><\/td><td><strong>Qu\u00e9 observar<\/strong><\/td><\/tr><tr><td>TTFT<\/td><td>Impacta en la percepci\u00f3n de respuesta.<\/td><td>Aumentos con prompts largos o cola.<\/td><\/tr><tr><td>Tokens por segundo<\/td><td>Mide la velocidad de generaci\u00f3n.<\/td><td>Variaci\u00f3n por modelo y concurrencia.<\/td><\/tr><tr><td>Concurrencia<\/td><td>Determina usuarios simult\u00e1neos.<\/td><td>Colas, latencia y saturaci\u00f3n.<\/td><\/tr><tr><td>Memoria GPU<\/td><td>Limita modelo, contexto y KV cache.<\/td><td>OOM y reinicios del contenedor.<\/td><\/tr><tr><td>Errores HTTP<\/td><td>Revela fallos operativos.<\/td><td>429, 5xx y timeouts.<\/td><\/tr><tr><td>Disco de cach\u00e9<\/td><td>Puede crecer con varios modelos.<\/td><td>Capacidad y limpieza controlada.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Errores habituales y c\u00f3mo resolverlos<\/h1>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>S\u00edntoma<\/strong><\/td><td><strong>Causa probable<\/strong><\/td><td><strong>Qu\u00e9 revisar<\/strong><\/td><\/tr><tr><td>permission denied al usar Docker<\/td><td>El usuario no tiene acceso al socket.<\/td><td>Grupo docker, sesi\u00f3n actual y pol\u00edtica de privilegios.<\/td><\/tr><tr><td>could not select device driver<\/td><td>Runtime NVIDIA ausente o mal configurado.<\/td><td>Driver, Container Toolkit y prueba nvidia-smi en contenedor.<\/td><\/tr><tr><td>401 o 403 al descargar<\/td><td>Token inv\u00e1lido o licencia no aceptada.<\/td><td>Permisos del token y acceso al modelo en Hugging Face.<\/td><\/tr><tr><td>CUDA out of memory<\/td><td>Modelo, contexto o concurrencia excesivos.<\/td><td>Reducir MAX_MODEL_LEN, utilizaci\u00f3n o elegir otro modelo.<\/td><\/tr><tr><td>El contenedor se detiene<\/td><td>Error durante la carga o par\u00e1metros incompatibles.<\/td><td>docker logs vllm-server y receta del modelo.<\/td><\/tr><tr><td>finish_reason: length<\/td><td>Presupuesto de salida insuficiente.<\/td><td>Aumentar max_tokens o reducir el prompt.<\/td><\/tr><tr><td>Respuesta lenta en la primera petici\u00f3n<\/td><td>Carga inicial, compilaci\u00f3n o cach\u00e9s fr\u00edas.<\/td><td>Separar warm-up de las m\u00e9tricas estables.<\/td><\/tr><tr><td>Puerto 8000 inaccesible<\/td><td>Firewall, bind, red o contenedor no operativo.<\/td><td>curl local, docker ps, reglas y publicaci\u00f3n de puertos.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Recomendaciones de hardening<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fijar versiones de la imagen y validar actualizaciones antes de desplegarlas.<\/li>\n\n\n\n<li>No incluir HF_TOKEN en scripts, repositorios, im\u00e1genes ni historiales compartidos. Utilizar un gestor de secretos.<\/li>\n\n\n\n<li>Publicar la API \u00fanicamente en redes autorizadas y a\u00f1adir TLS y autenticaci\u00f3n.<\/li>\n\n\n\n<li>Aplicar cuotas, l\u00edmites de concurrencia, tama\u00f1o m\u00e1ximo de entrada y timeouts.<\/li>\n\n\n\n<li>Ejecutar el servicio con la m\u00ednima superficie de privilegios compatible con el modelo.<\/li>\n\n\n\n<li>Registrar accesos y errores sin almacenar prompts sensibles de forma indiscriminada.<\/li>\n\n\n\n<li>Revisar licencias del modelo, condiciones de uso y requisitos de atribuci\u00f3n.<\/li>\n\n\n\n<li>Separar entornos de laboratorio y producci\u00f3n, y disponer de rollback.<\/li>\n\n\n\n<li>Monitorizar GPU, memoria, disco, latencia y disponibilidad.<\/li>\n\n\n\n<li>Evaluar filtros, guardrails y pol\u00edticas de datos seg\u00fan el caso de uso.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Operaci\u00f3n diaria<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Estos comandos cubren las acciones m\u00e1s habituales durante el laboratorio:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">docker ps &#8211;filter name=vllm-server<br>docker logs &#8211;tail 100 vllm-server<br>docker stats vllm-server<br>docker restart vllm-server<br>docker stop vllm-server<br>docker rm vllm-server<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eliminar el contenedor no borra la cach\u00e9 montada desde el host. Para liberar espacio debemos identificar primero la ruta exacta del modelo y aplicar el procedimiento de limpieza aprobado. Evitad comandos recursivos sin validar el destino.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Checklist antes de pasar a producci\u00f3n<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Modelo y licencia aprobados.<\/li>\n\n\n\n<li>Imagen fijada por versi\u00f3n o digest.<\/li>\n\n\n\n<li>Capacidad validada con prompts y concurrencias reales.<\/li>\n\n\n\n<li>TLS, autenticaci\u00f3n y autorizaci\u00f3n configurados.<\/li>\n\n\n\n<li>Token y secretos fuera de la l\u00ednea de comandos y del repositorio.<\/li>\n\n\n\n<li>Monitorizaci\u00f3n, alertas y logs definidos.<\/li>\n\n\n\n<li>L\u00edmites de consumo y protecci\u00f3n frente a abuso.<\/li>\n\n\n\n<li>Pol\u00edtica de datos, retenci\u00f3n y privacidad revisada.<\/li>\n\n\n\n<li>Procedimiento de actualizaci\u00f3n, rollback y recuperaci\u00f3n probada.<\/li>\n\n\n\n<li>Documentaci\u00f3n operativa y responsables identificados.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Para finalizar<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Con vLLM podemos convertir un modelo de Hugging Face en un servicio de inferencia accesible mediante una API compatible con OpenAI. El flujo b\u00e1sico es sencillo: validamos Docker y la GPU, elegimos el modelo, arrancamos el contenedor, esperamos al endpoint de salud y enviamos una petici\u00f3n de chat.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La parte importante empieza despu\u00e9s de la primera respuesta. En un entorno real debemos dimensionar memoria y concurrencia, proteger el endpoint, controlar secretos, respetar la licencia del modelo y monitorizar el servicio. Con estas bases, vLLM se convierte en una pieza muy \u00fatil para laboratorios de IA, asistentes internos y aplicaciones que requieren inferencia privada o cercana a los datos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ya sabemos c\u00f3mo desplegar y servir un LLM con vLLM. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">   Nos vemos en el siguiente art\u00edculo.<br><br>Saludos.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una gu\u00eda pr\u00e1ctica con Docker, GPU NVIDIA y una API compatible con OpenAI Hola a tod@s, Hoy voy a hablar de inteligencia artificial aplicada a infraestructura. En esta ocasi\u00f3n vamos a desplegar un LLM con vLLM, uno de los motores de inferencia m\u00e1s utilizados cuando necesitamos servir modelos con buen rendimiento y exponerlos mediante una [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":629,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36,35],"tags":[37],"class_list":["post-613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ia","category-linux","tag-ia-linux"],"_links":{"self":[{"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/posts\/613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/comments?post=613"}],"version-history":[{"count":11,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/posts\/613\/revisions"}],"predecessor-version":[{"id":628,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/posts\/613\/revisions\/628"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/media\/629"}],"wp:attachment":[{"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/media?parent=613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/categories?post=613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.darifer.net\/index.php\/wp-json\/wp\/v2\/tags?post=613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}