Saltar al contenido
AI•3 min de lectura

Tu primer servidor vLLM (hello world)

El pod ya corre. Ahora lo importante: instalar vLLM, descargar un modelo de 30B y encender tu primer servidor de inferencia en internet. Son 20 minutos de trabajo real; el resto es espera de descarga.

Vamos a servir Qwen3-Coder-30B-A3B-Instruct-FP8, el mismo modelo de mi PoC: un MoE de 30B totales con ~3B activos por token (expliqué cómo funciona eso en MoE por dentro), en FP8 para caber en los 48 GB de la L40S, y con licencia Apache-2.0.

1. Preparar el entorno

Copia bloque por bloque en la terminal web del pod:

# terminal del pod
pip install -q uv
uv venv /root/venv-vllm --python 3.12
source /root/venv-vllm/bin/activate
uv pip install vllm hf_transfer

vllm --version    # anótala: te servirá para reproducir todo
nvidia-smi        # debes ver 1x L40S con 48 GB

El venv vive en /root (container disk) porque necesita permisos POSIX reales; los pesos irán al volumen. Si te pierdes en el porqué, es la lección del capítulo 3.

2. Descargar el modelo (~31 GB)

# terminal del pod
export HF_HUB_ENABLE_HF_TRANSFER=1
hf download Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8
du -sh /workspace/hf    # debe dar ~31 GB

HF_HOME ya apunta a /workspace/hf gracias al .bashrc del capítulo 3. La descarga tarda 5-12 minutos según la red. hf_transfer acelera con descargas paralelas.

3. Inventar tu API key

# terminal del pod
echo 'export VLLM_API_KEY=sk-vllm-cambia-esto-123' >> ~/.bashrc
source ~/.bashrc

¿Por qué proteger un servidor que acabas de crear? Porque la URL del pod es pública: cualquiera con tu Pod ID llega. vLLM arranca con --api-key y punto.

4. Levantar vLLM

# terminal del pod
mkdir -p /workspace/poc && cd /workspace/poc

nohup vllm serve Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8 \
  --served-model-name qwen3-coder-30b \
  --max-model-len 65536 \
  --gpu-memory-utilization 0.92 \
  --kv-cache-dtype fp8 \
  --enable-prefix-caching \
  --enable-auto-tool-choice --tool-call-parser qwen3_coder \
  --api-key $VLLM_API_KEY \
  --host 0.0.0.0 --port 8000 \
  > /workspace/vllm.log 2>&1 &

tail -f /workspace/vllm.log

Los flags los diseccionamos en el capítulo 5; por ahora solo tres notas:

  • nohup ... & manda el proceso a segundo plano con log en archivo, para que no muera cuando cierres el navegador.
  • --host 0.0.0.0 es lo que hace el servidor accesible desde la URL pública. Sin eso, 502.
  • --served-model-name define el nombre con el que los clientes llamarán al modelo. No tiene que ver con el nombre de Hugging Face.

Espera 3-5 minutos y sal del tail con Ctrl-C cuando veas Uvicorn running on http://0.0.0.0:8000.

Anota el número más importante del log:

# terminal del pod
grep -i "kv cache size" /workspace/vllm.log

En una L40S deberías ver entre 150K y 200K tokens. Ese número es la memoria de contexto que te queda después de cargar los pesos, y es el que decide cuántas sesiones concurrentes aguantas. La matemática por token está en 48 KB por token.

5. Probar que responde

# terminal del pod
curl -s localhost:8000/v1/chat/completions \
  -H "Authorization: Bearer $VLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"qwen3-coder-30b","messages":[{"role":"user","content":"Di hola en 3 palabras"}]}' \
  | head -c 400

Si ves un JSON con contenido, el modelo ya está sirviendo. Ahora desde tu Mac, con la URL pública:

# tu máquina
curl -N https://TU_POD_ID-8000.proxy.runpod.net/v1/chat/completions \
  -H "Authorization: Bearer sk-vllm-cambia-esto-123" \
  -H "Content-Type: application/json" \
  -d '{"model":"qwen3-coder-30b","messages":[{"role":"user","content":"Cuenta del 1 al 5"}],"stream":true}' \
  | head -20

Ves los fragmentos data: {...} llegar uno a uno, igual que en Ollama. Mismo idioma, hardware de 48 GB al otro lado.

Checkpoint y el error típico

Checkpoint: un servidor vLLM tuyo, con 30B de parámetros, accesible por internet y hablando OpenAI-compatible. ~20 minutos de trabajo, unos $2 de GPU entre descarga y arranque.

El error típico: llamar al modelo por su nombre de Hugging Face (Qwen/Qwen3-...) en vez del --served-model-name (qwen3-coder-30b). El servidor responde "model not found" y parece que todo se rompió, cuando solo es el alias.

Dos síntomas más que verás: la URL del proxy da 502 (el servicio aún no termina de arrancar, mira vllm.log), o hf: command not found (te faltó source /root/venv-vllm/bin/activate).

Siguiente capítulo

Los 5 flags de ese comando deciden tu capacidad, tu costo y si tu agente funciona. Los abrimos uno por uno, con el número real que cada uno mueve.

¿Corrió a la primera o te comió algún flag? Cuéntame cuál en los comentarios.


> Más posts