Туториалы AI Ops

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.

Процесс калибровки:

  1. Собрать набор из 500–1000 решений модели с confidence scores
  2. Разметить каждое решение как правильное/неправильное (ручная разметка или LLM-as-Judge)
  3. Построить кривую: при каждом пороге — какой процент решений уходит на ревью, какой процент ошибок проходит мимо
  4. Выбрать порог по бизнес-требованиям: допустимый процент пропущенных ошибок 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.608.2%12%8800 из 10000
0.753.1%28%7200 из 10000
0.851.4%41%5900 из 10000
0.920.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 Utilizationfeedback → улучшение моделимесячный цикл

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 повторяющимся паттернам. Этот асинхронный подход требует меньше дисциплины от ревьюеров и при этом поддерживает цикл улучшений — ежемесячная рекалибровка порогов является минимумом для системы, обрабатывающей тысячи решений в неделю.