# vLLM

Servidor de inferencia LLM de alto rendimiento para cargas de trabajo de producción en GPUs de CLORE.AI.

{% hint style="success" %}
Todos los ejemplos pueden ejecutarse en servidores GPU alquilados a través de [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

{% hint style="info" %}
**Versión actual: v0.7.x** — Esta guía cubre vLLM v0.7.3+. Las nuevas funciones incluyen compatibilidad con DeepSeek-R1, salidas estructuradas con selección automática de herramientas, servicio multi-LoRA y una mejor eficiencia de memoria.
{% endhint %}

## Requisitos del servidor

| Parámetro        | Mínimo       | Recomendado |
| ---------------- | ------------ | ----------- |
| RAM              | **16 GB**    | 32 GB+      |
| VRAM             | 16 GB (7B)   | 24 GB+      |
| Red              | 500 Mbps     | 1 Gbps+     |
| Tiempo de inicio | 5-15 minutos | -           |

{% hint style="info" %}
¿Necesitas una GPU compatible? Una [RTX 4090 (24 GB)](https://clore.ai/rent-4090.html?utm_source=docs\&utm_medium=guide\&utm_campaign=vllm) maneja cómodamente 7B–13B; para modelos de 70B+ una [H100 (80 GB)](https://clore.ai/rent-h100.html?utm_source=docs\&utm_medium=guide\&utm_campaign=vllm) es la opción más segura.
{% endhint %}

{% hint style="danger" %}
**Importante:** vLLM requiere una cantidad significativa de RAM y VRAM. Los servidores con menos de 16 GB de RAM no podrán ejecutar ni siquiera modelos de 7B.
{% endhint %}

{% hint style="warning" %}
**Tiempo de inicio:** El primer inicio descarga el modelo desde HuggingFace (5-15 minutos según el tamaño del modelo y la velocidad de la red). Un HTTP 502 durante este tiempo es normal.
{% endhint %}

## ¿Por qué vLLM?

* **Mayor rendimiento** - PagedAttention para un rendimiento 24x mayor
* **Listo para producción** - API compatible con OpenAI desde el principio
* **Batching continuo** - Servicio eficiente para múltiples usuarios
* **Streaming** - Generación de tokens en tiempo real
* **Multi-GPU** - Paralelismo de tensores para modelos grandes
* **Multi-LoRA** - Sirve varios adaptadores ajustados simultáneamente (v0.7+)
* **Salidas estructuradas** - Aplicación de esquema JSON y llamada de herramientas (v0.7+)

## Despliegue rápido en CLORE.AI

**Imagen de Docker:**

```
vllm/vllm-openai:v0.7.3
```

**Puertos:**

```
22/tcp
8000/http
```

**Comando:**

```bash
vllm serve mistralai/Mistral-7B-Instruct-v0.2 --host 0.0.0.0 --port 8000
```

### Verifica que esté funcionando

Después del despliegue, encuentra tu `http_pub` URL en **Mis pedidos**:

```bash
# Comprueba el estado (puede tardar 5-15 min en la primera ejecución)
curl https://your-http-pub.clorecloud.net/health

# Lista los modelos (solo funciona después de que el modelo se cargue)
curl https://your-http-pub.clorecloud.net/v1/models
```

{% hint style="warning" %}
Si obtienes HTTP 502 durante más de 15 minutos, comprueba:

1. El servidor tiene 16 GB+ de RAM
2. El servidor tiene suficiente VRAM para el modelo
3. El token de HuggingFace está configurado para modelos restringidos
   {% endhint %}

## Acceso a tu servicio

Cuando se despliega en CLORE.AI, accede a vLLM a través de la `http_pub` URL:

```bash
# Finalización de chat
curl https://your-http-pub.clorecloud.net/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistralai/Mistral-7B-Instruct-v0.2",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

{% hint style="info" %}
Todos `localhost:8000` los ejemplos a continuación funcionan cuando se conecta por SSH. Para acceso externo, reemplaza con tu `https://your-http-pub.clorecloud.net/` URL.
{% endhint %}

## Instalación

### Usando Docker (recomendado)

```bash
docker run -d --gpus all \
    -p 8000:8000 \
    --ipc=host \
    vllm/vllm-openai:v0.7.3 \
    --model mistralai/Mistral-7B-Instruct-v0.2 \
    --host 0.0.0.0
```

### Usando pip

```bash
pip install vllm==0.7.3

# Iniciar servidor
python -m vllm.entrypoints.openai.api_server \
    --model mistralai/Mistral-7B-Instruct-v0.2
```

## Modelos compatibles

| Modelo                        | Parámetros | VRAM requerida     | RAM requerida |
| ----------------------------- | ---------- | ------------------ | ------------- |
| Mistral 7B                    | 7B         | 14 GB              | 16 GB+        |
| Llama 3.1 8B                  | 8B         | 16 GB              | 16 GB+        |
| Llama 3.1 70B                 | 70B        | 140 GB (o 2x80 GB) | 64 GB+        |
| Mixtral 8x7B                  | 47B        | 90 GB              | 32 GB+        |
| Qwen2.5 7B                    | 7B         | 14 GB              | 16 GB+        |
| Qwen2.5 72B                   | 72B        | 145 GB             | 64 GB+        |
| DeepSeek-V3                   | 236B MoE   | Multi-GPU          | 128 GB+       |
| DeepSeek-R1-Distill-Qwen-7B   | 7B         | 14 GB              | 16 GB+        |
| DeepSeek-R1-Distill-Qwen-32B  | 32B        | 64 GB              | 32 GB+        |
| DeepSeek-R1-Distill-Llama-70B | 70B        | 140 GB             | 64 GB+        |
| Phi-4                         | 14B        | 28 GB              | 32 GB+        |
| Gemma 2 9B                    | 9B         | 18 GB              | 16 GB+        |
| CodeLlama 34B                 | 34B        | 68 GB              | 32 GB+        |

## Opciones del servidor

### Servidor básico

```bash
vllm serve mistralai/Mistral-7B-Instruct-v0.2 \
    --host 0.0.0.0 \
    --port 8000
```

### Servidor de producción

```bash
vllm serve mistralai/Mistral-7B-Instruct-v0.2 \
    --host 0.0.0.0 \
    --port 8000 \
    --tensor-parallel-size 1 \
    --max-model-len 8192 \
    --gpu-memory-utilization 0.9 \
    --max-num-seqs 256 \
    --enable-prefix-caching
```

### Con cuantización (menor VRAM)

```bash
# Modelo cuantizado AWQ (usa menos VRAM)
vllm serve TheBloke/Mistral-7B-Instruct-v0.2-AWQ \
    --host 0.0.0.0 \
    --quantization awq
```

### Salidas estructuradas y llamada de herramientas (v0.7+)

Habilita la elección automática de herramientas y salidas JSON estructuradas:

```bash
vllm serve mistralai/Mistral-7B-Instruct-v0.2 \
    --host 0.0.0.0 \
    --enable-auto-tool-choice \
    --tool-call-parser mistral
```

Usar en Python:

```python
from openai import OpenAI
import json

client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Obtener el clima actual de una ciudad",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "Nombre de la ciudad"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["city"]
            }
        }
    }
]

response = client.chat.completions.create(
    model="mistralai/Mistral-7B-Instruct-v0.2",
    messages=[{"role": "user", "content": "¿Cuál es el clima en París?"}],
    tools=tools,
    tool_choice="auto"
)

# Analizar la llamada a la herramienta
tool_call = response.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
print(f"Herramienta: {tool_call.function.name}, Args: {args}")
```

Salida JSON estructurada mediante el formato de respuesta:

```python
response = client.chat.completions.create(
    model="mistralai/Mistral-7B-Instruct-v0.2",
    messages=[{"role": "user", "content": "Extrae: John Smith, 30 años, ingeniero de software"}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "person",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "occupation": {"type": "string"}
                },
                "required": ["name", "age", "occupation"]
            }
        }
    }
)
print(response.choices[0].message.content)
```

### Servicio Multi-LoRA (v0.7+)

Sirve un modelo base con múltiples adaptadores LoRA simultáneamente:

```bash
vllm serve meta-llama/Meta-Llama-3.1-8B-Instruct \
    --host 0.0.0.0 \
    --enable-lora \
    --lora-modules \
        sql-adapter=path/to/sql-lora \
        code-adapter=path/to/code-lora \
        chat-adapter=path/to/chat-lora \
    --max-lora-rank 64
```

Consulta un adaptador LoRA específico por nombre de modelo:

```python
# Usar el adaptador SQL
response = client.chat.completions.create(
    model="sql-adapter",
    messages=[{"role": "user", "content": "Escribe una consulta SQL para encontrar los 10 principales clientes"}]
)

# Usar el adaptador de código
response = client.chat.completions.create(
    model="code-adapter",
    messages=[{"role": "user", "content": "Escribe una función de Python para ordenar una lista"}]
)
```

## Compatibilidad con DeepSeek-R1 (v0.7+)

vLLM v0.7+ tiene compatibilidad nativa con los modelos distill de DeepSeek-R1. Estos modelos de razonamiento producen `<think>` etiquetas que muestran su proceso de razonamiento.

### DeepSeek-R1-Distill-Qwen-7B (GPU única)

```bash
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \
    --host 0.0.0.0 \
    --port 8000 \
    --max-model-len 16384
```

### DeepSeek-R1-Distill-Qwen-32B (GPU doble)

```bash
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-32B \
    --host 0.0.0.0 \
    --port 8000 \
    --tensor-parallel-size 2 \
    --max-model-len 32768 \
    --gpu-memory-utilization 0.90
```

### DeepSeek-R1-Distill-Llama-70B (GPU cuádruple)

```bash
vllm serve deepseek-ai/DeepSeek-R1-Distill-Llama-70B \
    --host 0.0.0.0 \
    --port 8000 \
    --tensor-parallel-size 4 \
    --max-model-len 32768
```

### Consulta de DeepSeek-R1

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")

response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
    messages=[
        {
            "role": "user",
            "content": "Resuelve: Si un tren recorre 120 km en 1,5 horas, ¿cuál es su velocidad en m/s?"
        }
    ],
    max_tokens=2048,
    temperature=0.6
)

content = response.choices[0].message.content
# La respuesta incluye un bloque de razonamiento <think>...</think> seguido de la respuesta
print(content)
```

Analizando etiquetas think:

```python
import re

def parse_deepseek_r1_response(content: str) -> dict:
    """Extraer el pensamiento y la respuesta de la respuesta de DeepSeek-R1."""
    think_match = re.search(r'<think>(.*?)</think>', content, re.DOTALL)
    thinking = think_match.group(1).strip() if think_match else ""
    answer = re.sub(r'<think>.*?</think>', '', content, flags=re.DOTALL).strip()
    return {"thinking": thinking, "answer": answer}

result = parse_deepseek_r1_response(content)
print("Pensamiento:", result["thinking"][:200], "...")
print("Respuesta:", result["answer"])
```

## Uso de la API

### Completions de chat (compatible con OpenAI)

```python
from openai import OpenAI

# Para acceso externo, usa tu URL http_pub:
client = OpenAI(
    base_url="https://your-http-pub.clorecloud.net/v1",
    api_key="not-needed"
)

# O mediante túnel SSH:
# client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")

response = client.chat.completions.create(
    model="mistralai/Mistral-7B-Instruct-v0.2",
    messages=[
        {"role": "user", "content": "Explica la computación cuántica"}
    ],
    max_tokens=500,
    temperature=0.7
)

print(response.choices[0].message.content)
```

### Streaming

```python
stream = client.chat.completions.create(
    model="mistralai/Mistral-7B-Instruct-v0.2",
    messages=[{"role": "user", "content": "Escribe un poema"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
```

### cURL

```bash
curl https://your-http-pub.clorecloud.net/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistralai/Mistral-7B-Instruct-v0.2",
    "messages": [{"role": "user", "content": "Hello!"}],
    "max_tokens": 100
  }'
```

### Completions de texto

```bash
curl https://your-http-pub.clorecloud.net/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistralai/Mistral-7B-Instruct-v0.2",
    "prompt": "La capital de Francia es",
    "max_tokens": 50
  }'
```

## Referencia completa de la API

vLLM proporciona endpoints compatibles con OpenAI, además de endpoints de utilidad adicionales.

### Endpoints estándar

| Endpoint               | Método | Descripción                                   |
| ---------------------- | ------ | --------------------------------------------- |
| `/v1/models`           | GET    | Lista los modelos disponibles                 |
| `/v1/chat/completions` | POST   | Finalización de chat                          |
| `/v1/completions`      | POST   | Finalización de texto                         |
| `/health`              | GET    | Verificación de estado (puede devolver vacío) |

### Endpoints adicionales

| Endpoint      | Método | Descripción                 |
| ------------- | ------ | --------------------------- |
| `/tokenize`   | POST   | Tokenizar texto             |
| `/detokenize` | POST   | Convertir tokens a texto    |
| `/version`    | GET    | Obtener la versión de vLLM  |
| `/docs`       | GET    | Documentación de Swagger UI |
| `/metrics`    | GET    | Métricas de Prometheus      |

#### Tokenizar texto

Útil para contar tokens antes de enviar solicitudes:

```bash
curl https://your-http-pub.clorecloud.net/tokenize \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistralai/Mistral-7B-Instruct-v0.2",
    "prompt": "Hola mundo"
  }'
```

Respuesta:

```json
{"count": 2, "max_model_len": 32768, "tokens": [9707, 1879]}
```

#### Detokenizar

Convierte IDs de tokens de nuevo a texto:

```bash
curl https://your-http-pub.clorecloud.net/detokenize \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistralai/Mistral-7B-Instruct-v0.2",
    "tokens": [9707, 1879]
  }'
