Дайджесты новостей
Инфографический чертёж калибровки decision-модели на бумаге с графиком кривой Precision-Recall и порогом отсечения 0.80.

Decision-модели вместо LLM-судей: как настроить пороги отсечения и не разориться на эвалюации

Если ты когда-нибудь строил автономного ИИ-агента, то наверняка знаешь главную боль продакшена: как понять, что бот прямо сейчас не запутался в вызове сторонних API и не выдает клиенту вежливую чепуху? Стандартный подход, который советуют в большинстве модных туториалов, выглядит прямолинейно: берем логи диалога (трейсы), отправляем их в тяжелую флагманскую модель вроде GPT-4o или Claude Opus с промптом «Оцени, была ли здесь ошибка от 1 до 5», и надеемся на чудо.

Но давай посчитаем экономику. Когда агент выполняет тысячи сессий в день, использование полноразмерной LLM в качестве «судьи» (LLM-as-a-judge) на каждый чих превращается в огромную финансовую дыру. К тому же ты получаешь задержку в 3–5 секунд на каждый проверочный запрос.

Инженер и практик эвалюации Хамель Хусейн вместе с Антарипой Саха опубликовали подробный разбор альтернативного пути: использование специализированных decision-моделей. Это компактные негенеративные классификаторы, которые не рассуждают вслух о смысле жизни, а возвращают конкретную вероятность ошибки. Ранее мы уже касались негенеративной модели Typesafe Jev, а теперь появились свежие данные практического бенчмарка на реальных логах.

98 продакшен-трейсов и битва классификаторов

Авторы эксперимента взяли реальную задачу: 98 валидных трейсов сложного агента по поиску и бронированию жилья. В этой выборке было зафиксировано 61 фактическое падение (ошибки аргументов инструментов, неверные даты, сбои логики) и 37 успешных завершений задачи.

Эти трейсы скормили пяти актуальным decision-моделям:

  • Perplexity Decider 1.1 (27B): показал рекордную дешевизну — всего $0.0082 за проверку всех 100 сессий при итоговом F1-score 0.79. Правда, среднее время ответа оказалось ощутимым — 7.85 секунды.
  • OpenAI Decisions (на базе GPT-6 Luna): продемонстрировал наивысшую точность с F1-score 0.87, но обошелся в $0.0372 за 100 прогонов — в 4.5 раза дороже Perplexity.
  • Liquid d1 и d1-ultra: сверхбыстрые модели с экстремально низкой стоимостью ($0.02 и $0.042 за 1 миллион токенов) и временем отклика всего 1.56 секунды.
  • Cloudflare Clef Flash и TypeSafe Jev 1.13: крепкие легковесные классификаторы со строгой структуризацией ответов.

Ловушка стандартного порога 0.50

Главное открытие исследования заключается в том, что большинство разработчиков выбрасывают деньги на ветер из-за одной школьной привычки. Получив от классификатора вероятность ошибки от 0.0 до 1.0, инженеры по умолчанию ставят условие: «Если скор больше 0.50, поднимаем тревогу».

Это фатальная ошибка. Сырые скоры моделей смещены: одни архитектуры систематически занижают оценки, другие — завышают. На пороге 0.50 модель Liquid d1 пропускала больше половины реальных сбоев, а Perplexity Decider выдавала шквал ложных срабатываний, заставляя дежурных инженеров отключать алерты в Slack.

В реальном бизнесе у тебя всегда есть развилка между Precision (точностью: если сработал алерт, там действительно сбой) и Recall (полнотой: какой процент реальных сбоев мы поймали). Чтобы система работала предсказуемо, порог отсечения нужно калибровать математически.

Ищем оптимальный порог на Python

Вот как выглядит расчет оптимального порога по сохраненным историческим скорам с помощью библиотеки scikit-learn. Мы ставим жесткое бизнес-требование: точность и полнота должны быть не ниже 80%, после чего максимизируем F1-score:

import numpy as np
from sklearn.metrics import precision_recall_curve

def find_optimal_threshold(y_true, y_scores, min_precision=0.80, min_recall=0.80):
    """
    Поиск порога отсечения, гарантирующего минимальные границы точности и полноты.
    y_true: массив истинных меток (1 - ошибка, 0 - успех)
    y_scores: массив вероятностей от decision-модели
    """
    precisions, recalls, thresholds = precision_recall_curve(y_true, y_scores)
    best_threshold = 0.50
    best_f1 = 0.0

    for p, r, t in zip(precisions[:-1], recalls[:-1], thresholds):
        if p >= min_precision and r >= min_recall:
            # Вычисляем гармоническое среднее Precision и Recall
            f1 = 2 * (p * r) / (p + r) if (p + r) > 0 else 0.0
            if f1 > best_f1:
                best_f1 = f1
                best_threshold = float(t)

    return best_threshold, best_f1

Сдвиг порога с 0.50 до вычисленного оптимума (например, 0.38 для моделей со смещением) мгновенно поднимает F1-score на 10–15 пунктов без дообучения весов и без изменения промпта.

Калибровка вероятностей: метод Платта

Вторая проблема сырых моделей — искажение абсолютных значений. Если модель вернула 0.90, это не значит, что в 90 случаях из 100 там действительно ошибка. Для выравнивания вероятностей отлично подходит Platt scaling — обучение логистической регрессии поверх логарифмических шансов (log-odds):

from sklearn.linear_model import LogisticRegression

def calibrate_platt_scaling(train_scores, train_labels, test_scores):
    """
    Калибровка выходов классификатора методом Платта.
    Служит для приведения сырых скоров к честным статистическим вероятностям.
    """
    eps = 1e-6
    # Обрезаем экстремальные значения для стабильности логарифма
    clipped_train = np.clip(train_scores, eps, 1.0 - eps)
    log_odds_train = np.log(clipped_train / (1.0 - clipped_train)).reshape(-1, 1)

    calibrator = LogisticRegression(C=1.0, solver='lbfgs')
    calibrator.fit(log_odds_train, train_labels)

    clipped_test = np.clip(test_scores, eps, 1.0 - eps)
    log_odds_test = np.log(clipped_test / (1.0 - clipped_test)).reshape(-1, 1)
    
    # Возвращаем калиброванную вероятность положительного класса
    return calibrator.predict_proba(log_odds_test)[:, 1]
Ограничения калибровки на малых выборках

Метод Платта существенно улучшает метрику Brier score для моделей с системным сдвигом (Perplexity, Liquid d1), но на крошечных датасетах (меньше 50 примеров) есть риск переобучения. Всегда фиксируй тестовую отложенную выборку перед подгонкой весов калибратора.

В сухом остатке: перестань гонять тяжелые LLM для рутинной проверки каждого агентного шага. Связка из недорогой decision-модели за доли цента и аккуратно вычисленного порога срабатывания дает такую же надежность, экономя бюджет и нервы команды поддержки.