> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-fr/modeles-de-vision/llava-vision-language.md).

# LLaVA

Discutez avec des images en utilisant LLaVA - l'alternative open-source à GPT-4V.

{% hint style="success" %}
Tous les exemples peuvent être exécutés sur des serveurs GPU loués via [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## Location sur CLORE.AI

1. Visitez [CLORE.AI Marketplace](https://clore.ai/marketplace)
2. Filtrer par type de GPU, VRAM et prix
3. Choisir **À la demande** (tarif fixe) ou **Spot** (prix d'enchère)
4. Configurez votre commande :
   * Sélectionnez l'image Docker
   * Définissez les ports (TCP pour SSH, HTTP pour les interfaces web)
   * Ajoutez des variables d'environnement si nécessaire
   * Entrez la commande de démarrage
5. Sélectionnez le paiement : **CLORE**, **BTC**, ou **USDT/USDC**
6. Créez la commande et attendez le déploiement

### Accédez à votre serveur

* Trouvez les détails de connexion dans **Mes commandes**
* Interfaces Web : utilisez l'URL du port HTTP
* SSH : `ssh -p <port> root@<adresse-proxy>`

## Qu'est-ce que LLaVA ?

LLaVA (Large Language and Vision Assistant) peut :

* Comprendre et décrire des images
* Répondre aux questions sur le contenu visuel
* Analyser des graphiques, diagrammes, captures d'écran
* OCR et compréhension de documents

## Variantes de modèle

| Modèle        | Taille | VRAM   | Qualité  |
| ------------- | ------ | ------ | -------- |
| LLaVA-1.5-7B  | 7B     | 8 Go   | Bon      |
| LLaVA-1.5-13B | 13B    | 16Go   | Meilleur |
| LLaVA-1.6-34B | 34B    | 40Go   | Meilleur |
| LLaVA-NeXT    | 7-34B  | 8-40GB | Dernier  |

## Déploiement rapide

**Image Docker :**

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

**Ports :**

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

**Commande :**

```bash
pip install llava torch transformers accelerate gradio && \
python -m llava.serve.cli --model-path liuhaotian/llava-v1.5-7b --load-4bit
```

## Accéder à votre service

Après le déploiement, trouvez votre `http_pub` URL dans **Mes commandes**:

1. Aller à la **Mes commandes** page
2. Cliquez sur votre commande
3. Trouvez l' `http_pub` URL (par ex., `abc123.clorecloud.net`)

Utilisez `https://VOTRE_HTTP_PUB_URL` au lieu de `localhost` dans les exemples ci-dessous.

## Installation

```bash
git clone https://github.com/haotian-liu/LLaVA.git
cd LLaVA
pip install -e .
pip install flash-attn --no-build-isolation
```

## Utilisation de base

### API Python

```python
from llava.model.builder import load_pretrained_model
from llava.mm_utils import get_model_name_from_path
from llava.eval.run_llava import eval_model
from PIL import Image

model_path = "liuhaotian/llava-v1.5-7b"
tokenizer, model, image_processor, context_len = load_pretrained_model(
    model_path=model_path,
    model_base=None,
    model_name=get_model_name_from_path(model_path)
)

# Inférence simple
args = type('Args', (), {
    "model_path": model_path,
    "model_base": None,
    "model_name": get_model_name_from_path(model_path),
    "query": "Décris cette image en détail",
    "conv_mode": None,
    "image_file": "photo.jpg",
    "sep": ",",
    "temperature": 0.2,
    "top_p": None,
    "num_beams": 1,
    "max_new_tokens": 512
})()

output = eval_model(args)
print(output)
```

### Utilisation de Transformers

```python
from transformers import LlavaNextProcessor, LlavaNextForConditionalGeneration
import torch
from PIL import Image

processor = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    torch_dtype=torch.float16,
    device_map="auto"
)

# Charger l'image
image = Image.open("photo.jpg")

# Créer la conversation
conversation = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Que montre cette image ?"}
        ]
    }
]

prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
inputs = processor(prompt, image, return_tensors="pt").to("cuda")

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

## Intégration Ollama (recommandée)

La façon la plus simple d'exécuter LLaVA sur CLORE.AI :

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

# Récupérer le modèle LLaVA
ollama pull llava:7b

# Exécuter avec une image (CLI)
ollama run llava:7b "Décris cette image : /chemin/vers/image.jpg"
```

### API LLaVA via Ollama

{% hint style="warning" %}
**Important :** La vision LLaVA fonctionne **uniquement** via le `/api/generate` endpoint avec le `paramètre images` Le `/api/chat` et les endpoints compatibles OpenAI **ne** prennent pas en charge les images avec LLaVA.
{% endhint %}

#### Mode de fonctionnement : /api/generate

```bash
# Encoder l'image en base64 d'abord
BASE64_IMAGE=$(base64 -i photo.jpg | tr -d '\n')

# Envoyer la requête vision
curl https://your-http-pub.clorecloud.net/api/generate -d "{
  \"model\": \"llava:7b\",
  \"prompt\": \"Que voyez-vous dans cette image ? Décrivez en détail.\",
  \"images\": [\"$BASE64_IMAGE\"],
  \"stream\": false
}"
```

Réponse :

```json
{
  "model": "llava:7b",
  "response": "L'image montre un magnifique coucher de soleil sur des montagnes...",
  "done": true
}
```

#### Ne fonctionne PAS : /api/chat (retourne null pour la vision)

```bash
# Ceci NE fonctionne PAS pour les requêtes vision :
curl https://your-http-pub.clorecloud.net/api/chat -d '{
  "model": "llava:7b",
  "messages": [{"role": "user", "content": "describe", "images": ["..."]}]
}'
# Retourne null pour les réponses liées aux images
```

### Python avec Ollama

```python
import requests
import base64

def encode_image(image_path):
    with open(image_path, "rb") as f:
        return base64.b64encode(f.read()).decode()

# Utilisez /api/generate pour la vision (PAS /api/chat !)
response = requests.post(
    "https://your-http-pub.clorecloud.net/api/generate",
    json={
        "model": "llava:7b",
        "prompt": "Que voyez-vous dans cette image ?",
        "images": [encode_image("photo.jpg")],
        "stream": False
    }
)

print(response.json()["response"])
```

### Exemple complet fonctionnel

```python
import requests
import base64
import sys

def analyze_image(ollama_url, image_path, question):
    """Analyser une image en utilisant LLaVA via Ollama"""

    # Encoder l'image
    with open(image_path, "rb") as f:
        image_base64 = base64.b64encode(f.read()).decode()

    # Utilisez /api/generate (le seul endpoint fonctionnel pour la vision)
    response = requests.post(
        f"{ollama_url}/api/generate",
        json={
            "model": "llava:7b",
            "prompt": question,
            "images": [image_base64],
            "stream": False
        }
    )

    return response.json()["response"]

# Utilisation
url = "https://your-http-pub.clorecloud.net"
result = analyze_image(url, "photo.jpg", "Décris cette image en détail")
print(result)
```

## Cas d'utilisation

### Description de l'image

```python
prompt = "Décris cette image en détail, y compris les couleurs, les objets et l'atmosphère."
```

### OCR / Extraction de texte

```python
prompt = "Extraire tout le texte visible dans cette image. Formatez-le clairement."
```

### Analyse de graphiques

```python
prompt = "Analysez ce graphique. Quelles sont les tendances et les idées clés ?"
```

### Code à partir d'une capture d'écran

```python
prompt = "Extrayez le code affiché dans cette capture d'écran. Fournissez uniquement le code."
```

### Détection d'objets

```python
prompt = "Listez tous les objets visibles dans cette image avec leurs emplacements approximatifs."
```

## Interface Gradio

```python
import gradio as gr
from transformers import LlavaNextProcessor, LlavaNextForConditionalGeneration
import torch

processor = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    torch_dtype=torch.float16,
    device_map="auto"
)

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

    prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
    inputs = processor(prompt, image, return_tensors="pt").to("cuda")

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

    # Extraire la réponse de l'assistant
    return response.split("[/INST]")[-1].strip()

demo = gr.Interface(
    fn=analyze_image,
    inputs=[
        gr.Image(type="pil", label="Image"),
        gr.Textbox(label="Question", value="Décris cette image en détail")
    ],
    outputs=gr.Textbox(label="Réponse"),
    title="Assistant de vision LLaVA"
)

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

## Serveur API

```python
from fastapi import FastAPI, UploadFile, File, Form
from transformers import LlavaNextProcessor, LlavaNextForConditionalGeneration
import torch
from PIL import Image
import io

app = FastAPI()

processor = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    torch_dtype=torch.float16,
    device_map="auto"
)

@app.post("/analyze")
async def analyze(
    image: UploadFile = File(...),
    question: str = Form(default="Décris cette image")
):
    img = Image.open(io.BytesIO(await image.read()))

    conversation = [
        {
            "role": "user",
            "content": [
                {"type": "image"},
                {"type": "text", "text": question}
            ]
        }
    ]

    prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
    inputs = processor(prompt, img, return_tensors="pt").to("cuda")

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

    return {"response": response.split("[/INST]")[-1].strip()}

# Lancer : uvicorn server:app --host 0.0.0.0 --port 8000
```

## Traitement par lots

```python
from transformers import LlavaNextProcessor, LlavaNextForConditionalGeneration
import torch
from PIL import Image
import os

processor = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    torch_dtype=torch.float16,
    device_map="auto"
)

def analyze_image(image_path, question):
    image = Image.open(image_path)

    conversation = [
        {"role": "user", "content": [
            {"type": "image"},
            {"type": "text", "text": question}
        ]}
    ]

    prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
    inputs = processor(prompt, image, return_tensors="pt").to("cuda")

    output = model.generate(**inputs, max_new_tokens=300)
    return processor.decode(output[0], skip_special_tokens=True).split("[/INST]")[-1].strip()

# Traiter un dossier d'images
image_folder = "./images"
results = []

for filename in os.listdir(image_folder):
    if filename.endswith(('.jpg', '.png', '.jpeg')):
        path = os.path.join(image_folder, filename)
        description = analyze_image(path, "Décris brièvement cette image")
        results.append({"file": filename, "description": description})
        print(f"{filename}: {description[:100]}...")

# Enregistrer les résultats
import json
with open("descriptions.json", "w") as f:
    json.dump(results, f, indent=2)
```

## Optimisation de la mémoire

### Quantification 4 bits

```python
from transformers import BitsAndBytesConfig

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

model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    quantization_config=quantization_config,
    device_map="auto"
)
```

### Déchargement CPU

```python
model = LlavaNextForConditionalGeneration.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    torch_dtype=torch.float16,
    device_map="auto",
    offload_folder="offload"
)
```

## Performances

| Modèle        | GPU      | Tokens/sec |
| ------------- | -------- | ---------- |
| LLaVA-1.5-7B  | RTX 3090 | \~30       |
| LLaVA-1.5-7B  | RTX 4090 | \~45       |
| LLaVA-1.6-7B  | RTX 4090 | \~40       |
| LLaVA-1.5-13B | A100     | \~35       |

## Dépannage

### Mémoire insuffisante

```python

# Utiliser la quantification 4 bits

# Ou utiliser un modèle plus petit (7B au lieu de 13B)

# Ou traiter des images plus petites
image = image.resize((336, 336))
```

### Génération lente

* Utiliser l'attention flash
* Réduire max\_new\_tokens
* Utiliser un modèle quantifié

### Mauvaise qualité

* Utiliser un modèle plus grand
* Meilleurs prompts avec contexte
* Images de résolution plus élevée

## Estimation des coûts

Tarifs typiques du marché CLORE.AI (à partir de 2024) :

| GPU       | Tarif horaire | Tarif journalier | Session de 4 heures |
| --------- | ------------- | ---------------- | ------------------- |
| 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             |

*Les prix varient selon le fournisseur et la demande. Vérifiez* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *pour les tarifs actuels.*

**Économisez de l'argent :**

* Utilisez **Spot** market pour les charges de travail flexibles (souvent 30-50 % moins cher)
* Payer avec **CLORE** jetons
* Comparer les prix entre différents fournisseurs

## Prochaines étapes

* LLMs Ollama - Exécuter LLaVA avec Ollama
* RAG + LangChain - Vision + RAG
* vLLM Inference - Mise en production


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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-fr/modeles-de-vision/llava-vision-language.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.
