# Llama 3.2 Vision

Ejecute los modelos multimodales Llama 3.2 Vision de Meta para comprensión de imágenes en las GPU de CLORE.AI.

{% 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 %}

## ¿Por qué Llama 3.2 Vision?

* **Multimodal** - Comprende tanto texto como imágenes
* **Múltiples tamaños** - Versiones de 11B y 90B parámetros
* **Versátil** - OCR, preguntas y respuestas visuales, generación de subtítulos de imágenes, análisis de documentos
* **Pesos abiertos** - Completamente de código abierto por Meta
* **Ecosistema Llama** - Compatible con Ollama, vLLM, transformers

## Variantes de modelo

| Modelo                        | Parámetros | VRAM (FP16) | Contexto | Mejor para             |
| ----------------------------- | ---------- | ----------- | -------- | ---------------------- |
| Llama-3.2-11B-Vision          | 11B        | 24GB        | 128K     | Uso general, GPU única |
| Llama-3.2-90B-Vision          | 90B        | 180GB       | 128K     | Calidad máxima         |
| Llama-3.2-11B-Vision-Instruct | 11B        | 24GB        | 128K     | Chat/asistente         |
| Llama-3.2-90B-Vision-Instruct | 90B        | 180GB       | 128K     | Producción             |

## Despliegue rápido en CLORE.AI

**Imagen Docker:**

```
vllm/vllm-openai:latest
```

**Puertos:**

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

**Comando:**

```bash
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.2-11B-Vision-Instruct \
    --host 0.0.0.0 \
    --port 8000 \
    --max-model-len 8192
```

## 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.

## Requisitos de hardware

| Modelo     | GPU mínima    | Recomendado  | Óptimo    |
| ---------- | ------------- | ------------ | --------- |
| 11B Vision | RTX 4090 24GB | A100 40GB    | A100 80GB |
| 90B Vision | 4x A100 40GB  | 4x A100 80GB | 8x H100   |

## Instalación

### Usando Ollama (Más fácil)

```bash
# Descargar el modelo
ollama pull llama3.2-vision:11b

# Ejecutar interactivo
ollama run llama3.2-vision:11b
```

### Usando vLLM

```bash
pip install vllm

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.2-11B-Vision-Instruct \
    --host 0.0.0.0 \
    --port 8000
```

### Usando Transformers

```python
import torch
from transformers import MllamaForConditionalGeneration, AutoProcessor

model_id = "meta-llama/Llama-3.2-11B-Vision-Instruct"

model = MllamaForConditionalGeneration.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto"
)
processor = AutoProcessor.from_pretrained(model_id)
```

## Uso básico

### Comprensión de imágenes

```python
import torch
from transformers import MllamaForConditionalGeneration, AutoProcessor
from PIL import Image
import requests

model_id = "meta-llama/Llama-3.2-11B-Vision-Instruct"

model = MllamaForConditionalGeneration.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto"
)
processor = AutoProcessor.from_pretrained(model_id)

# Cargar imagen
url = "https://example.com/image.jpg"
image = Image.open(requests.get(url, stream=True).raw)

# Crear prompt
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "¿Qué hay en esta imagen? Describe en detalle."}
        ]
    }
]

input_text = processor.apply_chat_template(messages, add_generation_prompt=True)
inputs = processor(image, input_text, return_tensors="pt").to(model.device)

output = model.generate(**inputs, max_new_tokens=500)
print(processor.decode(output[0], skip_special_tokens=True))
```

### Con Ollama

```bash
# Describir una imagen
ollama run llama3.2-vision:11b "Describe esta imagen: /ruta/a/imagen.jpg"

# O usa la API
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2-vision:11b",
  "prompt": "¿Qué hay en esta imagen?",
  "images": ["imagen_codificada_en_base64_aquí"]
}'
```

### Con la API de vLLM

