Los flags de vllm serve explicados, con valores iniciales sensatos
Un recorrido práctico por los flags de vllm serve que de verdad se ajustan: dtype, uso de memoria, longitud de contexto, paralelismo, claves de API y cuantización, con valores para empezar.
vLLM es uno de los motores de referencia para servir modelos de lenguaje grandes, sobre todo por su rendimiento y por cómo PagedAttention gestiona la memoria. Lo normal es manejarlo desde la línea de comandos, ya sea con vllm serve o con la forma antigua python -m vllm.entrypoints.openai.api_server. Aquí tiene un comando concreto y después un repaso de los flags que más tocará, cada uno con un valor inicial sensato.
Un comando para empezar
Este sirve un modelo de tamaño medio en una máquina con varias GPU. Está escrito para PowerShell, así que las continuaciones de línea son acentos graves:
vllm serve meta-llama/Llama-3.1-8B-Instruct `
--host 0.0.0.0 `
--port 8000 `
--tensor-parallel-size 2 `
--gpu-memory-utilization 0.90 `
--max-model-len 8192 `
--max-num-seqs 256 `
--dtype bfloat16 `
--served-model-name llama3-8b `
--api-key $env:VLLM_API_KEY
Cada flag se explica a continuación, junto con algunos más que merecen mención.
Elegir el modelo y la precisión
model es el argumento posicional: un ID de modelo de Hugging Face o una ruta local a los pesos. Es lo único que hay que indicar obligatoriamente. Las demás opciones tienen valores por defecto, pero rara vez son los que querría en producción.
dtype fija la precisión numérica de los pesos y las activaciones. Las opciones habituales son auto, float16, bfloat16 y float32. En GPU de clase Ampere o más recientes, elija bfloat16. Es numéricamente más estable que float16, apenas cuesta rendimiento y evita los problemas de desbordamiento que algunas arquitecturas sufren en float16.
trust-remote-code permite a vLLM ejecutar código de modelado propio alojado en el repositorio del modelo en Hugging Face. Algunas arquitecturas lo necesitan para poder cargarse. Manténgalo desactivado salvo que la ficha del modelo diga lo contrario, porque activarlo supone ejecutar código arbitrario de ese repositorio.
quantization elige un esquema de compresión como awq, gptq o fp8, que reduce el uso de memoria a cambio de algo de calidad. Úselo solo cuando cargue pesos ya cuantizados o cuando la memoria de la GPU no deje otra opción. Si hay margen suficiente, bfloat16 o la precisión completa son mejor opción.
Repartir la memoria de la GPU y el contexto
gpu-memory-utilization es la parte de la memoria de la GPU que vLLM puede reservar para pesos, activaciones y caché KV. Afecta a la estabilidad y al rendimiento más que casi cualquier otro ajuste. Empiece con 0.90. Si lo sube mucho, otros procesos en la tarjeta pueden provocar errores de falta de memoria. Si lo baja, desperdicia espacio de caché KV, lo que limita cuántas peticiones puede atender a la vez.
max-model-len limita la suma de tokens del prompt y generados en cada petición. El techo es la longitud de contexto con la que se entrenó el modelo, pero puede fijarlo más bajo para ahorrar memoria de caché. Ajústelo a lo que su aplicación necesita de verdad. Si un modelo admite 128K tokens y usted solo tiene turnos de chat cortos, no tiene sentido reservar todo eso. Un valor menor deja sitio para más secuencias simultáneas.
max-num-seqs limita cuántas peticiones se agrupan en un lote, así que controla la concurrencia. 256 sirve para muchas cargas de trabajo. Súbalo si hay memoria de GPU libre y mucho tráfico, y bájelo si los contextos largos están presionando la memoria.
block-size es el número de tokens por bloque en la caché KV de PagedAttention. Bloques más grandes implican menos gestión, pero más espacio desperdiciado en secuencias cortas. El valor por defecto de 16 vale para la mayoría de configuraciones y rara vez tendrá que tocarlo.
swap-space reserva RAM de la CPU, en gigabytes por GPU, donde se pueden aparcar bloques de la caché KV cuando falta memoria en lugar de rechazar peticiones. Empiece con 4. Si los picos de tráfico provocan fallos en vez de una cola ordenada, súbalo.
Repartir el modelo entre varias GPU
tensor-parallel-size indica entre cuántas GPU se divide cada capa. Es la solución cuando un modelo no cabe en una sola tarjeta y, en máquinas con varias GPU, también una forma de cambiar algo de latencia por rendimiento. Póngalo igual al número de GPU del nodo, preferiblemente potencias de dos (1, 2, 4, 8), ya que el número de cabezas de atención suele dividirse de forma exacta entre ellas.
pipeline-parallel-size fija el número de etapas del pipeline, normalmente combinado con paralelismo de tensores cuando un modelo tiene que repartirse entre varios nodos. Déjelo en 1 salvo que el modelo sea demasiado grande para el paralelismo de tensores por sí solo dentro de un nodo.
Exponer el servidor
host y port deciden dónde escucha el servidor de la API. Use 0.0.0.0 cuando otras máquinas necesiten acceder, o 127.0.0.1 para acceso solo local. 8000 es el puerto habitual.
served-model-name es el nombre que los clientes ponen en las peticiones a la API, y puede ser distinto del ID de Hugging Face. Resulta útil para darle a un despliegue una etiqueta limpia y versionada. Elija algo corto y estable para que las aplicaciones posteriores no dependan de una ruta concreta de pesos.
api-key obliga a los clientes a enviar un token bearer. Sin él, cualquiera que llegue al puerto puede enviar peticiones. Configúrelo para todo lo que vaya más allá de experimentos locales y léalo de una variable de entorno en lugar de escribirlo en scripts o dejarlo en el historial de la shell.
enforce-eager desactiva la captura de grafos CUDA y ejecuta PyTorch en modo eager. Renuncia a algo de rendimiento a cambio de un arranque más rápido y una depuración más sencilla. En producción, déjelo desactivado, porque los grafos CUDA suelen dar una aceleración considerable. Actívelo temporalmente cuando esté persiguiendo un fallo, ya que el modo eager produce trazas de pila más claras.
Cómo ajustar
La mayor parte del trabajo es un equilibrio a tres bandas frente a la memoria de GPU disponible: la longitud de contexto con max-model-len, la concurrencia con max-num-seqs y la precisión con dtype y quantization. Empiece con prudencia con gpu-memory-utilization, mida el rendimiento y la latencia reales con una carga realista y ajuste a partir de ahí en lugar de adivinar cifras de antemano.