Коротко: чем structured output отличается от просьбы в промпте

Коротко: обычный промпт с просьбой вернуть JSON дает лишь вероятностный, ничем не строго ограниченный формат, тогда как JSON mode и structured outputs на уровне API включают механизмы, которые заставляют модель генерировать синтаксически валидный JSON и, при наличии схемы, следовать конкретному JSON Schema или response schema.

Если просто написать в промпте «ответь JSON-объектом по такой структуре», модель воспринимает это как текстовую инструкцию, а не как формальный контракт. Она может забыть поле, перепутать тип, добавить лишние ключи или вообще вернуться в обычный текст при сложных задачах, и никакой автоматической проверки или коррекции на стороне API не происходит.

JSON mode и structured outputs отличаются тем, что включают ограничения на уровне генерации или проверки: API требует, чтобы выходные токены образовали валидный JSON, а в режиме со схемой - чтобы структура соответствовала заданному JSON Schema или response schema. Это превращает формат ответа из «желательного» (prompt-only) в «обязательный» (schema-constrained), что критично для продакшн-пайплайнов, парсеров, БД и оркестрации агентов.

OpenAI: JSON mode и Structured Outputs

OpenAI выделяет два основных механизма работы с JSON в API:

JSON mode - включается через response_format с type: "json_object" и заставляет модель возвращать валидный JSON, но без проверки соответствия конкретной схеме.

Structured Outputs - включаются через response_format типа json_schema (или через tools с strict: true в определении функции) и гарантируют соответствие выходных данных заданному JSON Schema.

Документация прямо говорит: JSON mode улучшает надежность генерации валидного JSON, но не гарантирует, что ответ соответствует конкретной схеме, а Structured Outputs именно это и решают.

Как включается в API

В Responses API JSON mode включается примерно так: указать формат текста как {"type": "json_object"}.

Пример тела запроса (схематично):

{
 "model": "gpt-4o-mini",
 "input": "Извлеки данные о продукте",
 "response_format": {
 "type": "json_object"
 }
}

Этот вызов гарантирует синтаксически валидный JSON, но не фиксирует структуру (набор полей, типы, обязательность).

Structured Outputs через response format включаются так: text: { format: { type: "json_schema", strict: true, schema: ... } } для Responses API. Для Chat Completions структура параметра аналогична: response_format с типом "json_schema" и вложенным объектом схемы.

Обязательность схемы

Для JSON mode схема не обязательна - достаточно указать тип json_object, и модель будет стремиться выдавать валидный JSON любого вида.

Для Structured Outputs JSON Schema обязателен: feature прямо описывается как «ensure model responses follow specific JSON Schema you define» и включается только при наличии schema внутри json_schema конфигурации.

Минимальный пример схемы и вызова

Простой JSON Schema для ответа OpenAI:

{
 "name": "product",
 "schema": {
 "type": "object",
 "properties": {
 "name": { "type": "string", "description": "Название продукта" },
 "price": { "type": "number", "description": "Цена в евро" }
 },
 "required": ["name", "price"]
 },
 "strict": true
}

Такую схему передают в response_format в виде:

"response_format": {
 "type": "json_schema",
 "json_schema": {
 "name": "product",
 "schema": { ... },
 "strict": true
 }
}

Документация описывает этот паттерн как стандартный способ задать JSON Schema, чтобы модель строго ему следовала.

Anthropic Claude: tool use и input_schema

На стороне Anthropic Claude structured outputs реализуются через механизм tool use (function calling). В API вы передаете список инструментов в параметре tools каждого запроса к messages.create, где для каждого инструмента определяется name, description и input_schema - это JSON Schema, описывающий ожидаемые параметры.

Документация говорит, что input_schema - JSON Schema object defining the expected parameters for the tool, а tool_use блок в ответе содержит input - объект, который «conforming to the tool's input_schema». Это и есть точка структурированного вывода: Claude генерирует JSON аргументы инструмента в соответствии с формальным описанием.

Как включается в API

Tool use включается добавлением tools к вызову client.messages.create (или соответствующему REST-вызову):

{
 "model": "claude-3-5-sonnet-latest",
 "messages": [
 { "role": "user", "content": "Извлеки данные о продукте" }
 ],
 "tools": [
 {
 "name": "extract_product",
 "description": "Извлекает структуру данных о продукте",
 "input_schema": {
 "type": "object",
 "properties": {
 "name": { "type": "string" },
 "price": { "type": "number" }
 },
 "required": ["name", "price"]
 }
 }
 ]
}

Claude, решив использовать инструмент, вернет tool_use блок, в котором input будет JSON-объектом, построенным по указанному input_schema.

На данный момент в официальной документации Claude нет отдельного параметра «JSON mode» или явного response_schema для основного текстового ответа, аналогичного OpenAI или Gemini. Поэтому жестко гарантировать формат «весь ответ - JSON по такой схеме» на уровне общего текста можно только косвенно, например, моделируя весь желаемый вывод как аргументы инструмента и обрабатывая их в своем коде. Это уже developer-паттерн, а не официальная отдельная фича API.

