# Modelo de lenguaje y visión Qwen2.5-VL

Qwen2.5-VL de Alibaba (diciembre de 2024) es el modelo visión-texto (VLM) de peso abierto con mejor rendimiento. Disponible en tamaños de 3B, 7B y 72B de parámetros, entiende imágenes, fotogramas de video, PDFs, gráficos y diseños visuales complejos. La variante de 7B encuentra el punto óptimo: supera a muchos modelos más grandes en benchmarks mientras funciona cómodamente en una sola GPU de 24 GB.

En [Clore.ai](https://clore.ai/) puedes alquilar la GPU exacta que necesitas — desde una RTX 3090 para el modelo 7B hasta configuraciones multi-GPU para la variante de 72B — y comenzar a analizar contenido visual en minutos.

## Características clave

* **Entrada multimodal** — imágenes, video, PDFs, capturas de pantalla, gráficos y diagramas en un único modelo.
* **Tres escalas** — 3B (edge/móvil), 7B (punto óptimo para producción), 72B (calidad SOTA).
* **Resolución dinámica** — procesa imágenes en su resolución nativa; sin forzar redimensionamiento a 224×224.
* **Comprensión de video** — acepta entrada de video con múltiples fotogramas y razonamiento temporal.
* **OCR de documentos** — extrae texto de documentos escaneados, recibos y notas manuscritas.
* **Multilingüe** — rendimiento sólido en inglés, chino y más de 20 idiomas adicionales.
* **Soporte Ollama** — ejecútalo localmente con `ollama run qwen2.5vl:7b` para despliegue sin código.
* **Integración con Transformers** — `Qwen2_5_VLForConditionalGeneration` en HuggingFace `transformers`.

## Requisitos

| Componente      | 3B    | 7B       | 72B                |
| --------------- | ----- | -------- | ------------------ |
| VRAM de GPU     | 8 GB  | 16–24 GB | 80+ GB (multi-GPU) |
| RAM del sistema | 16 GB | 32 GB    | 128 GB             |
| Disco           | 10 GB | 20 GB    | 150 GB             |
| Python          | 3.10+ | 3.10+    | 3.10+              |
| CUDA            | 12.1+ | 12.1+    | 12.1+              |

**Recomendación de GPU de Clore.ai:** Para el **modelo 7B**, un **RTX 4090** (24 GB, \~0,5–2 $/día) o **RTX 3090** (24 GB, \~0,3–1 $/día) es ideal. Para **72B**, filtra el mercado por **A100 80 GB** o configuraciones multi-GPU.

## Inicio rápido

### Opción A: Ollama (La más simple)

```bash
# Instalar ollama
curl -fsSL https://ollama.ai/install.sh | sh

# Descargar y ejecutar el modelo de visión 7B
ollama run qwen2.5vl:7b
```

Luego en el prompt de ollama:

```
>>> Describe esta imagen: /path/to/photo.jpg
```

### Opción B: Python / Transformers

```bash
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124
pip install transformers accelerate qwen-vl-utils pillow
```

## Ejemplos de uso

### Comprensión de imágenes con Transformers

```python
import torch
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info

model_name = "Qwen/Qwen2.5-VL-7B-Instruct"

model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)
processor = AutoProcessor.from_pretrained(model_name)

messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "image": "https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg"},
            {"type": "text", "text": "¿Qué especie es este insecto? Describe sus características identificativas clave."},
        ],
    }
]

text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)

inputs = processor(
    text=[text],
    images=image_inputs,
    videos=video_inputs,
    padding=True,
    return_tensors="pt",
).to(model.device)

output_ids = model.generate(**inputs, max_new_tokens=512)
response = processor.batch_decode(
    output_ids[:, inputs.input_ids.shape[1]:],
    skip_special_tokens=True,
)[0]

print(response)
```

### Análisis de video

```python
import torch
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info

model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
    "Qwen/Qwen2.5-VL-7B-Instruct",
    torch_dtype=torch.bfloat16,
    device_map="auto",
)
processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-7B-Instruct")

messages = [
    {
        "role": "user",
        "content": [
            {"type": "video", "video": "file:///workspace/clip.mp4", "max_pixels": 360 * 420, "fps": 1.0},
            {"type": "text", "text": "Resume lo que sucede en este video. Enumera los eventos clave en orden."},
        ],
    }
]

text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)

inputs = processor(
    text=[text],
    images=image_inputs,
    videos=video_inputs,
    padding=True,
    return_tensors="pt",
).to(model.device)

output_ids = model.generate(**inputs, max_new_tokens=1024)
print(processor.batch_decode(output_ids[:, inputs.input_ids.shape[1]:], skip_special_tokens=True)[0])
```

### OCR y extracción de documentos

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "image": "file:///workspace/receipt.jpg"},
            {"type": "text", "text": "Extrae todos los artículos, cantidades y precios de este recibo. Devuélvelo en formato JSON."},
        ],
    }
]

