Настройка A/B-тестирования ML-моделей в продакшене

Модель ведёт себя иначе в продакшене, чем на стенде, и расхождение версий обходится дорого. Мы настраиваем контур A/B-тестирования ML-моделей под ключ: теневая и канареечная раскатка, понятные метрики, регламент отката. Сокращаем долю ручных проверок и время на выпуск новых версий в разы.
Часто задаваемые вопросы

Почему A/B-тестирование ML-моделей ломается в продакшене

Самый дорогой сбой в A/B-тестировании ML-моделей — не падение сервиса, а уверенный ответ не той моделью. В реестре лежит нужная версия, но признаки на входе собирает другой код, справочники обновлены отдельно, и расхождение версий модели между контурами всплывает через недели после запуска.

Вторая поломка — метрики. Тестирование моделей в продакшене сравнивает контроль и эксперимент на разных срезах: в одном контуре окно агрегации шире, в другом выбросы отфильтрованы иначе. Нестабильные метрики дают разброс больше самого эффекта модели, и эксперимент закрывают по шуму, а не по результату.

Третья — невоспроизводимость. Через месяц уже никто не восстановит, какие признаки, версии справочников и пороги стояли в момент замера. Даже когда версии артефактов логируются в MLflow, в реестре хранится модель, а не полный контекст её запуска — сравнить эксперименты постфактум нечем.

И четвёртая — откат модели. Если предыдущий артефакт не сохранён вместе с конфигурацией, возврат превращается в ручную сборку под давлением: качество падает прямо сейчас, а восстановление занимает часы. Цена задержки измеряется долей испорченных решений пользователя за это время.

Разбираем, как это закрывается: неизменяемые версии модели и признаков, единый слой расчёта метрик для обоих контуров и откат одной операцией.

Измеримые эффекты: задержка, откаты, доля ручных проверок

Управляемый контур меняет сам цикл: гипотеза проверяется на контрольной и тестовой группах до того, как версия уедет на всю аудиторию. Переключение доли трафика становится операцией в настройках эксперимента, а не отдельным релизом, поэтому время от гипотезы до выкатки модели сокращается с дней до часов — согласования заменяет регламент.

Доля ручных сверок падает по той же причине: метрики считаются на одном размеченном срезе для обеих групп, значимость эффекта проверяется автоматически, а аналитик смотрит только спорные сегменты. То, что раньше требовало ежедневных выгрузок и сведения таблиц вручную, превращается в отчёт, который обновляется сам.

Отдельно уходит класс отказов, который дороже всего: «тихая» деградация на узком сегменте и выкатка версии, обученной на устаревшем срезе. Пороговая метрика качества останавливает раскатку и возвращает предыдущую версию автоматически — время восстановления измеряется минутами, а простой из-за ошибки перестаёт быть событием на весь день.

MLflow в этой схеме отвечает за воспроизводимость: каждая версия модели привязана к параметрам, данным и метрике, поэтому результат эксперимента можно перепроверить, а откат — это переключение на зафиксированную предыдущую версию, а не сборка заново. Эффект от эксперимента становится измеримым до выкатки, а не по факту инцидента.

Варианты раскатки: теневой запуск, канареечный, поэтапный

Режим выпуска выбирают не по удобству, а по тому, какую долю трафика допустимо отдать новой модели и насколько дорого стоит ошибка на живом запросе. Теневой запуск отвечает на вопрос «сходится ли новая модель с текущей», канареечная раскатка — «не деградирует ли продукт на реальных пользователях», поэтапный выпуск — «какой из вариантов выигрывает по метрике».

Ограничения режимов упираются в маршрутизацию запросов и в способ сбора метрик. Пока метрика не привязана к версии модели и к когорте, любое сравнение подходов превращается в набор догадок.

Режим Когда подходит Ограничения
Теневой запуск Перенос логики на новую модель, проверка качества на реальном трафике без влияния на ответ Вариант не влияет на выдачу, поэтому продуктовые метрики по нему не собираются; нужен дублирующий контур и запас по ресурсам
Канареечная раскатка Модель уже обучена, но нужна страховка от деградации на живых запросах Требует автоматического отката и разметки метрик по когортам; на малой доле трафика статистика набирается медленно
Поэтапный выпуск Нужна проверка эффекта по сегментам и сравнение версий с накоплением данных Идёт дольше; без контроля однородности групп сравнение теряет смысл

На практике режимы комбинируют: теневой запуск как допуск к живому трафику, канареечная раскатка как страховка, поэтапный выпуск как способ собрать статистику по сегментам.

Этапы внедрения: от аудита до передачи в эксплуатацию

