Structured Output
structured output — гарантированный формат ответа модели
Structured Output — режим LLM, в котором модель **гарантированно** возвращает ответ в заданном формате (обычно JSON по схеме). Раньше приходилось парсить и переспрашивать, теперь OpenAI и Anthropic дают строгий контроль: модель сэмплирует только токены, соответствующие схеме. Главный механизм для интеграции LLM в продакшен-код, где формат критичен.
Коротко
Коротко. Structured Output — это режим API, гарантирующий, что модель вернёт строго в указанной структуре: JSON со схемой, XML, конкретный список значений. До этого режима LLM иногда возвращали «почти JSON» с лишним текстом или обрывали ответ. Теперь OpenAI (с 2024) и Anthropic дают токен-ограниченную генерацию: модель не может выйти за рамки схемы. Главный путь использовать LLM в продакшене.
Что это такое
Программист пишет API: пользователь загружает резюме, получает разбор по полям (имя, опыт, навыки, контакт). Использует GPT для извлечения.
Без structured output:
Извлеки данные из резюме в JSON со схемой
{name, experience_years, skills (array), contact_email}.
В 95% случаев получает правильный JSON. В 5% — сюрпризы:
Вот разбор резюме: {...}— лишний текст до/после.{"name": "Иван", ...}обрывается на середине.{"experience": "5 лет"}— полеexperienceвместоexperience_years.{"skills": "Python, JavaScript"}— строка вместо массива.
Каждые 5% означают, что приложение падает или показывает мусор. Приходится писать обработку ошибок, переспрашивать модель.
С Structured Output:
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[...],
response_format={
"type": "json_schema",
"json_schema": {
"name": "resume_data",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"experience_years": {"type": "integer"},
"skills": {"type": "array", "items": {"type": "string"}},
"contact_email": {"type": "string"}
},
"required": ["name", "experience_years", "skills"],
"additionalProperties": false
},
"strict": true
}
}
)
100% случаев — правильный JSON по схеме. Никаких сюрпризов. Если поле experience_years обязательно — оно будет integer, не строка.
К 2026-му это стандарт для LLM-в-проде:
- OpenAI: Structured Outputs (с 2024) — JSON Schema или Pydantic-модели.
- Anthropic: Tool Use с принудительным схемой ответа.
- Gemini:
response_schemaпараметр. - Локальные: llama.cpp grammar-режимы (GBNF), Outlines, Guidance.
Как это работает
Магия не в промпте, а в сэмплировании токенов. Обычно модель на каждом шаге выбирает следующий токен из 50000+ возможных. С Structured Output эта выборка ограничена:
- Токенайзер строит грамматику из JSON Schema.
- На каждом шаге модель смотрит, какие токены допустимы по грамматике в текущем состоянии.
- Невалидные токены отключаются (логит-маска).
- Модель сэмплирует только из валидных.
В результате каждый сгенерированный токен гарантированно ведёт к корректному JSON. Невозможно сгенерировать «почти-JSON».
Поддерживаемые форматы (по моделям):
- JSON Schema — universal (OpenAI, Gemini, локальные).
- Pydantic-модели — OpenAI Python SDK конвертирует в схему автоматически.
- TypeScript-интерфейсы — Vercel AI SDK конвертирует.
- Регулярные выражения — Outlines, Guidance.
- Grammar (BNF) — llama.cpp, очень гибко.
Пример на практике
Команда строит сервис для контент-аналитики. На вход — статья с сайта, на выход — структурированные метаданные для индексации.
Через OpenAI Structured Output + Pydantic:
from openai import OpenAI
from pydantic import BaseModel
from typing import Literal
class ArticleMetadata(BaseModel):
title: str
summary: str
topic: Literal["tech", "business", "lifestyle", "science"]
sentiment: Literal["positive", "neutral", "negative"]
keywords: list[str]
estimated_reading_minutes: int
client = OpenAI()
resp = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[
{"role": "system", "content": "Extract article metadata."},
{"role": "user", "content": article_text}
],
response_format=ArticleMetadata
)
metadata = resp.choices[0].message.parsed # уже Pydantic-объект
print(metadata.topic) # "tech" — гарантированно одно из 4
print(metadata.keywords) # list[str] — гарантированно список строк
Никакого парсинга, никакой обработки ошибок формата. Если topic объявлен как Literal из 4 вариантов — модель не может вернуть пятый. Если keywords это list[str] — не вернёт str или dict.
Обработали 100 000 статей за неделю. Ошибок формата — 0.
В Anthropic похожий результат через Tool Use: определяется «инструмент» с input-схемой, модель должна вызвать инструмент с правильными аргументами. Получается тот же эффект — гарантированный формат.
С чем часто путают
- Structured Output и JSON Mode — JSON Mode гарантирует, что ответ — валидный JSON, но не контролирует схему. Structured Output — гарантирует и формат, и схему.
- Structured Output и Function Calling — Function Calling построен на Structured Output: модель «вызывает функцию» с строго типизированными аргументами.
- Structured Output и Few-Shot для JSON — Few-shot повышает шансы правильного формата, но не гарантирует. Structured Output — гарантирует на уровне сэмплинга.
- Structured Output и Output Parsing — Parsing это разбор уже сгенерированного текста (post-process). Structured Output — контроль самой генерации.
- strict: true и strict: false —
strict: trueэто полная гарантия схемы (медленнее, иногда отказывает).strict: false— best-effort.
Частые ошибки и заблуждения
- «Structured Output замедляет генерацию». Чуть-чуть (5–15%) — на проверку грамматики на каждом токене. Но качество гарантированно, что обычно стоит этой цены.
- «Можно использовать любую JSON Schema». Не любую. Поддержка ограничена:
oneOf,allOf,if/then/elseчасто не работают. Поддерживается базовый набор: типы, required, enum, nested objects, arrays. - «Structured Output избавляет от галлюцинаций». Только от формата. Содержание всё равно может быть выдумкой. Если попросить вернуть
experience_years: integer, и в резюме это не указано — модель сама что-то впишет. - «Это работает в любых LLM». Только в моделях с поддержкой. GPT-4 (с 4o-2024-08-06), Claude (через Tool Use), Gemini 1.5+, локальные с Outlines/Guidance. Старые модели — нет.
- «Pydantic-модели лучше JSON Schema». Удобнее в Python, но под капотом конвертируются в JSON Schema. Возможностей не больше.
Связанные термины
- JSON Mode — упрощённая версия Structured Output.
- Function Calling / Tool Calling — построены на Structured Output.
- JSON Schema — стандарт описания структуры.
- Pydantic — Python-библиотека для типизации, удобна с SO.
- Grammar (GBNF) — низкоуровневый аналог в llama.cpp.
- Outlines / Guidance — библиотеки для SO в локальных моделях.
- API — главное место применения Structured Output.
Частые вопросы
В каких моделях OpenAI работает Structured Output? GPT-4o (2024-08-06+), GPT-4o-mini (2024-07-18+), o1, o3 и новее. Старые версии — только JSON Mode без схемы.
Что такое strict: true?
Параметр, который включает 100% гарантию схемы. Без него модель «старается», но может изредка нарушить. С strict: true нарушение физически невозможно (за счёт логит-масок).
Можно ли вложить объекты? Да, но с ограничениями глубины (обычно 5 уровней). Сложные nested-структуры лучше упростить.
Structured Output работает с потоковой генерацией (streaming)? Да. Можно стримить чанки, парсить incrementally. SDK обычно даёт partial-объекты по мере генерации.
Дороже ли Structured Output по токенам? Нет. Стоимость — обычные input + output токены. Дополнительной платы за схему нет.
В Claude как это работает? Через Tool Use: определяете «инструмент» с input-схемой, модель должна его «вызвать». Эквивалент Structured Output, синтаксис другой.
Главное
Structured Output — это режим LLM-API, гарантирующий, что ответ будет строго по заданной схеме. Не «попросили JSON и надеемся», а «модель физически не может вернуть не-JSON по схеме». Реализуется через ограничение сэмплинга на токенах: невалидные варианты отключаются на каждом шаге. Главные применения: API в проде, извлечение данных, классификация с фиксированным списком значений, любая интеграция, где формат важнее, чем «креатив». Лучшая практика — описывать схему через Pydantic (Python) или TypeScript (Node.js), SDK конвертирует в JSON Schema автоматически. К 2026-му без Structured Output работать с LLM в проде уже не принято.