Профилировать негативные эффекты reranker

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Профилировать негативные эффекты reranker

1. Цель задачи

Научиться выявлять сценарии, в которых применение reranker в RAG-системе не только не улучшает, но и ухудшает качество retrieval. Провести A/B-тест: пайплайн с reranker vs без reranker на синтетическом датасете, измерить метрики (NDCG@K, MRR, Recall@K) и определить условия, при которых reranker приносит вред (например, малый top‑k, низкое качество первичного поиска, смещение к популярным документам).

Ключевой результат Отчёт с количественными критериями «вредности» reranker и рекомендациями по его конфигурации / отключению.


2. Исходные данные

Что нужноОткуда взять
Набор пар запрос–релевантные документы (ground truth)Сгенерировать синтетически (см. ниже)
RAG-пайплайн c rerankerРеализовать средствами Python + HuggingFace
Метрики качества retrieval (NDCG@K, MRR, Recall@K)Написать скрипт расчёта (numpy, sklearn)
Профилировщик времени выполнения (latency)time.perf_counter или cProfile

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

  1. Создать корпус документов 5000 коротких текстов (2–5 предложений) на русском/английском. Можно взять случайные фрагменты из Wikipedia dump или сгенерировать через LLM (например, 200 тем по 25 документов).
  2. Сформировать запросы (100–200 шт.): на каждый запрос вручную отметить 3–5 релевантных документов (ground truth). Использовать для этого 20% корпуса как «специально подобранные» (остальные — нерелевантные или слабо релевантные).
  3. Создать два варианта первичного поиска a) качественный (embedding model high‑quality + top‑k=20) и b) заведомо плохой (embedding model low‑quality или уменьшенный top‑k=3).
  4. Выбрать reranker использовать BAAI/bge-reranker-base (бесплатный, HuggingFace).

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

КомпонентИнструментыНазначение
Первичный поиск (embedding)sentence-transformers/all-MiniLM-L6-v2 (базовый) и intfloat/multilingual-e5-large (качественный)Получить предварительный топ документов
RerankerBAAI/bge-reranker-base (HuggingFace Transformers)Переранжирование выдачи
Векторная БДFAISS (in‑memory)Хранение эмбеддингов и быстрый поиск
Оценка метрикPython (numpy, scikit‑learn)NDCG, MRR, Recall
ВизуализацияMatplotlib + SeabornГрафики зависимости метрик от конфигураций
Управление экспериментомShell‑скрипт или Python loopA/B-тест на разных top‑k и threshold
ВерсионированиеGit + DVC (опционально)Фиксация данных и результатов

4. Этапы выполнения

Этап 1: Генерация синтетического датасета (1 час)

Действия

  1. Сформировать корпус (5000 документов) — каждому документу присвоить уникальный ID и topic_id (тема).
  2. Создать запросы (150 шт): 100 из тех же тем, 50 — из пересекающихся или общих тем.
  3. Построить ground truth для каждого запроса выбрать 3 релевантных документа (по теме) и дополнительно добавить 2 «почти релевантных» (смежная тема). Результат сохранить в data/ground_truth.json:
{
  "query_0": {"relevant_ids": ["doc_12", "doc_87", "doc_203"], "near_relevant_ids": ["doc_45", "doc_301"]},
  ...
}
  1. Вычислить эмбеддинги для всех документов (двумя моделями) и сохранить в FAISS индексы: index_mini.faiss, index_e5.faiss.
  2. Разделить датасет на 70% train (для настройки параметров) и 30% test (для финальной оценки).

Ожидаемый результат этапа Директория data/ с файлами:

  • corpus.json (документы)
  • queries.json (запросы)
  • ground_truth.json
  • два FAISS индекса

Этап 2: Реализация поискового пайплайна (1 час)

Действия

  1. Написать класс SearchPipeline с методами:

    • retrieve(query, top_k, model_type) — поиск по FAISS, возвращает список [(doc_id, score)].
    • rerank(query, doc_ids, reranker_model) — использует bge-reranker-base, возвращает переранжированный список.
    • evaluate(query, retrieved_ids, ground_truth, metric) — расчёт одной метрики.
  2. Реализовать два режима

    Код для примера:

