Как вы отслеживаете data drift для распределения запросов к RAG?
Краткий тезис
Data drift (дрейф данных) в контексте RAG — это изменение статистических свойств входящих запросов пользователей относительно тех, на которых система обучалась или тестировалась. Отслеживание дрифта критически важно, потому что смещение распределения запросов может привести к падению качества retrieval (поиска) и, как следствие, к ухудшению ответов LLM. Основные методы включают сравнение распределений эмбеддингов запросов (KL-дивергенция, расстояние Вассерштейна), мониторинг тематических сдвигов через topic modeling, а также отслеживание простых статистик (длина запроса, частота ключевых слов). При обнаружении значимого дрифта (p-value < 0.01 через bootstrap) необходимо предпринимать действия: переобучать модель эмбеддингов, перекалибровать пороги релевантности, обновлять few-shot примеры.
1. Термин: Data drift в RAG
Data drift — это изменение распределения входных данных модели по сравнению с распределением на этапе обучения или валидации. В RAG-системе входными данными являются запросы пользователей (queries). Дрифт может проявляться в:
- Covariate shift — изменение распределения самих запросов (например, пользователи начали задавать вопросы на другую тему).
- Concept drift — изменение смысла одних и тех же запросов (например, запрос «погода» раньше означал текущую температуру, а теперь — прогноз на неделю).
- Prior probability shift — изменение соотношения классов запросов (например, резко выросла доля вопросов по новому продукту).
Почему это важно для RAG:
- Модель эмбеддингов обучена на определённом распределении текстов. Если запросы смещаются, эмбеддинги могут хуже отражать семантику, и retrieval будет находить нерелевантные чанки.
- Пороги релевантности (thresholds), настроенные на старом распределении, перестают работать (например, раньше cosine similarity > 0.7 давал хорошие результаты, а теперь — шум).
- Few-shot примеры в промпте могут стать нерепрезентативными, что ухудшит качество генерации.
2. Метрики для обнаружения дрифта
2.1 Статистические тесты на распределениях эмбеддингов
Эмбеддинги запросов — это плотные векторы (например, размерности 768 от all-MiniLM-L6-v2). Сравниваем распределение эмбеддингов за текущее окно (например, последние 24 часа) с эталонным окном (например, последние 7 дней или данные валидации).
KL-дивергенция (Kullback–Leibler divergence) — мера того, насколько одно распределение отличается от другого. Для эмбеддингов её можно оценить через дискретизацию (разбить пространство на ячейки) или через оценку плотности ядра (KDE). Недостаток: KL несимметрична и чувствительна к выбору числа ячеек.
Расстояние Вассерштейна (Wasserstein distance, Earth Mover's Distance) — более устойчивая метрика, учитывающая геометрию пространства. Для эмбеддингов можно использовать Sliced Wasserstein Distance (SWD), которая аппроксимирует расстояние через случайные проекции.
Maximum Mean Discrepancy (MMD) — непараметрический тест, основанный на воспроизводящем ядре. Часто используется в GAN для оценки сходимости.
Практический подход
- Берём N эмбеддингов из эталонного окна и M из текущего.
- Вычисляем попарные расстояния (например, евклидовы) между всеми точками.
- Применяем bootstrap для оценки p-value: многократно перемешиваем метки окон и пересчитываем метрику. Если наблюдаемое значение метрики попадает в хвост распределения (p-value < 0.01), объявляем дрифт.
Пример кода на Python для bootstrap-теста с использованием Wasserstein distance:
import numpy as np
from scipy.stats import wasserstein_distance
from sklearn.utils import resample
def detect_drift(ref_embeddings, cur_embeddings, n_bootstrap=1000, alpha=0.01):
# ref_embeddings, cur_embeddings: списки векторов
# Используем среднее попарное расстояние Вассерштейна по каждому измерению
def wasserstein_mean(emb1, emb2):
d = 0
for i in range(emb1.shape[1]):
d += wasserstein_distance(emb1[:, i], emb2[:, i])
return d / emb1.shape[1]
obs_stat = wasserstein_mean(ref_embeddings, cur_embeddings)
combined = np.vstack([ref_embeddings, cur_embeddings])
n_ref = len(ref_embeddings)
bootstrap_stats = []
for _ in range(n_bootstrap):
idx = resample(range(len(combined)), n_samples=len(combined))
boot_ref = combined[idx[:n_ref]]
boot_cur = combined[idx[n_ref:]]
bootstrap_stats.append(wasserstein_mean(boot_ref, boot_cur))
p_value = np.mean(np.array(bootstrap_stats) >= obs_stat)
return p_value < alpha, p_value
2.2 Тематическое моделирование (Topic Modeling)
Дрифт может быть вызван появлением новых тем или изменением частоты старых. Используем LDA (Latent Dirichlet Allocation) или BERTopic для выделения тем из запросов.
- Обучаем модель тем на эталонном окне.
- Для каждого нового запроса предсказываем тему.
- Сравниваем распределение тем в текущем окне с эталонным с помощью хи-квадрат теста или JS-дивергенции (Jensen–Shannon divergence).
Пример метрик
- Доля запросов, отнесённых к новой теме (если модель не видела её раньше) — триггер дрифта.
- Изменение топ-3 тем по частоте более чем на 20% — сигнал.
2.3 Простые статистики запросов
Не все дрифты требуют сложных эмбеддингов. Иногда достаточно отслеживать:
- Средняя длина запроса (в символах или токенах). Резкое увеличение может означать, что пользователи стали задавать более развёрнутые вопросы.
- Частота стоп-слов или специфических паттернов (например, запросы, содержащие «ID» или «номер заказа»).
- Доля запросов с отрицанием («не», «без») — может указывать на изменение сентимента.
- Количество уникальных запросов в единицу времени — всплеск может быть аномалией.
Эти метрики легко считать в реальном времени и использовать для быстрых алертов.
3. Пороги и алерты
Порог значимости p-value < 0.01 (1% уровень) — стандартный для bootstrap-тестов. Можно использовать правило трёх сигм для метрик, распределённых нормально.
Типы алертов
- Жёлтый (warning): p-value < 0.05 или изменение метрики на 1-2 стандартных отклонения. Требует внимания, но не немедленных действий.
- Красный (critical): p-value < 0.001 или изменение более 3 сигм. Запускает автоматический пересмотр компонентов RAG.
Инструменты мониторинга
- Evidently AI — open-source библиотека для мониторинга ML-моделей, поддерживает дрифт эмбеддингов, текстовых данных.
- WhyLabs — платформа для observability AI, автоматически детектит дрифт.
- MLflow — можно логировать распределения эмбеддингов и настраивать алерты через Model Registry.
- Prometheus + Grafana — для кастомных метрик (длина запроса, частота тем) в production.
4. Действия при обнаружении дрифта
4.1 Переобучение модели эмбеддингов (retrieval)
Если дрифт связан с изменением семантики запросов (новые термины, жаргон), может потребоваться fine-tuning модели эмбеддингов на новых данных. Альтернатива — domain adaptation через contrastive learning на парах (запрос, релевантный документ) из текущего окна.
4.2 Перекалибровка порогов релевантности
Порог cosine similarity, при котором чанк считается релевантным, может устареть. Нужно пересчитать его на свежих данных: взять выборку запросов, вручную разметить релевантные документы и подобрать порог, максимизирующий F1-score.
4.3 Обновление few-shot примеров
Если в промпте используются статические примеры (few-shot), они могут перестать отражать текущие запросы. Нужно заменить их на примеры из последнего окна, где retrieval сработал хорошо (например, запросы с высоким faithfulness).
4.4 Аугментация данных для re-ranker
Если используется re-ranker (вторая стадия ранжирования), его можно дообучить на новых данных, добавив негативные примеры из текущего дрифта.
5. Мониторинг в production: архитектура
Рекомендуемая архитектура для отслеживания дрифта:
- Сборщик логов (например, Kafka) — все запросы пользователей пишутся в топик.
- Stream processor (Spark Streaming, Flink) — вычисляет эмбеддинги запросов в реальном времени (через предобученную модель) и агрегирует статистики за окно.
- Хранилище эталонных распределений — S3 или Redis, где хранятся эмбеддинги за эталонный период.
- Детектор дрифта — периодически (каждые 10 минут) запускает bootstrap-тест и обновляет метрики в Prometheus.
- Alert manager — при превышении порога отправляет уведомление в Slack/PagerDuty и запускает пайплайн переобучения (через Airflow).
6. Связь с A/B тестированием
Дрифт запросов может исказить результаты A/B тестов. Если во время эксперимента распределение запросов изменилось, метрики (например, click-through rate) могут стать несравнимыми. Поэтому перед запуском A/B теста нужно убедиться, что дрифта нет, или стратифицировать выборку по темам запросов.
Пет-проект для закрепления
Задача Разработать систему мониторинга дрифта запросов для RAG-бота, который отвечает на вопросы по документации продукта.
Инструменты Python, sentence-transformers (для эмбеддингов), scipy (Wasserstein distance), evidently (для визуализации), streamlit (дашборд).
Шаги:
- Сгенерировать синтетический датасет запросов: 10 000 запросов по старой версии документации (эталон), затем 2 000 запросов по новой версии (дрифт).
- Вычислить эмбеддинги для всех запросов (модель
all-MiniLM-L6-v2). - Реализовать bootstrap-тест на основе Wasserstein distance (как в коде выше).
- Добавить мониторинг тематического дрифта через BERTopic: обучить на эталоне, предсказать темы для новых запросов, сравнить распределение через JS-дивергенцию.
- Построить дашборд в Streamlit: график метрики дрифта во времени, p-value, распределение тем, alert-индикатор.
- При обнаружении дрифта (p-value < 0.01) выводить рекомендацию: «Переобучить retrieval» или «Обновить пороги».
Ожидаемый результат Работающий прототип, который на синтетических данных показывает, как меняется метрика дрифта при смене тематики запросов, и выдает алерты.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 511 | Как вы мониторите RAG-систему в production? |
| 512 | Какие метрики качества RAG вы используете? |
| 513 | Как вы обновляете эмбеддинги документов? |
| 514 | Как вы настраиваете пороги релевантности в RAG? |
| 516 | Как вы проводите A/B тестирование изменений в RAG? |
| 520 | Как вы обрабатываете запросы с новыми терминами? |
Навигация
- Предыдущий: 514
- Следующий: 516
- Индекс: 00. Индекс разборов