Перейти до вмісту
Структуровані відповіді

Структуровані відповіді

Попросіть відповідь у JSON: будь-який JSON-об'єкт або JSON, що відповідає схемі, яку ви надсилаєте. Використовуйте це, коли відповідь читає програма, а не людина.

POST https://api.shannon-ai.com/v1/chat/completions

import json
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1")

response = client.chat.completions.create(
    model="Kimi-K3-3BIT-REAP",
    messages=[
        {"role": "user", "content": "Extract the person: John Doe, 30 years old, engineer."}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "person",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "occupation": {"type": "string"},
                },
                "required": ["name", "age", "occupation"],
            },
        },
    },
)

# The JSON arrives as text in message.content: parse it, then check it.
try:
    person = json.loads(response.choices[0].message.content)
except json.JSONDecodeError:
    person = None  # ask again, or report the failure

print(person)

JSON — це текст відповіді, у choices[0].message.content:

200 JSON
{
  "id": "chatcmpl-0c4e7a1b9d2f4e6a8b3c5d7e9f1a2b3c",
  "object": "chat.completion",
  "created": 1791590400,
  "model": "Kimi-K3-3BIT-REAP",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "{\"name\":\"John Doe\",\"age\":30,\"occupation\":\"engineer\"}",
        "reasoning_content": null
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 96,
    "completion_tokens": 19,
    "total_tokens": 115,
    "prompt_tokens_details": {"cached_tokens": 0},
    "completion_tokens_details": {"reasoning_tokens": 0}
  }
}

Режими response_format

response_format — це поле /v1/chat/completions. Без нього відповідь — звичайний текст.

Режим Значення Що ви отримуєте
JSON-об'єкт {"type": "json_object"} Відповідь — це JSON без заданої форми. Вкажіть у промпті, які ключі вам потрібні.
JSON-схема {"type": "json_schema", "json_schema": {"name": "…", "schema": {…}}} Відповідь відповідає схемі, яку ви надсилаєте: її ключам, типам і обов'язковим полям.
Strict "strict": true Поле json_schema, а не третій режим. Дорівнює true, якщо ви не надішлете false.
Поле Тип За замовчуванням Опис Застосовують
type string json_object або json_schema. Обов'язкове всередині response_format. text приймається й дає звичайну текстову відповідь. Кожна модель, що приймає режим
json_schema.schema object JSON Schema, якої дотримується відповідь. Надсилайте її щоразу, коли type дорівнює json_schema. Кожна модель, що приймає режим
json_schema.name string Мітка схеми, як у форматі OpenAI. Хостовані open-weight моделі
json_schema.strict boolean true Чи має відповідь точно відповідати схемі. Моделі Shannon застосовують кожну схему як strict. Хостовані open-weight моделі

Режим JSON-об'єкта не потребує схеми. Назвіть ключі в промпті:

Тіло запиту
{
  "model": "shannon-3",
  "messages": [
    {
      "role": "user",
      "content": "Name the capital of France. Answer as JSON with the keys city and country."
    }
  ],
  "response_format": {"type": "json_object"}
}

Підтримка за моделями

Модель json_object json_schema
Кожна модель Shannon (shannon-*) Так Так
Хостовані open-weight моделі, окрім названих нижче Так Так
Laguna-S-2.1-W4A16-AUTOROUND-REAP — —
inkling-W4A16-AUTOROUND-REAP Так —

GET /v1/models повідомляє те саме для кожного id: capabilities.json_schema на кожній моделі та capabilities.response_format на хостованих open-weight моделях. Моделі та ціни

Підтримувані ключові слова схеми

Що модель отримує з вашої схеми, залежить від моделі та ендпоінта:

Моделі /v1/chat/completions /v1/responses
Моделі Shannon Підмножина ключових слів нижче, застосована як strict. Схема така, як ви її надсилаєте, застосована як strict.
Хостовані open-weight моделі Схема така, як ви її надсилаєте. strict дорівнює true, якщо ви його не надсилаєте. Схема така, як ви її надсилаєте. strict дорівнює true, якщо ви його не надсилаєте.

Підмножина ключових слів моделей Shannon на /v1/chat/completions:

