> 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 grâce au modèle vision-langage LLaVA sur Clore.ai

Discutez avec des images grâce à 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 [la place de marché CLORE.AI](https://clore.ai/marketplace).
{% endhint %}

## Louer sur CLORE.AI

1. Visitez [la place de marché CLORE.AI](https://clore.ai/marketplace)
2. Filtrez par type de GPU, VRAM et prix
3. Choisissez **À 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@<proxy-address>`

## Qu'est-ce que LLaVA ?

LLaVA (Large Language and Vision Assistant) peut :

* Comprendre et décrire des images
* Répondre à des questions sur le contenu visuel
* Analyser des graphiques, des diagrammes, des 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    | 16 Go   | Meilleur         |
| LLaVA-1.6-34B | 34B    | 40 Go   | Meilleur         |
| LLaVA-NeXT    | 7-34B  | 8-40 Go | Dernière version |

## Déploiement rapide

**Image Docker :**

```
pytorch/pytorch:2.11.0-cuda12.8-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. Accédez à **Mes commandes** la page
2. Cliquez sur votre commande
3. Trouvez le `http_pub` URL (par ex., `abc123.clorecloud.net`)

Utilisez `https://YOUR_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écrivez 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": "Qu'est-ce qui est montré dans 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

# Télécharger le modèle LLaVA
ollama pull llava:7b

# Exécuter avec une image (CLI)
ollama run llava:7b "Décrivez cette image : /path/to/image.jpg"
```

### API LLaVA via Ollama

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

#### Méthode fonctionnelle : /api/generate

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

# Envoyer une requête de 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
}
```

#### Non fonctionnel : /api/chat (renvoie null pour la vision)

```bash
# Ceci ne fonctionne PAS pour les requêtes de vision :
curl https://your-http-pub.clorecloud.net/api/chat -d '{
  "model": "llava:7b",
  "messages": [{"role": "user", "content": "décrire", "images": ["..."]}]
}'
# Renvoie 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()

# Utiliser /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 avec LLaVA via Ollama"""

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

    # Utiliser /api/generate (le seul point de terminaison 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écrivez cette image en détail")
print(result)
```

## Cas d’usage

### Description de l'image

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

### OCR / extraction de texte

```python
prompt = "Extrayez tout le texte visible dans cette image. Présentez-le clairement."
```

### Analyse de graphique

```python
prompt = "Analysez ce graphique. Quelles sont les principales tendances et informations ?"
```

### Code à partir de 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 leur emplacement approximatif."
```

## 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écrivez cette image en détail")
    ],
    outputs=gr.Textbox(label="Réponse"),
    title="Assistant 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écrivez 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()}

# Exécuter : 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écrivez 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 sur 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      | Jetons/s |
| ------------- | -------- | -------- |
| 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 Flash Attention
* Réduire max\_new\_tokens
* Utiliser un modèle quantifié

### Qualité médiocre

* Utiliser un modèle plus grand
* De meilleurs prompts avec contexte
* Images à plus haute résolution

## Estimation des coûts

Tarifs typiques du marché CLORE.AI (en 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 40 Go | \~$0.17       | \~$4.00          | \~$0.70             |
| A100 80 Go | \~$0.25       | \~$6.00          | \~$1.00             |

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

**Économisez de l'argent :**

* Utilisez le **Spot** marché pour les travaux interrompables — environ un tiers des serveurs ont un prix spot inférieur au tarif à la demande (médiane \~13 % de remise), les autres s'alignent dessus
* Payez avec **CLORE** jetons
* Comparez les prix entre différents fournisseurs

## Étapes suivantes

* LLM Ollama - Exécuter LLaVA avec Ollama
* RAG + LangChain - Vision + RAG
* Inférence vLLM - Service de 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, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-fr/modeles-de-vision/llava-vision-language.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