```python
from openai import OpenAI
import base64

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

# Codificar imagen a base64
with open("image.jpg", "rb") as f:
    image_base64 = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="meta-llama/Llama-3.2-11B-Vision-Instruct",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "¿Qué hay en esta imagen?"},
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/jpeg;base64,{image_base64}"}
                }
            ]
        }
    ],
    max_tokens=500
)

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

## Casos de uso

### OCR / Extracción de texto

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Extrae todo el texto de esta imagen. Formatea como markdown."}
        ]
    }
]
```

### Análisis de documentos

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Analiza este documento. Resume los puntos clave."}
        ]
    }
]
```

### Preguntas y respuestas visuales

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "¿Cuántas personas hay en esta foto? ¿Qué están haciendo?"}
        ]
    }
]
```

### Generación de subtítulos para imágenes

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Escribe un subtítulo detallado para esta imagen adecuado para redes sociales."}
        ]
    }
]
```

### Código a partir de capturas de pantalla

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Convierte esta captura de pantalla de la interfaz en código HTML/CSS."}
        ]
    }
]
```

## Múltiples imágenes

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "image"},
            {"type": "text", "text": "Compara estas dos imágenes. ¿Cuáles son las diferencias?"}
        ]
    }
]

# Procesar con múltiples imágenes
inputs = processor(
    images=[image1, image2],
    text=input_text,
    return_tensors="pt"
).to(model.device)
```

## Procesamiento por lotes

```python
import os
from PIL import Image

def process_images(image_paths, prompt):
    results = []

    for path in image_paths:
        image = Image.open(path)

        messages = [
            {
                "role": "user",
                "content": [
                    {"type": "image"},
                    {"type": "text", "text": prompt}
                ]
            }
        ]

        input_text = processor.apply_chat_template(messages, add_generation_prompt=True)
        inputs = processor(image, input_text, return_tensors="pt").to(model.device)

        output = model.generate(**inputs, max_new_tokens=300)
        result = processor.decode(output[0], skip_special_tokens=True)

        results.append({"file": path, "description": result})

        # Limpiar caché entre imágenes
        torch.cuda.empty_cache()

    return results

# Procesar carpeta
images = [f"./images/{f}" for f in os.listdir("./images") if f.endswith(('.jpg', '.png'))]
results = process_images(images, "Describe esta imagen en un párrafo.")
```

## Interfaz Gradio

```python
import gradio as gr
import torch
from transformers import MllamaForConditionalGeneration, AutoProcessor
from PIL import Image

model_id = "meta-llama/Llama-3.2-11B-Vision-Instruct"
model = MllamaForConditionalGeneration.from_pretrained(
    model_id, torch_dtype=torch.bfloat16, device_map="auto"
)
processor = AutoProcessor.from_pretrained(model_id)

def analyze_image(image, question):
    messages = [
        {
            "role": "user",
            "content": [
                {"type": "image"},
                {"type": "text", "text": question}
            ]
        }
    ]

    input_text = processor.apply_chat_template(messages, add_generation_prompt=True)
    inputs = processor(image, input_text, return_tensors="pt").to(model.device)

    output = model.generate(**inputs, max_new_tokens=500)
    return processor.decode(output[0], skip_special_tokens=True)

demo = gr.Interface(
    fn=analyze_image,
    inputs=[
        gr.Image(type="pil", label="Subir imagen"),
        gr.Textbox(label="Pregunta", placeholder="¿Qué hay en esta imagen?")
    ],
    outputs=gr.Textbox(label="Response"),
    title="Llama 3.2 Vision - Análisis de imágenes",
    description="Sube una imagen y hazle preguntas. Ejecutándose en CLORE.AI."
)

