# Modèle vision-langage Qwen2.5-VL

Qwen2.5-VL d'Alibaba (décembre 2024) est le modèle vision-langage (VLM) open-weight le plus performant. Disponible en tailles 3B, 7B et 72B de paramètres, il comprend les images, les images vidéo, les PDF, les graphiques et les mises en page visuelles complexes. La variante 7B représente le meilleur compromis — elle surpasse de nombreux modèles plus grands sur les benchmarks tout en fonctionnant confortablement sur un seul GPU de 24 Go.

Sur [Clore.ai](https://clore.ai/) vous pouvez louer le GPU exact dont vous avez besoin — d'une RTX 3090 pour le modèle 7B aux configurations multi-GPU pour la variante 72B — et commencer à analyser du contenu visuel en quelques minutes.

## Principales caractéristiques

* **Entrée multimodale** — images, vidéo, PDF, captures d'écran, graphiques et schémas dans un seul modèle.
* **Trois tailles** — 3B (edge/mobile), 7B (point idéal pour la production), 72B (qualité SOTA).
* **Résolution dynamique** — traite les images à leur résolution native ; pas de redimensionnement forcé en 224×224.
* **Compréhension vidéo** — accepte des vidéos multi-images avec raisonnement temporel.
* **OCR de documents** — extrait le texte des documents numérisés, des reçus et des notes manuscrites.
* **Multilingue** — bonnes performances en anglais, chinois et plus de 20 autres langues.
* **Support Ollama** — exécutez localement avec `ollama run qwen2.5vl:7b` pour un déploiement sans code.
* **Intégration Transformers** — `Qwen2_5_VLForConditionalGeneration` dans HuggingFace `transformers`.

## Exigences

| Composant   | 3B    | 7B       | 72B                |
| ----------- | ----- | -------- | ------------------ |
| VRAM GPU    | 8 Go  | 16–24 Go | 80+ Go (multi-GPU) |
| RAM système | 16 Go | 32 Go    | 128 Go             |
| Disque      | 10 Go | 20 Go    | 150 Go             |
| Python      | 3.10+ | 3.10+    | 3.10+              |
| CUDA        | 12.1+ | 12.1+    | 12.1+              |

**Recommandation GPU Clore.ai :** Pour le **modèle 7B**, un **RTX 4090** (24 Go, \~0,5–2 $/jour) ou **RTX 3090** (24 Go, \~0,3–1 $/jour) est idéal. Pour **72B**, filtrez la place de marché pour **A100 80 Go** ou des configurations multi-GPU.

## Démarrage rapide

### Option A : Ollama (la plus simple)

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

# Télécharger et exécuter le modèle vision 7B
ollama run qwen2.5vl:7b
```

Puis dans l'invite ollama :

```
>>> Décrivez cette image : /chemin/vers/photo.jpg
```

### Option B : Python / Transformers

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

## Exemples d'utilisation

### Compréhension d'image avec 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": "Quelle est l'espèce de cet insecte ? Décrivez ses principales caractéristiques distinctives."},
        ],
    }
]

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)
```

### Analyse vidéo

```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": "Résumez ce qui se passe dans cette vidéo. Énumérez les événements clés dans l'ordre."},
        ],
    }
]

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 et extraction de documents

```python
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "image": "file:///workspace/receipt.jpg"},
            {"type": "text", "text": "Extrait tous les articles, quantités et prix de ce reçu. Retourner au format JSON."},
        ],
    }
]

# Traiter en utilisant la même configuration modèle/processor ci-dessus
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 Ollama pour le traitement par lots

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

def analyze_image(image_path: str, question: str) -> str:
    """Envoyer une image à Qwen2.5-VL via l'API 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"]

# Traiter par lots un dossier d'images
from pathlib import Path
for img in sorted(Path("./photos").glob("*.jpg")):
    result = analyze_image(str(img), "Décrivez cette image en une phrase.")
    print(f"{img.name}: {result}")
```

## Conseils pour les utilisateurs de Clore.ai

1. **Ollama pour un déploiement rapide** — `ollama run qwen2.5vl:7b` est le chemin le plus rapide vers un VLM opérationnel. Aucun code Python requis pour une utilisation interactive.
2. **7B est le point idéal** — la variante 7B Instruct tient dans 16 Go de VRAM avec quantification 4 bits et offre une qualité concurrente de modèles beaucoup plus grands.
3. **La résolution dynamique est importante** — Qwen2.5-VL traite les images à la résolution native. Pour les grandes images (>4K), redimensionnez à une largeur maximale de 1920 px pour éviter une utilisation excessive de la VRAM.
4. **Paramètre fps vidéo** — pour l'entrée vidéo, définissez `fps=1.0` pour échantillonner 1 image par seconde. Des valeurs plus élevées consomment rapidement la VRAM ; 1 fps suffit pour la plupart des tâches d'analyse.
5. **Stockage persistant** — définissez `HF_HOME=/workspace/hf_cache`; le modèle 7B fait \~15 Go. Pour ollama, les modèles vont dans `~/.ollama/models/`.
6. **Sortie structurée** — Qwen2.5-VL suit bien les instructions de formatage JSON. Demandez « Retourner au format JSON » et vous obtiendrez une sortie analysable la plupart du temps.
7. **Comparaison multi-images** — vous pouvez passer plusieurs images dans un seul message pour des tâches de comparaison (par ex. « Lequel de ces deux produits a l'air le plus premium ? »).
8. **tmux** — exécutez toujours à l'intérieur de `tmux` sur les locations Clore.ai.

## Dépannage

| Problème                                           | Corriger                                                                                               |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `OutOfMemoryError` avec 7B                         | Utilisez `load_in_4bit=True` dans `from_pretrained()` avec `bitsandbytes`; ou utilisez la variante 3B  |
| Modèle Ollama introuvable                          | `ollama pull qwen2.5vl:7b` — assurez-vous d'avoir le bon tag                                           |
| Traitement vidéo lent                              | Réduire `fps` à 0,5 et `max_pixels` à `256 * 256`; moins d'images = inférence plus rapide              |
| Sortie brouillée ou vide                           | Augmentez `max_new_tokens`; la valeur par défaut peut être trop basse pour des descriptions détaillées |
| `ImportError : qwen_vl_utils`                      | `pip install qwen-vl-utils` — requis pour `process_vision_info()`                                      |
| Le modèle 72B ne tient pas                         | Utilisez 2× A100 80 Go avec `device_map="auto"` ou appliquez la quantification AWQ                     |
| Chemin de l'image introuvable                      | Pour les fichiers locaux dans les messages, utilisez `file:///chemin/absolu` format                    |
| Chinois dans la sortie lors d'un prompt en anglais | Ajoutez « Répondez uniquement en anglais. » à votre prompt                                             |
