Human-in-the-Loop для AI-продуктов: когда решает модель, а когда человек
Что такое Human-in-the-Loop (HITL) в AI-системах?
Human-in-the-Loop (HITL) — архитектурный паттерн, определяющий, где AI-система работает автономно, а где уступает управление человеку-ревьюеру. Вместо проверки каждого решения модели (убивает экономику) или ни одного (убивает доверие), HITL использует confidence threshold и risk matrix для маршрутизации: уверенные, низкорисковые решения выполняются автономно; неопределённые или высокорисковые — эскалируются. Хорошо откалиброванные HITL-системы достигают 70-85% автоматизации при уровне пропущенных ошибок ниже 2%.
TL;DR
- -При пороге 0.85 откалиброванная HITL-система обрабатывает 59% запросов автономно с ошибкой 1.4% — оставшиеся 41% уходят на ревью к человеку
- -Confidence threshold без калибровки хуже его отсутствия: модель, выдающая 0.9 на каждый ответ включая неправильные, бесполезна для маршрутизации
- -Risk matrix добавляет вторую ось: высокий confidence при высоком риске всё равно требует контроля — модерация контента и автоматическое ценообразование требуют выборочной проверки даже выше порога уверенности
- -Экономика Cascading Validation: автоматические правила обрабатывают 100% за $0, LLM-as-Judge — 85% за $0.002-0.01 на запрос, человек — только 5-10% за $0.50-2.00
- -Reviewer Agreement ниже 85% имеет две разные причины: плохая работа модели или несогласованность ревьюеров — нужно диагностировать до корректировки порогов
Полностью автономные AI-системы в production допускают критические ошибки. Добавление human-in-the-loop снижает их число в разы, но увеличивает latency и стоимость обработки.
Вопрос не в том, нужен ли человек в контуре. Вопрос в том, где именно его поставить, чтобы ловить опасные решения и не превращать AI-систему в дорогой интерфейс для ручной работы.
Когда автономность работает, а когда убивает продукт
Две крайности. Полная автономность: модель решает всё сама, человек видит результат постфактум. Полный контроль: каждый ответ модели проходит ручную проверку до отправки пользователю. Первое масштабируется, но ломает доверие при ошибках. Второе надёжно, но убивает экономику.
Реальные AI-продукты живут между этими полюсами. Задача архитектора: определить, какие решения модель принимает автономно, а какие требуют подтверждения человека.
Три фактора определяют границу:
Цена ошибки. Чат-бот рекомендует ресторан с неправильным рейтингом — неприятно. AI-система одобряет кредит на $50 000 по галлюцинирующему анализу — судебный иск. Чем выше стоимость ошибки, тем ниже порог эскалации к человеку.
Обратимость. Отправленное push-уведомление не вернуть. Сгенерированный черновик email легко исправить до отправки. Необратимые действия требуют подтверждения.
Уверенность модели. Модель с confidence 0.95 ошибается реже, чем с 0.6. Но даже 0.95 означает одну ошибку на двадцать решений. Порог зависит от задачи.
Confidence Threshold: фреймворк принятия решений
Confidence threshold — числовой порог, ниже которого решение модели уходит на ревью человеку. Звучит просто. На практике требует калибровки под каждый тип задачи.
Базовая формула
ЕСЛИ confidence >= threshold И risk_level == "low"
→ автономное решение
ЕСЛИ confidence >= threshold И risk_level == "high"
→ автономное решение + асинхронный аудит
ЕСЛИ confidence < threshold
→ эскалация к человеку
Threshold не фиксированный. Для классификации тикетов поддержки достаточно 0.7. Для медицинской триажной системы нужен 0.95+. Для финансовых решений — 0.99.
Калибровка порога
Неоткалиброванный порог хуже его отсутствия. Модель, которая выдаёт confidence 0.9 на каждом ответе (включая неправильные), бесполезна для HITL.
Процесс калибровки:
- Собрать набор из 500–1000 решений модели с confidence scores
- Разметить каждое решение как правильное/неправильное (ручная разметка или LLM-as-Judge)
- Построить кривую: при каждом пороге — какой процент решений уходит на ревью, какой процент ошибок проходит мимо
- Выбрать порог по бизнес-требованиям: допустимый процент пропущенных ошибок vs. нагрузка на ревьюеров
from sklearn.metrics import precision_recall_curve
import numpy as np
def find_optimal_threshold(
confidences: list[float],
is_correct: list[bool],
max_error_rate: float = 0.02, # макс 2% ошибок в автономных решениях
) -> dict:
"""Находит порог, при котором ошибки в автономной зоне <= max_error_rate."""
confidences = np.array(confidences)
is_correct = np.array(is_correct)
thresholds = np.arange(0.5, 1.0, 0.01)
results = []
for t in thresholds:
autonomous = confidences >= t
escalated = confidences < t
if autonomous.sum() == 0:
continue
error_rate = 1 - is_correct[autonomous].mean()
escalation_rate = escalated.sum() / len(confidences)
results.append({
"threshold": round(t, 2),
"error_rate": round(error_rate, 4),
"escalation_rate": round(escalation_rate, 4),
"autonomous_volume": int(autonomous.sum()),
})
# Выбрать наименьший порог, при котором error_rate <= max_error_rate
valid = [r for r in results if r["error_rate"] <= max_error_rate]
if not valid:
return results[-1] # самый строгий порог
return min(valid, key=lambda r: r["threshold"])
Типичные результаты калибровки:
| Порог | Ошибки в автономных | Эскалация | Автономный объём |
|---|---|---|---|
| 0.60 | 8.2% | 12% | 8800 из 10000 |
| 0.75 | 3.1% | 28% | 7200 из 10000 |
| 0.85 | 1.4% | 41% | 5900 из 10000 |
| 0.92 | 0.3% | 58% | 4200 из 10000 |
При пороге 0.85 система автономно обрабатывает 59% запросов с ошибкой в 1.4%. Оставшиеся 41% уходят на ревью. Для большинства B2B-продуктов это приемлемый баланс.
Risk Matrix: второе измерение фильтрации
Confidence threshold работает по одной оси. Risk matrix добавляет вторую: тип и последствия решения. Высокий confidence при высоком риске всё равно требует контроля.
Low Risk High Risk
┌─────────────────┬─────────────────┐
High Confidence │ AUTO │ AUTO + AUDIT │
│ Полная │ Автономно, но │
│ автономность │ логируем для │
│ │ выборочной │
│ │ проверки │
├─────────────────┼─────────────────┤
Low Confidence │ QUEUE │ ESCALATE │
│ В очередь на │ Немедленная │
│ пакетный │ эскалация к │
│ ревью │ человеку │
│ │ │
└─────────────────┴─────────────────┘
Четыре зоны — четыре поведения:
AUTO. Низкий риск, высокая уверенность. Модель решает, результат отправляется сразу. Примеры: классификация тикетов поддержки, генерация тегов для контента, автодополнение поискового запроса.
AUTO + AUDIT. Высокий риск, высокая уверенность. Модель решает автономно, но каждое решение записывается в аудит-лог. Ревьюер проверяет выборку (10–20%) постфактум. Примеры: модерация контента, автоматическое ценообразование, персонализация рекомендаций.
QUEUE. Низкий риск, низкая уверенность. Решение уходит в пакетную очередь для ревью. Не срочно, но модель не справляется сама. Примеры: категоризация нестандартных запросов, генерация описаний для edge-case товаров.
ESCALATE. Высокий риск, низкая уверенность. Немедленная эскалация к человеку. Блокирует процесс до получения решения. Примеры: подозрение на мошенничество, медицинские рекомендации при неоднозначных симптомах, решения об удалении аккаунта.
Определение уровня риска
Риск определяется статически (по типу задачи) или динамически (по содержанию запроса).
Статическая классификация:
RISK_LEVELS = {
"ticket_classification": "low",
"content_moderation": "high",
"price_adjustment": "high",
"search_autocomplete": "low",
"fraud_detection": "high",
"tag_generation": "low",
"medical_triage": "critical",
"account_deletion": "critical",
}
Динамическая классификация — через вторую модель или набор правил. Запрос о возврате товара за $5 — low risk. Запрос о возврате $50 000 — high risk. Та же задача, разный уровень контроля.
def assess_risk(task_type: str, context: dict) -> str:
base_risk = RISK_LEVELS.get(task_type, "medium")
# Динамические модификаторы
if context.get("amount", 0) > 10_000:
return "critical"
if context.get("is_new_user", False):
return max_risk(base_risk, "high")
if context.get("affects_multiple_users", False):
return "critical"
return base_risk
Паттерны HITL в production
Пять паттернов. Каждый решает конкретную архитектурную задачу.
Паттерн 1: Pre-action Gate
Модель генерирует решение, но не выполняет действие. Человек подтверждает или отклоняет.
Запрос → LLM генерирует решение → Gate → [Человек подтверждает] → Действие
↓
[Человек отклоняет] → Feedback → Модель пробует снова
Применение: любые необратимые действия. Отправка email от имени пользователя, публикация контента, финансовые транзакции.
Реализация: модель возвращает structured JSON с предлагаемым действием. Система записывает его в очередь ревью. Ревьюер нажимает Approve/Reject. При Approve система выполняет действие. При Reject — feedback возвращается модели для повторной генерации.
class PreActionGate:
def __init__(self, queue: ReviewQueue, executor: ActionExecutor):
self.queue = queue
self.executor = executor
async def process(self, llm_decision: dict, context: dict) -> str:
risk = assess_risk(llm_decision["action_type"], context)
confidence = llm_decision["confidence"]
if confidence >= THRESHOLDS[risk] and risk != "critical":
# Автономное выполнение
return await self.executor.execute(llm_decision)
# Эскалация
review_id = await self.queue.enqueue(
decision=llm_decision,
context=context,
priority="urgent" if risk == "critical" else "normal",
)
return f"Awaiting review: {review_id}"
Паттерн 2: Post-action Audit
Модель действует автономно. Человек проверяет выборку решений постфактум. Ошибочные решения откатываются или компенсируются.
Запрос → LLM → Действие → Лог в аудит
↓
Ревьюер проверяет выборку
↓
Ошибка → Откат + корректировка модели
Применение: высокообъёмные решения с низкой ценой отдельной ошибки. Модерация комментариев, классификация тикетов, генерация метаданных.
Размер выборки зависит от зрелости модели. На старте — 20–30% решений. После стабилизации — 5–10%. При обнаружении деградации — возврат к 20–30%.
Паттерн 3: Confidence-based Routing
Запросы распределяются между моделью и человеком на основе confidence score. Модель обрабатывает простые кейсы, человек — сложные.
Запрос → LLM оценивает → confidence >= 0.85 → Автономный ответ
→ confidence 0.6-0.85 → LLM отвечает + флаг для ревью
→ confidence < 0.6 → Человек отвечает
Три зоны вместо двух. Средняя зона — модель отвечает сразу (latency не страдает), но ответ попадает в очередь на проверку. Если ревьюер находит ошибку, пользователь получает исправленный ответ.
Этот паттерн эффективен для support-ботов. 60–70% запросов типовые — модель справляется с confidence 0.9+. 20–25% запросов средней сложности — модель отвечает, ревьюер проверяет. 5–15% сложных кейсов — сразу к человеку.
Паттерн 4: Cascading Validation
Несколько уровней проверки. Каждый следующий дороже, но точнее. Запрос проходит столько уровней, сколько нужно для достижения требуемой уверенности.
LLM Generator → Автоматические правила (regex, schema validation)
↓ (прошёл)
→ LLM-as-Judge (вторая модель оценивает)
↓ (прошёл)
→ Автономный ответ
↓ (не прошёл на любом уровне)
→ Эскалация к человеку
Подробнее о втором уровне — в статье LLM-as-Judge: автоматический quality gate.
Каждый уровень отсекает часть ошибок. Автоматические правила ловят очевидные нарушения формата (отсутствие обязательных полей, SQL-injection в ответе, запрещённый контент по стоп-словам). LLM-as-Judge ловит смысловые ошибки: галлюцинации, нерелевантность, нарушение тона. Человек ловит то, что пропустили оба автоматических уровня.
Экономика: автоматические правила обрабатывают 100% запросов за $0. LLM-as-Judge обрабатывает 85% (15% отсеяны правилами) за $0.002–$0.01 на запрос. Человек обрабатывает 5–10% (остальное прошло оба уровня) за $0.50–$2.00 на запрос.
Паттерн 5: Feedback Loop с обучением
Решения ревьюеров возвращаются в систему для улучшения модели. Со временем модель учится на правках и требует меньше ревью.
LLM → Решение → Ревью → [Correct] → +1 к обучающей выборке
→ [Incorrect] → Корректировка + обучающий пример
↓
Fine-tuning / prompt update
↓
Threshold recalibration
Feedback loop работает только при структурированном сборе данных. Ревьюер не просто нажимает Reject — указывает причину отказа, правильный ответ, категорию ошибки. Эти данные формируют evaluation dataset для автоматического мониторинга качества.
Реализация HITL-системы: архитектура
Минимальная production-архитектура включает пять компонентов.
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │────→│ AI Service │────→│ Review Queue │
└──────────┘ │ │ │ (Redis/SQS) │
│ - LLM call │ └──────┬───────┘
│ - Confidence│ │
│ - Risk │ ┌──────▼───────┐
│ - Routing │ │ Review UI │
└──────────────┘ │ (Dashboard) │
│ └──────┬───────┘
│ │
┌──────▼───────┐ ┌──────▼───────┐
│ Action │ │ Feedback │
│ Executor │ │ Store │
└──────────────┘ └──────────────┘
AI Service вызывает модель, получает confidence, определяет risk level, маршрутизирует решение.
Review Queue хранит решения, ожидающие ревью. Redis для простых случаев, SQS/RabbitMQ для распределённых систем. Каждое решение в очереди содержит: оригинальный запрос, ответ модели, confidence, risk level, контекст, timestamp, приоритет.
Review UI показывает ревьюеру решение модели с контекстом. Ревьюер подтверждает, корректирует или отклоняет. Хороший UI показывает confidence модели, подсвечивает зоны неуверенности, предлагает альтернативы.
Action Executor выполняет подтверждённое действие. Идемпотентный — повторный вызов с тем же ID не дублирует действие.
Feedback Store собирает решения ревьюеров для обучения. Структурированные данные: решение модели, решение человека, delta, причина корректировки.
Метрики HITL-системы
Шесть метрик для мониторинга.
| Метрика | Формула | Целевое значение |
|---|---|---|
| Escalation Rate | эскалации / все запросы | 15-30% (зависит от домена) |
| Auto-resolve Rate | автономные / все запросы | 70-85% |
| Error Escape Rate | ошибки в автономных / автономные | < 2% |
| Review Latency | среднее время ревью | < 5 мин (P95) |
| Reviewer Agreement | согласие с решением модели | > 85% |
| Feedback Utilization | feedback → улучшение модели | месячный цикл |
Escalation Rate растёт — модель деградирует или порог слишком строгий. Падает — модель улучшается или порог слишком мягкий.
Error Escape Rate — главная метрика безопасности. Если растёт, нужна рекалибровка порога или переобучение модели.
Reviewer Agreement ниже 85% означает одно из двух: модель плохо справляется (ревьюеры часто корректируют) или ревьюеры несогласованы между собой (нужна калибровка ревьюеров).
Антипаттерны
Threshold без калибровки. Порог 0.8, установленный «потому что кажется разумным». Без данных о реальных ошибках невозможно определить правильный порог. Начните с ручного ревью 100% решений, накопите данные, откалибруйте.
Ревью как bottleneck. Очередь на ревью растёт быстрее, чем ревьюеры обрабатывают. Решения ждут часами. Пользователи не получают ответов. Решение: автоматический fallback — если решение ждёт ревью дольше SLA, отправить ответ модели с пометкой «может быть скорректирован».
Слепое доверие confidence. Модели галлюцинируют с высоким confidence. GPT-4 выдаёт 0.95 на фактически неправильном ответе. Confidence из logprobs и confidence из самооценки модели — разные вещи. Logprobs показывают уверенность в выборе токена, а не в правильности ответа. Нужна внешняя калибровка.
HITL на каждом шаге. Человек подтверждает каждое решение модели. AI-система превращается в UI для ручной работы. Если 90% решений ревьюер подтверждает без правок — порог слишком строгий.
Feedback без действий. Ревьюеры корректируют решения, данные собираются, но модель не улучшается. Каждый месяц: анализ типичных ошибок, обновление промптов, рекалибровка порогов.
Чеклист: выбор паттерна HITL
Алгоритм для выбора правильного паттерна.
1. Действие необратимо?
ДА → Pre-action Gate (паттерн 1)
НЕТ → далее
2. Объём > 1000 решений/день?
ДА → Confidence-based Routing (паттерн 3)
НЕТ → далее
3. Цена единичной ошибки > $100?
ДА → Cascading Validation (паттерн 4)
НЕТ → далее
4. Есть ресурсы на ревью 20-30% решений?
ДА → Post-action Audit (паттерн 2)
НЕТ → Confidence-based Routing с высоким порогом (паттерн 3)
Всегда: добавить Feedback Loop (паттерн 5) поверх любого выбранного паттерна.
Итого
Human-in-the-loop — не fallback для плохой модели. Это архитектурный паттерн, который определяет, где AI работает автономно, где под наблюдением, а где уступает место человеку.
Три инструмента: confidence threshold (откалиброванный на реальных данных), risk matrix (статический + динамический уровень риска), паттерн маршрутизации (выбранный по чеклисту). Метрики мониторинга показывают, работает ли система и когда пора рекалибровать.
Начните с Post-action Audit на 100% решений. Через 1–2 недели накопится достаточно данных для калибровки порога. После этого переходите на Confidence-based Routing. Через месяц добавляйте Cascading Validation для высокорисковых решений. Каждый шаг уменьшает нагрузку на ревьюеров и увеличивает автономность модели.
FAQ
Как не допустить, чтобы очередь ревью стала узким местом в высоконагруженных системах?
Три механизма предотвращают перегрузку очереди. Первый — автоматический fallback по SLA: если решение ждёт ревью дольше N минут, отправить ответ модели с видимой пометкой «на проверке», а не блокировать пользователя. Второй — динамическое повышение порога при пиковой нагрузке: временно поднять confidence threshold, чтобы меньше решений попадало в очередь. Третий — модель пропускной способности ревьюеров: если скорость эскалаций Tier A стабильно превышает производительность ревьюеров, нужна рекалибровка порога, а не увеличение штата.
Можно ли доверять LLM-генерируемому confidence как сигналу для маршрутизации?
Confidence из самооценки модели не откалиброван по умолчанию. GPT-4 с ненулевой частотой выдаёт высокие оценки уверенности на фактически неправильных ответах. Logprobs надёжнее — они отражают уверенность в выборе токена, а не субъективную самооценку — но тоже требуют внешней калибровки на размеченных данных перед использованием. Процесс калибровки из этой статьи (сбор 500-1000 решений и сравнение scores с метками правильно/неправильно) — минимально необходимый шаг перед запуском любой production HITL-системы.
Как организовать Feedback Loop, если ревьюеры недоступны ежедневно?
Собирать обратную связь пакетами. Вместо real-time фидбека от каждого ревьюера — собирать решения ежедневно и проводить еженедельный цикл анализа: экспортировать все корректировки ревьюеров, кластеризовать по категориям ошибок, обновлять промпт или порог по топ 2-3 повторяющимся паттернам. Этот асинхронный подход требует меньше дисциплины от ревьюеров и при этом поддерживает цикл улучшений — ежемесячная рекалибровка порогов является минимумом для системы, обрабатывающей тысячи решений в неделю.