Возможности
ВОЗМОЖНОСТИ

Изображения на вход (Vision)

Отправка изображений в модель для анализа — описание содержимого, OCR, классификация, ответы на вопросы по картинке.

Vision (мультимодальный ввод) — это когда модель получает на вход не только текст, но и изображения. Подходит для описания содержимого, OCR, классификации, ответов на вопросы по картинке, разбора скриншотов и диаграмм.

Не путайте с генерацией изображений: vision — это картинка на вход, image-generation — картинка на выход.

Поддерживающие модели

Vision поддерживает любая модель, у которой в карточке (GET /v1/models) поле input_modalities содержит "image". Это, как правило, актуальные версии Claude (Sonnet/Opus), GPT-4o, Gemini, а также часть open-source моделей (Llama Vision, Qwen-VL). Точный актуальный список — в каталоге с фильтром «принимает изображения».

Минимальный пример

Передайте картинку как content-part типа image_url внутри user-сообщения:

curl -s https://api.hubris.pw/v1/chat/completions \
  -H "Authorization: Bearer sk-gw-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-haiku-4.5",
    "messages": [
      {
        "role": "user",
        "content": [
          { "type": "text", "text": "Что изображено на картинке?" },
          {
            "type": "image_url",
            "image_url": {
              "url": "https://example.com/photo.jpg"
            }
          }
        ]
      }
    ]
  }'

Контент user-сообщения — это массив content-part'ов. Каждая часть — либо { "type": "text", "text": "..." }, либо { "type": "image_url", "image_url": { "url": "..." } }. Порядок свободный.

Два способа передать картинку

URL

{
  "type": "image_url",
  "image_url": {
    "url": "https://example.com/photo.jpg"
  }
}

Должен быть публично-доступный HTTPS URL. Провайдер модели скачает картинку сам. Размер и формат — на усмотрение провайдера; типичный лимит 5–20 МБ, поддерживаются JPEG, PNG, WebP, GIF.

Base64 data URL

Когда картинка не лежит в публичном интернете (генерится на лету, приходит от пользователя), кодируйте её в base64 и шлите как data URL:

{
  "type": "image_url",
  "image_url": {
    "url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAAAAAAA..."
  }
}

Формат — data:image/<mime>;base64,<base64-blob>. Mime может быть image/jpeg, image/png, image/webp, image/gif. Base64-сам по себе делает строку на ~33 % длиннее, поэтому общий размер запроса может быть значительным — учитывайте при тарификации (см. ниже).

Несколько изображений в одном запросе

Можно передать сколько угодно картинок в одном сообщении — добавляйте content-part'ы по одной:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "Сравни эти два скриншота интерфейса." },
    { "type": "image_url", "image_url": { "url": "https://.../before.png" } },
    { "type": "image_url", "image_url": { "url": "https://.../after.png" } }
  ]
}

Модель увидит обе картинки и сможет ссылаться на них в ответе («на первом скриншоте...»).

Параметр detail

Часть моделей (gpt-4o-семейство) принимают подсказку о требуемой детализации:

{
  "type": "image_url",
  "image_url": {
    "url": "https://...",
    "detail": "high"
  }
}
ЗначениеЧто значит
"low"модель смотрит на картинку в низком разрешении — дёшево, годится для общего описания
"high"детальное чтение — мелкий текст, цифры, диаграммы
"auto" (по умолчанию)модель решает сама

Не все модели поддерживают detail — он пробрасывается как есть; если модель его не понимает, пара значение/поле просто игнорируется апстримом.

OpenAI SDK

Vision работает в официальных SDK OpenAI без дополнительных манипуляций.

Python:

from openai import OpenAI

client = OpenAI(
    base_url="https://api.hubris.pw/v1",
    api_key="sk-gw-...",
)

resp = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Распознай текст на этом скриншоте."},
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://example.com/screenshot.png",
                        "detail": "high",
                    },
                },
            ],
        }
    ],
)

print(resp.choices[0].message.content)

TypeScript:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://api.hubris.pw/v1',
  apiKey: 'sk-gw-...',
});

const resp = await client.chat.completions.create({
  model: 'openai/gpt-4o-mini',
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: 'Опиши, что на фото.' },
        {
          type: 'image_url',
          image_url: { url: 'https://example.com/photo.jpg' },
        },
      ],
    },
  ],
});

console.log(resp.choices[0].message.content);

Base64 в Python из файла

import base64

with open("photo.jpg", "rb") as f:
    encoded = base64.b64encode(f.read()).decode()

data_url = f"data:image/jpeg;base64,{encoded}"

resp = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Опиши фото."},
                {"type": "image_url", "image_url": {"url": data_url}},
            ],
        }
    ],
)

Стриминг

stream: true работает с vision-запросами как с обычными — ответ модели приходит чанками, prompt с изображениями просто длиннее. Никаких особенностей.

Биллинг

Изображение на вход тарифицируется как дополнительные prompt-токены. Количество токенов на одну картинку зависит от модели и от её размера/разрешения. Грубо:

  • Маленькая картинка в detail: "low" — порядка сотни prompt-токенов.
  • Стандартное разрешение в detail: "auto"/"high" — от нескольких сотен до нескольких тысяч prompt-токенов.

Точное количество видно в usage.prompt_tokens в ответе. Списание с баланса — стандартная формула: prompt + completion токены умножаются на цену модели из каталога.

Base64 в URL не добавляет токенов — это просто способ доставки байтов. Тарифицируется только распарсенная картинка, не размер JSON-запроса.

Что важно знать

  • Большие картинки = большой prompt. Если шлёте 2K-скриншоты, ожидайте по 1000–3000 prompt-токенов на каждую. На сессии с десятком картинок это заметные деньги.
  • Картинка в URL должна быть публично-доступной. Авторизованные URL (Authorization: ... заголовок при загрузке) не подойдут — провайдер скачивает анонимно. Если картинка приватная — шлите как base64.
  • Vision и structured output совмещаются. Можно передать картинку и попросить вернуть JSON по схеме — например, извлечь поля из чека.
  • Vision и tool calling тоже совмещаются. Модель может смотреть на картинку и вызывать функции на основе того, что увидела.

Что дальше

Обновлено:

Изображения на вход (Vision) · Hubris