demo.launch(server_name="0.0.0.0", server_port=7860)
```

## Rendimiento

| Tarea                       | Modelo | GPU       | Tiempo |
| --------------------------- | ------ | --------- | ------ |
| Descripción de imagen única | 11B    | RTX 4090  | \~3s   |
| Descripción de imagen única | 11B    | A100 40GB | \~2s   |
| OCR (1 página)              | 11B    | RTX 4090  | \~5s   |
| Análisis de documentos      | 11B    | A100 40GB | \~8s   |
| Lote (10 imágenes)          | 11B    | A100 40GB | \~25s  |

## Cuantización

### 4-bit con bitsandbytes

```python
from transformers import BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = MllamaForConditionalGeneration.from_pretrained(
    model_id,
    quantization_config=quantization_config,
    device_map="auto"
)
```

### GGUF con Ollama

```bash
# Cuantizado a 4 bits (cabe en 8GB de VRAM)
ollama pull llama3.2-vision:11b-q4_K_M

# Cuantizado a 8 bits
ollama pull llama3.2-vision:11b-q8_0
```

## Estimación de costos

Tarifas típicas del mercado de CLORE.AI:

| GPU           | Tarifa por hora | Mejor para             |
| ------------- | --------------- | ---------------------- |
| RTX 4090 24GB | \~$0.10         | Modelo 11B             |
| A100 40GB     | \~$0.17         | 11B con contexto largo |
| A100 80GB     | \~$0.25         | 11B óptimo             |
| 4x A100 80GB  | \~$1.00         | Modelo 90B             |

*Los precios varían. Consulta* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *para las tarifas actuales.*

**Ahorra dinero:**

* Usa **Spot** órdenes para procesamiento por lotes
* Paga con **CLORE** tokens
* Use modelos cuantizados (4 bits) para desarrollo

## Solución de problemas

### Memoria insuficiente

```python
# Usar cuantización de 4 bits
model = MllamaForConditionalGeneration.from_pretrained(
    model_id,
    load_in_4bit=True,
    device_map="auto"
)

# O reduzca max_new_tokens
output = model.generate(**inputs, max_new_tokens=256)
```

### Generación lenta

* Asegúrese de que se esté usando la GPU (verifique `nvidia-smi`)
* Use bfloat16 en lugar de float32
* Reduzca la resolución de la imagen antes de procesarla
* Use vLLM para mejor rendimiento

### Imagen no cargando

```python
from PIL import Image
import requests
from io import BytesIO

# Desde URL
response = requests.get(url)
image = Image.open(BytesIO(response.content)).convert("RGB")

# Desde archivo
image = Image.open("path/to/image.jpg").convert("RGB")

# Redimensionar si es demasiado grande
max_size = 1024
if max(image.size) > max_size:
    image.thumbnail((max_size, max_size))
```

### Token de HuggingFace requerido

```bash
# Establecer token para modelos con acceso restringido
export HUGGING_FACE_HUB_TOKEN=hf_xxxxx

# O iniciar sesión
huggingface-cli login
```

## Llama Vision vs Otros

| Función        | Llama 3.2 Vision | LLaVA 1.6  | GPT-4V       |
| -------------- | ---------------- | ---------- | ------------ |
| Parámetros     | 11B / 90B        | 7B / 34B   | Desconocido  |
| Código abierto | Sí               | Sí         | No           |
| Calidad de OCR | Excelente        | Bueno      | Excelente    |
| Contexto       | 128K             | 32K        | 128K         |
| Multi-imagen   | Sí               | Limitado   | Sí           |
| Licencia       | Llama 3.2        | Apache 2.0 | Proprietario |

**Usa Llama 3.2 Vision cuando:**

* Necesitas multimodal de código abierto
* OCR y análisis de documentos
* Integración con el ecosistema Llama
* Comprensión de contexto largo

## Próximos pasos

* [LLaVA](/guides/guides_v2-es/modelos-de-vision/llava-vision-language.md) - Modelo de visión alternativo
* [Florence-2](/guides/guides_v2-es/modelos-de-vision/florence2.md) - Modelo de visión de Microsoft
* [Ollama](/guides/guides_v2-es/modelos-de-lenguaje/ollama.md) - Despliegue sencillo
* [vLLM](/guides/guides_v2-es/modelos-de-lenguaje/vllm.md) - Servir en producción


---

# 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-vision/llama-vision.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.