Порядок работ строим так, чтобы ошибку в схеме было видно до запуска на реальном трафике, а не через неделю разбора метрик. Каждый этап заканчивается проверяемым артефактом — тогда включение не превращается в «включили и смотрим».

  1. Аудит схемы эксперимента. Смотрим, какая метрика считается целевой, где и на каком объёме трафика она собирается, хватает ли наблюдений, чтобы различить версии. Проверяем, не пересекаются ли группы с другими запущенными экспериментами и нет ли смещения в том, как события попадают в хранилище.

  2. Разметка трафика. Определяем единицу рандомизации — пользователь, сессия или запрос — и способ закрепления: один и тот же признак даёт стабильную группу при повторных визитах. Фиксируем долю трафика на эксперимент и правила исключения, чтобы в сравнение не попали служебные запросы.

  3. Настройка контура. Разворачиваем сервис сравнения: он принимает запрос, адресует его нужной версии модели, а предсказание и признак версии пишет в лог. Теневой режим даёт прогнать новую версию на живом трафике, не влияя на ответ пользователю.

  4. Контрольные проверки. Прогоняем A/A-тест на однородность групп, сверяем распределение признаков между ветками, проверяем поведение при отказе одной из версий и при недоступности сервиса сравнения. Метрику на обеих ветках считаем по одному и тому же правилу — иначе разница будет в расчёте, а не в модели.

  5. Передача в эксплуатацию. Отдаём команде регламент запуска и остановки, описание отката, панель с метриками и настройки оповещений. Документируем разметку и конфигурацию контура, чтобы следующий эксперимент запускался без нас.

Артефакты передачи: схемы, политики доступа, регламенты

После сдачи контура у команды заказчика остаётся комплект артефактов, по которому новые A/B-тесты запускаются самостоятельно — без восстановления логики по переписке и памяти инженеров. Ниже перечень того, что передаём и зачем каждый документ нужен в работе.

  • Конфигурации контура. Файлы развёртывания и параметры сред: тестовая и продуктивная отличаются только значениями, поэтому новый вариант модели поднимается копированием конфигурации, а не сборкой заново.
  • Схемы потоков данных. Путь от запроса до записи метрики: где фиксируется вариант, как считается целевая метрика, где расходятся выборки. По схеме новый инженер разбирается в контуре за час.
  • Политики доступа. Разграничение ролей: кто меняет долю трафика на вариант, кто останавливает тест, кому доступны сырые логи. Эксперимент нельзя сломать случайной правкой.
  • Регламент эксперимента. Обязательные шаги: гипотеза, целевая метрика, минимальный объём выборки, критерий остановки и порядок отката на контрольную модель.
  • Шаблон отчёта. Единая форма фиксации результата: версии сравниваемых моделей, период, метрики по группам, вывод и решение — продолжать, дорабатывать или закрывать.
  • Инструкции и обучение. Разбор контура с командой заказчика и короткие памятки по типовым операциям: запуск теста, остановка, откат, чтение отчёта, добавление новой метрики.

Такой комплект снимает зависимость от подрядчика: изменения в контур вносятся по документированным правилам, а не по устным договорённостям. Обсудим задачу — вернёмся с планом работ и составом артефактов под ваш контур.

Кейс: убрали расхождение версий между контуром и продакшеном

Заказчик выкатывал несколько моделей в месяц, а контур обучения и продакшен жили отдельной жизнью. Артефакты переносили скриптами, признаки пересобирали руками, и расхождение версий между средами всплывало уже на живом трафике. Слепая выкатка без разбиения аудитории не давала заметить деградацию раньше, чем проседали метрики продукта.

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

Что изменили

Обе среды свели к единому реестру моделей на MLflow: версия, набор признаков и качество на контрольной выборке привязаны к одному артефакту, а перевод в продакшен идёт только через автоматическую проверку манифеста. Выкатку перевели на разбиение трафика 5/95 с автооткатом по ключевой метрике вместо слепой замены всей модели. Решения логируются вместе с версией, поэтому разбор сбоя начинается с готовой картины, а не с ручной сверки логов.

Через квартал ручные сверки сократились до одной плановой, расхождения версий между контуром и продакшеном не воспроизводились ни разу, а восстановление занимало минуты: откат срабатывал сам по порогу. Доля путей, покрытых автоматическими проверками перед выкаткой, выросла с трети до девяти десятых.

Что делать, если модель уже в продакшене, а разметки нет?

