Коротко: чем 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» в промпте?
Гарантирует ли JSON mode соответствие конкретной схеме?
Можно ли в OpenAI обойтись без схемы и все равно получать структурированный JSON?
Есть ли у Anthropic Claude отдельный JSON mode или response schema для основного текста?
Как включить строгий structured output в Gemini?
Можно ли использовать Pydantic/Zod вместо ручного JSON Schema?
Источники (10)
- OpenAI - Structured model outputs guide
- OpenAI - Introducing Structured Outputs in the API (анонс фичи)
- OpenAI - Responses API Reference (response_format и json_schema/json_object)
- Anthropic Claude - How to implement tool use (tools и input_schema)
- Anthropic Claude - How tool use works (tool_use и tool_result)
- Google Gemini - Structured outputs (Interactions / generateContent)
- Google Gemini - Structured outputs - generateContent API
- Google Cloud - Control generated output with response_schema (Gemini / Vertex AI)
- Google Gemini - JSON mode and structured outputs (Get JSON object responses)
- Google GenAI Python SDK - JSON Response Schema