中文翻译暂不可用,显示俄语原文。
Настроить retrieval quality dashboard
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить retrieval quality dashboard
1. Цель задачи
Создать дашборд мониторинга качества retrieval в RAG-системе, который в реальном времени отображает hit rate, MRR и NDCG, сгруппированные по типам запросов. Дашборд должен позволять команде обнаруживать деградацию retrieval до того, как поступят жалобы пользователей, и предоставлять достаточно контекста для быстрой диагностики причины.
Ключевой результат Рабочий дашборд в Grafana (или аналоге), который автоматически обновляется при поступлении новых логов retrieval, содержит минимум три панели (hit rate, MRR, NDCG) с разбивкой по типам запросов, и настроенные алерты при падении метрик ниже заданных порогов.
2. Исходные данные
Перед началом необходимо иметь:
| Что нужно | Откуда взять |
|---|---|
| RAG-система (рабочая или тестовая) | Собранный пет-проект или существующая система (например, на базе LangChain + Qdrant) |
| Логи retrieval с полями: query, retrieved_docs, relevant_docs (ground truth), timestamp, query_type | Генерировать синтетически с помощью Python-скрипта, либо из production-логов |
| Метрики качества (hit rate, MRR, NDCG) расчётная функция | Базовые реализации из RAGAS или написать самостоятельно |
| Инструмент мониторинга и визуализации | Prometheus + Grafana; если нет доступа — локальный Python + Plotly/Dash |
| Источник метрик для алертов | Prometheus Alertmanager или встроенные алерты Grafana |
Если нет реального инструмента — симулируем:
- Поднять инстанс Prometheus и Grafana через Docker Compose (файл прилагается в репозитории упражнения).
- Написать Python-сервис, который читает логи retrieval из CSV/JSON и экспортирует метрики в формате Prometheus (через prometheus_client library).
- Настроить Grafana datasource на этот Prometheus.
- Если нет ground truth (релевантные документы), сгенерировать синтетические данные: для каждого запроса создать случайный набор релевантных документов (2-5 штук) и симулировать их ранжирование retrieval-системой.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| База метрик | Prometheus (или VictoriaMetrics) | Хранение временных рядов hit rate, MRR, NDCG |
| Визуализация | Grafana (или Plotly Dash) | Построение дашборда с панелями |
| Генерация метрик | Python + prometheus_client | Экспорт метрик из логов retrieval в Prometheus |
| Библиотека метрик retrieval | RAGAS / numpy / scipy | Расчёт hit rate, MRR, NDCG |
| Хранилище логов | Loki / ClickHouse / CSV-файлы | Исходные данные retrieval (query, retrieved docs, ground truth) |
| Разбивка по типам запросов | Python-функция классификации (regex, LLM или label) | Определение query_type для каждой метрики |
| Алерты | Alertmanager / Grafana Alerting | Уведомления при падении качества |
4. Этапы выполнения
Этап 1: Подготовка данных и расчёт метрик (2-3 часа)
Действия
-
Определить типы запросов (query_type). Создайте словарь с примерами (не менее 3 типов, например: «фактографический», «инструкционный», «рекомендательный»).
-
Сгенерировать синтетические логи retrieval (если нет production-логов). Каждая запись включает:
- query (строка)
- query_type (один из типов)
retrieved_docs(список имён документов в порядке ранжирования)relevant_docs(список ground truth релевантных документов)- timestamp (datetime) Пример структуры DataFrame:
import pandas as pd import numpy as np from datetime import datetime, timedelta np.random.seed(42) n_queries = 1000 types = ['factual', 'instructional', 'recommendational'] data = { 'query': [f'q{i}' for i in range(n_queries)], 'query_type': np.random.choice(types, n_queries), 'retrieved_docs': [['doc'+str(j) for j in np.random.choice(range(20), 10, replace=False)] for _ in range(n_queries)], 'relevant_docs': [['doc'+str(j) for j in np.random.choice(range(20), 3, replace=False)] for _ in range(n_queries)], 'timestamp': [datetime.now() - timedelta(minutes=np.random.randint(0, 1440)) for _ in range(n_queries)] } df = pd.DataFrame(data) df.to_csv('retrieval_logs.csv', index=False) -
Реализовать функцию расчёта метрик (hit rate, MRR, NDCG@k). Для hit rate используйте 1 если хотя бы один релевантный документ попал в top-k, иначе 0. Для MRR —
1/rank первого релевантного документа. Для NDCG используйте реализацию из RAGAS или напишите самостоятельно:from sklearn.metrics import ndcg_score import numpy as np def hit_rate(retrieved, relevant, k=10): return 1 if any(doc in retrieved[:k] for doc in relevant) else 0 def mrr(retrieved, relevant): for i, doc in enumerate(retrieved, start=1): if doc in relevant: return 1/i return 0.0 def ndcg(retrieved, relevant, k=10): # relevance binary: 1 если doc in relevant else 0 y_true = [1 if doc in relevant else 0 for doc in retrieved[:k]] y_score = [1/(i+1) for i in range(len(y_true))] # ideal ranking: descending if sum(y_true) == 0: return 0.0 ideal = sorted(y_true, reverse=True) dcg = sum((2**rel - 1) / np.log2(i+2) for i, rel in enumerate(y_true)) idcg = sum((2**rel - 1) / np.log2(i+2) for i, rel in enumerate(ideal)) return dcg / idcg if idcg > 0 else 0.0 -
Применить функции к DataFrame и создать агрегированные временные ряды по query_type с окном (например, 1 час). Полученные значения сохранить в CSV или напрямую экспортировать в Prometheus (см. Этап 2).
Ожидаемый результат этапа
Файл retrieval_logs.csv с синтетическими данными и функция расчёта метрик, готовая к интеграции.
Этап 2: Экспорт метрик в Prometheus (2-3 часа)
Действия
-
Написать Python-сервис
metrics_exporter.py, который:- Загружает DataFrame с логами (или подписывается на поток логов).
- Раз в N секунд (например, 60) пересчитывает агрегированные метрики за последний час для каждого query_type.
- Экспортирует метрики в формате Prometheus с помощью библиотеки prometheus_client.
Пример кода:
from prometheus_client import start_http_server, Gauge import pandas as pd import time # Определяем метрики hit_rate_gauge = Gauge('retrieval_hit_rate', 'Hit Rate', ['query_type']) mrr_gauge = Gauge('retrieval_mrr', 'Mean Reciprocal Rank', ['query_type']) ndcg_gauge = Gauge('retrieval_ndcg', 'NDCG@10', ['query_type']) def update_metrics(): df = pd.read_csv('retrieval_logs.csv') df['timestamp'] = pd.to_datetime(df['timestamp']) now = pd.Timestamp.now() last_hour = now - pd.Timedelta(hours=1) recent = df[df['timestamp'] >= last_hour] for qtype in recent['query_type'].unique(): subset = recent[recent['query_type'] == qtype] # расчёт средних hr = np.mean(subset['retrieved_docs'].apply( lambda docs: hit_rate(eval(docs), eval(subset['relevant_docs'].iloc[0])) # упрощённо )) # ... аналогично для MRR и NDCG hit_rate_gauge.labels(query_type=qtype).set(hr) mrr_gauge.labels(query_type=qtype).set(mr) ndcg_gauge.labels(query_type=qtype).set(nd) if __name__ == '__main__': start_http_server(8000) while True: update_metrics() time.sleep(60) -
Запустить сервис на порту 8000. Проверить, что метрики доступны по http://localhost:8000/metrics.
-
Настроить Prometheus (если используется Docker Compose):
- В prometheus.yml добавить job:
scrape_configs: - job_name: 'retrieval_metrics' static_configs: - targets: ['localhost:8000'] - Перезапустить Prometheus.
- В prometheus.yml добавить job:
-
Верифицировать появление метрик в Prometheus через его веб-интерфейс (
http://localhost:9090). Выполните запросretrieval_hit_rateи убедитесь, что данные отображаются.
Ожидаемый результат этапа
Работающий эндпоинт с метриками, видимые в Prometheus.
Этап 3: Создание дашборда в Grafana (2-3 часа)
Действия
-
Подключить Grafana к Prometheus как data source (URL:
http://prometheus:9090, если в одном Docker Compose, илиhttp://localhost:9090). -
Создать новый дашборд с именем «Retrieval Quality Dashboard».
-
Добавить панели для каждой метрики, используя переменную для выбора query_type (или отображать все сразу через
legend). Рекомендуемая разбивка:- Hit Rate per Query Type (Time series, lines):
avg(retrieval_hit_rate) by (query_type) - MRR per Query Type (Time series):
avg(retrieval_mrr) by (query_type) - NDCG@10 per Query Type (Time series):
avg(retrieval_ndcg) by (query_type) - Overall Average (опционально) :
avg(retrieval_hit_rate)без группировки.
- Hit Rate per Query Type (Time series, lines):
-
Настроить пороговые линии (thresholds) для каждой панели:
-
Добавить переменные для гибкой фильтрации:
$query_type→ тип: query, multi-value. Значения из меткиquery_type.$time_range→ тип: interval (по умолчанию 6h, 24h, 7d).
-
Настроить алерты:
-
Экспортировать дашборд в JSON (Share → Export) для воспроизводимости.
Ожидаемый результат этапа
Полностью рабочий дашборд Grafana с тремя панелями по query_type, пороговыми линиями и настроенными алертами.
Этап 4: Интеграция с системой логирования (опционально, 1-2 часа)
Действия
- Настроить сбор логов retrieval в Loki (или ClickHouse) — для drill-down анализа при срабатывании алерта.
- Добавить в дашборд ссылки «View logs» для каждой точки, где значение упало.
- Добавить панель «Logs» (если используется Loki) для просмотра последних деградировавших запросов.
Ожидаемый результат этапа
Дашборд содержит ссылки на логи, позволяющие быстро понять причину снижения метрик.
Этап 5: Тестирование и верификация (1-2 часа)
Действия
- Симулировать деградацию retrieval: изменить синтетические данные так, чтобы hit rate упал ниже порога (например, уменьшить количество релевантных документов в top-k).
- Проверить, что алерт срабатывает в Grafana и приходит уведомление (если настроено).
- Проверить дашборд на корректность отображения при пустом наборе данных за последний час (должны отображаться NaN или отсутствовать линии).
- Проверить производительность: при 1000+ запросов в час, метрики должны обновляться без задержек.
- Задокументировать дашборд: написать README с описанием панелей, порогов и действий при алерте.
Ожидаемый результат этапа
Дашборд успешно проходит тесты, алерты работают, документация готова.
5. Критерии приемки (Definition of Done)
- Создан дашборд Grafana (или аналог) с тремя панелями: hit rate, MRR, NDCG.
- Каждая панель отображает метрики, сгруппированные по
query_type. - Дашборд обновляется автоматически каждые 1–5 минут.
- Настроены пороговые линии и алерты для каждой метрики (минимум hit rate < 0.6).
- Алерты отправляют уведомления в настроенный канал (Slack/Telegram/email).
- При деградации метрик на дашборде видна дата и время начала падения.
- Имеется возможность фильтрации по query_type и временному интервалу.
- Исходный код генератора метрик (metrics_exporter.py) лежит в git-репозитории.
- Написан README с инструкцией по запуску, описанием дашборда и действиями при алерте.
- Дашборд сохранён в формате JSON для экспорта.
6. Ожидаемый результат
Основной артефакт дашборд retrieval_quality_dashboard.json — экспортированный JSON-файл дашборда Grafana.
Дополнительно
- Файл
metrics_exporter.pyс кодом генерации метрик. - Файл
retrieval_logs.csvс синтетическими данными (или ссылка на источник). - Файл
README.mdс инструкцией по запуску. - Скриншоты дашборда в нормальном состоянии и при срабатывании алерта (опционально).
Содержание дашборда
- Hit Rate per query type (line chart)
- MRR per query type (line chart)
- NDCG@10 per query type (line chart)
- Thresholds и алерты
- Переменная
query_typeиtime_range
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Нет production-логов retrieval | Сгенерировать синтетические данные с помощью Python-скрипта (описано в Этапе 1) |
| Prometheus + Grafana не установлены | Использовать Docker Compose (готовый compose-файл предоставить в репозитории) |
| Метрики не появляются в Prometheus | Проверить правильность адреса target и доступность эндпоинта /metrics |
| Алерты не срабатывают | Проверить настройки Alertmanager и каналов уведомлений; убедиться, что временной период (for) достаточен |
| Некорректный расчёт NDCG | Использовать готовую реализацию из sklearn.metrics.ndcg_score или RAGAS; проверить, что relevance scores бинарные |
| Разбивка по query_type неоднозначна | Заранее определить фиксированные типы и написать простой классификатор (регулярные выражения или rule-based) |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Подготовка данных и расчёт метрик | 2-3 ч |
| Этап 2: Экспорт метрик в Prometheus | 2-3 ч |
| Этап 3: Создание дашборда в Grafana | 2-3 ч |
| Этап 4: Интеграция с логированием (опционально) | 1-2 ч |
| Этап 5: Тестирование и верификация | 1-2 ч |
| Итого | 8-13 ч |
Примечание Для первого выполнения задачи может потребоваться до 2 дополнительных часов на установку Docker и освоение Grafana.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 14 | Как настроить Prometheus + Grafana? |
| 23 | Основные метрики качества retrieval (hit rate, MRR, NDCG) |
| 27 | Разработка дашборда для мониторинга RAG |
| 42 | Алертинг по метрикам ML-систем |
| 58 | Генерация синтетических данных для тестирования RAG |
| 73 | Мониторинг деградации retrieval с помощью Prometheus |
| 89 | Экспорт метрик из Python в Prometheus |
| 104 | Настройка Grafana Alerting |
| 121 | Best practices по визуализации метрик retrieval |
| 156 | Обработка отсутствия ground truth в production |
10. Чек-лист самопроверки
- Я проверил, что дашборд отображает hit rate, MRR и NDCG отдельно по каждому query_type.
- Я убедился, что при падении любой метрики ниже порога в течение 5 минут приходит алерт.
- Я протестировал фильтрацию по query_type и временному интервалу — все панели корректно обновляются.
- Я сохранил дашборд в JSON и добавил его в репозиторий вместе с кодом генератора метрик.
- Я написал README, в котором описал, как запустить дашборд, какие метрики показывают и что делать при алерте.