# SGLang Structured Output: JSON Schema и проверка локального ответа

Источник: https://modelium.tech/zhurnal/sglang-structured-output/

SGLang ограничивает формат ответа локальной модели через `response_format` с `type: json_schema` в Chat Completions API. Используйте совместимую модель, передайте небольшую схему и отдельно проверьте полученный JSON валидатором: соблюдение структуры не подтверждает правильность извлечённых фактов. Пример ниже — протокол по документации, а не результат собственного запуска Modelium.

По документации SGLang, на момент проверки 5 октября 2026 года сервер ограничивает генерацию JSON Schema, регулярным выражением либо EBNF, но для одного запроса выбирается только один вид ограничения. По умолчанию документация указывает XGrammar; существуют также Outlines и llguidance. Формат — механизм управления выводом, не проверка истинности содержания. [s1](#src-s1)

## Когда это полезно и что именно будет проверено

Если локальный агент возвращает объект с заранее известными полями для последующей обработки, задайте JSON Schema и отдельно проверьте ответ в своём приложении. Например, из короткого обезличенного фрагмента можно запросить поля `category` и `evidence`, а затем сверить `evidence` с исходником вручную. Наличие строки в обязательном поле ещё не означает, что цитата верна: это граница между проверкой *структуры* и проверкой *смысла*. Сами ограничения JSON Schema и образец запроса описаны официальной документацией. [s1](#src-s1)

Это узкая страница про SGLang: общий разбор структурированного вывода через Ollama, llama.cpp и vLLM доступен в [отдельном руководстве](/zhurnal/structured-output-lokalno-json-schema/). Для исполнения инструментов агентом нужен другой протокол и проверка фактического вызова, а не просто похожая на JSON строка. [s1](#src-s1)

## Как подготовить модель, сервер и локальный адрес

Официальный пример SGLang Chat API использует `qwen/qwen2.5-0.5b-instruct` и обращается к локальному `/v1` через клиент OpenAI; в карточке соответствующей модели Hugging Face указаны точное имя `Qwen/Qwen2.5-0.5B-Instruct` и метка лицензии `apache-2.0`. Это **пример для проверки протокола**, не рекомендация качества для русских документов; автор карточки заявляет поддержку русского языка, но мы её не измеряли. [s2](#src-s2) [s3](#src-s3)

Сначала откройте [гайд SGLang](/zhurnal/sglang/) и подготовьте поддерживаемое этим runtime оборудование и установленный пакет. Затем в изолированной среде запустите `python3 -m sglang.launch_server --model-path Qwen/Qwen2.5-0.5B-Instruct --revision 7ae557604adf67be50417f59c2c2f167def9a775 --host 127.0.0.1 --port 30000`; аргументы `--model-path`, `--revision`, `--host` и `--port` документированы. Это **предлагаемая команда по документации**, Modelium не запускал её и не гарантирует совместимость конкретного GPU или объём памяти. Держите адрес на loopback, пока не настроены отдельная авторизация и защита доступа. [s2](#src-s2) [s4](#src-s4)

Здесь используется Chat Completions API: сервер применяет chat template токенизатора при его наличии. Не смешивайте его с native `/generate`: там в запросе передают `text` и `sampling_params`, а значение `json_schema` в примерах native API сериализуется в строку. Переносить тот же payload между двумя endpoint без изменения формата нельзя. [s2](#src-s2) [s1](#src-s1) [s5](#src-s5) [s7](#src-s7)

## Как отправить запрос с JSON Schema

Используйте `POST http://127.0.0.1:30000/v1/chat/completions` с JSON-объектом, где `model` равен загруженной модели, `messages` содержит вопрос пользователя, `temperature` равен 0, а `response_format` задаёт `type: "json_schema"`. Внутри `json_schema` укажите `name` и объект `schema`. Эта форма повторяет официальный пример SGLang для OpenAI-совместимого endpoint. [s1](#src-s1) [s2](#src-s2)

Для безопасного пробного сценария задайте в `schema`: `type: "object"`; `properties.category.type: "string"`; `properties.evidence.type: "string"`; `required: ["category", "evidence"]`; `additionalProperties: false`. Передайте короткий, заведомо обезличенный фрагмент и просьбу вернуть строго эти два поля. Простая схема облегчает диагностику; качество реальных ответов зависит от модели и входа, а не выводится из наличия `response_format`. Проверка `additionalProperties` должна выполняться вашим валидатором, а совместимость конкретной конструкции с выбранным grammar backend надо проверить на своём стенде. [s1](#src-s1)

После ответа извлеките `choices[0].message.content`, разберите как JSON и проверьте *полученный объект* против той же схемы самостоятельным JSON Schema валидатором в своём приложении; SGLang в официальном примере отдельно вызывает Pydantic `model_validate_json`. Если ваше приложение на Python, локальный Pydantic может выполнять эту проверку; версия схемы в генерации и проверке должна быть одна. Не выдавайте HTTP 200 или просто успешно разобранный JSON за валидацию и тем более за точность извлечения. [s1](#src-s1)

## Как понять, что результат подходит задаче

Проверьте три разных результата: сервер принял запрос к загруженной модели, JSON прошёл независимую проверку структуры и значение `evidence` действительно встречается в исходном фрагменте. Последняя проверка — редакционная рекомендация; никакой из документации серверных endpoint не заменяет сверку с первичным документом. На серии собственных тестовых фрагментов отдельно считайте отказы, пустые значения и неверные цитаты; Modelium не проводил таких измерений. [s1](#src-s1) [s2](#src-s2)

Если сервер возвращает ошибку на `response_format`, сверяйте API и версию/бэкенд ограниченной генерации с закреплённой документацией. Если JSON валиден, но поля бессодержательны, уточните запрос и тестируйте другую совместимую модель: документация SGLang сама рекомендует явные инструкции о формате в prompt. Если ответы обрываются, проверьте лимит выходных токенов на одном и том же тесте, не обещая результата от простого увеличения лимита. [s1](#src-s1)

## Какие есть ограничения и следующий шаг

`json_schema`, `regex` и `ebnf` нельзя одновременно использовать в одном запросе. Для reasoning-моделей SGLang отдельно описывает `--reasoning-parser`, который различает свободный блок рассуждений и ограничиваемый финальный ответ; не переносите выводы базового примера Qwen2.5 на DeepSeek-R1 и другие модели с отдельным thinking-блоком без нового теста. [s1](#src-s1) [s6](#src-s6)

JSON-структура не является универсальной безопасностью агентной системы. Для доступа из сети, обработки чужого документа или исполнения инструмента проверяйте права, вход и реальные действия отдельно. Начните с [запуска SGLang](/zhurnal/sglang/) на доступном устройстве, затем сохраните один запрос, схему, локально валидированный ответ и исходный фрагмент для сверки. Собственных измерений скорости, памяти или точности Modelium не проводил. [s2](#src-s2)

## Источники

1. [SGLang: Structured Outputs и OpenAI Compatible API](https://github.com/sgl-project/sglang/blob/a977e3b9d517a1eb16e68ae5c6b06562073d661a/docs/docs/advanced_features/structured_outputs.mdx) — получено 2026-10-05
2. [SGLang: OpenAI APIs — Completions](https://github.com/sgl-project/sglang/blob/a977e3b9d517a1eb16e68ae5c6b06562073d661a/docs/docs/basic_usage/openai_api_completions.mdx) — получено 2026-10-05
3. [Qwen/Qwen2.5-0.5B-Instruct: закреплённая карточка](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/blob/7ae557604adf67be50417f59c2c2f167def9a775/README.md) — получено 2026-10-05
4. [SGLang: Server Arguments — модель, revision, host, port](https://github.com/sgl-project/sglang/blob/a977e3b9d517a1eb16e68ae5c6b06562073d661a/docs/docs/advanced_features/server_arguments.mdx) — получено 2026-10-05
5. [SGLang: Native APIs — различие /generate и Chat API](https://github.com/sgl-project/sglang/blob/a977e3b9d517a1eb16e68ae5c6b06562073d661a/docs/docs/basic_usage/native_api.mdx) — получено 2026-10-05
6. [SGLang: Structured Outputs for Reasoning Models](https://github.com/sgl-project/sglang/blob/a977e3b9d517a1eb16e68ae5c6b06562073d661a/docs/docs/advanced_features/structured_outputs_for_reasoning_models.mdx) — получено 2026-10-05
7. [SGLang: Sampling Parameters — native generation](https://github.com/sgl-project/sglang/blob/a977e3b9d517a1eb16e68ae5c6b06562073d661a/docs/docs/basic_usage/sampling_params.mdx) — получено 2026-10-05