Ключове слово Як читається
Ключові слова, що читаються type, format, title, description, nullable, enum, items, properties, required, minItems, maxItems, minimum, maximum, minLength, maxLength, pattern, anyOf, default
$ref Розв'язується з $defs або definitions на верхньому рівні схеми. Ключові слова, записані поруч із $ref, як-от description, зберігаються. Посилання без відповідного визначення читається як {"type": "object"}.
allOf Члени зливаються в одну схему. Де два члени задають те саме ключове слово, діє пізніший.
oneOf Читається як anyOf.
Схеми, що посилаються на себе Розгортаються до 24 рівнів. Глибший рівень читається як {"type": "object"}.
Поза підмножиною Кожне інше ключове слово, наприклад additionalProperties, const, multipleOf, uniqueItems, exclusiveMinimum, exclusiveMaximum, patternProperties, prefixItems, minProperties, maxProperties, not і if / then / else. Вони не входять до схеми, яку отримує модель.

На ендпоінті /v1/responses: поле text.format

/v1/responses записує той самий запит як text.format. Схема міститься безпосередньо в format, поруч із name і strict, а не під ключем json_schema. Для режиму JSON-об'єкта надішліть {"format": {"type": "json_object"}}.

Тіло запиту
{
  "model": "Kimi-K3-3BIT-REAP",
  "input": "Extract the person: John Doe, 30 years old, engineer.",
  "text": {
    "format": {
      "type": "json_schema",
      "name": "person",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "age": {"type": "integer"},
          "occupation": {"type": "string"}
        },
        "required": ["name", "age", "occupation"]
      }
    }
  }
}

JSON — це text частини output_text елемента message:

200 JSON
{
  "output": [
    {
      "id": "msg_7e1d3c5b9a2f4d6e8c0b1a3f5e7d9c2b",
      "type": "message",
      "role": "assistant",
      "status": "completed",
      "content": [
        {
          "type": "output_text",
          "text": "{\"name\":\"John Doe\",\"age\":30,\"occupation\":\"engineer\"}",
          "annotations": []
        }
      ]
    }
  ]
}

Підтримка за моделями та помилки такі самі, як на /v1/chat/completions. Responses API

На /v1/messages: інструмент як схема

Формат Messages не має поля структурованого виводу. Щоб отримати JSON від тих самих моделей, викликайте /v1/chat/completions або /v1/responses з тим самим ключем.

Щоб залишитися на /v1/messages, опишіть об'єкт як інструмент: помістіть свою схему в input_schema і назвіть інструмент у tool_choice. Тоді input блока tool_use — це ваш об'єкт, уже розібраний. Названий tool_choice застосовують хостовані open-weight моделі.

Тіло запиту
{
  "model": "Kimi-K3-3BIT-REAP",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "Extract the person: John Doe, 30 years old, engineer."
    }
  ],
  "tools": [
    {
      "name": "record_person",
      "description": "Record the extracted person.",
      "input_schema": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "age": {"type": "integer"},
          "occupation": {"type": "string"}
        },
        "required": ["name", "age", "occupation"]
      }
    }
  ],
  "tool_choice": {"type": "tool", "name": "record_person"}
}
200 JSON
{
  "stop_reason": "tool_use",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_4b8d2f6a1c3e4a5b9d7f0e2c4a6b8d1f",
      "name": "record_person",
      "input": {"name": "John Doe", "age": 30, "occupation": "engineer"}
    }
  ]
}

Перш ніж читати блок, перевірте, що stop_reason дорівнює tool_use. Виклик функцій

Як надходить JSON

  • JSON — це рядок. Розібраного об'єкта поряд у відповіді немає: запустіть свій парсер JSON на message.content.
  • З stream: true JSON надходить шматками delta.content. З'єднайте їх і розберіть після завершення стріму; окремий шматок не є коректним JSON.
  • Хостована open-weight модель відповідає на запит response_format без тексту міркувань: reasoning_content дорівнює null.

Перевіряйте отримане

Схема спрямовує, як модель пише. API не порівнює готову відповідь із вашою схемою, тож остаточну перевірку робить ваш код:

  • Розбирайте всередині обробника помилок, як у прикладі вгорі.
  • Перевірте розібраний об'єкт тією самою схемою у власному коді, наприклад за допомогою бібліотеки JSON Schema, Pydantic або Zod.
  • Довга відповідь може закінчитися, перш ніж JSON буде повним. Відповідь без стрімінгу повідомляє finish_reason лише як stop або tool_calls, тож сигналом є помилка розбору. Запитайте знову або попросіть менший об'єкт.

Помилки

Статус Тип Повідомлення Коли
400 invalid_request_error <id> does not accept response_format Модель не приймає жодного з режимів.
400 invalid_request_error <id> does not accept response_format json_schema; use json_object Модель приймає json_object, а ви надіслали json_schema.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … response_format не має type або не є JSON-об'єктом.

Обидві відповіді 400 надсилаються, перш ніж щось списується з вашого балансу. Обробка помилок