Гайд · TNWS AI

Как получить JSON по схеме через response_format в llama.cpp server

4 мин—

Задаём объектную JSON Schema в chat endpoint, разбираем строку content и валидируем обязательные поля отдельно.

Задача и применимость

Поисковый вопрос: «как получить JSON по схеме llama.cpp response_format json_schema». Извлекать типизированные поля из короткой заметки без свободного текста вокруг JSON. llama.cpp server с генеративной GGUF-моделью, поддерживаемым чат-шаблоном и endpoint /v1/chat/completions; синтаксис response_format сверен с README проекта на 20 сентября 2026 года.

Пример рассчитан на уже имеющийся файл модели, полученный законным способом по условиям его лицензии. Здесь не утверждается, что любая GGUF-модель одинаково понимает русский язык или имеет один и тот же чат-шаблон. Фактический номер сборки узнавайте локально через llama-server --version и повторяйте контрольный опыт после обновления бинарника.

Что подтверждено документацией

Документация llama.cpp описывает response_format для plain JSON и JSON, ограниченного схемой: type json_object или json_schema со вложенным schema. Это ограничение синтаксиса генерации; оно не гарантирует истинность извлечённых значений. Схему надо сверять с поддерживаемым подмножеством JSON Schema в вашей сборке.

Порядок действий

  1. Составьте документ с однозначными полями, не включайте в него личные данные.
  2. Определите объектную JSON Schema с типами и обязательными ключами.
  3. Отправьте messages и response_format на /v1/chat/completions со stream:false.
  4. Разберите choices[0].message.content как JSON и проверьте значения против исходного текста.
  5. Запрещайте автоматическую запись результата, если поле отсутствует или подменено догадкой модели.

Локальный запуск для описанного сценария (замените путь к файлу на ваш):

./build/bin/llama-server -m /models/your-chat-model.gguf --host 127.0.0.1 --port 8080

Готовый шаблон запроса и проверки

import json, urllib.request
base = "http://127.0.0.1:8080"
model = json.load(urllib.request.urlopen(base + "/v1/models"))["data"][0]["id"]
schema = {"type": "object", "properties": {
    "order_id": {"type": "string"}, "days": {"type": "integer"}},
    "required": ["order_id", "days"]}
body = {"model": model, "stream": False,
    "messages": [{"role": "user", "content":
       "Извлеки только явные факты: Заказ K-17 доставят через 3 дня."}],
    "response_format": {"type": "json_schema", "schema": schema}}
req = urllib.request.Request(base + "/v1/chat/completions",
    data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
    headers={"Content-Type": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=90) as reply:
    raw = json.load(reply)["choices"][0]["message"]["content"]
data = json.loads(raw)
assert data["order_id"] == "K-17" and data["days"] == 3
print(data)

Входные данные и ожидаемый результат

Вход: «Заказ K-17 доставят через 3 дня». Ожидаемая проверка: словарь с order_id=K-17 и days=3, где days — integer, а не строка. Если модель выдаст 4, это валидный по типам JSON, но неверный факт; assert остановит процесс.

Почему важна именно эта проверка

Принудительный формат полезен там, где следующий модуль ждёт строгую структуру, например для заполнения тестовой карточки заказа. Однако JSON Schema регулирует форму, а не подтверждает источник данных. Отличайте три независимые проверки: удачный HTTP-ответ, успешно разобранный JSON и совпадение фактов с документом. В демонстрации третью проверку можно записать жёстким assert, потому что факт известен. В приложении с неизвестными документами потребуются правила извлечения, ручная проверка сложных случаев или сравнение с авторитетной базой.

Работа с реальными данными

Схема должна соответствовать содержанию входа. Если в тексте нет срока доставки, нельзя оставлять обязательное поле days и требовать догадку: лучше разрешить null через поддерживаемую конструкцию либо отправить запись на ручной разбор после проверки возможностей версии. Не задавайте слишком широкий объект «что угодно»: тогда ограничение теряет практический смысл. Не включайте конфиденциальные документы в debug-логи целиком. При обработке настоящих заказов сохраняйте ссылку на источник, версию схемы и исходный идентификатор, чтобы результат можно было перепроверить.

Проверка после изменения модели или нагрузки

При обновлении бинарника или замене GGUF сохраните серию контрольных кейсов: точный факт, отсутствующее поле, противоречивые цифры, пустой текст и невалидный ввод. Замеряйте долю удачных разобранных ответов отдельно от доли верных фактов. Документация показывает варианты json_object и json_schema, но не обещает совместимости всех возможных ключевых слов JSON Schema; проверяйте реально использованные ограничения на своей сборке. Не отправляйте сырое содержимое модели на выполнение как Python-код: json.loads трактует его как данные.

При построении карточки заказа помните о различии между «через 3 дня» и календарной датой. Пример извлекает ровно то число, которое явно написано во входе; он не рассчитывает дату доставки и не знает часовой пояс. Если бизнес-процессу нужна дата, её следует вычислять отдельно по проверенной дате заказа и правилам календаря. Такой разделённый конвейер проще тестировать: модель отвечает за извлечение, обычный код — за арифметику, а документ-источник остаётся доступным для проверки.

Критерии приёмки

  1. Ответ проходит json.loads и имеет необходимые типы.
  2. K-17 и 3 совпадают с текстом источника.
  3. Отсутствующие либо сомнительные поля не записываются как достоверные.

Частые ошибки и чего не делать

  • Не считать синтаксически правильный JSON истинным.
  • Не требовать от модели факт, которого нет во входе.
  • Не исполнять сгенерированный JSON как программу.

Краткие ответы на вопросы

Достаточно ли json_object?

Он ограничивает формат, но точную структуру лучше проверять схемой и кодом.

Гарантирует ли схема правильные факты?

Нет, значения проверяются отдельно.

Какие данные в content?

Строка JSON, которую нужно разобрать.

Официальные источники

Частые вопросы

Достаточно ли json_object?

Он ограничивает формат, но точную структуру лучше проверять схемой и кодом.

Гарантирует ли схема правильные факты?

Нет, значения проверяются отдельно.

Какие данные в content?

Строка JSON, которую нужно разобрать.

Читайте также

Комментарии

Пока тихо. Скажите первое слово