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.0es lo que hace el servidor accesible desde la URL pública. Sin eso, 502.--served-model-namedefine 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.