# Procesar usando la misma configuración de modelo/procesador anterior
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt").to(model.device)
output_ids = model.generate(**inputs, max_new_tokens=2048)
print(processor.batch_decode(output_ids[:, inputs.input_ids.shape[1]:], skip_special_tokens=True)[0])
```

### API de Ollama para procesamiento por lotes

```python
import ollama
import base64
from pathlib import Path

def analyze_image(image_path: str, question: str) -> str:
    """Enviar una imagen a Qwen2.5-VL a través de la API de Ollama."""
    image_data = base64.b64encode(Path(image_path).read_bytes()).decode()
    response = ollama.chat(
        model="qwen2.5vl:7b",
        messages=[{
            "role": "user",
            "content": question,
            "images": [image_data],
        }],
    )
    return response["message"]["content"]

# Procesar por lotes una carpeta de imágenes
from pathlib import Path
for img in sorted(Path("./photos").glob("*.jpg")):
    result = analyze_image(str(img), "Describe esta imagen en una frase.")
    print(f"{img.name}: {result}")
```

## Consejos para usuarios de Clore.ai

1. **Ollama para despliegue rápido** — `ollama run qwen2.5vl:7b` es la vía más rápida hacia un VLM funcionando. No se necesita código Python para uso interactivo.
2. **7B es el punto óptimo** — la variante 7B Instruct cabe en 16 GB de VRAM con cuantización a 4 bits y ofrece una calidad competitiva con modelos mucho más grandes.
3. **La resolución dinámica importa** — Qwen2.5-VL procesa imágenes en resolución nativa. Para imágenes grandes (>4K), redimensiona a un ancho máximo de 1920 px para evitar uso excesivo de VRAM.
4. **Configuración de fps de video** — para entrada de video, establece `fps=1.0` para muestrear 1 fotograma por segundo. Valores más altos consumen VRAM rápidamente; 1 fps es suficiente para la mayoría de las tareas de análisis.
5. **Almacenamiento persistente** — establece `HF_HOME=/workspace/hf_cache`; el modelo 7B ocupa \~15 GB. Para ollama, los modelos se ubican en `~/.ollama/models/`.
6. **Salida estructurada** — Qwen2.5-VL sigue bien las instrucciones de formato JSON. Pide "Devolver como JSON" y obtendrás una salida parseable la mayoría de las veces.
7. **Comparación de múltiples imágenes** — puedes pasar varias imágenes en un solo mensaje para tareas de comparación (por ejemplo, "¿Cuál de estos dos productos parece más premium?").
8. **tmux** — siempre ejecútalo dentro de `tmux` en los alquileres de Clore.ai.

## Solución de problemas

| Problema                                  | Solucionar                                                                                            |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `OutOfMemoryError` con 7B                 | Usa `load_in_4bit=True` en `from_pretrained()` con `bitsandbytes`; o usa la variante 3B               |
| Modelo de Ollama no encontrado            | `ollama pull qwen2.5vl:7b` — asegúrate de tener la etiqueta correcta                                  |
| Procesamiento de video lento              | Reducir `fps` a 0.5 y `max_pixels` a `256 * 256`; menos fotogramas = inferencia más rápida            |
| Salida garbled o vacía                    | Aumenta `max_new_tokens`; el valor por defecto puede ser demasiado bajo para descripciones detalladas |
| `ImportError: qwen_vl_utils`              | `pip install qwen-vl-utils` — requerido para `process_vision_info()`                                  |
| El modelo 72B no cabe                     | Usa 2× A100 80 GB con `device_map="auto"` o aplica cuantización AWQ                                   |
| Ruta de imagen no encontrada              | Para archivos locales en mensajes, usa `file:///absolute/path` formato                                |
| Chino en la salida al solicitar en inglés | Agrega "Responde solo en inglés." a tu prompt                                                         |


---

# 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/qwen-vl.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.