class SearchPipeline:
    def __init__(self, index_path, docs, reranker_model_name="BAAI/bge-reranker-base"):
        self.index = faiss.read_index(index_path)
        self.docs = docs
        self.reranker = CrossEncoder(reranker_model_name) if reranker_model_name else None

    def retrieve(self, query_emb, top_k=10):
        scores, indices = self.index.search(query_emb, top_k)
        return [(self.docs[i], scores[0][j]) for j, i in enumerate(indices[0])]

    def rerank(self, query, candidates):
        pairs = [(query, doc[0]) for doc in candidates]
        scores = self.reranker.predict(pairs)
        return [doc for _, doc in sorted(zip(scores, candidates), key=lambda x: -x[0])]
  1. Добавить профилирование времени каждого этапа.

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


Этап 3: A/B-тест на разных конфигурациях (1.5 часа)

Действия

  1. Определить факторы эксперимента

    • embedding_model: качественный (e5) vs базовый (miniLM)
    • top_k для первичного поиска: 3, 5, 10, 20
    • threshold (число документов, передаваемых в reranker): top_k (все) или min(top_k, 5)
    • reranker: включён / выключен
  2. Составить план — полный факторный эксперимент (2×4×2×2 = 32 комбинации) на train-выборке (105 запросов).

  3. Запустить цикл по всем комбинациям, сохранить метрики в CSV:

results = []
for emb_model in ['miniLM', 'e5']:
    for top_k in [3, 5, 10, 20]:
        for threshold in [top_k, min(top_k, 5)]:   # threshold ≤ top_k
            for use_reranker in [True, False]:
                avg_metrics = run_experiment(emb_model, top_k, threshold, use_reranker)
                results.append({
                    'embedding': emb_model,
                    'top_k': top_k,
                    'threshold': threshold,
                    'reranker': use_reranker,
                    **avg_metrics
                })
  1. Добавить сбор latency (среднее время на запрос).

Ожидаемый результат этапа Файл results/experiment_results.csv со всеми метриками и временем.


Этап 4: Анализ и выявление негативных эффектов (1 час)

Действия

  1. Построить сводные таблицы (pandas pivot) и визуализации:

    • Heatmap средней NDCG@10 по комбинациям «embedding × top_k» для режимов с reranker и без.
    • Box plot разницы метрик (reranker — baseline) для каждого сценария.
    • График зависимости latency от threshold.
  2. Определить условия, при которых reranker значимо ухудшает метрики (p‑value < 0.05 по t‑test или bootstrap):

    • Когда первичный поиск слабый (miniLM, top_k ≤ 5) — reranker не может компенсировать плохой набор кандидатов.
    • Когда threshold мал (≤5) и top_k большой — reranker отбрасывает полезные документы за пределами threshold.
    • Когда запрос короткий или общий — reranker может смещать ранжирование в сторону популярных документов.
  3. Вычислить «точку перехода» — пороговое значение NDGC@K, ниже которого reranker скорее вреден.

Ожидаемый результат этапа Графики и таблица с рекомендациями (например, «если NDCG@10 ≤ 0.6, отключить reranker»).


Этап 5: Оформление отчёта (30 минут)

Действия

  1. Написать отчёт в формате Markdown с разделами:

    • Цель эксперимента
    • Методология (датасет, метрики, факторы)
    • Результаты (ключевые тепловые карты, таблицы разницы)
    • Выводы (при каких конфигурациях reranker вреден)
    • Рекомендации (конкретные пороги и настройки)
  2. Включить файлы отчёта в репозиторий: report.md, charts/ (PNG), results/experiment_results.csv.

  3. Добавить раздел «Как проверить на новых данных» — скрипт quick_check.py, который для заданного запроса и выдачи вычисляет вероятность того, что reranker навредит.

Ожидаемый результат этапа Итоговый репозиторий с кодом, данными, отчётом.