```

Respuesta:

```json
{"prompt": "Hola mundo"}
```

#### Obtener versión

```bash
curl https://your-http-pub.clorecloud.net/version
```

Respuesta:

```json
{"version": "0.7.3"}
```

#### Documentación de Swagger

Ábrelo en el navegador para una documentación interactiva de la API:

```
https://your-http-pub.clorecloud.net/docs
```

#### Métricas de Prometheus

Para monitoreo:

```bash
curl https://your-http-pub.clorecloud.net/metrics
```

{% hint style="info" %}
**Modelos de razonamiento:** DeepSeek-R1 y modelos similares incluyen `<think>` etiquetas en las respuestas que muestran el proceso de razonamiento del modelo antes de la respuesta final.
{% endhint %}

## Puntos de referencia

### Rendimiento (tokens/seg por usuario)

| Modelo             | RTX 3090 | RTX 4090 | A100 40 GB | A100 80 GB |
| ------------------ | -------- | -------- | ---------- | ---------- |
| Mistral 7B         | 100      | 170      | 210        | 230        |
| Llama 3.1 8B       | 95       | 150      | 200        | 220        |
| Llama 3.1 8B (AWQ) | 130      | 190      | 260        | 280        |
| Mixtral 8x7B       | -        | 45       | 70         | 85         |
| Llama 3.1 70B      | -        | -        | 25 (2x)    | 45 (2x)    |
| DeepSeek-R1 7B     | 90       | 145      | 190        | 210        |
| DeepSeek-R1 32B    | -        | -        | 40         | 70 (2x)    |

*Puntos de referencia actualizados en enero de 2026.*

### Longitud de contexto vs VRAM

| Modelo   | ctx de 4K | ctx de 8K | ctx de 16K | ctx de 32K |
| -------- | --------- | --------- | ---------- | ---------- |
| 8B FP16  | 18 GB     | 22 GB     | 30 GB      | 46 GB      |
| 8B AWQ   | 8 GB      | 10 GB     | 14 GB      | 22 GB      |
| 70B FP16 | 145 GB    | 160 GB    | 190 GB     | 250 GB     |
| 70B AWQ  | 42 GB     | 50 GB     | 66 GB      | 98 GB      |

## Autenticación de Hugging Face

Para modelos restringidos (Llama, etc.):

```bash
# Establecer token en el comando
vllm serve meta-llama/Meta-Llama-3.1-8B-Instruct \
    --host 0.0.0.0 \
    --env HUGGING_FACE_HUB_TOKEN=hf_xxxxx
```

O establecerlo como variable de entorno:

```bash
export HUGGING_FACE_HUB_TOKEN=hf_xxxxx
```

## Requisitos de GPU

| Modelo | VRAM mín. | RAM mín.  | Recomendado                 |
| ------ | --------- | --------- | --------------------------- |
| 7-8B   | 16 GB     | **16 GB** | 24 GB de VRAM, 32 GB de RAM |
| 13B    | 26 GB     | 32 GB     | 40 GB de VRAM               |
| 34B    | 70 GB     | 32 GB     | 80 GB de VRAM               |
| 70B    | 140 GB    | 64 GB     | 2x80 GB                     |

## Estimación de costos

Tarifas típicas del marketplace de CLORE.AI:

| GPU      | VRAM  | Precio/día | Ideal para        |
| -------- | ----- | ---------- | ----------------- |
| RTX 3090 | 24 GB | $0.30–1.00 | modelos de 7-8B   |
| RTX 4090 | 24 GB | $0.50–2.00 | 7-13B, rápido     |
| A100     | 40 GB | $1.50–3.00 | modelos de 13-34B |
| A100     | 80 GB | $2.00–4.00 | modelos de 34-70B |

*Precios en USD/día. Las tarifas varían según el proveedor — consulta* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *para ver las tarifas actuales.*

## Solución de problemas

### HTTP 502 durante mucho tiempo

1. **Comprueba la RAM:** El servidor debe tener 16 GB+ de RAM
2. **Comprueba la VRAM:** Debe caber el modelo
3. **Descarga del modelo:** La primera ejecución descarga desde HuggingFace (5-15 min)
4. **Token HF:** Los modelos restringidos requieren autenticación

### Falta de memoria

```bash
# Reducir el uso de memoria
--gpu-memory-utilization 0.8
--max-model-len 4096
--max-num-seqs 64

