Структурированный вывод (Structured Output)
Структурированный вывод - это функция, которая заставляет LLM возвращать ответы, соответствующие заданной схеме, обычно схеме JSON. Вместо того чтобы надеяться, что модель выдаст разбираемый JSON, движок вывода ограничивает выборку токенов так, чтобы вывод гарантированно проходил валидацию.
Структурированный вывод - это функция, которая заставляет LLM возвращать ответы, соответствующие заданной схеме, обычно схеме JSON. Вместо того чтобы надеяться, что модель выдаст разбираемый JSON, движок вывода ограничивает выборку токенов так, чтобы вывод гарантированно проходил валидацию.
Почему это важно
LLM, возвращающие текст в свободной форме, трудно использовать программно. Даже когда модели дают указание "верни JSON", они иногда добавляют прозу, пропускают поля или выдумывают типы. Это ломает последующий код и вынуждает писать защитный парсинг. Структурированный вывод решает проблему на уровне декодирования - вы получаете валидный JSON в 100% случаев, а не в 95%. OpenAI, Anthropic, Google и движки с открытым исходным кодом вроде vLLM и Outlines теперь поддерживают его нативно, что делает его способом по умолчанию для построения надёжных конвейеров LLM.
Как это работает
Ограниченное декодирование: на каждом шаге генерации модель может выбирать только те токены, которые сохраняют совместимость вывода со схемой. Токены, которые нарушили бы схему, маскируются нулевой вероятностью.
Спецификация схемы: вы предоставляете схему JSON (или модель Pydantic, схему Zod, тип TypeScript), описывающую обязательные поля, типы и перечисления.
Парсинг без валидации: вызывающая сторона может выполнить JSON.parse для результата без try/catch вокруг некорректного вывода.
Режим JSON против структурированного вывода
| Аспект | Режим JSON | Структурированный вывод |
|---|---|---|
| Гарантия | Валидный синтаксис JSON | Валидный JSON, соответствующий вашей схеме |
| Принуждение к схеме | Нет | Полное |
| Наличие полей | Не гарантировано | Гарантировано |
| Выдуманные поля | Возможны | Невозможны |
| Накладные расходы по задержке | ~0 | Небольшие (компиляция ограничений) |
Режим JSON лишь гарантирует, что вывод разбирается. Структурированный вывод гарантирует, что он разбирается и соответствует точной форме, которая вам нужна. Для продакшен-систем всегда используйте структурированный вывод, когда он доступен.
Когда его применять
Извлечение данных из текста: вытягивание имён, дат, адресов из неструктурированного ввода.
Построение агентов, вызывающих инструменты: аргументы вызова инструмента должны точно соответствовать схеме параметров инструмента.
Классификация по перечислениям: заставить модель выбрать один из фиксированного набора меток.
Генерация ответов с несколькими полями: заголовки, сводки, теги, оценки за один проход.
Везде, где вы сейчас разбираете вывод модели регулярными выражениями: это ошибка, ждущая своего часа.
Компромиссы
Небольшие накладные расходы по задержке: декодеру приходится отслеживать состояние грамматики. Обычно пренебрежимо мало.
Сниженная креативность: жёсткие ограничения схемы могут сделать генерацию механической. Для творческого письма предпочтительнее свободная форма.
Дизайн схемы имеет значение: чрезмерно строгие схемы (обязательны: все 20 полей) вынуждают модель выдумывать значения. Делайте необязательным то, что действительно необязательно.
Не все модели это поддерживают: старые модели и некоторые модели с открытым исходным кодом всё ещё не имеют нативной поддержки. Outlines и подобные библиотеки могут её дооснастить.
Пример
Схема:
{
"type": "object",
"properties": {
"title": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } },
"sentiment": { "enum": ["positive", "negative", "neutral"] }
},
"required": ["title", "tags", "sentiment"]
}
Гарантированный вывод:
{ "title": "Launch recap", "tags": ["product", "Q2"], "sentiment": "positive" }
Никаких ошибок разбора. Никаких пропущенных полей. Никаких выдуманных значений перечисления.
Источники: