> 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-ru/modeli-dlya-zreniya/llava-vision-language.md).

# LLaVA

Общайтесь с изображениями с помощью зрительно-языковой модели LLaVA на Clore.ai

Общайтесь с изображениями с помощью LLaVA — альтернативы GPT-4V с открытым исходным кодом.

{% hint style="success" %}
Все примеры можно запускать на GPU-серверах, арендованных через [маркетплейс CLORE.AI](https://clore.ai/marketplace).
{% endhint %}

## Аренда на CLORE.AI

1. Перейдите на [маркетплейс CLORE.AI](https://clore.ai/marketplace)
2. Отфильтруйте по типу GPU, объёму VRAM и цене
3. Выберите **On-Demand** (фиксированная ставка) или **Spot** (цена ставки)
4. Настройте свой заказ:
   * Выберите Docker-образ
   * Установите порты (TCP для SSH, HTTP для веб-интерфейсов)
   * При необходимости добавьте переменные окружения
   * Введите команду запуска
5. Выберите способ оплаты: **CLORE**, **BTC**, или **USDT/USDC**
6. Создайте заказ и дождитесь развертывания

### Получите доступ к своему серверу

* Найдите данные для подключения в **Мои заказы**
* Веб-интерфейсы: используйте URL HTTP-порта
* SSH: `ssh -p <port> root@<proxy-address>`

## Что такое LLaVA?

LLaVA (Large Language and Vision Assistant) может:

* Понимать и описывать изображения
* Отвечать на вопросы о визуальном содержимом
* Анализировать графики, диаграммы, скриншоты
* OCR и понимание документов

## Варианты модели

| Модель        | Размер | VRAM   | Качество    |
| ------------- | ------ | ------ | ----------- |
| LLaVA-1.5-7B  | 7B     | 8 ГБ   | Хорошо      |
| LLaVA-1.5-13B | 13B    | 16GB   | Лучше       |
| LLaVA-1.6-34B | 34B    | 40 ГБ  | Лучше всего |
| LLaVA-NeXT    | 7-34B  | 8-40GB | Последняя   |

## Быстрое развёртывание

**Docker-образ:**

```
pytorch/pytorch:2.11.0-cuda12.8-cudnn9-devel
```

**Порты:**

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

**Команда:**

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

## Доступ к вашему сервису

После развертывания найдите свой `http_pub` URL в **Мои заказы**:

1. Перейдите на **Мои заказы** страницу
2. Нажмите на свой заказ
3. Найдите `http_pub` URL (например, `abc123.clorecloud.net`)

Используйте `https://YOUR_HTTP_PUB_URL` вместо `localhost` в примерах ниже.

## Установка

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

## Базовое использование

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

# Простая инференция
args = type('Args', (), {
    "model_path": model_path,
    "model_base": None,
    "model_name": get_model_name_from_path(model_path),
    "query": "Опиши это изображение подробно",
    "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)
```

### Использование 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"
)

# Загрузить изображение
image = Image.open("photo.jpg")

# Создать диалог
conversation = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "Что изображено на этой картинке?"}
        ]
    }
]

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 (рекомендуется)

Самый простой способ запустить LLaVA на CLORE.AI:

```bash
# Установите Ollama
curl -fsSL https://ollama.com/install.sh | sh

# Скачать модель LLaVA
ollama pull llava:7b

# Запуск с изображением (CLI)
ollama run llava:7b "Опиши это изображение: /path/to/image.jpg"
```

### API LLaVA через Ollama

{% hint style="warning" %}
**Важно:** Зрение LLaVA работает **только** через `/api/generate` конечную точку с `images` параметром. `/api/chat` и совместимые с OpenAI конечные точки **не** поддерживают изображения в LLaVA.
{% endhint %}

#### Рабочий способ: /api/generate

```bash
# Сначала закодируйте изображение в base64
BASE64_IMAGE=$(base64 -i photo.jpg | tr -d '\n')

# Отправить запрос на распознавание изображения
curl https://your-http-pub.clorecloud.net/api/generate -d "{
  \"model\": \"llava:7b\",
  \"prompt\": \"Что вы видите на этом изображении? Опишите подробно.\",
  \"images\": [\"$BASE64_IMAGE\"],
  \"stream\": false
}"
```

Ответ:

```json
{
  "model": "llava:7b",
  "response": "На изображении показан красивый закат над горами...",
  "done": true
}
```

#### НЕ работает: /api/chat (возвращает null для задач с изображениями)

```bash
# Это НЕ работает для запросов к изображению:
curl https://your-http-pub.clorecloud.net/api/chat -d '{
  "model": "llava:7b",
  "messages": [{"role": "user", "content": "опиши", "images": ["..."]}]
}'
# Возвращает null для ответов, связанных с изображением
```

### Python с Ollama

```python
import requests
import base64

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

# Используйте /api/generate для зрения (НЕ /api/chat!)
response = requests.post(
    "https://your-http-pub.clorecloud.net/api/generate",
    json={
        "model": "llava:7b",
        "prompt": "Что вы видите на этом изображении?",
        "images": [encode_image("photo.jpg")],
        "stream": False
    }
)

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

### Полный рабочий пример

```python
import requests
import base64
import sys

def analyze_image(ollama_url, image_path, question):
    """Анализ изображения с помощью LLaVA через Ollama"""

    # Закодировать изображение
    with open(image_path, "rb") as f:
        image_base64 = base64.b64encode(f.read()).decode()

    # Используйте /api/generate (единственная рабочая конечная точка для зрения)
    response = requests.post(
        f"{ollama_url}/api/generate",
        json={
            "model": "llava:7b",
            "prompt": question,
            "images": [image_base64],
            "stream": False
        }
    )

    return response.json()["response"]

# Использование
url = "https://your-http-pub.clorecloud.net"
result = analyze_image(url, "photo.jpg", "Опиши это изображение подробно")
print(result)
```

## Сценарии использования

### Описание изображения

```python
prompt = "Опишите это изображение подробно, включая цвета, объекты и атмосферу."
```

### OCR / Извлечение текста

```python
prompt = "Извлеките весь текст, видимый на этом изображении. Оформите его чётко."
```

### Анализ графика

```python
prompt = "Проанализируйте этот график. Каковы ключевые тенденции и выводы?"
```

### Код со скриншота

```python
prompt = "Извлеките код, показанный на этом скриншоте. Предоставьте только код."
```

### Обнаружение объектов

```python
prompt = "Перечислите все объекты, видимые на этом изображении, с их приблизительным расположением."
```

## Интерфейс 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)

    # Извлечь ответ ассистента
    return response.split("[/INST]")[-1].strip()

demo = gr.Interface(
    fn=analyze_image,
    inputs=[
        gr.Image(type="pil", label="Изображение"),
        gr.Textbox(label="Вопрос", value="Опишите это изображение подробно")
    ],
    outputs=gr.Textbox(label="Ответ"),
    title="Ассистент по зрению LLaVA"
)

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

## 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="Опишите это изображение")
):
    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()}

