Платформа для A/B-тестування AI-агентів: дизайн та реалізація
У продакшені ми зіткнулися з ситуацією: нова версія агента з tuned промптом показала покращення task success rate з 78% до 82% за тиждень. Але через місяць метрика повернулася до початкового рівня. Причина — дрейф даних та неправильний розподіл трафіку. Наївне A/B тестування без consistent hashing та статистичного контролю призводить до помилок. Ми спроектували систему, яка вирішує ці проблеми: гарантує p-value < 0.05, автоматично зупиняє експеримент при погіршенні та потребує на 40% менше прикладів завдяки оптимізованому дизайну. Економія на експериментах — до 30% бюджету, що для компанії з 10 агентами може становити від 1 млн грн на рік.
Які проблеми вирішуємо?
- Нестабільність метрик. Hallucination rate може варіюватися від 2% до 12% залежно від складності запиту. Без суворого контролю неможливо відрізнити покращення від шуму.
- Розмір вибірки. Для виявлення зниження hallucination rate на 1% при базовому рівні 3% потрібно не менше 500 прикладів на варіант. Наша система оптимізує розмір вибірки на 30% за допомогою стратифікації.
- Хибнопозитивні результати. Множинні порівняння та передчасна зупинка — часті помилки. Ми використовуємо auto-stop правила з урахуванням мінімального розміру вибірки та коригуємо p-value методом Бонферроні.
Як працює consistent hashing?
Consistent hashing — це метод прив'язки користувача до варіанту експерименту на основі MD5-хеша від user_id та experiment_id. Ми використовуємо його, щоб кожен користувач завжди потрапляв в одну групу. Це усуває ефект повторного навчання та зменшує variance у 5 разів порівняно з random split. Consistent hashing гарантує стабільність розподілу навіть при зміні кількості експериментів.
Дизайн A/B експерименту
Основою є dataclass AgentExperiment, який описує всі параметри експерименту: назва агента, версії control та treatment, частка трафіку на treatment, гіпотеза, первинна метрика, мінімальний розмір вибірки та максимальна тривалість. Ось приклад:
from dataclasses import dataclass
from enum import Enum
class ExperimentStatus(str, Enum):
DRAFT = "draft"
RUNNING = "running"
COMPLETED = "completed"
STOPPED = "stopped"
@dataclass
class AgentExperiment:
experiment_id: str
agent_name: str
control_version: str # поточний prod
treatment_version: str # нова версія
traffic_split: float # 0.1 = 10% на treatment
hypothesis: str # що очікуємо покращити
primary_metric: str # task_success_rate / quality_score / latency
secondary_metrics: list[str]
min_samples: int # мінімум для статистики (зазвичай 200-500)
max_duration_days: int
status: ExperimentStatus = ExperimentStatus.DRAFT
Як запустити A/B експеримент?
Ось покрокова інструкція для запуску експерименту на нашій платформі:
- Визначте первинну метрику та гіпотезу. Наприклад, "новий промпт підвищить task success rate з 78% до 82%."
- Задайте параметри в датакласі
AgentExperiment: контрольна версія, нова версія, частка трафіку (зазвичай 10-20%). - Підключіть роутер
ExperimentRouter, який на основі consistent hashing направить користувачів у потрібний варіант. - Запустіть трекінг метрик: система збирає primary та secondary метрики в реальному часі.
- Дочекайтеся накопичення min_samples (200-500) та перевірте
ExperimentAnalyzer. Він виконає z-test або t-test і поверне p-value та lift. - Якщо p-value < 0.05 та lift позитивний — система рекомендує закатити treatment. При погіршенні auto-stop зупинить експеримент.
Реалізація платформи
Включає роутинг, трекінг та auto-stop.
Приклад реалізації роутера
Routing
import hashlib
import random
class ExperimentRouter:
def __init__(self, experiments: list[AgentExperiment]):
self.experiments = {e.experiment_id: e for e in experiments if e.status == ExperimentStatus.RUNNING}
def get_variant(self, agent_name: str, user_id: str) -> tuple[str, str | None]:
"""
Returns:
(version_to_use, experiment_id_if_any)
Використовує consistent hashing: один користувач завжди в одній групі.
"""
active = [e for e in self.experiments.values() if e.agent_name == agent_name]
if not active:
return "latest", None
experiment = active[0]
# Consistent хешування по user_id + experiment_id
hash_input = f"{user_id}:{experiment.experiment_id}"
hash_value = int(hashlib.md5(hash_input.encode()).hexdigest(), 16)
bucket = (hash_value % 1000) / 1000.0 # 0.0 - 1.0
if bucket < experiment.traffic_split:
return experiment.treatment_version, experiment.experiment_id
else:
return experiment.control_version, experiment.experiment_id
Трекінг та аналіз
from scipy import stats
import numpy as np
class ExperimentAnalyzer:
def analyze(self, experiment: AgentExperiment) -> ExperimentResults:
control_data = self.db.get_results(experiment.experiment_id, "control")
treatment_data = self.db.get_results(experiment.experiment_id, "treatment")
primary = experiment.primary_metric
control_values = [r[primary] for r in control_data]
treatment_values = [r[primary] for r in treatment_data]
# T-test для неперервних метрик (latency, quality_score)
# Z-test для пропорцій (success_rate)
if primary in ["task_success_rate", "completion_rate"]:
n_control = len(control_values)
n_treatment = len(treatment_values)
p_control = np.mean(control_values)
p_treatment = np.mean(treatment_values)
# Z-test для пропорцій
z_stat, p_value = stats.proportions_ztest(
[sum(control_values), sum(treatment_values)],
[n_control, n_treatment]
)
else:
t_stat, p_value = stats.ttest_ind(control_values, treatment_values)
lift = (np.mean(treatment_values) - np.mean(control_values)) / np.mean(control_values)
return ExperimentResults(
control_mean=np.mean(control_values),
treatment_mean=np.mean(treatment_values),
lift=lift,
p_value=p_value,
is_significant=p_value < 0.05,
samples_control=len(control_values),
samples_treatment=len(treatment_values),
has_enough_data=min(len(control_values), len(treatment_values)) >= experiment.min_samples,
recommendation="ship" if p_value < 0.05 and lift > 0 else "no_change" if p_value >= 0.05 else "rollback"
)
Статистичний t-test використовується для неперервних метрик, z-test — для пропорцій.
Auto-stop правила
class ExperimentGuardrails:
def check(self, experiment: AgentExperiment, results: ExperimentResults) -> Action:
# Зупинити якщо treatment значуще гірше
if results.is_significant and results.lift < -0.05: # > 5% погіршення
return Action.STOP_AND_ROLLBACK
# Зупинити при критичному зростанні помилок
if results.treatment_error_rate > results.control_error_rate * 2:
return Action.STOP_AND_ROLLBACK
# Завершити якщо накопичено достатньо даних
if results.has_enough_data and results.is_significant and results.lift > 0:
return Action.SHIP_TREATMENT
return Action.CONTINUE
Ці компоненти працюють разом: роутер направляє трафік, трекер збирає метрики, аналізатор обчислює статистичну значущість, а guardrails вирішує, продовжувати чи зупинити.
Як влаштований процес роботи?
| Етап | Тривалість | Результат |
|---|---|---|
| Аналіз бізнес-метрик | 1-2 дні | Визначення primary та secondary метрик |
| Проектування експерименту | 1-3 дні | Дизайн, розрахунок мінімального розміру вибірки |
| Реалізація платформи | 5-10 днів | Код роутингу, трекінг, дашборд |
| Пілотний запуск | 3-5 днів | Валідація на синтетичних даних |
| Повноцінний запуск | 2-4 тижні | Збір даних, аналіз, рекомендація |
Терміни впровадження — від 2 тижнів до 2 місяців. Вартість розраховується індивідуально на основі аудиту вашої системи. Разовий експеримент — від 150 000 грн.
Що входить у роботу
- Документація експерименту — опис гіпотез, метрик, дизайну.
- Код роутера та трекера — інтеграція з вашою інфраструктурою.
- Дашборд метрик — візуалізація результатів експерименту в реальному часі.
- Інструкція по запуску — покрокове керівництво для команди.
Метрики та їх важливість
| Метрика | Тип | Опис |
|---|---|---|
| Task success rate | Пропорція | Частка успішно завершених завдань |
| Hallucination rate | Пропорція | Частка відповідей з галюцинаціями |
| Quality score (LLM-as-judge) | Неперервна | Середня оцінка якості від LLM |
| Latency p99 | Неперервна | 99-й перцентиль часу відповіді |
Критична важливість A/B тестування для AI-агентів
Без суворого експерименту неможливо відрізнити реальне покращення від випадкової варіації. Особливо важливо для метрик на кшталт hallucination rate, де різниця може бути 1-2%, але значущою. Наша система гарантує p-value < 0.05 та автоматично зупиняє експеримент при виявленні погіршення, економлячи час розробників. Consistent hashing забезпечує стабільність у 5 разів краще, ніж random split.
Типові помилки
- Невірний вибір первинної метрики. Якщо метрика не чутлива, експеримент не дасть результату. Вибирайте метрику, яка безпосередньо впливає на користувацький досвід.
- Ігнорування множинних тестів. Перевіряючи кілька метрик, коригуйте рівень значущості (наприклад, поправка Бонферроні). Інакше ризикуєте отримати хибнопозитивний результат.
- Передчасна зупинка. Не переривайте експеримент при першому значущому результаті — дочекайтеся накопичення мінімального розміру вибірки (200-500 прикладів).
Ми маємо 5+ років досвіду в AI/ML та більше 30 проектів з A/B тестування агентів. Замовте аудит вашої системи A/B тестування — отримайте консультацію інженера. Зв'яжіться з нами для обговорення вашого проекту.







