Instalación de vLLM para Inferencia de Alto Rendimiento con LLMs
vLLM es el framework de inferencia de LLMs de mayor rendimiento disponible actualmente, gracias a su implementación de PagedAttention que gestiona la memoria de atención de forma mucho más eficiente que las implementaciones estándar. Comparado con Hugging Face Transformers, vLLM puede multiplicar el throughput por 24x con el mismo hardware. Esta guía cubre la instalación, la carga de modelos, la API compatible con OpenAI, las técnicas de cuantización y la optimización de memoria GPU.
Requisitos Previos
- Servidor Linux (Ubuntu 20.04+)
- GPU NVIDIA con al menos 16 GB VRAM (para modelos 7B sin cuantización)
- CUDA 11.8 o superior
- Python 3.9 o superior
- Al menos 50 GB de espacio en disco (para modelos)
# Verificar la GPU y la VRAM disponible
nvidia-smi
# Verificar la versión de CUDA
nvcc --version
# Verificar Python
python3 --version
VRAM necesaria por modelo
| Modelo | Sin cuantización | AWQ/GPTQ (4-bit) |
|---|---|---|
| 7B | 14 GB | 4-5 GB |
| 13B | 26 GB | 7-8 GB |
| 70B | 140 GB | 35-40 GB |
Instalación de vLLM
# Crear un entorno virtual dedicado
python3 -m venv /opt/vllm-venv
source /opt/vllm-venv/bin/activate
# Instalar vLLM (incluye PyTorch con CUDA)
# La instalación descarga ~2 GB de dependencias
pip install vllm
# Verificar la instalación
python3 -c "import vllm; print(f'vLLM {vllm.__version__} instalado correctamente')"
# Instalación con soporte para modelos cuantizados (AWQ, GPTQ)
pip install vllm autoawq auto-gptq
Instalación desde el código fuente (para la última versión)
# Clonar el repositorio
git clone https://github.com/vllm-project/vllm.git /opt/vllm-src
cd /opt/vllm-src
# Instalar en modo desarrollo
pip install -e .
Servidor de Inferencia Básico
# Activar el entorno virtual
source /opt/vllm-venv/bin/activate
# Iniciar el servidor con un modelo de Hugging Face
python3 -m vllm.entrypoints.openai.api_server \
--model mistralai/Mistral-7B-Instruct-v0.3 \
--host 0.0.0.0 \
--port 8000
# El servidor descarga el modelo en la primera ejecución
# Los modelos se almacenan en ~/.cache/huggingface/
# Verificar que el servidor está activo
curl http://localhost:8000/health
# Ver los modelos disponibles
curl http://localhost:8000/v1/models
API Compatible con OpenAI
vLLM expone una API completamente compatible con la API de OpenAI, lo que permite sustituirla sin cambiar el código de la aplicación.
# Chat completions (compatible con openai.ChatCompletion)
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mistralai/Mistral-7B-Instruct-v0.3",
"messages": [
{"role": "system", "content": "Eres un asistente experto en Linux."},
{"role": "user", "content": "¿Cómo puedo ver los puertos abiertos en mi servidor?"}
],
"max_tokens": 512,
"temperature": 0.7
}'
# Text completions
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mistralai/Mistral-7B-Instruct-v0.3",
"prompt": "Los 5 comandos Linux más útiles son:",
"max_tokens": 200
}'
Uso con la librería oficial de OpenAI
#!/usr/bin/env python3
# Usar vLLM con el SDK oficial de OpenAI apuntando al servidor local
from openai import OpenAI
# Apuntar al servidor vLLM en lugar de a la API de OpenAI
cliente = OpenAI(
api_key="no-se-usa", # vLLM no requiere autenticación por defecto
base_url="http://localhost:8000/v1"
)
# Chat completion
respuesta = cliente.chat.completions.create(
model="mistralai/Mistral-7B-Instruct-v0.3",
messages=[
{"role": "system", "content": "Eres un experto en sistemas Linux."},
{"role": "user", "content": "¿Cuál es la diferencia entre proceso y hilo?"}
],
max_tokens=400,
temperature=0.7
)
print(respuesta.choices[0].message.content)
print(f"\nTokens usados: {respuesta.usage.total_tokens}")
Modelos Soportados y Descarga
# Descargar un modelo de Hugging Face antes de iniciarlo
# (útil para tener el modelo disponible sin internet en producción)
pip install huggingface-hub
# Descargar un modelo específico
huggingface-cli download \
mistralai/Mistral-7B-Instruct-v0.3 \
--local-dir /opt/modelos/mistral-7b
# Iniciar vLLM con el modelo local
python3 -m vllm.entrypoints.openai.api_server \
--model /opt/modelos/mistral-7b \
--host 0.0.0.0 \
--port 8000
# Otros modelos populares compatibles con vLLM
# Meta Llama 3.1 8B
huggingface-cli download meta-llama/Meta-Llama-3.1-8B-Instruct \
--local-dir /opt/modelos/llama-3.1-8b
# Qwen 2.5 7B
huggingface-cli download Qwen/Qwen2.5-7B-Instruct \
--local-dir /opt/modelos/qwen-2.5-7b
Cuantización para Optimizar Memoria
La cuantización reduce el uso de VRAM a costa de una pequeña pérdida de calidad.
AWQ (Activation-aware Weight Quantization) - Recomendado
# Usar modelos pre-cuantizados AWQ (disponibles en Hugging Face)
python3 -m vllm.entrypoints.openai.api_server \
--model TheBloke/Mistral-7B-Instruct-v0.2-AWQ \
--quantization awq \
--host 0.0.0.0 \
--port 8000
# Cuantizar un modelo propio con AWQ
pip install autoawq
python3 << 'EOF'
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
modelo_base = "mistralai/Mistral-7B-Instruct-v0.3"
ruta_salida = "/opt/modelos/mistral-7b-awq"
# Configuración de cuantización AWQ
config_cuant = {
"zero_point": True,
"q_group_size": 128,
"w_bit": 4,
"version": "GEMM"
}
# Cargar y cuantizar
modelo = AutoAWQForCausalLM.from_pretrained(modelo_base, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(modelo_base)
modelo.quantize(tokenizer, quant_config=config_cuant)
# Guardar el modelo cuantizado
modelo.save_quantized(ruta_salida)
tokenizer.save_pretrained(ruta_salida)
print(f"Modelo cuantizado guardado en {ruta_salida}")
EOF
GPTQ
# Usar modelos GPTQ pre-cuantizados
python3 -m vllm.entrypoints.openai.api_server \
--model TheBloke/Llama-2-7B-Chat-GPTQ \
--quantization gptq \
--host 0.0.0.0 \
--port 8000
FP8 (para GPUs H100/H200)
# Cuantización FP8 en tiempo de carga (requiere GPU Hopper/Ada)
python3 -m vllm.entrypoints.openai.api_server \
--model mistralai/Mistral-7B-Instruct-v0.3 \
--quantization fp8 \
--host 0.0.0.0 \
--port 8000
Configuración para Producción
# Parámetros de producción recomendados
python3 -m vllm.entrypoints.openai.api_server \
--model /opt/modelos/mistral-7b \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \ # Longitud máxima del contexto
--max-num-seqs 256 \ # Máximo de solicitudes concurrentes
--gpu-memory-utilization 0.90 \ # Usar el 90% de la VRAM
--disable-log-requests \ # No registrar cada solicitud en producción
--served-model-name mi-llm # Nombre de alias para el modelo
# Para múltiples GPUs (tensor parallelism)
python3 -m vllm.entrypoints.openai.api_server \
--model /opt/modelos/llama-70b \
--tensor-parallel-size 4 \ # Distribuir entre 4 GPUs
--host 0.0.0.0 \
--port 8000
Configurar como servicio systemd
sudo cat > /etc/systemd/system/vllm.service << 'EOF'
[Unit]
Description=vLLM Inference Server
After=network.target
[Service]
Type=simple
User=vllm
Group=vllm
WorkingDirectory=/opt/modelos
ExecStart=/opt/vllm-venv/bin/python3 -m vllm.entrypoints.openai.api_server \
--model /opt/modelos/mistral-7b \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.90
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
EOF
sudo useradd -r -s /bin/false vllm
sudo systemctl daemon-reload
sudo systemctl enable vllm
sudo systemctl start vllm
Inferencia por Lotes con Python
#!/usr/bin/env python3
# Inferencia batch directa sin servidor (para procesamiento offline)
from vllm import LLM, SamplingParams
# Cargar el modelo directamente en memoria
llm = LLM(
model="/opt/modelos/mistral-7b",
gpu_memory_utilization=0.85,
max_model_len=4096
)
# Configurar los parámetros de muestreo
params = SamplingParams(
temperature=0.8,
top_p=0.95,
max_tokens=256
)
# Procesar múltiples prompts en paralelo (batch)
prompts = [
"Explica qué es Docker en 3 puntos:",
"¿Cuáles son las ventajas de Kubernetes?",
"¿Cómo funciona una VPN?",
"Describe el proceso de arranque de Linux:",
]
# Inferencia batch (mucho más eficiente que una por una)
salidas = llm.generate(prompts, params)
for prompt, salida in zip(prompts, salidas):
print(f"Pregunta: {prompt}")
print(f"Respuesta: {salida.outputs[0].text}")
print(f"Tokens: {len(salida.outputs[0].token_ids)}")
print("---")
Solución de Problemas
Error: CUDA out of memory
# Reducir el uso de memoria o usar cuantización
python3 -m vllm.entrypoints.openai.api_server \
--model /opt/modelos/mistral-7b \
--gpu-memory-utilization 0.80 \ # Reducir desde 0.90
--max-model-len 4096 # Reducir el contexto máximo
El servidor tarda mucho en iniciar
# El tiempo de inicio incluye la carga del modelo en VRAM
# Normal: 30-120 segundos dependiendo del tamaño del modelo
# Ver el progreso
sudo journalctl -u vllm -f
Alta latencia en la primera solicitud
# El primer token es siempre el más lento (TTFT - Time To First Token)
# Esto es normal, las solicitudes siguientes son más rápidas
# Para aplicaciones interactivas, usa streaming
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mistral-7b",
"messages": [{"role": "user", "content": "Hola"}],
"stream": true
}'
Error: Model not found
# Verificar que el modelo está en el directorio correcto
ls -la /opt/modelos/mistral-7b/
# Verificar los archivos del modelo
ls /opt/modelos/mistral-7b/*.safetensors
ls /opt/modelos/mistral-7b/config.json
Conclusión
vLLM es la opción definitiva para servir LLMs en producción cuando el rendimiento es crítico. Su algoritmo PagedAttention elimina el desperdicio de memoria y permite procesar muchas más solicitudes concurrentes con el mismo hardware comparado con cualquier alternativa. Con la API compatible con OpenAI y el soporte para cuantización AWQ/GPTQ, migrar aplicaciones existentes a un servidor de inferencia local es tan simple como cambiar la URL base del cliente.