Обязательность схемы

Для tool use input_schema обязателен: таблица параметров инструмента прямо указывает, что каждый инструмент содержит input_schema как JSON Schema, который определяет форму входных данных. Без него Claude не знает, какие аргументы можно передавать, а значит, нет и строгой структуры JSON.

Минимальный пример схемы и вызова

Минимальная схема для инструмента:

"input_schema": {
 "type": "object",
 "properties": {
 "title": { "type": "string", "description": "Заголовок карточки" },
 "available": { "type": "boolean" }
 },
 "required": ["title"]
}

Claude вернет tool_use с input, который структурирован в соответствии с этой схемой, а ваше приложение прочитает и обработает JSON.

Google Gemini: JSON mode и response schema

Для Gemini официальная документация описывает два уровня контроля формата:

JSON mode - включает синтаксически валидный JSON без жесткого соответствия конкретной схеме, например через response_format с {"type": "json_object"} или установку response_mime_type: "application/json" без схемы.

Structured outputs / response schema - добавляет формальную схему в поле schema или response_json_schema / response_schema, заставляя модель генерировать JSON, который соответствует этой структуре.

Cloud-документация явно говорит: установка response_mime_type без response_schema является только сильной подсказкой и несет небольшой риск некорректного JSON, а для 100% валидных JSON-объектов нужно задавать и response_schema, и response_mime_type как application/json.

Как включается в API

В Gemini API (generateContent) structured outputs включаются через response_format с типом text, MIME-типом JSON и JSON Schema в schema.

Пример (REST):

{
 "model": "models/gemini-2.5-flash",
 "contents": [{ "role": "user", "parts": [{ "text": "Дай структуру продукта" }] }],
 "response_format": {
 "type": "text",
 "mime_type": "application/json",
 "schema": {
 "type": "object",
 "properties": {
 "name": { "type": "string", "description": "Название продукта" },
 "price": { "type": "number" }
 },
 "required": ["name", "price"]
 }
 }
}

Документация описывает этот паттерн: schema должна быть валидным JSON Schema объектом, а модель генерирует строку, которая является валидным JSON, соответствующим этой схеме.

В Google GenAI SDK для Python structured outputs включаются через конфиг с response_mime_type и response_json_schema (название поля в SDK).

Пример из SDK-документации (адаптированный):

user_profile = {
 "type": "object",
 "properties": {
 "username": {
 "type": "string",
 "description": "Имя пользователя"
 },
 "age": {
 "anyOf": [
 {"type": "integer", "minimum": 0, "maximum": 120},
 {"type": "null"}
 ]
 }
 },
 "required": ["username", "age"]
}

response = client.models.generate_content( model="gemini-2.5-flash", contents="Сгенерируй профиль пользователя", config={ "response_mime_type": "application/json", "response_json_schema": user_profile } )

Здесь SDK использует JSON Schema, а возвращаемый response.parsed следует указанной структуре.

Обязательность схемы

В JSON mode схема не обязательна: можно задать только response_mime_type: "application/json" или response_format: {"type": "json_object"}, модель будет стремиться к валидному JSON, но конкретная структура не фиксируется.

Для structured outputs response schema обязательна: именно она задает структуру, а документация описывает, что при ее наличии модель генерирует ответы, которые соответствуют указанной схеме и идут в том же порядке, что и ключи в схеме.

4 практических правила проектирования схемы

Ниже - три практических правила, опирающихся на официальные рекомендации OpenAI (JSON Schema) и Google (structured output), плюс общий JSON Schema-стандарт.

1. Ясное именование и описания полей

Документация Gemini советует использовать поле description в схеме, чтобы дать модели ясные инструкции о назначении каждого свойства. Имена полей должны быть говорящими и стабильными, чтобы и модель, и ваш код однозначно понимали структуру.

Пример:

{
 "type": "object",
 "properties": {
 "product_name": {
 "type": "string",
 "description": "Человекочитаемое название продукта"
 },
 "currency": {
 "type": "string",
 "description": "Трехбуквенный код валюты ISO 4217"
 }
 },
 "required": ["product_name"]
}

Такое именование и описания помогают модели правильно заполнить поля, а вам - облегчить валидацию и дальнейшее использование данных.

2. Четко разделяйте обязательные и опциональные поля

JSON Schema различает обязательные поля (через массив required) и опциональные, которые могут отсутствовать или иметь тип null. Google прямо показывает использование null как дополнительного типа для свойств, которые могут отсутствовать по смыслу.

Пример:

{
 "type": "object",
 "properties": {
 "name": { "type": "string" },
 "discount_percent": {
 "type": ["number", "null"],
 "description": "Скидка в процентах, может отсутствовать"
 }
 },
 "required": ["name"]
}

