Техническая ветка для разработчиков Собрать руками
Structured outputs для бизнес-процессов
Structured outputs — это не просто «JSON вместо текста». Это фундамент для построения отказоустойчивых AI-агентов и интеграций. В этой статье — как делать это правильно, с примерами, ловушками и готовым чеклистом.
Что такое structured outputs и зачем он бизнесу
Structured outputs — это формат ответа LLM, где результат представлен в строго определённой структуре (обычно JSON), соответствующей заранее заданной схеме (schema). В отличие от свободного текста, такие ответы можно напрямую использовать в коде: сохранять в БД, передавать в API, валидировать, логировать и автоматизировать.
Для бизнеса это означает:
- Устранение «человеческого» парсинга («надо вытащить сумму из текста»)
- Гарантированная структура данных — даже если модель ошиблась, она вернёт JSON, а не «сломанный» текст
- Прямая интеграция с системами: CRM, ERP, бэкенд, workflow-движки
- Возможность автоматической валидации и ретраев
Как это работает: пайплайн от промпта до JSON
flowchart TD
A[Пользовательский запрос] --> B[Промпт с schema]
B --> C[LLM API call]
C --> D{Ответ валиден?}
D -->|Да| E[JSON-объект]
D -->|Нет| F[Retry / Fallback]
E --> G[Валидация по схеме]
G --> H[Использование в бизнес-логике]
Ключевой момент: схема (schema) задаётся до вызова API. Это может быть JSON Schema, Pydantic-модель или встроенный тип (например, в OpenAI — response_format).
Пример: из промпта к JSON в Python
Базовый пример с OpenAI API (через Pydantic):
from pydantic import BaseModel
from openai import OpenAI
class InvoiceData(BaseModel):
amount: float
currency: str = "RUB"
invoice_id: str
status: "paid" | "unpaid" | "overdue"
client = OpenAI()
completion = client.beta.chat.completions.parse(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Извлеки данные из счета. Используй только данные из текста."},
{"role": "user", "content": "Счет №INV-2024-089 от 12.05.2024: сумма 45 000 руб., статус — оплачен."}
],
response_format=InvoiceData
)
invoice = completion.choices[0].message.parsed
print(invoice.amount, invoice.status) # 45000.0, 'paid'
Важно: parse() вместо create(), и модель сама гарантирует, что ответ будет соответствовать схеме (или вернёт ошибку).
Бизнес-кейс: автоматизация обработки входящих писем
Сценарий: приходит письмо от клиента с просьбой изменить срок оплаты. Нужно:
- Извлечь ID заказа, новую дату, причину
- Проверить, что заказ существует и не просрочен
- Создать задачу в Jira / CRM
Без structured outputs — 3 этапа: LLM → текст → regex → данные. С ним — 1 этап: LLM → JSON → данные.
Пример схемы для запроса:
class RequestChange(BaseModel):
order_id: str
new_due_date: str # ISO 8601
reason: str
priority: "low" | "medium" | "high"
После этого — просто вызов API, валидация, и можно отправлять данные в CRM.
Типичные ошибки и как их избежать
- Слишком сложная схема → модель «обманывает» (возвращает JSON, но с ложными данными). Решение: разбивайте на подзадачи, используйте step-by-step reasoning.
- Нет fallback-логики → при ошибке пайплайн падает. Решение: всегда обрабатывайте
ValidationErrorи возвращайте fallback-значения (null, default, human review). - Игнорирование типов →
"45 000"вместо45000.0. Решение: используйте строгую валидацию (Pydantic v2, strict=True). - Нет логирования → невозможно отладить, почему модель «неправильно» спарсила. Решение: логируйте вход, выход и ошибки (включая raw response).
Чеклист внедрения structured outputs
- [ ] Схема описана в виде JSON Schema / Pydantic и версионирована
- [ ] В API вызове указан
response_format(или эквивалент) - [ ] Есть обработка
ValidationErrorи fallback-логика - [ ] Логируется raw response + parsed объект + ошибка (если есть)
- [ ] Проведена тестовая валидация на 10–20 реальных примерах
- [ ] Определён SLA: сколько времени отводится на парсинг и ретраи
Следующий шаг: от outputs к агенту
Structured outputs — это не конечная точка. Это основа для агентов, которые:
- Парсят вход → принимают решение → вызывают tool → возвращают структурированный результат
- Могут обрабатывать ошибки и ретраить вызовы
- Интегрируются в очереди (например, RabbitMQ) для масштабирования
Дальше — в Telegram-канале и в следующих статьях: как собрать агента с tool-calling, как тестировать его поведение и как сделать production-ready workflow.