English translation is not available yet. Showing Russian content.

Настроить 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

Если нет реального инструмента — симулируем:

  1. Поднять инстанс Prometheus и Grafana через Docker Compose (файл прилагается в репозитории упражнения).
  2. Написать Python-сервис, который читает логи retrieval из CSV/JSON и экспортирует метрики в формате Prometheus (через prometheus_client library).
  3. Настроить Grafana datasource на этот Prometheus.
  4. Если нет ground truth (релевантные документы), сгенерировать синтетические данные: для каждого запроса создать случайный набор релевантных документов (2-5 штук) и симулировать их ранжирование retrieval-системой.

3. Технологический стек

КомпонентИнструментыНазначение
База метрикPrometheus (или VictoriaMetrics)Хранение временных рядов hit rate, MRR, NDCG
ВизуализацияGrafana (или Plotly Dash)Построение дашборда с панелями
Генерация метрикPython + prometheus_clientЭкспорт метрик из логов retrieval в Prometheus
Библиотека метрик retrievalRAGAS / 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 часа)

Действия

  1. Определить типы запросов (query_type). Создайте словарь с примерами (не менее 3 типов, например: «фактографический», «инструкционный», «рекомендательный»).

  2. Сгенерировать синтетические логи 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)
    
  3. Реализовать функцию расчёта метрик (hit rate, MRR, NDCG@k). Для hit rate используйте 1 если хотя бы один релевантный документ попал в top-k, иначе 0. Для MRR1/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
    
  4. Применить функции к DataFrame и создать агрегированные временные ряды по query_type с окном (например, 1 час). Полученные значения сохранить в CSV или напрямую экспортировать в Prometheus (см. Этап 2).

Ожидаемый результат этапа
Файл retrieval_logs.csv с синтетическими данными и функция расчёта метрик, готовая к интеграции.

Этап 2: Экспорт метрик в Prometheus (2-3 часа)

Действия

  1. Написать 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)
    
  2. Запустить сервис на порту 8000. Проверить, что метрики доступны по http://localhost:8000/metrics.

  3. Настроить Prometheus (если используется Docker Compose):

    • В prometheus.yml добавить job:
      scrape_configs:
        - job_name: 'retrieval_metrics'
          static_configs:
            - targets: ['localhost:8000']
      
    • Перезапустить Prometheus.
  4. Верифицировать появление метрик в Prometheus через его веб-интерфейс (http://localhost:9090). Выполните запрос retrieval_hit_rate и убедитесь, что данные отображаются.

Ожидаемый результат этапа
Работающий эндпоинт с метриками, видимые в Prometheus.

Этап 3: Создание дашборда в Grafana (2-3 часа)

Действия

  1. Подключить Grafana к Prometheus как data source (URL: http://prometheus:9090, если в одном Docker Compose, или http://localhost:9090).

  2. Создать новый дашборд с именем «Retrieval Quality Dashboard».

  3. Добавить панели для каждой метрики, используя переменную для выбора 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) без группировки.
  4. Настроить пороговые линии (thresholds) для каждой панели:

    • Hit rate < 0.7 → жёлтый, < 0.5 → красный.
    • MRR < 0.5 → жёлтый, < 0.3 → красный.
    • NDCG < 0.6 → жёлтый, < 0.4 → красный.
  5. Добавить переменные для гибкой фильтрации:

    • $query_type → тип: query, multi-value. Значения из метки query_type.
    • $time_range → тип: interval (по умолчанию 6h, 24h, 7d).
  6. Настроить алерты:

    • Для каждой панели создать алерт: если значение падает ниже порога (например, hit_rate < 0.6) в течение 5 минут.
    • Канал уведомлений: Slack / Email / Telegram (настроить в Grafana Alerting).
  7. Экспортировать дашборд в JSON (Share → Export) для воспроизводимости.

Ожидаемый результат этапа
Полностью рабочий дашборд Grafana с тремя панелями по query_type, пороговыми линиями и настроенными алертами.

Этап 4: Интеграция с системой логирования (опционально, 1-2 часа)

Действия

  1. Настроить сбор логов retrieval в Loki (или ClickHouse) — для drill-down анализа при срабатывании алерта.
  2. Добавить в дашборд ссылки «View logs» для каждой точки, где значение упало.
  3. Добавить панель «Logs» (если используется Loki) для просмотра последних деградировавших запросов.

Ожидаемый результат этапа
Дашборд содержит ссылки на логи, позволяющие быстро понять причину снижения метрик.

Этап 5: Тестирование и верификация (1-2 часа)

Действия

  1. Симулировать деградацию retrieval: изменить синтетические данные так, чтобы hit rate упал ниже порога (например, уменьшить количество релевантных документов в top-k).
  2. Проверить, что алерт срабатывает в Grafana и приходит уведомление (если настроено).
  3. Проверить дашборд на корректность отображения при пустом наборе данных за последний час (должны отображаться NaN или отсутствовать линии).
  4. Проверить производительность: при 1000+ запросов в час, метрики должны обновляться без задержек.
  5. Задокументировать дашборд: написать 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: Экспорт метрик в Prometheus2-3 ч
Этап 3: Создание дашборда в Grafana2-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
121Best practices по визуализации метрик retrieval
156Обработка отсутствия ground truth в production

10. Чек-лист самопроверки

  • Я проверил, что дашборд отображает hit rate, MRR и NDCG отдельно по каждому query_type.
  • Я убедился, что при падении любой метрики ниже порога в течение 5 минут приходит алерт.
  • Я протестировал фильтрацию по query_type и временному интервалу — все панели корректно обновляются.
  • Я сохранил дашборд в JSON и добавил его в репозиторий вместе с кодом генератора метрик.
  • Я написал README, в котором описал, как запустить дашборд, какие метрики показывают и что делать при алерте.