llama.cpp multimodal API: передать изображение и проверить ответ
На странице · 4 разделов
llama.cpp принимает изображение в локальном `/v1/chat/completions`, если загружены совместимая vision-модель и её мультимодальный проектор. В примере Gemma 3 4B запрос передаёт JPEG или PNG как data URL, а пользователь сравнивает ответ с заранее записанными признаками своего снимка. Успешный HTTP-ответ подтверждает работу API, но не точность распознавания и не отсутствие сетевой активности при загрузке модели.
Сверено 28 сентября 2026 года с llama.cpp
v0.5.0(commit7fe450e1) и GGUF-репозиторием Gemma 3 4B (revisiond0976223). Ни сервер, ни веса на Modelium не запускались; команды ниже — воспроизводимая инструкция для вашего стенда, а не отчёт о собственном тесте. Мультимодальная подсистема остаётся экспериментальной. s1 s2 s8
Что именно проверяет этот гайд?
Результат — локальный HTTP-запрос с одним своим изображением, содержательный текст в choices[0].message.content и ваша ручная сверка с тем, что действительно видно на исходнике. Это маршрут «тестовое изображение → Gemma 3 4B GGUF и совместимый проектор → llama-server → ответ → сверка». Работа API и качество зрения — разные проверки: JSON с текстом не доказывает, что модель верно распознала предмет. s1 s4 s7
В llama.cpp мультимодальные данные проходят через libmtmd; в типичном сценарии требуются GGUF языковой модели и отдельный совместимый mmproj для изображения. Передача JPEG/PNG по image_url в chat API относится к конкретному серверу, не к API Ollama и не к текстовому llama-cli без проектора. Документация серверной подсистемы называет эту возможность экспериментальной. s1 s2 s4
Какие файлы, версия и оборудование нужны?
Для примера выбран ggml-org/gemma-3-4b-it-GGUF, а не семейство Gemma в целом. На закреплённой HF-ревизии d0976223747697cb51e056d85c532013931fe52e перечислены gemma-3-4b-it-Q4_K_M.gguf и mmproj-model-f16.gguf. Их нужно взять из одной ревизии и совместимого набора, а не подставлять проектор от другой модели. Карточка помечена license: gemma: это не Apache/MIT и не автоматическое разрешение на любое коммерческое использование; перед реальным применением прочтите действующие условия автора. Файловый размер и пример сборки не равны минимуму RAM/VRAM; запуск и время ответа зависят от вашей памяти, backend, размера изображения и настроек. s2 s7 s8
Официальный quickstart отмечает, что Gemma 3 1B не поддерживает зрение; 4B взята здесь именно как документированный пример. Подготовьте собственную JPEG/PNG-картинку без личных или клиентских данных — например, фотографию чашки на столе с заметным цветом. Запишите до запроса видимые признаки: есть ли чашка, её цвет и что находится рядом. Это контрольная разметка, а не обещанный ответ модели. s3 s7
Выполните сборку llama.cpp на выбранном закреплённом Git commit и получите build/bin/llama-server (путь относится к стандартной CMake-сборке). Команды ниже не обновляют репозиторий за пределы этого commit; зависимости сборки и доступность backend надо проверить для вашей ОС. Скачайте оба GGUF с указанной выше HF-ревизии на свой компьютер в каталог models/gemma3/; не полагайтесь на плавающее -hf для воспроизводимого рабочего стенда, хотя для быстрого ознакомления он поддерживается и умеет подобрать mmproj автоматически. Не публикуйте на сервере образы с клиентскими данными. s1 s4 s6 s8
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
git checkout 7fe450e19305b828c199d602c23a8337aaa1f03b
cmake -B build
cmake --build build --config Release --target llama-server
# Скопируйте оба файла из ревизии d0976223 в models/gemma3/
./build/bin/llama-server \
-m models/gemma3/gemma-3-4b-it-Q4_K_M.gguf \
--mmproj models/gemma3/mmproj-model-f16.gguf \
--host 127.0.0.1 --port 8080
Если тестируете через документированный короткий вариант llama-server -hf ggml-org/gemma-3-4b-it-GGUF, файлы могут быть загружены из сети, а их ревизия может отличаться от указанной выше; зафиксируйте фактически полученные файлы. Для локальных файлов укажите оба пути. При отсутствии GPU проектор можно оставить на CPU с --no-mmproj-offload, но это не гарантия производительности и не тест поддержки железа. s1 s4
Как проверить готовность и отправить изображение?
В новом терминале вызовите health и список моделей. /health выдаёт HTTP 503, пока модель загружается, и 200 с status: ok после готовности; GET /v1/models возвращает ID модели. Наличие ID или 200 само по себе не проверяет путь мультимодального кодирования — нужен отдельный запрос с изображением. На loopback сервер по умолчанию не требует API-ключа, но для доступа извне требуются собственная защита и контроль сети; в этом гайде не включайте --host 0.0.0.0, серверные инструменты или MCP. s4
curl -fsS http://127.0.0.1:8080/health
curl -fsS http://127.0.0.1:8080/v1/models
Следующий скрипт принимает путь к вашему JPEG или PNG, кодирует байты в data:image/...;base64 и отправляет messages[0].content из двух частей: текст и image_url. Этот тип и data URL описаны в серверном README; обработка media-поля есть в закреплённом коде. model берётся из ответа /v1/models, а не угадывается по имени GGUF. Скрипт проверяет структуру JSON, не выставляет оценку качеству картинки. s4 s5
python3 - /путь/к/вашему-тестовому-фото.jpg <<'PY'
import base64, json, pathlib, sys, urllib.request
image = pathlib.Path(sys.argv[1])
raw = image.read_bytes()
if raw.startswith(b'\x89PNG\r\n\x1a\n'):
mime = 'image/png'
elif raw.startswith(b'\xff\xd8\xff'):
mime = 'image/jpeg'
else:
raise SystemExit('Ожидался JPEG или PNG; проверьте файл')
if not raw or len(raw) > 8 * 1024 * 1024:
raise SystemExit('Используйте небольшой тестовый файл не больше 8 МиБ')
base = 'http://127.0.0.1:8080'
with urllib.request.urlopen(base + '/v1/models', timeout=30) as response:
models = json.load(response)['data']
if not models or not models[0].get('id'):
raise SystemExit('Сервер ещё не сообщил ID загруженной модели')
payload = {
'model': models[0]['id'], 'stream': False, 'max_tokens': 160,
'messages': [{'role': 'user', 'content': [
{'type': 'text', 'text': 'Опиши видимые предметы и цвета. Если деталь неразличима, скажи об этом; не угадывай.'},
{'type': 'image_url', 'image_url': {
'url': 'data:' + mime + ';base64,' + base64.b64encode(raw).decode('ascii')
}}
]}]
}
request = urllib.request.Request(
base + '/v1/chat/completions',
data=json.dumps(payload).encode('utf-8'),
headers={'Content-Type': 'application/json'}, method='POST'
)
with urllib.request.urlopen(request, timeout=180) as response:
result = json.load(response)
answer = result['choices'][0]['message']['content']
if not isinstance(answer, str) or not answer.strip():
raise SystemExit('HTTP ответ получен, но текстовое описание пустое')
print(json.dumps({'model': models[0]['id'], 'answer': answer}, ensure_ascii=False, indent=2))
PY
Лимит 8 МиБ в примере — консервативный предел этого клиентского скрипта, не документированный лимит llama.cpp. Отправка base64 увеличивает размер запроса; большие изображения сначала уменьшите локально. Не используйте удалённый image_url, если задача — ограничить передачу снимка loopback-сервером: сервер поддерживает remote URL и может загрузить его отдельно. Локальный data URL в запросе ещё не доказывает отсутствие внешнего трафика при скачивании модели или обновлениях окружения. s4 s5
Когда проверка считается успешной — и что делать при ошибке?
Сравните ответ с заранее записанными видимыми признаками: предмет назван верно, цвет не выдуман, несуществующие детали отмечены как неизвестные. Зафиксируйте три состояния отдельно: сервер готов, ответ непустой, описание совпадает с картинкой. Для пары разных своих снимков повторите процедуру и сохраните конкретные совпадения и ошибки. Нельзя объявлять модель пригодной для OCR, документов, контроля качества или русской речи на основании одной фотографии: для каждого сценария нужен размеченный набор и ручной разбор ошибок. s4 s7
Если /health отвечает 503, дождитесь окончания загрузки и проверьте локальные логи. Если мультимодальный запрос не обрабатывается, сверяйте GGUF и mmproj с одной ревизией, наличие опции --mmproj и тип сообщения image_url; --no-mmproj отключает мультимодальность. Если JSON есть, а содержание неверно, не лечите это подменой фактов: упрощайте снимок и вопрос, проверяйте реальную пару файлов, а затем тестируйте на собственных данных другую документированную vision-модель. Мультимодальный путь меняется быстро; перепроверьте версию при обновлении. s1 s2 s4 s8
После испытания остановите процесс llama-server через Ctrl-C; не удаляйте чужие модели. Сохраните commit сервера, ревизию и имена обоих файлов, параметры запуска, исходное изображение (если есть право хранить), записанные до запроса признаки, текст ответа и дату проверки. Для анализа сетевых обращений отдельным следующим шагом откройте протокол проверки офлайн-контура; для другого runtime сравните Ollama Vision API. s4 s8
Источники
- llama.cpp v0.5.0 — Multimodal documentation — revision 7fe450e19305b828c199d602c23a8337aaa1f03b. Получено 28.09.2026.
- llama.cpp v0.5.0 — libmtmd and projector — revision 7fe450e19305b828c199d602c23a8337aaa1f03b. Получено 28.09.2026.
- llama.cpp v0.5.0 — Gemma 3 vision quickstart — revision 7fe450e19305b828c199d602c23a8337aaa1f03b. Получено 28.09.2026.
- llama.cpp v0.5.0 — llama-server API and options — revision 7fe450e19305b828c199d602c23a8337aaa1f03b. Получено 28.09.2026.
- llama.cpp v0.5.0 — server multimodal request implementation — revision 7fe450e19305b828c199d602c23a8337aaa1f03b. Получено 28.09.2026.
- llama.cpp v0.5.0 — Build documentation — revision 7fe450e19305b828c199d602c23a8337aaa1f03b. Получено 28.09.2026.
- Gemma 3 4B IT GGUF — закреплённая карточка автора — revision d0976223747697cb51e056d85c532013931fe52e. Получено 28.09.2026.
- Gemma 3 4B IT GGUF — перечень файлов на закреплённой ревизии — revision d0976223747697cb51e056d85c532013931fe52e. Получено 28.09.2026.