В предыдущих публикациях этой серии рассматривалисьзачем агентам нужен JSON(Вызов инструмент в потоке данных MCP),почему JSON Schema⟧ стала инфраструктурой(Схема, Вызова функция и MCP эволюция), иКонфигурация Structured Output, специфичная для Gemini(Gemini API руководство).
Эта статья уменьшена:независимо от того, какую модель API вы используете, как перейти от «пожалуйста, ответьте в JSON» к «вывод должен соответствовать этой JSON схеме⟧»? Поставщики сошлись на этом в 2024–2026 годах под такими названиями, как Structured Outputs⟧ / JSON Schema⟧ mode — та же идея, немного другие имена полей, подмножества схемы и границы с Tool Calling.
Четыре уровня, каждый из которых «строже» предыдущего.
Для получения JSON из модели команды обычно используют четыре подхода — надежность различается на порядок:
| Уровень | Подход | Что вы контролируете | Типичный отказ |
|---|---|---|---|
| L0 | Только запрос: «вывод JSON» | Мягкое ограничение | ```json fences, prose, single quotes, trailing commas |
| L1 | Подсказка + несколько примеров JSON | Формируйте на собственном примере, без жестких правил | Дрейф имени поля, отсутствующие поля, смешанные типы |
| L2 | JSON Mode⟧ (response_format: json_object, etc.) | Вывод должен быть действительным JSON | Parses, but price may be a string |
| L3 | Структурированный вывод+ JSON Схема⟧ | Поля, типы, перечисления, обязательные | Семантическая галлюцинация, усечение, игнорируемые ключевые слова |
For production extraction, classification, or form filling, aim for L3. L0–L1 suit exploration; L2 when shape varies and you only need JSON.parse. L3 is the contract programs can consume directly.
Что контролирует JSON Schema⟧, а что нет
JSON Схема⟧описывает структуру документа: поля, типы, необходимые ключи, перечисления, диапазоны, форму элемента массива. Поставщик Структурированный выводs⟧ компилирует эту схему в генерацию, а не просто вставляет ее в командную строку.
Schema can enforce: syntax shape (object / array / string / integer), required, enum, minimum / maximum, additionalProperties: false, nested objects and arrays.
Schema cannot enforce business correctness. Example: “total_cents must equal sum of line items” — assert that in code after Schema validation. Schema also does not fact-check: a well-typed fabricated invoice number is still hallucination.
Tool inputSchema uses the same language; Structured Output constrains the final reply, Tool Calling constrains tool arguments. See руководство по потоку данных.
Ограниченное декодирование: почему Schema превосходит Prompt
Подсказки только повышают шансы на соблюдение требований. Структурированный вывод используетограниченное декодирование: для каждого токена декодер подавляет токены, которые могут нарушить синтаксис JSON или схему.
Обычно вы получаете анализируемый, корректный по форме JSON без ограничений уценки с удалением регулярных выражений. Реализации различаются (FSM, грамматика, логит-маски), но контракт разработчика тот же:передать схему в API, а не только приглашение.
Ограниченные гарантии декодированияструктура, нетсемантика. Всегда выполняйте повторную проверку с использованием той же схемы и добавляйте бизнес-правила в производство.
OpenAI, Gemini, Anthropic сравнение
Та же концепция, разные имена полей. Пример: извлеките один объект счета.
| Продавец | Режим JSON | Структурированный вывод/Схема | Примечания |
|---|---|---|---|
| OpenAI | response_format: { type: "json_object" } | response_format: { type: "json_schema", json_schema: { name, schema, strict: true } } | strict: true rejects undeclared fields; works with Pydantic model_json_schema() |
| Google Близнецы | responseMimeType: "application/json" | Above + responseJsonSchema or SDK response_schema | Видетьспециальная статья о Gemini API |
| Антропный | Подсказка + разбор | output_format (Claude structured output) or schema in Messages API | Поля развиваются вместе с SDK; сохранять схему плоской |
When migrating vendors, keep the Schema itself standard JSON Schema⟧ (type, properties, required, enum); SDKs only wrap the request. Do not mix OpenAPI 3.0 uppercase types (OBJECT) with JSON Schema⟧ lowercase (object).
Написание хорошей схемы: от Pydantic к производству
Recommended flow: define types in Pydantic / Zod → export JSON Schema⟧ → tune → send to API. Put semantics in description — it enters model context and disambiguates “qty = pieces vs boxes”; type: integer alone cannot.
from pydantic import BaseModel, Field
class LineItem(BaseModel):
name: str = Field(description="Product name")
qty: int = Field(description="Quantity, positive integer", ge=1)
unit_price_cents: int = Field(description="Unit price in cents", ge=0)
class Invoice(BaseModel):
vendor: str
currency: str = Field(description="ISO 4217, e.g. CNY")
items: list[LineItem]
total_cents: int
schema = Invoice.model_json_schema()
# In production add additionalProperties: false
Практические правила:
- Prefer object root over root-level array;
{ "items": [...] }is more stable on some APIs. - Start with type / properties / required / enum, then add
additionalProperties, min/max; do not dump full Draft 2020-12 — some keywords are ignored. - Продолжайте вкладывать неглубоко; циклические ссылки отклоняются — сглаживайте схему.
- Разделенная схема против подсказки: Схема = форма; Подсказка = семантика («извлечь счет из текста ниже…»).
OpenAI Пример структурированного выводаs⟧
Chat Completions supports json_schema response format since 2024. With strict: true, output should only contain Schema fields:
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class Invoice(BaseModel):
vendor: str
total_cents: int
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{"role": "user", "content": "Extract invoice: Acme sold 2 keyboards for 398 CNY."}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "invoice",
"strict": True,
"schema": Invoice.model_json_schema(),
},
},
)
data = response.choices[0].message.content # JSON string
import json
invoice = json.loads(data)
Gemini uses response_mime_type + response_json_schema — see the dedicated Gemini API article. For Anthropic, check current SDK structured output docs — same idea, official field names.
Производственный конвейер: генерировать → анализировать → проверять → повторять попытку.
Структурированный вывод — это не «один вызов API и готово». Исправьте эти четыре шага:
- Generate: call model with Schema; log prompt, Schema version, raw
content. - Parse:
JSON.parse(or SDKparsed); on failure, retry whole response — no half-parse. - Schema validate: run same JSON Schema⟧ via AJV /
jsonschema/ Pydantic; retry or degrade on failure. - Бизнес-подтверждение: пользовательские утверждения (итогов, внешние ключи); человек или правила двигателя при сбое.
В разработке сохраните Schema плюс 2–3 положительных/отрицательных образца в репозитории; используйте JSON Toolbox⟧ локально для структуры и Diff — тот же подход, что и для контрактных тестов REST, потребитель — это LLM.
Распространенные ошибки: запрос «объясните тогда JSON», когда режим JSON включен; усечение (увеличение максимального количества токенов или разделение задач); API ключи в демоверсиях интерфейса; Версия схемы отклоняется от подсказки.
Чем он отличается от Tool Calling
| Структурированный вывод | Вызов инструмента / MCP | |
|---|---|---|
| Ограничения | Окончательный ответ пользователю в формате JSON | Tool argument JSON (inputSchema) |
| Побочные эффекты | Нет — только данные | Host / MCP Сервер выполняет |
| Типичное использование | Извлечение, классификация, заполнение форм, передача агента | Инвентарь, файлы, внешние API |
| При неудаче | Повторить попытку или человек | Ошибка в сообщении инструмента → спросите модель еще раз |
Полный цикл агента часто выглядит так:Структурированный вывод извлекает намерение → Вызов инструмента действует → Структурированный вывод или суммирует для пользователя. Не используйте Structured Output, чтобы представить «вызов платежа API» — модель его не вызывала.
Часто задаваемые вопросы
Достаточно ли в командной строке «пожалуйста, выведите JSON»?
Нет. Подсказки только повышают шансы на соответствие — ограничения уценки, конечные запятые и дрейф полей по-прежнему случаются. В рабочей среде включите как минимум JSON Mode⟧; в идеале передать JSON Schema⟧ через канал API Structured Output, чтобы декодирование исключало незаконные токены.
В чем разница между JSON Mode⟧ и Structured Output?
JSON Mode⟧ гарантирует только действительный текст JSON, а не имена полей, типы или обязательные ключи. Структурированный вывод добавляет JSON Schema⟧ и фильтрует токены во время генерации — форма стабилизируется, поэтому вы можете напрямую сохранить или передать их следующему прыжку.
Являются ли поля конфигурации OpenAI, Gemini и Anthropic одинаковыми?
Одна и та же концепция, разные названия. OpenAI: формат ответа с json_schema и strict; Gemini: responseMimeType + responseJsonSchema; Антропный: output_format или структурированный вывод в инструментах. Сохраняйте стандарт схемы; SDK оборачивают запросы.
Может ли Структурированный вывод заменить Вызов инструмента?
Нет. Структурированный вывод ограничивает окончательный ответ JSON; Вызов инструмента ограничивает аргумент инструмента JSON и требует, чтобы хост выполнял инструменты. Используйте первое для извлечения/классификации/заполнения; последний для инвентаря, файлов, MCP. Полные агентские сети часто используют оба варианта.
Нужно ли мне еще проверять выходные данные модели?
Да. Ограниченное декодирование сокращает синтаксические ошибки и дрейф типов, но не семантическую корректность (допустимые типы, сфабрикованные значения). Повторно запустите ту же самую JSON Schema⟧ в рабочей среде; повторите попытку, ухудшите качество или проверьте в случае неудачи.
Как проверить схему и образец вывода локально?
Сохраните JSON Schema⟧ и несколько образцов выходных данных модели в виде файлов JSON; используйте JSON Toolbox⟧ в браузере для проверки синтаксиса и структуры — ничего не загружается.
Краткое содержание
Чтобы получить JSON, соответствующий JSON Schema⟧ от ИИ, порядок имеет значение:сначала определите схему, включите JSON Mode⟧ / Structured Output, затем напишите приглашение. Подсказка = семантика; Схема = форма; Pydantic / Zod — дружественные к авторам фронты; API поставщика предоставляют каналы схемы.
Запустите один реальный счет или сквозную расшифровку расшифровки: Схема → API вызов → вставьте выходные данные в валидатор. Когда оно совпадает, подключите базу данных или следующего агента. Инструментальные аргументы по-прежнему проходят через Tool Calling/MCP — не сливаются в один API.