Гайд · TNWS AI
Как извлечь JSON по схеме в vLLM через response_format
Схема для извлечения артикула и количества из текста: разбираем ответ и проверяем значения против исходника.
Задача и применимость
Вопрос читателя: «как получить json schema в vLLM response_format». Для vLLM Chat API с генеративной моделью; официальный пример response_format типа json_schema проверен 20 сентября 2026 года. Старые guided_json-аргументы удалены начиная с v0.12.0, поэтому пример использует поддерживаемую актуальную форму.
Для воспроизводимости запишите фактическую версию установленного vLLM, модельный checkpoint и параметры запуска. Путь /models/your-chat-checkpoint либо /models/your-embedding-checkpoint в команде ниже — заполнитель, а не реальный файл. Наличие GPU, объём памяти и условия лицензии весов проверяются до запуска. Демонстрация не утверждает, что ответ модели заранее известен по буквам.
Проверенные возможности
Документация показывает response_format с type=json_schema и вложенным json_schema, где есть name и schema. Также описан extra_body={"structured_outputs":{"json":...}}. Параметр guided_json удалён с v0.12.0. Структурный формат не доказывает истинность самих значений.
Пошаговая процедура
- Выделите два поля, которые явно есть в исходном документе.
- Определите JSON Schema объекта с required и дополнительной проверкой типов.
- Отправьте messages и response_format через Chat API.
- Разберите content при помощи json.loads, затем проверьте конкретные факты.
- При отсутствующем или противоречивом поле передайте запись на ручной разбор.
Команда для тестового запуска на локальном адресе (подставьте законно полученный checkpoint):
vllm serve /models/your-chat-checkpoint --host 127.0.0.1 --port 8000
Готовый запрос и контроль ответа
В приведённом фрагменте используется стандартная библиотека Python и простой общий помощник для отправки JSON. Подставьте при необходимости Bearer-токен через защищённую переменную окружения и проверьте, что ваш сервер его ожидает.
import json, urllib.request
BASE = "http://127.0.0.1:8000"
def call(path, payload):
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
request = urllib.request.Request(BASE + path, data=data,
headers={"Content-Type": "application/json"}, method="POST")
with urllib.request.urlopen(request, timeout=120) as reply:
return json.load(reply)
model = json.load(urllib.request.urlopen(BASE + "/v1/models"))["data"][0]["id"]
schema = {"type": "object", "properties": {
"sku": {"type": "string"}, "quantity": {"type": "integer"}},
"required": ["sku", "quantity"], "additionalProperties": False}
payload = {"model": model, "messages": [{"role": "user",
"content": "Извлеки факты: товар AB-17, количество 3 штуки."}],
"response_format": {"type": "json_schema", "json_schema": {
"name": "line_item", "schema": schema}}, "max_tokens": 80}
result = call("/v1/chat/completions", payload)
data = json.loads(result["choices"][0]["message"]["content"])
assert data == {"sku": "AB-17", "quantity": 3}
print(data)
Пример входа и ожидаемого результата
На входе «товар AB-17, количество 3 штуки». Ожидается объект с sku AB-17 и quantity 3 типа integer. Если модель вернёт quantity 4, JSON будет синтаксически корректным, но проверка остановит запись. Проверяйте именно отличие структуры от достоверности.
Как интерпретировать результат
JSON Schema ограничивает форму ответа, что полезно при заполнении карточек товаров. Но она не обращается к внешнему учёту склада и не проверяет, существует ли артикул AB-17. Поэтому делите конвейер на три шага: валидный HTTP, структурный разбор и проверка фактов по входной записи. Даже модель, выполняющая схему почти без ошибок, способна перепутать соседние числа. Для случаев без quantity не заставляйте модель выдумывать цифру: меняйте контракт на поддерживаемую nullable-форму либо помечайте запись как требующую уточнения.
Развёртывание без потери контекста
Старый пример из блога с guided_json может перестать работать после обновления vLLM. Проверьте номер установленной версии и используйте документированный response_format или structured_outputs. Сохраняйте схему вместе с материалом: изменение обязательных полей без миграции ухудшит обработку старых записей. Когда в исходном тексте два артикула, заранее определите, какой именно извлекается и зачем. В примере одна позиция намеренно однозначна; реальная накладная требует более богатой схемы и тестов.
Проверки качества и границы метода
Постройте набор из пяти отрицательных примеров: нет артикула, нет количества, количество написано словами, два товара и противоречащие строки. Для каждого заранее решите, выводить ли null, список элементов или отказ; универсальная схема для всех случаев не возникает сама. После обновления модели проверьте совпадение каждого поля со своим источником. Не исполняйте content как произвольный Python, используйте json.loads и строгий валидатор. Не отправляйте документы с персональными данными в открытые отладочные логи.
В сценарии контент-менеджера нельзя автоматически публиковать цену или количество из одного текста модели. Добавьте проверку по первичной системе учёта и отметку времени сверки. Если цена вообще не упоминалась, поле не должно появляться в результате по умолчанию. Для SEO-статьи с техническим примером полезнее честно показать отказ на неоднозначном вводе, чем заставлять нейросеть «догадаться». Тестируя ограничения, измеряйте долю корректных структур и долю правильных фактов отдельно.
Критерии готовности
- Схема и content успешно проходят разбор.
- Артикул и число совпадают с входом.
- Неизвестные поля не публикуются как факт.
Типичные ошибки и чего не делать
- Не применять удалённый guided_json к новой версии.
- Не считать структурный JSON достоверным.
- Не выдумывать отсутствующее количество.
Частые вопросы
Что вместо guided_json?
response_format или structured_outputs.
Сколько полей вернётся?
Структуру задаёт схема, но факты проверяют отдельно.
Можно ли пропустить json.loads?
Нет, content приходит как текст.
Официальные источники
Частые вопросы
Что вместо guided_json?
response_format или structured_outputs.
Сколько полей вернётся?
Структуру задаёт схема, но факты проверяют отдельно.
Можно ли пропустить json.loads?
Нет, content приходит как текст.
Читайте также
Как обработать named tool call в vLLM без произвольного выполнения кода
Требуем вызов одной безопасной функции, валидируем аргументы и не отдаём модели право запускать произвольные команды.
Как ограничить ответ vLLM вариантами choice при классификации заявок
Получаем одну из заранее разрешённых меток и отдельно проверяем, что классификация совпала с текстом обращения.
Как найти очередь запросов vLLM по метрикам /metrics
Разделяем очередь и генерацию через метрики ожидающих запросов и времени ожидания; строим контрольный замер.
Комментарии
Пока тихо. Скажите первое слово