Перейти к содержимому

Structured outputs

Structured outputs заставляют модель отвечать JSON заданной формы. Это убирает разбор свободного текста и «почти правильные» ответы: ключи, типы и обязательные поля описываются схемой один раз.

Проверить поддержку у модели можно по GET /v1/models: в capabilities.features есть structured_outputs (строгая схема) или response_format (режим JSON без схемы). См. Модели.

Схема передаётся в response_format с типом json_schema.

structured.sh
curl https://api.waibee.com/v1/chat/completions \
-H "Authorization: Bearer $WAIBEE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.4-mini",
"messages": [
{ "role": "user", "content": "Извлеки данные: Иван Петров, 34 года, Берлин, senior backend." }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" },
"city": { "type": "string" },
"role": { "type": "string" }
},
"required": ["name", "age", "city", "role"],
"additionalProperties": false
}
}
}
}'

Ответ приходит обычным сообщением, JSON лежит строкой в content:

response.json
{
"choices": [{
"index": 0,
"finish_reason": "stop",
"message": {
"role": "assistant",
"content": "{\"name\":\"Иван Петров\",\"age\":34,\"city\":\"Берлин\",\"role\":\"senior backend\"}"
}
}],
"usage": { "prompt_tokens": 68, "completion_tokens": 30, "total_tokens": 98 }
}

Поля json_schema:

Поле Назначение
name Имя схемы. Модель видит его и трактует как подсказку о смысле объекта
strict true требует точного соответствия схеме
schema Сама схема в формате JSON Schema

Более простой режим {"type": "json_object"} требует только валидный JSON, без схемы. Он подходит, когда форма ответа заранее не важна.

На POST /v1/messages структура задаётся полем format внутри output_config:

{
"model": "anthropic/claude-sonnet-5",
"max_tokens": 1024,
"output_config": {
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": { "city": { "type": "string" }, "temp_c": { "type": "number" } },
"required": ["city", "temp_c"]
}
}
},
"messages": [{ "role": "user", "content": "В Берлине 19 градусов. Оформи ответ по схеме." }]
}

Ответ приходит текстовым блоком, внутри которого лежит JSON: {"city":"Berlin","temp_c":19}.

output_config проходит к провайдеру как есть, поэтому набор его полей определяется моделью. Там же задаётся уровень рассуждений, см. Reasoning.

  • Схема ограничивает форму, не смысл. Модель заполнит все обязательные поля, даже если данных во вводе нет: для «не знаю» предусмотрите явное значение (null в списке типов или поле-флаг).
  • Держите схему плоской. Глубокая вложенность и большие oneOf заметно чаще приводят к отказам и лишним токенам. Часто проще сделать два запроса с простыми схемами.
  • Схема не отменяет валидацию. Разбирайте ответ своим валидатором: он всё равно нужен, чтобы отличить сбой модели от рабочего ответа.
  • Ограничение по длине обрезает JSON. Если ответ упирается в max_tokens, придёт незакрытая строка с finish_reason: "length". Проверяйте это отдельно от ошибок разбора.
  • Не совмещайте со стримингом без необходимости. Частичный JSON в потоке всё равно нельзя разобрать до конца генерации.
  • Для аргументов функций схема своя. Structured outputs описывают ответ модели, а не вызовы инструментов, см. Вызов инструментов.