Как вы делаете A/B тестирование двух моделей в production?

Краткий тезис

A/B тестирование в production ML позволяет объективно сравнить две модели (обычно текущую стабильную и новую кандидата) на реальном трафике. Ключевые принципы: стабильная рандомизация трафика (один пользователь всегда видит одну и ту же модель), изоляция инфраструктуры (отдельные поды) и сбор как количественных (latency, cost, токены), так и качественных (LLM-as-a-judge, пользовательская обратная связь) метрик. Решение принимается на основе статистической значимости различий, после чего трафик полностью переводится на победителя с возможностью быстрого роллбэка.


1. Термин: A/B тестирование в ML

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

2. Дизайн эксперимента: стабильная рандомизация

Рандомизация должна быть стабильной: один и тот же пользователь всегда попадает в одну и ту же группу (control или treatment) на протяжении всего эксперимента. Иначе — смещение оценок из-за переключения между моделями.

Практическая реализация — хэширование user_id по модулю 100 и направление в группу:

  • 0–49 → контроль (старая модель)
  • 50–99 → тест (новая модель)
import hashlib

def get_experiment_group(user_id: str) -> str:
    hash_value = int(hashlib.sha256(user_id.encode()).hexdigest(), 16) % 100
    return "control" if hash_value < 50 else "treatment"

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

3. Инфраструктура: изоляция и роутинг

Каждая модель разворачивается в собственном поде (Kubernetes) с отдельным endpoint. Роутинг трафика реализуется на уровне API-шлюза (например, Kong, Envoy) или через Service Mesh (Istio). Feature-флаги (например, LaunchDarkly, OpenFeature) позволяют динамически менять распределение без передеплоя.

КомпонентРоль
Ingress/GatewayПринимает запрос, вычисляет группу по user_id, направляет к нужному service
Service A (control)Старая модель (репликация 1+ для надёжности)
Service B (treatment)Новая модель (такая же репликация)
Feature Flag SDKЦентрализованное управление экспериментом (например, % трафика)
Monitoring stackPrometheus + Grafana для сбора метрик

4. Метрики: количественные и качественные

4.1 Количественные (легко измерить)

  • Latency (p50, p95, p99) — время ответа модели
  • Cost — затраты на инференс (GPU/CPU, токены)
  • Token usage — количество входных/выходных токенов (особенно для LLM)
  • Throughput — запросов в секунду
  • Error rate — 5xx ошибки

4.2 Качественные (требуют оценки)

  • LLM-as-a-judge — использование сильной LLM (GPT-4, Claude) для оценки ответов по критериям (полезность, безопасность, точность). Дёшево, но может быть bias.
  • Human evaluation — краудсорсинг или внутренние эксперты (дорого, медленно, но надёжно).
  • User feedback — лайки/дизлайки, thumbs up/down, доля «решения задачи» (conversion rate).
МетрикаТипПлюсыМинусы
LatencyКоличественнаяОбъективно, непрерывноНе отражает качество
LLM-as-a-judgeКачественнаяМасштабируетсяДорого, bias
Human evaluationКачественнаяЗолотой стандартМедленно, дорого
User conversionБизнесоваяРеальный эффектШум, требуется много данных

5. Длительность эксперимента

Минимальная длительность определяется power analysis (расчёт необходимого размера выборки). Для LLM-приложений типичный период — 1–2 недели, чтобы:

  • собрать достаточное количество событий для значимости;
  • учесть недельные циклы (понедельник vs суббота);
  • снизить эффект novelty effect (временное повышение интереса к новинке).

Условие остановки: достижение статистической значимости (p < 0.05) по ключевым метрикам при power >= 0.8.

6. Статистическая значимость и принятие решений

Для сравнения двух групп применяют t-тест Стьюдента (для нормально распределённых метрик) или Mann-Whitney U (для ненормальных). Для долей (conversion rate) — Z-тест для пропорций.

from scipy.stats import ttest_ind
import numpy as np

control_latencies = np.array([...])
treatment_latencies = np.array([...])
stat, p_value = ttest_ind(control_latencies, treatment_latencies)
print(f"p-value: {p_value:.4f}")
if p_value < 0.05:
    print("Различие статистически значимо")

Множественные сравнения: если метрик много, применяют поправку Bonferroni или Benjamini-Hochberg.

Решение:

  • Если treatment значимо лучше по всем ключевым метрикам → победитель.
  • Если значимо хуже хотя бы по одной (например, latency) → отказ.
  • Если нет значимых различий → принимается бизнес-решение (например, оставляют старую или выпускают новую, если она дешевле).

7. Роллбэк и rollout победителя

После принятия решения трафик переключается постепенно (canary rollout) или полностью (big bang). В любом случае должна быть возможность быстрого отката в течение минут:

  • Сохранить оба deployment'а;
  • Переключить feature flag на 100% одной группы;
  • Мониторить метрики первые часы (возможны отложенные проблемы).

8. Подводные камни и их решения

ПроблемаОписаниеРешение
Novelty effectНовая модель кажется лучше из-за новизныУвеличить длительность, или сделать holdout после эксперимента
Network effectsВзаимодействие пользователей (в соцсетях)Проводить эксперимент в изолированном сегменте (например, по региону)
Data driftИзменение распределения запросов во времениСкользящее окно при анализе, мониторинг drift
Неравномерное разделениеБаг в хэшированииЮнит-тесты на функцию рандомизации, логирование группы в ответе
Инфраструктурные сбоиПадение пода новой моделиАвтоматический failover на control, алерт

9. Пет-проект для закрепления

Задача: сравнить две LLM (например, Mistral-7B и Llama-2-7B) как чат-бота для поддержки на синтетическом трафике.

Инструменты: Kubernetes (minikube), Python (FastAPI для моделей), Argo Rollouts (canary), Prometheus + Grafana (метрики), MLflow (логирование).

Шаги:

  1. Развернуть оба инференс-сервиса в отдельных подах с метками model: control и model: treatment.
  2. Написать API-шлюз с хэшированием user_id (использовать заголовок X-User-Id).
  3. Настроить сбор метрик: latency (p50,p95), error rate, количество токенов.
  4. Подключить LLM-as-a-judge (GPT-4) для оценки качества ответов — отправлять 10% ответов на оценку, сохранять скоры.
  5. Запустить эксперимент на 7 дней с 50/50 трафика.
  6. Построить дашборд в Grafana: разница средних latency, p-value, распределение скоров.
  7. По окончании — выполнить t-тест. Если новая модель значимо лучше по качеству и не хуже по latency — переключить 100% трафика через feature flag.

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

10. Связь с другими вопросами

ВопросТема
5Оценка качества генерации (offline и LLM-as-a-judge)
7Уменьшение latency RAG-системы
74Оптимизация стоимости инференса
77Мониторинг модели в production
78CI/CD для ML-моделей
90Feature flags и управление экспериментами

Навигация