Перейти к основному содержимому
  1. Теория на русском языке/
  2. Начало работы/
  3. Интеграция инструментов/

Структурированные выводы

·833 слов·4 минут
Оглавление

Структурированные ответы — это ответы LLM, которые следуют определённому, машиночитаемому формату: JSON, XML или шаблон, заданный регулярным выражением. Вместо свободного текста модель выдаёт данные, которые можно сразу парсить и использовать в других системах.

Пример:

{
  "name": "LLM Inference Handbook",
  "author": "Rakhmankulov Bulat",
  "website": "https://rakhmankulov.github.io/theory",
  "summary": "Практическое руководство для инженеров по построению, оптимизации, масштабированию и эксплуатации LLM-инференса в продакшене."
}

Зачем нужны структурированные ответы?
#

Обычно LLM выдаёт свободный текст, который легко понять человеку.

Но если вы строите приложение с LLM (например, интеграция с сервисом, API или БД), нужен предсказуемый формат. Иначе программе непонятно, что и где искать.

Структурированные ответы дают модели чёткий машиночитаемый шаблон, что делает автоматизацию и интеграцию надёжнее.

Например, вы делаете ассистента-аналитика, который читает обращения в поддержку и формирует инсайты для продуктовой команды. Вы хотите, чтобы LLM вернула:

  • основные проблемы пользователей,
  • их частоту,
  • общий тон (sentiment).

Если модель ответит просто текстом:

«Большинство жалоб — на медленную загрузку и ошибки оплаты. В целом тон слегка негативный.»

Для человека это понятно, но для дашборда бесполезно: нужно вручную вытаскивать данные или писать сложный парсер.

А вот структурированный ответ:

{
  "issues": [
    {"topic": "Медленная загрузка", "count": 42},
    {"topic": "Ошибки оплаты", "count": 31}
  ],
  "sentiment": "negative",
  "confidence": 0.87
}

Системе не нужно ничего додумывать: можно сразу парсить, сохранять в БД и строить графики. Никакой ручной обработки.

Структурированные ответы уже стандарт во многих LLM-системах:

  • Извлечение информации: выделение сущностей, чисел или связей из документов в JSON или таблицы.
  • Обогащение данных: классификация, тегирование, суммирование записей для CRM или аналитики.
  • Вызов функций и API: модель выбирает инструмент и передаёт параметры в структурированном виде.
  • Оркестрация агентов: многошаговые сценарии, где каждый шаг использует результат предыдущего.
  • Оценка и тестирование: сбор однородных ответов для бенчмарков и проверки качества.
  • Модерация и комплаенс: структурированные решения, например { "action": "flag", "reason": "PII detected" }.

Как получить структурированные ответы
#

Теперь понятно, зачем они нужны. Но как их получить на практике?

Можно написать свой парсер, который будет вытаскивать нужные данные из ответа модели. Но это быстро становится неудобно: код сложный, ломкий, требует поддержки для каждого нового формата.

Лучше — заставить LLM сразу выдавать структурированные данные. Но не все модели поддерживают это «из коробки». Для таких моделей часто приходится аккуратно формулировать prompt или задавать схему через специальные фреймворки. Если формат чётко описан (например, через примеры или регулярки), модель обычно хорошо следует структуре.

Сегодня есть три основных способа получить структурированные ответы.

Облачные API моделей
#

Самый простой путь — использовать API моделей, которые поддерживают структурированные ответы нативно.

Провайдеры вроде OpenAI, Anthropic, Google позволяют указывать схему или структуру JSON прямо в API-запросе. Модель автоматически выдаёт ответ по этой схеме.

Эта функция выросла из раннего JSON mode, когда модель просто просили отвечать в формате JSON. Но JSON mode работал нестабильно: часто получался битый или неполный JSON. Для решения этой проблемы OpenAI ввели Structured Outputs — строгую систему, которая всегда проверяет соответствие схеме.

Пример с OpenAI API:

from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

# Описываем ожидаемые поля через Pydantic
class SupportSummary(BaseModel):
    issues: list[str]
    sentiment: str
    confidence: float

completion = client.chat.completions.parse(
    model="gpt-5",
    messages=[
        {"role": "system", "content": "Суммируй обращения в поддержку."},
        {"role": "user", "content": "Приложение ужасно! Оно падает при каждом запуске."},
    ],
    response_format=SupportSummary,
)

event = completion.choices[0].message.parsed

С такими API не нужно писать свой парсер — модель сама валидирует схему.

Минусы:

  • Привязка к провайдеру (vendor lock-in)
  • Ограничения на размер ответа — большие JSON могут обрезаться
  • Не всегда строгая проверка схемы — у разных провайдеров разная реализация

Перепрос (re-prompting)
#

Перепрос — простой и эффективный способ получить структурированный ответ с помощью библиотек вроде Instructor.

Как это работает:

  1. Вы отправляете prompt с описанием нужного формата (например, JSON-схема).
  2. Библиотека проверяет, валиден ли ответ.
  3. Если нет — автоматически перепрашивает модель с деталями ошибки.
  4. Цикл повторяется, пока не получится валидный ответ или не исчерпан лимит попыток.

Такой подход избавляет от необходимости писать свою retry-логику.

Плюсы: можно задавать свои правила (регулярки, форматы дат и чисел), работает с любыми моделями и API.

Минус — задержка и стоимость: каждая попытка — это новый запрос к модели. Если схема сложная или модель плохо следует инструкциям, может понадобиться много попыток.

Ограниченное декодирование (constrained decoding)
#

Если вы запускаете open-source LLM у себя, ограниченное декодирование (structured generation) — один из самых надёжных способов получить структурированный ответ.

Вместо проверки результата после генерации, структура навязывается прямо во время генерации токенов. Модель может выбирать только те токены, которые соответствуют схеме.

Что происходит внутри:

Когда LLM генерирует текст, она предсказывает вероятность каждого следующего токена (логиты). При ограниченном декодировании логиты в реальном времени модифицируются так, чтобы исключить токены, нарушающие структуру. Модель может продолжать только валидные варианты, и итоговый ответ всегда соответствует схеме.

Этот подход быстрый (нет перепросов и пост-обработки), отлично работает с open-source моделями и поддерживается такими библиотеками, как Outlines, Microsoft Guidance, XGrammar. Фреймворки инференса vLLM и SGLang уже интегрировали эти инструменты.

Преимущества: скорость, точность, надёжность. Команда Outlines даже показала, что structured output может улучшать качество LLM.

Дополнительные ресурсы
#