Техническая ветка для разработчиков Собрать руками
Structured outputs для бизнес-процессов
Structured outputs — это не просто «JSON вместо текста». Это фундамент для построения отказоустойчивых AI-агентов и интеграций. В этой статье — как делать это правильно, с примерами, ловушками и готовым чеклистом.
Видео по теме
Практический выпуск CodeVibers: собираем локальный pipeline обработки заявки. Показываю JSON Schema, llama.cpp/Qwen, retry при 503, независимую validation, business gate и routing в CRM либо review queue.
Таймкоды
- 00:00 Что строим
- 00:30 JSON Schema и два барьера
- 00:50 Пишем адаптер локальной модели
- 01:35 Запуск и тесты отказов
- 02:20 CRM payload или review queue
Shorts
- Как запретить модели выдумывать поля
- Response format не заменяет validation
- Что делать с 503 локальной модели
Источники выпуска
- ggml-org llama.cpp documentation
- JSON Schema documentation
Практический материал из выпуска
Артефакт: Рабочий Python pipeline: текст заявки -> llama.cpp/Qwen -> JSON Schema gate -> CRM payload или review queue -> HTML result.
Что должно получиться: Проект без внешних Python-зависимостей с schema, extractor, tests, action log и визуальным результатом.
Видимый результат: На экране меняются исходники, запускается локальная модель, проходят тесты и открывается итоговый routing result.
Вход для демо: Фиктивное обращение компании Север Маркет с задачей, бюджетом, сроком и целевыми системами без реальных контактов.
Выход демо: out/lead.json, out/crm_payload.json или out/review_queue.json, out/action_log.json и out/result.html.
Проверка результата: Schema validator запрещает missing/extra/wrong types; business gate требует confidence, budget и deadline; model 503 обрабатывается retry и review fallback.
Как собрать
- Создать lead_schema.json с required, enum, ranges и additionalProperties=false.
- Написать llama.cpp adapter с response_format и enable_thinking=false.
- Добавить независимую post-validation и CRM/review router.
- Запустить extraction на фиктивном обращении и сохранить action log.
- Прогнать unit tests и открыть итоговый HTML artifact.
- Define strict lead schema.
- Implement local llama.cpp adapter and retry.
- Implement independent validator and router.
- Run live extraction and persist action log.
- Run regression tests and render result UI.
Чеклист перед пилотом
- build_result.status equals passed.
- All unit tests pass.
- pipeline_result contains explicit status and reason.
- Every screen recording has passed privacy OCR report.
- Pipeline always returns crm_ready or review_required with a reason.
- All five regression tests pass and invalid fields never reach CRM payload.
- HTML result shows attempts, validation decision and output artifact.
Примеры команд, настроек или правил
python3 extract_lead.py fixtures/lead_request.txt
python3 -m unittest -v test_pipeline.py
response_format: {type: json_schema, schema: lead_schema}
additionalProperties: false
lead_schema.json
fixtures/lead_request.txt
pipeline.py
extract_lead.py
test_pipeline.py
render_result.py
python3 render_result.py
Требования и рекомендации
Требования
- Схема содержит required, типы, enum, диапазоны и запрет дополнительных полей.
- Thinking отключен для grammar-constrained ответа локального Qwen.
- Каждая попытка модели записывается в action log без публикации исходных персональных данных.
- CRM routing происходит только после schema и business validation.
Рекомендации
- Ограничивать generation JSON Schema, но все равно валидировать результат после модели.
- Запрещать дополнительные поля через additionalProperties=false.
- Разделять schema validity и business readiness.
- При 503, низкой confidence или неполных данных отправлять заявку в review queue, а не в CRM.
Что такое 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.