Блог • ИИ / JSON Schema
Зачем ИИ нужен JSON Schema? Structured Output, Function Calling и JSON Schema
Когда вы подключаете ChatGPT, Gemini или DeepSeek, в документации сразу встречаютсяFunction Calling, Structured Output иJSON Schema. Похоже на три возможности. Это три применения одного языка контракта.
JSON Schema описывает, как должен выглядеть JSON. Текущий мейнстрим —2020-12. Function Calling использует его для аргументов инструментов; Structured Output — для финального ответа. ИИ нужен он не потому, что JSON модный, а потому что естественный язык нельзя стабильно потреблять кодом ниже по потоку.
В этой статье:
- Что ограничивает каждое из трёх понятий
- Почему одного естественного языка недостаточно
- Как Function Calling использует schema для аргументов
- Как Structured Output использует schema для финального ответа
- Как переиспользовать одну schema в двух местах, затем выбрать и проверить
Запомните это: Выдать JSON и выдать JSON, соответствующий schema, — разные вещи. JSON Schema определяет второе. Function Calling отвечает за то, какой инструмент вызвать и верны ли аргументы; Structured Output — за форму финального ответа. Дальше: зачем → что → аргументы → ответ → выбор → проверка.
Три понятия в одной таблице
Сначала положите три слова в одну таблицу. Они делят JSON Schema как язык, но ограничивают разные объекты.
| Понятие | Что ограничивает | Типичное поле / стандарт | Что решает |
|---|---|---|---|
| JSON Schema | Поля, типы, обязательные ключи, enum JSON | JSON Schema 2020-12 | Сам контракт: как должны выглядеть данные |
| Function Calling | tool_calls.arguments |
tools[].parameters |
Какой инструмент вызвать и законны ли аргументы |
| Structured Output | JSON финального ответа | response_format.json_schema / responseSchema |
Можно ли результат сразу сохранить или отдать в пайплайн |
Три слова смешивают, потому что документация склеивает имя возможности и язык контракта. Запомните слои: JSON Schema — язык; Function Calling и Structured Output — два применения.
Почему ИИ не может жить только на естественном языке
Если в промпте только «верни JSON», появляются такие сбои.
| Режим сбоя | Типичный симптом | Причина |
|---|---|---|
| Синтаксические ошибки | Нет кавычек, висячие запятые, одинарные кавычки | Модель пишет как прозу; токены не ограничены |
| Дрейф полей | Один промпт даёт разные имена полей дважды | Нет контракта schema; модель импровизирует |
| Ошибки типов | Числа становятся строками, массивы — объектами | Промпт размыт; нет жёсткого type |
| Нет регрессии | Один и тот же кейс нельзя сравнить фикстурой | У естественного языка нет стабильного набора полей |
В демо это прячут ретраями или вторым парсингом. В продакшен-агентах, пайплайнах и автоматизации падает вниз по потоку. JSON Schema — контракт формата: объявить поля, типы и обязательные ключи до генерации.
JSON Schema — контракт, не комментарий
JSON Schema — стандарт описания структуры JSON. В интеграции ИИ это не комментарий для людей, а исполняемый машиной контракт:
-
1
Объявить имена и типы полей
Каждый ключ в properties — поле вывода; type задаёт string / integer / array и т.д.
-
2
Ограничить обязательные ключи и enum
required перечисляет обязательные поля; enum блокирует «творческие» значения.
-
3
Запретить лишние поля
additionalProperties: false запрещает незаявленные ключи. Strict Schema обычно требует это.
{
"type": "object",
"properties": {
"ticket_id": {
"type": "string",
"description": "Support ticket ID, e.g. TCK-1042"
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high"]
},
"summary": {
"type": "string",
"description": "One-sentence problem summary"
}
},
"required": ["ticket_id", "priority", "summary"],
"additionalProperties": false
}
Этой schema всё равно, живёт ли она в tools или response_format. Она отвечает только: законен ли этот JSON? Следующие два раздела вешают её на Function Calling и Structured Output.
Function Calling: schema для аргументов инструмента
Function Calling заставляет модель вернуть структурированный вызов инструмента, а не угадывать. У каждого инструментаtools[].parameters — это JSON Schema:
{
"model": "gpt-4o",
"messages": [
{ "role": "user", "content": "Create a high-priority ticket for checkout timeout." }
],
"tools": [
{
"type": "function",
"function": {
"name": "create_ticket",
"description": "Create a support ticket from the user request.",
"parameters": {
"type": "object",
"properties": {
"ticket_id": { "type": "string" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] },
"summary": { "type": "string" }
},
"required": ["ticket_id", "priority", "summary"],
"additionalProperties": false
}
}
}
]
}
Модель возвращаетtool_calls[0].function.arguments как JSON-строку. Она «старается» попасть в parameters, но не гарантирует валидность каждый раз — пропуски, неверные типы, сломанный синтаксис бывают. Парсинг и проверка — работа бизнес-слоя.
Цикл агента, MCP inputSchema и более полная запись инструментов — вЗачем агентам ИИ нужен JSON Schema.
Structured Output: schema для финального ответа
Structured Output ограничивает финальный ответ, не аргументы инструмента. OpenAI используетresponse_format; Gemini —responseSchema. Под капотом оба — JSON Schema:
{
"model": "gpt-4o-2024-08-06",
"messages": [
{ "role": "user", "content": "Extract a support ticket from this email." }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "support_ticket",
"strict": true,
"schema": {
"type": "object",
"properties": {
"ticket_id": { "type": "string" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] },
"summary": { "type": "string" }
},
"required": ["ticket_id", "priority", "summary"],
"additionalProperties": false
}
}
}
}
Сstrict: true схема ведёт токены на этапе инференса — не сгенерировать и надеяться, а генерировать только то, что соответствует.
Сравнение настроек ChatGPT и Gemini и что реально гарантируют JSON Mode и Strict Schema — вруководстве 2026 AI Structured Output.
Одна schema, две точки крепления
Смысл статьи: не пишите два расходящихся набора полей для аргументов и финального ответа. Тикет по-прежнему три поля. Меняется только точка крепления.
TICKET_SCHEMA = {
"type": "object",
"properties": {
"ticket_id": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high"]},
"summary": {"type": "string"},
},
"required": ["ticket_id", "priority", "summary"],
"additionalProperties": False,
}
# 1) Function Calling: constrain tool arguments
tools = [{
"type": "function",
"function": {
"name": "create_ticket",
"description": "Create a support ticket.",
"parameters": TICKET_SCHEMA,
},
}]
# 2) Structured Output: constrain the final answer
response_format = {
"type": "json_schema",
"json_schema": {
"name": "support_ticket",
"strict": True,
"schema": TICKET_SCHEMA,
},
}
Один контракт, три посадки:
-
1
Вызов инструмента
Модель выбирает create_ticket; arguments должны соответствовать schema.
-
2
Финальный ответ
Если инструмент не нужен, финальный JSON всё те же поля и его можно сразу сохранить.
-
3
Бизнес-проверка
Данные из tool_calls или message.content — один и тот же parse + validate.
Как выбрать из четырёх путей
В 2026 у структурированных данных LLM обычно четыре пути:
| Путь | Конфиг API | Что гарантирует | Когда использовать |
|---|---|---|---|
| Только промпт | Без особого конфига | Формат не гарантирован | Прототип, чтение человеком |
| JSON Mode | response_format: json_object |
Валидный JSON-объект | Простое извлечение, свободные поля |
| Function Calling | tools[].parameters |
arguments стараются попасть в parameters | Инструменты / запись в БД / HTTP |
| Structured Output | json_schema + strict: true |
Строгое соответствие schema | Финальный результат нужно сохранить или отдать в пайплайн |
Как собираются четыре слоя агента (LLM, Function Calling, MCP, JSON Schema):стек AI-агента 2026.
Продакшен-написание и проверка
Успех Structured Output и Function Calling зависит от качества schema. Бизнес-слой всё равно проверяет.
-
1
Писать description у каждого property
Модель читает description, чтобы заполнить значения. «Support ticket ID, e.g. TCK-1042» точнее голого имени поля.
-
2
Использовать enum, а не намёк в тексте
«low/medium/high» в предложении слабее, чем
enum. -
3
Ставить additionalProperties: false
OpenAI Strict обычно требует это. Поставьте
additionalProperties: falseна корневой объект, чтобы модель не подсовывала незаявленные ключи. -
4
Не углублять вложенность
Больше трёх уровней или много oneOf повышает ошибки. Сложные формы лучше разбить на несколько вызовов.
import json
from jsonschema import validate, ValidationError
def parse_model_json(raw: str, schema: dict) -> dict:
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON: {e}") from e
try:
validate(instance=data, schema=schema)
except ValidationError as e:
raise ValueError(f"Schema mismatch: {e.message}") from e
return data
ChatGPT, Gemini или DeepSeek — один и тот же parse → validate → бизнес-логика. На разработке вставьте schema и вывод в JSONNote — быстрее, чем print.
Отладка JSON модели в JSONNote
Медленная часть редко в написании API. Это увидеть, где JSON модели ломает контракт. JSONNote работает локально в браузере:
-
1
Проверить schema против вывода
Вставьте JSON API и schema на страницуJSON Schema, чтобы сразу увидеть поля вне контракта.
-
2
Форматировать ответ API
Используйтеформаттер JSON, чтобы поймать синтаксис и отступы.
-
3
Сравнить два вызова
ИспользуйтеJSON Diff, чтобы сравнить два structured output или tool arguments для регрессии.
FAQ
Чем Function Calling отличается от Structured Output?
Function Calling ограничивает tool_calls.arguments (какой инструмент и какие аргументы). Structured Output ограничивает финальный JSON. Оба используют JSON Schema на разных слоях. Агенты часто сочетают их: tools для внешних действий, Structured Output для финального структурированного результата.
Хватит ли JSON Mode?
Нет. JSON Mode (response_format.type=json_object) гарантирует только валидный JSON-объект, не поля и типы. Для сложных продакшен-форм используйте Structured Output (json_schema + strict:true или Gemini responseSchema).
Нужна ли ручная проверка при Strict Schema?
Да. Ограничения API не заменяют validate на бизнес-слое. Пустой content, обрезанный payload и крайние случаи остаются — try/except parse + JSON Schema validate это стандарт продакшена.
Какую версию JSON Schema использовать?
В 2026 году основные LLM API и контракты MCP сходятся на JSON Schema 2020-12. Ключевые слова: type, properties, required, enum, items, additionalProperties.
Можно ли одну схему дать и инструменту, и финальному выводу?
Да. Одно и то же определение объекта можно положить в tools[].parameters и response_format.json_schema.schema. Одна правда, чтобы контракты не расходились.
Итог
ИИ нужен JSON Schema, потому что он превращает вывод модели из «похоже на данные» в контракт, который машина может проверить.
JSON Schema — язык; Function Calling использует его для аргументов инструментов; Structured Output — для финального ответа.
Напишите одну schema, повесьте дважды, проверьте на бизнес-слое. Форматируйте, проверяйте и делайте Diff локально в JSONNote — самый короткий путь от демо к продакшену.