Платформа для 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 тестування — отримайте консультацію інженера. Зв'яжіться з нами для обговорення вашого проекту.







