Структурированный вывод (JSON mode)

Материал из llmdocs — справочник разработчика
Структурированный вывод (JSON mode)
Задачаполучать от LLM машиночитаемые данные вместо свободного текста
Формат схемJSON Schema
Уровни гарантийпромпт → JSON mode → строгая схема (constrained decoding)
БиблиотекиPydantic, Instructor, Outlines, XGrammar, llguidance
Поддержка в APIOpenAI, Anthropic, Google, vLLM, llama.cpp

Структурированный вывод (англ. structured output) — режим работы языковой модели, при котором ответ представляет собой данные заданной формы, чаще всего JSON по схеме, а не свободный текст. Это нужно везде, где ответ модели читает программа: извлечение полей из документов, классификация, заполнение форм, вызов функций в агентах. Без специальных мер модель время от времени добавляет пояснения, пропускает поля, путает типы или выдаёт синтаксически сломанный JSON — и каждый такой случай ломает конвейер.

Уровни гарантий

Подход Как Гарантия
Просьба в промпте «Ответь только JSON вида …» с примером никакой; ошибки в процентах случаев
JSON mode API гарантирует синтаксически корректный JSON синтаксис, но не схема
Строгая схема API или движок ограничивает генерацию по JSON Schema синтаксис и структура
Валидация и повтор проверить ответ, при ошибке отправить её модели зависит от числа попыток

Хорошая практика — сочетать строгую схему на уровне генерации и валидацию на стороне приложения: схема гарантирует форму, но не правильность значений.

Ограниченное декодирование

Модель генерирует текст по одному токену, каждый раз выбирая из распределения вероятностей по словарю. Ограниченное декодирование (constrained decoding) на каждом шаге обнуляет вероятность токенов, недопустимых по грамматике: после {"age": разрешены только цифры, после закрытия последнего обязательного поля — только }. Схема JSON или регулярное выражение компилируется в конечный автомат или грамматику, и проверка выполняется быстро.[4]

На этом принципе работают режим strict в API OpenAI, структурированный вывод Anthropic, движки Outlines, XGrammar и llguidance, встроенные в инференс-серверы, и грамматики GBNF в llama.cpp.[1][2][5][7] Поддерживается не вся JSON Schema: обычно доступны объекты, массивы, перечисления, обязательные поля и вложенность, но часть ограничений (форматы, сложные условия) не применяется.[3]

Пример

Схему удобно описывать классами Pydantic и получать сразу типизированный объект (см. Dataclasses и Pydantic):

from pydantic import BaseModel, Field
from openai import OpenAI

class Vacancy(BaseModel):
    title: str
    salary_from: int | None = Field(description="в рублях, без НДФЛ")
    remote: bool
    stack: list[str]

client = OpenAI()
resp = client.responses.parse(
    model="gpt-5-mini",
    input=[{"role": "user", "content": f"Извлеки поля из вакансии:\n{text}"}],
    text_format=Vacancy,
)
vacancy: Vacancy = resp.output_parsed

Библиотека Instructor даёт такой же интерфейс для разных провайдеров и локальных моделей, добавляя автоматический повтор с текстом ошибки валидации.[6]

Связь с вызовом инструментов

Вызов инструментов технически — тот же структурированный вывод: модель выдаёт имя функции и аргументы по JSON Schema. Поэтому один из способов получить структуру — объявить «инструмент» с нужной схемой и потребовать его вызова. Современные API предлагают для этого отдельный режим.

Практические советы

  • Порядок полей важен. Модель генерирует слева направо: поле с рассуждением (reasoning) перед итоговым ответом улучшает точность, после — бесполезно.
  • Описания полей в схеме работают как часть промпта: единицы измерения, формат дат, что делать при отсутствии значения.
  • Оставлять выход. Для извлечения данных нужен способ сказать «не найдено» (null, отдельное перечисление), иначе модель выдумает значение — см. Галлюцинации LLM.
  • Не перегружать схему. Глубоко вложенные структуры с десятками полей лучше разбить на несколько вызовов.
  • Жёсткие ограничения могут вредить. Если формат мешает модели «думать», качество падает; иногда лучше дать свободный ответ, а затем извлечь из него структуру вторым вызовом.
  • Проверять смысл, а не только форму: правильный по схеме JSON может содержать неверные данные. Качество измеряют на размеченном наборе — см. Оценка LLM (evals).

См. также

Источники

  1. OpenAI — Structured Outputs
  2. Anthropic — Structured outputs
  3. JSON Schema — specification
  4. Willard, Louf — Efficient Guided Generation for Large Language Models (Outlines, 2023)
  5. llama.cpp — GBNF grammars
  6. Instructor — документация
  7. vLLM — Structured Outputs