# O usar cuantización
--quantization awq
```

### La descarga del modelo falla

```bash
# Verificar token de HF
echo $HUGGING_FACE_HUB_TOKEN

# Pre-descargar el modelo
huggingface-cli download mistralai/Mistral-7B-Instruct-v0.2
```

## vLLM frente a otros

| Funcionalidad              | vLLM       | llama.cpp | Ollama   |
| -------------------------- | ---------- | --------- | -------- |
| Rendimiento                | Mejor      | Bueno     | Bueno    |
| Uso de VRAM                | Alto       | Bajo      | Medio    |
| Facilidad de uso           | Medio      | Medio     | Fácil    |
| Tiempo de inicio           | 5-15 min   | 1-2 min   | 30 seg   |
| Multi-GPU                  | Nativo     | Limitado  | Limitado |
| Invocación de herramientas | Sí (v0.7+) | Limitado  | Limitado |
| Multi-LoRA                 | Sí (v0.7+) | No        | No       |

**Usa vLLM cuando:**

* El alto rendimiento es la prioridad
* Sirves a varios usuarios
* Tienes suficiente VRAM y RAM
* Despliegue en producción
* Necesitas invocación de herramientas / salidas estructuradas

**Usa Ollama cuando:**

* Se necesita una configuración rápida
* Un solo usuario
* Hay menos recursos disponibles

## Próximos pasos

* [Ollama](/guides/guides_v2-es/modelos-de-lenguaje/ollama.md) - Alternativa más sencilla con inicio más rápido
* [DeepSeek-R1](/guides/guides_v2-es/modelos-de-lenguaje/deepseek-r1.md) - Guía del modelo de razonamiento
* [DeepSeek-V3](/guides/guides_v2-es/modelos-de-lenguaje/deepseek-v3.md) - Mejor modelo general
* [Qwen2.5](/guides/guides_v2-es/modelos-de-lenguaje/qwen25.md) - Modelos multilingües
* [Llama.cpp](/guides/guides_v2-es/modelos-de-lenguaje/llamacpp-server.md) - Opción de menor VRAM


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-es/modelos-de-lenguaje/vllm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
