Перейти к содержанию
modelium.
Начать с задачи
←

Ollama Vision API: как отправить изображение и проверить ответ локально

Для анализа изображения в локальной Ollama выберите модель с поддержкой Image input и передайте PNG как base64 в `messages[].images` метода `/api/chat`. Начните с искусственного рисунка с известными цветами, проверьте JSON-ответ и сверьте описание с оригиналом. Успешный HTTP-ответ не доказывает корректность распознавания или отсутствие обращений в сеть.

Документация и каталог просмотрены 26 сентября 2026 года. Команда и тест ниже описывают способ самостоятельной проверки, а не измерение Modelium: мы не скачивали модель и не выполняли inference. Формулировка запроса найдена в Google Suggest; его частотность неизвестна.

Что делает Vision API и когда он подходит?

Vision-модель принимает изображение вместе с текстовым вопросом. Документация Ollama показывает два пути: локальный CLI и REST-вызов, где изображение в images передают в base64; в Python/JavaScript SDK допускаются также путь, URL и байты s1. Здесь разбираем локальный REST API, чтобы видеть входной JSON, HTTP-ответ и текст модели по отдельности. Для пилота выберите изображение с заранее известной истиной, а не секретный скан клиента.

Задача этого гайда — получить описание простой картинки и отличить три результата: сервер ответил; мультимодальная модель действительно получила изображение; её ответ совпал с наблюдаемым содержимым. Первое не гарантирует второе и третье. Если нужны поля счёта или УПД, сравните задачу с извлечением документов для 1С: свободное описание картинки не равно верифицированному OCR и разбору реквизитов.

Какая модель и компьютер нужны до вызова API?

Предположим, что Ollama уже установлена и сервер слушает только локальный интерфейс. Для установки и проверки обычного сервера есть базовый гайд Ollama. Зафиксируйте вашу версию командой ollama --version; это значение пользователь получает на своей машине, а не из статьи. Без измерения на вашем устройстве не обещаем скорость или минимальную память.

В каталоге Ollama тег gemma3:4b обозначен Text, Image, а gemma3:1b — Text: не заменяйте 4b на 1b только потому, что он меньше s6. На дату просмотра у gemma3:4b в каталоге указан файл 3,3 ГБ и сокращённый идентификатор a2af6cc3eb7f; это размер артефакта и метка каталога, не нижняя граница RAM/VRAM, не benchmark и не гарантия неизменности тега s6. Для другого железа/качества выберите иной вариант с Image input; не переносите свойства модели автоматически на всё семейство.

# Команды выполняются на ВАШЕЙ локальной машине с уже установленной Ollama.
curl -fsS http://127.0.0.1:11434/api/tags
ollama pull gemma3:4b
curl -fsS http://127.0.0.1:11434/api/tags

/api/tags возвращает локальные модели, их name, digest и размер на диске; найдите там ровно gemma3:4b и запишите полный digest своего экземпляра для повторяемости s4. ollama pull обращается к реестру для получения весов: это сетевой шаг, а не проверка полностью автономного контура; документирован также POST /api/pull s7. До загрузки оцените свободное место и разрешённость модели/её условий для своей организации отдельно. Если модель уже установлена, повторная загрузка для выполнения примера не нужна. Никакого вывода об оперативной памяти из размера загрузки не делайте.

Как создать безопасную картинку с известным ответом?

Ниже собственный тестовый сценарий, а не характеристика Ollama. Python 3 из стандартной библиотеки создаёт PNG размером 192×96: слева сплошной красный прямоугольник, справа сплошной синий. Реальных документов и персональных данных здесь нет. Запускайте в пустом рабочем каталоге, чтобы не перезаписать свой test.png:

from pathlib import Path
import struct
import zlib

w, h = 192, 96
raw = b''.join(
b'\x00' + b''.join(
b'\xff\x00\x00' if x < w // 2 else b'\x00\x00\xff'
for x in range(w)
)
for _ in range(h)
)

def chunk(tag, data):
return (struct.pack('!I', len(data)) + tag + data
+ struct.pack('!I', zlib.crc32(tag + data) & 0xffffffff))

png = (b'\x89PNG\r\n\x1a\n'
+ chunk(b'IHDR', struct.pack('!2I5B', w, h, 8, 2, 0, 0, 0))
+ chunk(b'IDAT', zlib.compress(raw))
+ chunk(b'IEND', b''))
Path('test.png').write_bytes(png)
print('Создан test.png:', len(png), 'байт')

Откройте test.png обычным просмотрщиком, прежде чем обращаться к API. Истина для этой пробы: красный слева, синий справа; никаких букв, людей и предметов. Отдельно отметьте файл и дату пробы: если впоследствии подставить другое изображение, сравнение потеряет смысл.

Как отправить PNG в /api/chat?

В REST поле images находится внутри сообщения messages[]. Передавайте base64-содержимое PNG, не строку test.png: путь к файлу в примере документации работает для SDK, но JSON REST ожидает base64 s1s2. Этот пример выполняет один запрос к 127.0.0.1 без сторонних Python-пакетов; если сервер на другом компьютере, настройка сетевого доступа и его защита — отдельная задача, не выставляйте порт 11434 в интернет.

from pathlib import Path
from urllib.request import Request, urlopen
from urllib.error import HTTPError, URLError
import base64
import json

