# LLaVA

Chatten mit Bildern mithilfe von LLaVA – der Open-Source-Alternative zu GPT-4V.

{% hint style="success" %}
Alle Beispiele können auf GPU-Servern ausgeführt werden, die über [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## Mieten auf CLORE.AI

1. Besuchen Sie [CLORE.AI Marketplace](https://clore.ai/marketplace)
2. Nach GPU-Typ, VRAM und Preis filtern
3. Wählen **On-Demand** (Festpreis) oder **Spot** (Gebotspreis)
4. Konfigurieren Sie Ihre Bestellung:
   * Docker-Image auswählen
   * Ports festlegen (TCP für SSH, HTTP für Web-UIs)
   * Umgebungsvariablen bei Bedarf hinzufügen
   * Startbefehl eingeben
5. Zahlung auswählen: **CLORE**, **BTC**, oder **USDT/USDC**
6. Bestellung erstellen und auf Bereitstellung warten

### Zugriff auf Ihren Server

* Verbindungsdetails finden Sie in **Meine Bestellungen**
* Webschnittstellen: Verwenden Sie die HTTP-Port-URL
* SSH: `ssh -p <port> root@<proxy-address>`

## Was ist LLaVA?

LLaVA (Large Language and Vision Assistant) kann:

* Bilder verstehen und beschreiben
* Fragen zu visuellen Inhalten beantworten
* Diagramme, Grafiken und Screenshots analysieren
* OCR und Dokumentenverständnis

## Modellvarianten

| Modell        | Größe | VRAM   | Qualität  |
| ------------- | ----- | ------ | --------- |
| LLaVA-1.5-7B  | 7B    | 8GB    | Gut       |
| LLaVA-1.5-13B | 13B   | 16GB   | Besser    |
| LLaVA-1.6-34B | 34B   | 40GB   | Am besten |
| LLaVA-NeXT    | 7-34B | 8-40GB | Neueste   |

## Schnelle Bereitstellung

**Docker-Image:**

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

**Ports:**

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

**Befehl:**

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

## Zugriff auf Ihren Dienst

Nach der Bereitstellung finden Sie Ihre `http_pub` URL in **Meine Bestellungen**:

1. Gehen Sie zur **Meine Bestellungen** Seite
2. Klicken Sie auf Ihre Bestellung
3. Finden Sie die `http_pub` URL (z. B., `abc123.clorecloud.net`)

Verwenden Sie `https://IHRE_HTTP_PUB_URL` anstelle von `localhost` in den Beispielen unten.

## Installation

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

## Grundlegende Verwendung

### Python-API

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

# Einfache Inferenz
args = type('Args', (), {
    "model_path": model_path,
    "model_base": None,
    "model_name": get_model_name_from_path(model_path),
    "query": "Beschreibe dieses Bild ausführlich",
    "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)
```

### Verwendung von 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"
)

# Bild laden
image = Image.open("photo.jpg")

# Unterhaltung erstellen
conversation = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Was zeigt dieses Bild?"}
        ]
    }
]

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

## Ollama-Integration (empfohlen)

Der einfachste Weg, LLaVA auf CLORE.AI auszuführen:

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

# LLaVA-Modell herunterladen
ollama pull llava:7b

# Mit Bild ausführen (CLI)
ollama run llava:7b "Beschreibe dieses Bild: /path/to/image.jpg"
```

### LLaVA-API über Ollama

{% hint style="warning" %}
**Wichtig:** LLaVA-Vision funktioniert **nur** über das `/api/generate` Endpoint mit dem `images` Parameter. Die `/api/chat` und OpenAI-kompatible Endpunkte **unterstützen** keine Bilder mit LLaVA.
{% endhint %}

#### Funktionsweise: /api/generate

```bash
# Kodieren Sie das Bild zuerst in Base64
BASE64_IMAGE=$(base64 -i photo.jpg | tr -d '\n')

# Vision-Anfrage senden
curl https://your-http-pub.clorecloud.net/api/generate -d "{
  \"model\": \"llava:7b\",
  \"prompt\": \"Was sehen Sie auf diesem Bild? Beschreiben Sie es detailliert.\",
  \"images\": [\"$BASE64_IMAGE\"],
  \"stream\": false
}"
```

Antwort:

```json
{
  "model": "llava:7b",
  "response": "Das Bild zeigt einen schönen Sonnenuntergang über Bergen...",
  "done": true
}
```

#### NICHT funktionierend: /api/chat (gibt für Vision null zurück)

```bash
# Dies funktioniert NICHT für Vision-Anfragen:
curl https://your-http-pub.clorecloud.net/api/chat -d '{
  "model": "llava:7b",
  "messages": [{"role": "user", "content": "describe", "images": ["..."]}]
}'
# Gibt für bildbezogene Antworten null zurück
```

### Python mit Ollama

```python
import requests
import base64

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

# Verwenden Sie /api/generate für Vision (NICHT /api/chat!)
response = requests.post(
    "https://your-http-pub.clorecloud.net/api/generate",
    json={
        "model": "llava:7b",
        "prompt": "Was sehen Sie auf diesem Bild?",
        "images": [encode_image("photo.jpg")],
        "stream": False
    }
)

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

### Vollständiges funktionierendes Beispiel

```python
import requests
import base64
import sys

def analyze_image(ollama_url, image_path, question):
    """Analysiere ein Bild mit LLaVA über Ollama"""

    # Bild kodieren
    with open(image_path, "rb") as f:
        image_base64 = base64.b64encode(f.read()).decode()

    # Verwenden Sie /api/generate (der einzige funktionierende Endpoint für Vision)
    response = requests.post(
        f"{ollama_url}/api/generate",
        json={
            "model": "llava:7b",
            "prompt": question,
            "images": [image_base64],
            "stream": False
        }
    )

    return response.json()["response"]

# Verwendung
url = "https://your-http-pub.clorecloud.net"
result = analyze_image(url, "photo.jpg", "Beschreibe dieses Bild ausführlich")
print(result)
```

## Anwendungsfälle

### Bildbeschreibung

```python
prompt = "Beschreibe dieses Bild ausführlich, einschließlich Farben, Objekten und Atmosphäre."
```

### OCR / Textextraktion

```python
prompt = "Extrahiere allen sichtbaren Text in diesem Bild. Formatiere ihn klar."
```

### Diagrammanalyse

```python
prompt = "Analysiere dieses Diagramm. Was sind die wichtigsten Trends und Erkenntnisse?"
```

### Code aus Screenshot

```python
prompt = "Extrahiere den in diesem Screenshot gezeigten Code. Gib nur den Code an."
```

### Objekterkennung

```python
prompt = "Liste alle in diesem Bild sichtbaren Objekte mit ihren ungefähren Positionen auf."
```

## Gradio-Oberfläche

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

    # Assistant-Antwort extrahieren
    return response.split("[/INST]")[-1].strip()

demo = gr.Interface(
    fn=analyze_image,
    inputs=[
        gr.Image(type="pil", label="Bild"),
        gr.Textbox(label="Frage", value="Beschreibe dieses Bild ausführlich")
    ],
    outputs=gr.Textbox(label="Antwort"),
    title="LLaVA Vision Assistant"
)

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

## API-Server

```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="Beschreibe dieses Bild")
):
    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()}

# Ausführen: uvicorn server:app --host 0.0.0.0 --port 8000
```

## Batch-Verarbeitung

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

# Ordner mit Bildern verarbeiten
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, "Beschreibe dieses Bild kurz")
        results.append({"file": filename, "description": description})
        print(f"{filename}: {description[:100]}...")

# Ergebnisse speichern
import json
with open("descriptions.json", "w") as f:
    json.dump(results, f, indent=2)
```

## Speicheroptimierung

### 4-Bit-Quantisierung

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

### CPU-Auslagerung

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

## Leistung

| Modell        | 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       |

## Fehlerbehebung

### Kein Speicher mehr

```python

# Verwende 4-Bit-Quantisierung

# Oder verwende ein kleineres Modell (7B statt 13B)

# Oder verarbeite kleinere Bilder
image = image.resize((336, 336))
```

### Langsame Generierung

* Verwende Flash-Attention
* Reduziere max\_new\_tokens
* Verwende quantisiertes Modell

### Schlechte Qualität

* Verwende ein größeres Modell
* Bessere Prompts mit Kontext
* Höhere Auflösung der Bilder

## Kostenabschätzung

Typische CLORE.AI-Marktplatztarife (Stand 2024):

| GPU       | Stundensatz | Tagessatz | 4-Stunden-Sitzung |
| --------- | ----------- | --------- | ----------------- |
| 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           |

*Preise variieren je nach Anbieter und Nachfrage. Prüfen Sie* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *auf aktuelle Preise.*

**Geld sparen:**

* Verwenden Sie **Spot** Markt für flexible Workloads (oft 30–50% günstiger)
* Bezahlen mit **CLORE** Token
* Preise bei verschiedenen Anbietern vergleichen

## Nächste Schritte

* Ollama-LLMs – LLaVA mit Ollama ausführen
* RAG + LangChain - Vision + RAG
* vLLM-Inferenz - Produktionseinsatz


---

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