# Запуск: uvicorn server:app --host 0.0.0.0 --port 8000
```

## Пакетная обработка

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

# Обработать папку с изображениями
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, "Кратко опишите это изображение")
        results.append({"file": filename, "description": description})
        print(f"{filename}: {description[:100]}...")

# Сохранить результаты
import json
with open("descriptions.json", "w") as f:
    json.dump(results, f, indent=2)
```

## Оптимизация памяти

### 4-битная квантизация

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

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

## Производительность

| Модель        | GPU      | Токенов/сек |
| ------------- | -------- | ----------- |
| 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        |

## Устранение неполадок

### Недостаточно памяти

```python

# Используйте 4-битную квантизацию

# Или используйте меньшую модель (7B вместо 13B)

# Или обрабатывайте изображения меньшего размера
image = image.resize((336, 336))
```

### Медленная генерация

* Используйте flash attention
* Уменьшите max\_new\_tokens
* Используйте квантизованную модель

### Низкое качество

* Используйте более крупную модель
* Лучшие промпты с контекстом
* Изображения более высокого разрешения

## Оценка стоимости

Типичные цены на маркетплейсе CLORE.AI (по состоянию на 2024 год):

| GPU        | Почасовая ставка | Дневная ставка | 4-часовая сессия |
| ---------- | ---------------- | -------------- | ---------------- |
| 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 ГБ | \~$0.17          | \~$4.00        | \~$0.70          |
| A100 80 ГБ | \~$0.25          | \~$6.00        | \~$1.00          |

*Цены зависят от провайдера и спроса. Проверьте* [*маркетплейс CLORE.AI*](https://clore.ai/marketplace) *актуальные тарифы.*

**Сэкономьте деньги:**

* Используйте **Spot** рынок для прерываемых задач — примерно треть серверов оценивает spot-цены ниже on-demand (медиана \~13% скидки), остальные совпадают с ними
* Платите **CLORE** токенами
* Сравните цены у разных провайдеров

## Дальнейшие шаги

* LLM Ollama — запуск LLaVA с Ollama
* RAG + LangChain — Vision + RAG
* Инференс vLLM — промышленное обслуживание


---

# 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-ru/modeli-dlya-zreniya/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.