5. Критерии приемки (Definition of Done)

  • Реализован воспроизводимый пайплайн A/B-теста (один python run_experiment.py).
  • Получен CSV с метриками для всех 32+ комбинаций.
  • Созданы визуализации (минимум 3 графика), показывающие зависимость.
  • В отчёте указаны конкретные условия, при которых reranker ухудшает NDCG@K ≥0.05.
  • Приведены рекомендации по порогам (например, «отключать reranker при NDCG@10 < 0.55»).
  • Профилирование времени выполнения прилагается — показан рост latency ×5–10 при использовании reranker.
  • Отчёт рецензируем: содержит таблицы с числовыми значениями метрик.
  • Скрипт quick_check.py работоспособен на одном запросе.

6. Ожидаемый результат

Основной артефакт Репозиторий Git со следующей структурой:

├── data/
│   ├── corpus.json
│   ├── queries.json
│   ├── ground_truth.json
│   └── indices/ (FAISS .faiss + .pkl)
├── src/
│   ├── pipeline.py          # SearchPipeline класс
│   ├── experiment.py        # Запуск A/B-теста
│   ├── analyze.py           # Расчёт статистики и графики
│   └── quick_check.py       # Быстрая проверка одного запроса
├── results/
│   ├── experiment_results.csv
│   └── charts/              # *.png
├── report.md                # Полный отчёт
└── README.md                # Инструкция по запуску

Содержание отчёта (report.md):

  • Введение (1 абзац)
  • Описание датасета и эксперимента
  • Таблицы средних метрик (NDCG@5, NDCG@10, MRR) для каждого сценария
  • Анализ негативных эффектов: графики «разницы» (reranker - baseline)
  • Выводы: 3–5 bullet-пунктов о том, когда reranker вреден
  • Рекомендации: конкретные пороги и настройки

Опциональные дополнительные результаты

  • Bootstrap confidence intervals для различий метрик
  • Анализ влияния длины запроса и темы

7. Возможные сложности и их решение

СложностьРешение
Reranker слишком медленный для полного факторного экспериментаИспользовать предварительно кэшированные результаты reranker (разово расчитать и сохранить) или сократить выборку до 50 запросов на комбинацию.
Ground truth субъективенИспользовать несколько независимых аннотаторов или генерировать ground truth через LLM с проверкой. В данном ТЗ — синтетический, поэтому контролируется.
Разница метрик может быть статистически незначимойУвеличить число запросов (≥100) и применить permutation test при анализе.
Результаты зависят от конкретного rerankerПровести эксперимент с двумя разными reranker (например, BGE и Cohere) и сравнить паттерны.
Невозможно однозначно определить «вредность»Ввести порог ΔNDCG@10 = -0.03 как минимальный значимый негативный эффект.

8. Бюджет времени (оценка)

ЭтапВремя
Этап 1: Генерация датасета1 час
Этап 2: Реализация пайплайна1 час
Этап 3: A/B-тест1.5 часа
Этап 4: Анализ1 час
Этап 5: Оформление отчёта0.5 часа
Итого5 часов

Примечание При первом выполнении увеличьте время на 1–2 часа из-за отладки интеграции reranker. При использовании GPU (например, Colab) этап 2 можно ускорить.


9. Связанные вопросы из базы знаний

ВопросТема
41Как правильно подобрать top‑k для retrieval
58Что такое NDCG и как его считать
72Метрики качества ранжирования (MRR, MAP)
104A/B-тестирование в ML-системах
131Когда reranker не улучшает качество
157Влияние threshold на latency
183Сравнение embedding моделей для retrieval
209Bootstrap для оценки значимости различий метрик
244Профилирование latency в RAG-пайплайне
278Синтетические датасеты для оценки retrieval

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

  • Я сгенерировал датасет с ground truth, разделил на train/test.
  • Пайплайн поддерживает оба режима (с reranker / без) и корректно считает метрики.
  • Я запустил эксперимент для всех комбинаций и сохранил результаты.
  • Я построил графики, на которых видно, в каких сценариях reranker снижает метрики.
  • Я сформулировал конкретные рекомендации (например, «отключать reranker при top_k ≤ 5»).
  • Отчёт написан, содержит таблицы и выводы, воспроизводим.