image = base64.b64encode(Path('test.png').read_bytes()).decode('ascii')
payload = {
'model': 'gemma3:4b',
'messages': [{
'role': 'user',
'content': 'Опиши только цвета двух половин изображения слева направо. Если текста нет, не придумывай его.',
'images': [image],
}],
'stream': False,
}
request = Request(
'http://127.0.0.1:11434/api/chat',
data=json.dumps(payload).encode('utf-8'),
headers={'Content-Type': 'application/json'},
method='POST',
)
try:
with urlopen(request, timeout=120) as response:
result = json.load(response)
except (HTTPError, URLError) as exc:
raise SystemExit(f'Проверьте локальный сервер, модель и HTTP-ответ: {exc}')
print('model:', result.get('model'), 'done:', result.get('done'))
print('answer:', result.get('message', {}).get('content', ''))

stream: false важен для простого json.load: иначе API по умолчанию отправляет поток JSON-событий. Непотоковый /api/chat возвращает message.content и done; done: true означает завершение генерации, а не верность ответа s2. Не смешивайте вызовы: /api/generate кладёт images в корень JSON и отдаёт текст в response; этот пример намеренно использует только /api/chat s3. Не сохраняйте чувствительное изображение или длинный base64 в CI-логи.

Что считать подтверждённым результатом?

  1. /api/tags после загрузки содержит нужный тег и digest; запишите также ollama --version, ОС и путь к вашему PNG. Это подтверждает наличие модели, а не её использование s4.
  2. POST возвращает HTTP 200, done: true, поле model соответствует выбранному тегу и ответ не пуст. Это подтверждает завершение запроса, а не корректное восприятие картинки s2.
  3. Сравните ответ с test.png: красный должен быть слева, синий справа. Отметьте отдельно перепутанные цвета/стороны, придуманный текст или отказ; не переписывайте ожидаемый ответ по итогам модели. Повторите с переставленными цветами в новом PNG и новой записью истины, чтобы исключить шаблонное угадывание. Это предлагаемый протокол, не опубликованная оценка точности Modelium.
  4. После обращения запросите curl -fsS http://127.0.0.1:11434/api/ps: список показывает действительно загруженные модели, а size_vram — использование VRAM данным процессом в момент ответа. Пустой список позднее не доказывает отсутствие прогона: модель могла выгрузиться s5. ollama ps помогает увидеть размещение CPU/GPU; это не минимальное требование к железу s8.

Если все четыре проверки пройдены, у вас есть подтверждение собственного теста на синтетическом PNG и вашей ревизии модели. Это ещё не валидация для фото, русских сканов, таблиц или классификации документов. Для реальной задачи соберите раздельный набор с эталонной разметкой и фиксируйте ошибки по типам, а не один удачный ответ.

Почему запрос не работает или даёт неверный ответ?

  • Соединение отклонено: сначала проверьте запуск Ollama и точный адрес 127.0.0.1:11434; руководство по установке Ollama отделяет сервер от модели. Не чините локальную ошибку публикацией незащищённого API в интернет.
  • Модель не найдена: сверьте строку model с /api/tags, дождитесь окончания ollama pull и зафиксируйте локальный digest s4s7.
  • Текстовый тег вместо vision: проверьте входные модальности именно тега, а не название семейства; gemma3:1b в просмотренном каталоге не отмечен как Image input s6.
  • Неверный JSON или пустой message.content: проверьте base64 PNG без префикса data:image/..., вложенность messages[].images, stream: false, HTTP-ошибку и поле done s1s2.
  • Ответ уверенно неверен: зафиксируйте неудачу; другой prompt или модель — новый эксперимент, а не правка эталона. При сложной картинке сопоставляйте с исходным изображением и человеческой разметкой. Смена размера файла весов не даёт оценки качества.
  • Нужен закрытый контур: локальный адрес запроса не доказывает отсутствие прочих сетевых вызовов. По FAQ, облачные функции отключаются отдельно с OLLAMA_NO_CLOUD=1 или конфигурацией server.json; отдельно выполните проверку сетевого контура s8.

Для отката теста сохраните результаты и digest, затем удалите только созданный вами test.png. Удалять установленную модель ради отката одного запроса не нужно. Если задача стала извлечением реквизитов или данных таблиц, перейдите к сценарию документов для 1С вместо расширения одного vision-prompt. Следующий шаг: подготовьте и проверьте локальную Ollama, после чего выполните цветовой тест на своей машине и сохраните ответ рядом с эталоном.

Источники

  1. Ollama — Vision — REST images как base64; SDK принимает путь/URL/байты; сохранённый s1.md и SHA-256 в manifest.json.. Получено 26.09.2026.
  2. Ollama — API: Generate a chat message — Схема /api/chat, stream, messages.images и message.content; s2.md, manifest.json.. Получено 26.09.2026.
  3. Ollama — API: Generate a response — В /api/generate images — верхнеуровневое поле, ответ response; s3.md, manifest.json.. Получено 26.09.2026.
  4. Ollama — API: List models — name/digest/size установленных моделей; s4.md, manifest.json.. Получено 26.09.2026.
  5. Ollama — API: List running models — Проверка загрузки модели, size_vram и context_length; s5.md, manifest.json.. Получено 26.09.2026.
  6. Ollama — каталог тегов Gemma 3 — gemma3:4b поддерживает Text, Image; 1b только Text. 3.3GB — размер файла, не минимальная RAM/VRAM; s6.html, manifest.json.. Получено 26.09.2026.
  7. Ollama — API: Pull a model — Контракт /api/pull; s7.md, manifest.json.. Получено 26.09.2026.
  8. Ollama — FAQ: локальный режим, облако и размещение модели — OLLAMA_NO_CLOUD и ollama ps; s8.md, manifest.json.. Получено 26.09.2026.