Блог ИИ / 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 модный, а потому что естественный язык нельзя стабильно потреблять кодом ниже по потоку.

В этой статье:

Запомните это: Выдать 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. 1
    Объявить имена и типы полей

    Каждый ключ в properties — поле вывода; type задаёт string / integer / array и т.д.

  2. 2
    Ограничить обязательные ключи и enum

    required перечисляет обязательные поля; enum блокирует «творческие» значения.

  3. 3
    Запретить лишние поля

    additionalProperties: false запрещает незаявленные ключи. Strict Schema обычно требует это.

Пример 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:

Function Calling в стиле OpenAI: parameters и есть 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:

OpenAI Strict Structured Output: та же 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, две точки крепления

Смысл статьи: не пишите два расходящихся набора полей для аргументов и финального ответа. Тикет по-прежнему три поля. Меняется только точка крепления.

Python: один TICKET_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. 1
    Вызов инструмента

    Модель выбирает create_ticket; arguments должны соответствовать schema.

  2. 2
    Финальный ответ

    Если инструмент не нужен, финальный JSON всё те же поля и его можно сразу сохранить.

  3. 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. 1
    Писать description у каждого property

    Модель читает description, чтобы заполнить значения. «Support ticket ID, e.g. TCK-1042» точнее голого имени поля.

  2. 2
    Использовать enum, а не намёк в тексте

    «low/medium/high» в предложении слабее, чемenum.

  3. 3
    Ставить additionalProperties: false

    OpenAI Strict обычно требует это. ПоставьтеadditionalProperties: false на корневой объект, чтобы модель не подсовывала незаявленные ключи.

  4. 4
    Не углублять вложенность

    Больше трёх уровней или много oneOf повышает ошибки. Сложные формы лучше разбить на несколько вызовов.

Python: parse + JSON Schema validate
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. 1
    Проверить schema против вывода

    Вставьте JSON API и schema на страницуJSON Schema, чтобы сразу увидеть поля вне контракта.

  2. 2
    Форматировать ответ API

    Используйтеформаттер JSON, чтобы поймать синтаксис и отступы.

  3. 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 — самый короткий путь от демо к продакшену.

← Назад к блогу