# ExLlamaV2

Ejecuta LLMs a máxima velocidad con ExLlamaV2.

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

## Alquilar en CLORE.AI

1. Visita [CLORE.AI Marketplace](https://clore.ai/marketplace)
2. Filtrar por tipo de GPU, VRAM y precio
3. Elegir **Bajo demanda** (tarifa fija) o **Spot** (precio de puja)
4. Configura tu pedido:
   * Selecciona imagen Docker
   * Establece puertos (TCP para SSH, HTTP para interfaces web)
   * Agrega variables de entorno si es necesario
   * Introduce el comando de inicio
5. Selecciona pago: **CLORE**, **BTC**, o **USDT/USDC**
6. Crea el pedido y espera el despliegue

### Accede a tu servidor

* Encuentra los detalles de conexión en **Mis Pedidos**
* Interfaces web: Usa la URL del puerto HTTP
* SSH: `ssh -p <port> root@<proxy-address>`

## ¿Qué es ExLlamaV2?

ExLlamaV2 es el motor de inferencia más rápido para modelos de lenguaje grande:

* 2-3x más rápido que otros motores
* Excelente cuantización (EXL2)
* Bajo uso de VRAM
* Soporta decodificación especulativa

## Requisitos

| Tamaño del modelo | VRAM mínima | Recomendado |
| ----------------- | ----------- | ----------- |
| 7B                | 6GB         | RTX 3060    |
| 13B               | 10GB        | RTX 3090    |
| 34B               | 20GB        | RTX 4090    |
| 70B               | 40GB        | A100        |

## Despliegue rápido

**Imagen Docker:**

```
pytorch/pytorch:2.5.1-cuda12.4-cudnn9-devel
```

**Puertos:**

```
22/tcp
8080/http
```

**Comando:**

```bash
pip install exllamav2 && \
huggingface-cli download turboderp/Llama2-7B-exl2 --local-dir ./model && \
python -m exllamav2.server --model_dir ./model --host 0.0.0.0 --port 8080
```

## Accediendo a tu servicio

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

1. Ir a **Mis Pedidos** página
2. Haz clic en tu pedido
3. Encuentra la `http_pub` URL (por ejemplo, `abc123.clorecloud.net`)

Usa `https://TU_HTTP_PUB_URL` en lugar de `localhost` en los ejemplos abajo.

## Instalación

```bash

# Instalar desde PyPI
pip install exllamav2

# O desde la fuente (funciones más recientes)
git clone https://github.com/turboderp/exllamav2
cd exllamav2
pip install .
```

## Descargar modelos

### Modelos cuantizados EXL2

```bash

# Llama 3.1 8B (4.0 bpw)
huggingface-cli download turboderp/Llama2-7B-exl2 \
    --revision 4.0bpw \
    --local-dir ./llama2-7b-exl2

# Llama 3.1 8B (4.0 bpw)
huggingface-cli download turboderp/Llama2-13B-exl2 \
    --revision 4.0bpw \
    --local-dir ./llama2-13b-exl2

# Mistral 7B (4.0 bpw)
huggingface-cli download turboderp/Mistral-7B-instruct-exl2 \
    --revision 4.0bpw \
    --local-dir ./mistral-7b-exl2

# Mixtral 8x7B
huggingface-cli download turboderp/Mixtral-8x7B-instruct-exl2 \
    --revision 4.0bpw \
    --local-dir ./mixtral-exl2
```

### Bits por peso (bpw)

| BPW | Calidad   | VRAM (7B) |
| --- | --------- | --------- |
| 2.0 | Baja      | \~3GB     |
| 3.0 | Bueno     | \~4GB     |
| 4.0 | Genial    | \~5GB     |
| 5.0 | Excelente | \~6GB     |
| 6.0 | Casi-FP16 | \~7GB     |

## API de Python

### Generación básica

```python
from exllamav2 import ExLlamaV2, ExLlamaV2Config, ExLlamaV2Cache, ExLlamaV2Tokenizer
from exllamav2.generator import ExLlamaV2StreamingGenerator, ExLlamaV2Sampler

# Cargar modelo
config = ExLlamaV2Config()
config.model_dir = "./llama2-7b-exl2"
config.prepare()

model = ExLlamaV2(config)
model.load()

tokenizer = ExLlamaV2Tokenizer(config)
cache = ExLlamaV2Cache(model, lazy=True)

# Crear generador
generator = ExLlamaV2StreamingGenerator(model, cache, tokenizer)

# Configurar parámetros de muestreo
settings = ExLlamaV2Sampler.Settings()
settings.temperature = 0.7
settings.top_k = 50
settings.top_p = 0.9

# Generar
prompt = "El futuro de la inteligencia artificial es"
output = generator.generate_simple(prompt, settings, num_tokens=200)
print(output)
```

### Generación por streaming

```python
from exllamav2.generator import ExLlamaV2StreamingGenerator

generator = ExLlamaV2StreamingGenerator(model, cache, tokenizer)

prompt = "Escribe una historia corta sobre un robot:"
input_ids = tokenizer.encode(prompt)

generator.set_stop_conditions([tokenizer.eos_token_id])
generator.begin_stream(input_ids, settings)

while True:
    chunk, eos, _ = generator.stream()
    if eos:
        break
    print(chunk, end="", flush=True)
```

### Formato de chat

```python
def format_chat(messages):
    text = ""
    for msg in messages:
        role = msg["role"]
        content = msg["content"]
        if role == "system":
            text += f"[INST] <<SYS>>\n{content}\n<</SYS>>\n\n"
        elif role == "user":
            text += f"{content} [/INST]"
        elif role == "assistant":
            text += f" {content}</s><s>[INST] "
    return text

messages = [
    {"role": "system", "content": "Eres un asistente útil."},
    {"role": "user", "content": "¿Qué es Python?"}
]

prompt = format_chat(messages)
output = generator.generate_simple(prompt, settings, num_tokens=300)
```

## Modo servidor

### Iniciar servidor

```bash
python -m exllamav2.server \
    --model_dir ./llama2-7b-exl2 \
    --host 0.0.0.0 \
    --port 8080 \
    --max_seq_len 4096 \
    --cache_size 4096
```

### Uso de la API

```python
import requests

response = requests.post(
    "http://localhost:8080/v1/completions",
    json={
        "prompt": "Hola, ¿cómo estás?",
        "max_tokens": 100,
        "temperature": 0.7
    }
)

print(response.json()["choices"][0]["text"])
```

### Completados de chat

```python
import openai

client = openai.OpenAI(
    base_url="http://localhost:8080/v1",
    api_key="no-necesaria"
)

response = client.chat.completions.create(
    model="llama2-7b",
    messages=[{"role": "user", "content": "¡Hola!"}],
    temperature=0.7
)

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

## TabbyAPI (Servidor recomendado)

TabbyAPI proporciona un servidor ExLlamaV2 con muchas funciones:

```bash

# Clonar TabbyAPI
git clone https://github.com/theroyallab/tabbyAPI
cd tabbyAPI

# Instalar
pip install -r requirements.txt

# Configurar

# Edita config.yml con la ruta de tu modelo

# Ejecutar
python main.py
```

### Funciones de TabbyAPI

* API compatible con OpenAI
* Soporte para múltiples modelos
* Intercambio en caliente de LoRA
* Streaming
* Llamada a funciones
* API de administración

## Decodificación especulativa

Usa un modelo más pequeño para acelerar la generación:

```python
from exllamav2 import ExLlamaV2, ExLlamaV2Config, ExLlamaV2Cache

# Cargar modelo principal (13B)
main_config = ExLlamaV2Config()
main_config.model_dir = "./llama2-13b-exl2"
main_config.prepare()
main_model = ExLlamaV2(main_config)
main_model.load()

# Cargar modelo de borrador (7B)
draft_config = ExLlamaV2Config()
draft_config.model_dir = "./llama2-7b-exl2"
draft_config.prepare()
draft_model = ExLlamaV2(draft_config)
draft_model.load()

# Crear generador especulativo
from exllamav2.generator import ExLlamaV2DraftGenerator

generator = ExLlamaV2DraftGenerator(
    main_model, draft_model,
    cache_main, cache_draft,
    tokenizer
)

# Generar (más rápido con especulación)
output = generator.generate_simple(prompt, settings, num_tokens=500)
```

## Cuantiza tus propios modelos

### Convertir a EXL2

```python
from exllamav2 import ExLlamaV2, ExLlamaV2Config
from exllamav2.conversion import convert_model

# Fuente: modelo de HuggingFace

# Destino: cuantizado EXL2

convert_model(
    input_dir="./llama-3.1-8b-hf",
    output_dir="./llama-3.1-8b-exl2-4bpw",
    cal_dataset="wikitext",  # Conjunto de datos de calibración
    bits=4.0,  # Bits por peso
    head_bits=6,  # Mayor precisión para la atención
)
```

### Línea de comandos

```bash
python convert.py \
    -i ./llama-3.1-8b-hf \
    -o ./llama-3.1-8b-exl2 \
    -cf ./llama-3.1-8b-exl2 \
    -b 4.0 \
    -hb 6
```

## Gestión de memoria

### Asignación de caché

```python

# Tamaño de caché fijo
cache = ExLlamaV2Cache(model, max_seq_len=4096)

# Caché dinámico
cache = ExLlamaV2Cache(model, lazy=True)
cache.current_seq_len = 0  # Crece según sea necesario
```

### Multi-GPU

```python
config = ExLlamaV2Config()
config.model_dir = "./large-model"

# Dividir entre GPUs
config.set_auto_split([0.5, 0.5])  # 50% en cada GPU

model = ExLlamaV2(config)
model.load()
```

## Comparación de rendimiento

| Modelo       | Motor     | GPU      | Tokens/seg |
| ------------ | --------- | -------- | ---------- |
| Llama 3.1 8B | ExLlamaV2 | RTX 3090 | \~150      |
| Llama 3.1 8B | llama.cpp | RTX 3090 | \~100      |
| Llama 3.1 8B | vLLM      | RTX 3090 | \~120      |
| Llama 3.1 8B | ExLlamaV2 | RTX 3090 | \~90       |
| Mixtral 8x7B | ExLlamaV2 | A100     | \~70       |

## Ajustes avanzados

### Parámetros de muestreo

```python
settings = ExLlamaV2Sampler.Settings()
settings.temperature = 0.7
settings.top_k = 50
settings.top_p = 0.9
settings.token_repetition_penalty = 1.1
settings.token_frequency_penalty = 0.0
settings.token_presence_penalty = 0.0
settings.mirostat = False
settings.mirostat_tau = 5.0
settings.mirostat_eta = 0.1
```

### Generación por lotes

```python
prompts = [
    "El significado de la vida es",
    "La inteligencia artificial hará",
    "El cambio climático es"
]

outputs = []
for prompt in prompts:
    output = generator.generate_simple(prompt, settings, num_tokens=100)
    outputs.append(output)
```

## Solución de problemas

### CUDA: fuera de memoria

```python

# Usar caché más pequeño
cache = ExLlamaV2Cache(model, max_seq_len=2048)

# O modelo con bpw menor (3.0 en lugar de 4.0)
```

### Carga lenta

```python

# Habilitar carga rápida
config.fasttensors = True
```

### Modelo no encontrado

```bash

# Verificar que los archivos del modelo existan
ls ./model/

# Debe contener: config.json, *.safetensors, tokenizer.json
```

## Integración con LangChain

```python
from langchain.llms.base import LLM
from typing import Optional, List

class ExLlamaV2LLM(LLM):
    model: ExLlamaV2
    tokenizer: ExLlamaV2Tokenizer
    generator: ExLlamaV2StreamingGenerator
    settings: ExLlamaV2Sampler.Settings

    @property
    def _llm_type(self) -> str:
        return "exllamav2"

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        return self.generator.generate_simple(prompt, self.settings, num_tokens=500)

# Uso
llm = ExLlamaV2LLM(model=model, tokenizer=tokenizer, generator=generator, settings=settings)
result = llm("¿Qué es la computación cuántica?")
```

## Estimación de costos

Tarifas típicas del marketplace de CLORE.AI (a fecha de 2024):

| GPU       | Tarifa por hora | Tarifa diaria | Sesión de 4 horas |
| --------- | --------------- | ------------- | ----------------- |
| RTX 3060  | \~$0.03         | \~$0.70       | \~$0.12           |
| RTX 3090  | \~$0.06         | \~$1.50       | \~$0.25           |
| RTX 4090  | \~$0.10         | \~$2.30       | \~$0.40           |
| A100 40GB | \~$0.17         | \~$4.00       | \~$0.70           |
| A100 80GB | \~$0.25         | \~$6.00       | \~$1.00           |

*Los precios varían según el proveedor y la demanda. Consulta* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *para las tarifas actuales.*

**Ahorra dinero:**

* Usa **Spot** market para cargas de trabajo flexibles (a menudo 30-50% más barato)
* Paga con **CLORE** tokens
* Compara precios entre diferentes proveedores

## Próximos pasos

* vLLM Inference - Servicio de alto rendimiento
* [Servidor llama.cpp](https://docs.clore.ai/guides/guides_v2-es/modelos-de-lenguaje/llamacpp-server) - Multiplataforma
* [Text Generation WebUI](https://docs.clore.ai/guides/guides_v2-es/modelos-de-lenguaje/text-generation-webui) - Interfaz web