Отсутствие разметки под эксперимент блокирует не сравнение версий, а отсутствие управляемого переключателя между ними. Если модель уже в продакшене, сначала отделяем её от кода сервиса: версия модели и её параметры должны подставляться из конфигурации, а не быть вшитыми в вызов. Дальше на входе сервиса появляется тонкий слой маршрутизации, который по одному признаку запроса решает, какая версия его обработает.

Пока разметки нет, опираемся на косвенные сигналы: логи решений, отклик пользователей, доля ручных правок после ответа модели, распределение предсказаний по классам и сдвиг этого распределения во времени. Этого хватает, чтобы поймать деградацию и расхождение версий, а полноценный набор проверочных примеров досоздаётся позже — уже под собранный поток реальных запросов.

Вариант Когда подходит Ограничения
Теневой режим Нельзя рисковать качеством ответа пользователю Две версии считаются параллельно, нужен запас мощности
Канареечный запуск Нужно быстро поймать явный отказ на малой доле трафика Показывает сбои, но почти не различает качество
A/B по доле трафика Метрика измерима и накапливается за дни, а не месяцы Требует устойчивого распределения запросов по группам

Переход делаем постепенным: единицы процентов трафика на новую версию, выдержка на выбранной доле, затем шаг вверх. На каждом шаге сравниваем те же сигналы, что собирали до запуска, и держим готовым откат — возврат версии по конфигурации, без пересборки и остановки сервиса. Миграция без остановки получается именно из этого: маршрутизация живёт отдельно от модели, поэтому подмена версии занимает секунды и не прерывает обработку запросов.

Порог остановки задаём заранее и в измеримых величинах: просадка целевой метрики, рост доли ошибок, расхождение распределений выше допустимого. Если порог пройден — трафик возвращается на прежнюю версию автоматически, а не по звонку дежурного.

Частые технические сомнения заказчиков и инженеров

Сомнения на этом этапе обычно технические: хватает ли данных, не искажает ли картину сезонность, что делать с параллельными правками правил и модели. Ниже — короткие ответы о том, как мы закрываем эти места в разметке эксперимента.

Хватит ли трафика для достоверных метрик?

Считаем не общий трафик, а число целевых событий в каждой группе. Минимальный размер выборки определяем до старта — от ожидаемого эффекта и разброса метрики. Если событий меньше, сужаем метрику или удлиняем окно наблюдения, а не подгоняем тест под красивую цифру.

Не исказит ли картину сезонность?

Разбиение идёт по стабильному идентификатору пользователя, поэтому обе группы попадают в одни и те же дни, акции и пиковые часы. Сравнение идёт параллельно в одном окне, а результат перепроверяем на соседних периодах — эффект, который держится только в одной неделе, в выводы не идёт.

Что делать, если одновременно меняются правила и модель?

Один эксперимент — одно изменение. Если менять оба сразу, эффект не разделить: непонятно, что дало прирост, а что его съело. Разносим правки на последовательные этапы либо планируем схему с проверкой совместного влияния, чтобы оценить вклад каждого фактора.

Кому доступны результаты и что с безопасностью данных?

Отчёты смотрим по ролям: продуктовой команде — срезы по сегментам и метрикам, инженерам — события в хранилище для разбора. Персональные данные в отчётность не попадают, идентификаторы псевдонимизированы, выгрузка ограничена политикой доступа и логируется.

Обсудим задачу: как мы начнём работу над контуром

Чтобы контур A/B-тестирования моделей не превратился в череду переделок, начинаем с разбора того, что уже работает. От вас — доступ к репозиторию инфраструктуры, к текущей схеме вывода моделей в продакшен и к выгрузке по целевой метрике за прошлые периоды: без этого не посчитать размер групп и длительность окна наблюдения.

Порядок первых шагов:

  • описываем текущий путь модели: где хранятся версии, кто переключает трафик между ними, что уже логируется;
  • фиксируем целевую метрику и метрики-ограничители, которые не должны просесть ни при каком исходе теста;
  • выбираем единицу рандомизации — клиент, сессия или запрос — и способ закрепить её за группой, чтобы пользователь не перескакивал между вариантами;
  • согласуем схему расчёта: доли трафика, минимальный значимый эффект, критерий досрочной остановки;
  • проектируем откат: одной командой весь трафик возвращается на контрольную модель за считанные минуты;
  • добавляем наблюдение за дрейфом входных данных и за расхождением распределений между группами;
  • размечаем объём работ: где нужны изменения в коде вывода, а где достаточно конфигурации.

По итогам разбора вернёмся с оценкой и планом: состав этапов, сроки по каждому, зона ответственности нашей команды и вашей. Следующий шаг — опишите задачу, и мы назначим разбор.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    816
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142