Structured output + JSON Schema repair-loop для CRM-полей за 21 день
Structured output + JSON Schema repair-loop для CRM-полей за 21 день — это контур, где модель обязана вернуть валидный JSON по схеме обязательных полей, невалидный ответ чинится auto-repair с retry-budget, а при исчерпании бюджета карточка уходит в HITL, а не «кривым» объектом в Bitrix. Без schema и repair вы копите тихие дыры: пустой phone, строка вместо числа, enum вне списка.
Ниже — как я внедряю это на практике: схема, цикл починки, метрики parse/repair и критерии done на три недели.
Зачем schema, а не «попроси JSON в промпте»
«Верни JSON» без валидации — это надежда, не инженерия. CRM прощает один раз; на 500 лидах ломается отчётность и маршрутизация.
| Подход | Что получаете | Где ломается |
|---|---|---|
| Free text → regex | быстро на демо | любой новый формат |
| «JSON please» | 70–90% удачи | trailing comma, markdown fences, лишний текст |
| Structured output API | выше parse rate | всё равно нужен schema-check полей CRM |
| Schema + repair-loop + HITL | стабильный пайплайн | чуть больше кода — меньше ночных фиксов |
Обязательный минимум схемы (пример для квалификации лида):
{
"type": "object",
"required": ["intent", "contact_role", "next_step", "priority"],
"properties": {
"intent": { "type": "string", "enum": ["demo", "price", "support", "other"] },
"contact_role": { "type": "string", "minLength": 2, "maxLength": 80 },
"budget_band": { "type": ["string", "null"], "enum": ["lt50", "50_150", "gt150", null] },
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
"next_step": { "type": "string", "minLength": 5, "maxLength": 200 },
"reason_codes": {
"type": "array",
"items": { "type": "string", "pattern": "^[a-z0-9_]{3,40}$" },
"maxItems": 5
}
},
"additionalProperties": false
}
Правило: в CRM пишем только после validate(schema) = ok. Иначе — repair или HITL.
Repair-loop: алгоритм за 21 день
Цель спринта — не «идеальная модель», а предсказуемый parse/repair rate.
| День | Фокус | Артефакт |
|---|---|---|
| 1–3 | Инвентарь полей | словарь CRM: тип, enum, required, default, owner |
| 4–6 | JSON Schema v1 | required + enum + bounds; additionalProperties: false |
| 7–9 | Validator + нормализатор | trim, phone E.164 attempt, date ISO, enum map синонимов |
| 10–12 | Repair-loop | 1–2 LLM-repair + rule-repair; budget N=2 |
| 13–15 | HITL fallback | очередь «битый JSON» с diff ошибок |
| 16–18 | Метрики | parse_rate, repair_rate, hitl_rate, field_null_rate |
| 19–21 | Ужесточение | убрать лишние optional, сузить enum, freeze schema |
Псевдопоток:
LLM call (structured / json_mode)
→ strip fences / extract object
→ json.loads
→ jsonschema.validate
→ OK → map to CRM fields → write
→ FAIL → classify errors
→ rule-repair (типы, enum synonym, clamp)
→ if still fail && retries_left: LLM-repair(error_list, schema)
→ else: HITL ticket + raw payload
Retry-budget, который я ставлю по умолчанию:
- Rule-repair — бесплатно по latency, всегда первым.
- LLM-repair — максимум 2 попытки; в промпт только список ошибок schema, не весь диалог заново.
- Стоп — не крутить 10 раз: дороже HITL-минуты менеджера.
Классификация ошибок (чтобы repair был точечным):
| Класс | Пример | Кто чинит |
|---|---|---|
| Syntax | trailing comma, single quotes | extractor / second parse |
| Type | "priority": "high" | rule map → 4 или HITL |
| Enum | "intent": "прайс" | synonym table → price |
| Required missing | нет next_step | LLM-repair с forced field |
| Bounds | priority=9 | clamp 1..5 + flag |
| Hallucinated keys | foo_bar | drop (additionalProperties false) |
Метрики parse/repair и пороги quality
Без дашборда schema «живёт неделю и умирает».
| Метрика | Формула | Цель к дню 21 |
|---|---|---|
| Raw parse rate | valid JSON / all calls | ≥92% |
| Schema-valid rate (до repair) | validate ok first pass / all | ≥75% |
| After-repair valid rate | ok после rule+LLM repair / all | ≥96% |
| Repair rate | ушли в repair / all | 15–30% норма |
| HITL fallback rate | hitl / all | ≤4% |
| Field null rate (required) | null required after write / writes | ≈0% |
| p95 latency loop | end-to-end с repair | бюджет +1–2 LLM call max |
| Cost per accepted object | $ / successful CRM write | тренд вниз после freeze schema |
Алерты, которые я вешаю сразу:
- HITL rate > 8% за день — сломали schema или модель;
- один error_code > 40% repair — дыра в synonym/enum;
- null на required после «успешной» записи — баг маппера, не модели.
HITL fallback и границы scope
HITL — не «менеджер правит JSON руками в Notepad», а карточка:
- raw model output;
- список schema errors;
- best-effort partial object (только валидные поля);
- кнопки: принять partial / заполнить вручную / отклонить источник.
Что не входит в этот 21-дневный контур (чтобы не расползтись):
- prompt regression golden-set как отдельный R&D-пакет;
- canary/eval-gates на весь агент;
- budget cap/routing моделей;
- tool-calling whitelist;
- multi-tenant session isolation.
Здесь scope узкий: поля CRM ← structured object ← repair ← HITL.
Чеклист done на день 21:
- Schema v1 заморожена, versioned (
schema_idв логах). - After-repair valid ≥96% на проде (не на 10 демо-примерах).
- HITL ≤4%, очередь с SLA.
- Required fields в CRM не пишутся null «тихо».
- Дашборд parse/repair/hitl за 7 дней без дыр в логах.
Часто задаваемые вопросы
Structured output провайдера уже достаточен — зачем repair?
Провайдер гарантирует синтаксис JSON по своей схеме вызова. Ваша CRM-схема жёстче: enum статусов Bitrix, длины, обязательность next_step. Repair закрывает разрыв model schema → business schema.
Сколько retry безопасно?
Два LLM-repair максимум. Дальше — HITL. Третий-четвёртый retry почти не поднимает valid rate, но удваивает cost и latency.
Что логировать обязательно?
schema_id, raw, errors[], repair_path (rule/llm/hitl), latency, model, trace_id, entity_id CRM. Без этого вы не отличите регрессию модели от кривого деплоя схемы.
Можно ли писать partial object без HITL?
Только если missing — optional поля. Required missing → HITL или безопасный default, явно описанный в политике (и в activity «default applied»).
Читайте также
- Canary и eval-gates AI-агента в prod: golden-set, rollback, on-call за 30 дней
- Prompt regression suite для sales/ops-агентов: golden dialogs, gate, drift за 30 дней
- Tool-calling в Bitrix CRM: whitelist, dry-run, audit и откат
Нужен schema + repair-loop под ваши поля Bitrix — разберём на raisovich.ru: словарь полей, retry-budget и HITL так, чтобы в CRM не попадал «почти JSON».
Зачем additionalProperties false в JSON Schema для CRM?
Чтобы отсекать hallucinated keys и писать в Bitrix только согласованные поля. Иначе «лишние» ключи модели тихо разъезжают маппер и отчёты.
Какой after-repair valid rate цель к дню 21?
После rule+LLM repair — ≥96% schema-valid на проде, HITL fallback ≤4%, raw parse rate ≥92%. Без этих порогов schema «живёт неделю и умирает».
Что не входит в 21-дневный scope schema + repair?
Не входят golden-set regression, canary/eval-gates на весь агент, budget routing моделей, tool-calling whitelist и multi-tenant isolation — только поля CRM ← object ← repair ← HITL.
Подпишитесь на @raisovich_news
Первыми получайте новые статьи об AI-автоматизации, нейросетях для бизнеса и создании сайтов. Без спама — только полезный контент.
Часто задаваемые вопросы
Зачем additionalProperties false в JSON Schema для CRM?
Чтобы отсекать hallucinated keys и писать в Bitrix только согласованные поля. Иначе «лишние» ключи модели тихо разъезжают маппер и отчёты.
Какой after-repair valid rate цель к дню 21?
После rule+LLM repair — ≥96% schema-valid на проде, HITL fallback ≤4%, raw parse rate ≥92%. Без этих порогов schema «живёт неделю и умирает».