Здесь name всегда присутствует, а discount_percent может быть числом или null, что соответствует рекомендациям JSON Schema и Gemini по strong typing и явному указанию типов.

3. Вложенные объекты и типовые ограничения

Gemini и OpenAI поддерживают вложенные объекты через properties и тип object, а также поля для ограничения типов вроде minimum/maximum и anyOf для объединения вариантов. Это позволяет строить достаточно сложные структуры, оставаясь в рамках поддерживаемого подсета JSON Schema.

Пример вложенной структуры:

{
 "type": "object",
 "properties": {
 "product": {
 "type": "object",
 "properties": {
 "name": { "type": "string" },
 "price": {
 "type": "number",
 "minimum": 0
 }
 },
 "required": ["name", "price"]
 },
 "tags": {
 "type": "array",
 "items": { "type": "string" }
 }
 },
 "required": ["product"]
}

Этот пример показывает вложенный объект product с ограничением minimum для цены и массив строк tags, что соответствует тому набору ключевых слов JSON Schema, который описан в официальной документации Google и демонстрируется в примере user_profile.

4. Используйте enum и сильные типы там, где это возможно

Документация Gemini отдельно подчеркивает важность сильных типов и использования enum, если поле имеет ограниченный набор допустимых значений. Это уменьшает свободу модели и снижает риск «галлюцинаций» нестандартных значений.

Пример:

{
 "type": "object",
 "properties": {
 "status": {
 "type": "string",
 "enum": ["draft", "published", "archived"],
 "description": "Статус карточки продукта"
 }
 },
 "required": ["status"]
}

При такой схеме модель не должна выходить за пределы перечисленных значений, а вы можете строить строго типизированную логику в коде.

Чем structured outputs отличается от просто «верни JSON» в промпте?
Обычный промпт всего лишь просит модель соблюдать формат, но API не накладывает никаких ограничений: модель может нарушить структуру, и вы узнаете об этом только при парсинге. Structured outputs (OpenAI json_schema, Gemini response schema, Claude tools) задают формальный контракт в виде JSON Schema или аналогичной схемы, и модель вынуждена генерировать выход, который этому контракту соответствует.
Гарантирует ли JSON mode соответствие конкретной схеме?
Нет. OpenAI прямо пишет, что JSON mode «ensures that model output is valid JSON» и не гарантирует соответствие определенной схеме. Аналогично Gemini: установка только response_mime_type: "application/json" или response_format: {"type": "json_object"} обеспечивает синтаксически валидный JSON, но структура определяется промптом и может отличаться от ожидаемой.
Можно ли в OpenAI обойтись без схемы и все равно получать структурированный JSON?
Можно включить JSON mode без схемы, но тогда вы получаете только гарантию валидного JSON, а не структуры. Для гарантированного соответствия полей и типов OpenAI рекомендует использовать Structured Outputs и задавать JSON Schema либо через response_format: { type: "json_schema", ... }, либо в описании tools.
Есть ли у Anthropic Claude отдельный JSON mode или response schema для основного текста?
В официальной документации Claude нет отдельного параметра «JSON mode» или response_schema, аналогичного OpenAI и Gemini, для основного текстового ответа. Вместо этого structured outputs реализуются через tool use: вы определяете input_schema для инструмента, а Claude создает JSON-аргументы, которые должны соответствовать этой схеме.
Как включить строгий structured output в Gemini?
В Gemini structured output включается через комбинацию response_mime_type: "application/json" и схемы: либо schema внутри response_format типа text, либо response_json_schema / response_schema в конфигурации SDK или Vertex AI. Документация подчеркивает, что для гарантированно валидных JSON-объектов требуется указывать и MIME-тип, и схему.
Можно ли использовать Pydantic/Zod вместо ручного JSON Schema?
Да. И OpenAI, и Google в официальных гайдах прямо упоминают использование библиотек вроде Pydantic (Python) и Zod (JavaScript) для генерации JSON Schema и работы со structured outputs. В случае Gemini такие схемы передаются в response_json_schema или schema, а SDK обеспечивает парсинг в типизированные объекты.
Источники (10)
  1. OpenAI - Structured model outputs guide
  2. OpenAI - Introducing Structured Outputs in the API (анонс фичи)
  3. OpenAI - Responses API Reference (response_format и json_schema/json_object)
  4. Anthropic Claude - How to implement tool use (tools и input_schema)
  5. Anthropic Claude - How tool use works (tool_use и tool_result)
  6. Google Gemini - Structured outputs (Interactions / generateContent)
  7. Google Gemini - Structured outputs - generateContent API
  8. Google Cloud - Control generated output with response_schema (Gemini / Vertex AI)
  9. Google Gemini - JSON mode and structured outputs (Get JSON object responses)
  10. Google GenAI Python SDK - JSON Response Schema
← Все статьи блога