Aivaro
  • Оглавление
  • Вопросы
  • Практика
  • Вики
  • Материалы сообщества
  • Тесты
  • Поиск
✈Telegram @ai_varo
RUEN中文
…
Оглавление/Вопросы/#970

Как вы fine-tune reranker (cross-encoder) для RAG? Как генерировать hard negatives?

Краткий тезис

Тонкая настройка (fine-tune) cross-encoder (также известного как reranker) для RAG-пайплайна — это процесс дообучения модели, которая принимает на вход пару (query, document) и выдаёт скалярную оценку релевантности. Ключевая сложность — генерация качественных hard negatives (сложных отрицательных примеров), которые модель должна научиться отличать от релевантных. Обычно hard negatives добываются с помощью ретривера (например, BM25 или dense retriever), при этом ошибки первого этапа (false positives) становятся ценными обучающими примерами. Функция потерь — pairwise ranking loss или listwise/cross-entropy.

-----|----------| | Вход | Пара (question, passage) — до 512 токенов | | Выход | Оценка релевантности (0..1) или логит-бинарный | | Параметры | Обычно 50–300M, но могут быть до 1B+ | | Скорость | ~1–10 ms на пару, но линейно от числа документов | | Использование в RAG | После ретривера (top-k, обычно 50–200) ранжирует, оставляя top-n (1–10) |

При fine-tuning мы обновляем веса как трансформера, так и головы, используя размеченные пары (query, doc, label). Однако обычные положительные и случайные отрицательные примеры не дают достаточной трудности — поэтому нужны hard negatives.


2. Hard negatives: документы, релевантные, но не топ-1 от BM25

Hard negatives — это документы, которые:

  • не являются релевантными для запроса (по мнению человека или золотого стандарта);
  • но при этом имеют высокое сходство с запросом (по лексическим или семантическим признакам);
  • часто попадают в топ ретривера, обманывая наивные модели.

Типичный способ генерации:

  1. Взять обучающий пример (query, positive_passage).
  2. Использовать BM25 или Contriever для поиска по корпусу.
  3. Взять первый документ, который НЕ является релевантным — это и есть hard negative.
  4. Можно взять несколько (3–5) hard negatives на каждый запрос.

Важно, чтобы hard negatives были действительно сложными — например, документы из той же темы, но с другим ответом, или похожие по ключевым словам.


3. Mining: модель-ретривер даёт false positives

Процесс генерации hard negatives часто называют negative mining или hard negative mining. Основные подходы:

  • BM25-based mining: BM25 выдаёт top-k, помечаем все, кроме релевантного, как hard negatives.
  • Dense retriever mining (например, ANCE — Approximate Nearest Neighbor Negative Contrastive Estimation): в процессе обучения ретривера мы итеративно находим наиболее близкие векторы нерелевантных документов из индекса.
  • Cross-encoder bootstrap: можно прогнать через уже обученный (или предобученный) cross-encoder партии (query, doc) и взять пары с высоким score, но не релевантные — это самые «жирные» hard negatives.

Для RAG обычно делают так:

# Псевдокод для mining hard negatives
queries = ["как ускорить LLM?"]
corpus = ["...", "...", "..."]
retriever = BM25(corpus)
hard_negatives = []
for q in queries:
    top_k = retriever.retrieve(q, k=100)
    for doc in top_k:
        if not is_relevant(q, doc):
            hard_negatives.append((q, doc, 0))
            if len(hard_negatives) >= 3: break

4. Функция потерь: pairwise ranking loss

Наиболее распространённая функция для fine-tuning cross-encoder в ранжировании — pairwise ranking loss (также hinge loss или MarginRankingLoss).

Идея:

  • Для каждого запроса берётся положительный документ (score=1) и один или несколько hard negatives (score=0).
  • Модель обучается так, чтобы разница между оценками положительного и отрицательного документа была больше заданного маржина (margin).

Формула (для пары): [ \mathcal{L} = \max(0, margin - (s_positive - s_negative)) ]

В PyTorch это реализуется как:

import torch.nn as nn

criterion = nn.MarginRankingLoss(margin=0.3)
scores_pos = model(query, positive_doc)   # [batch]
scores_neg = model(query, negative_doc)   # [batch]
target = torch.ones_like(scores_pos)      # +1 означает, что первый аргумент должен быть больше второго
loss = criterion(scores_pos, scores_neg, target)

Альтернативы:

  • Listwise loss (ListNet, LambdaRank): учитывает порядок всего списка.
  • Cross-entropy with multiple negatives: берём 1 positive + N negatives как классы, предсказываем софтмакс. Это эквивалентно pairwise при N=1, но с несколькими минусами даёт более стабильное обучение.

Рекомендации:

  • Margin ~0.1–0.5.
  • Для каждого запроса использовать 3–7 hard negatives (можно динамически подбирать сложность).
  • Batch size 16–32, так как каждая пара требует отдельного forward.

5. Пет-проект для закрепления

Задача: Обучить cross-encoder ранжировать документы по запросу на датасете MS MARCO (или его подмножестве) с генерацией hard negatives через BM25.

Инструменты:

  • Python 3.10+ с Hugging Face Transformers и PyTorch.
  • Elasticsearch или pyserini для BM25 (можно локально).
  • Датасет: msmarco-passage (TREC 2019 Deep Learning Track).
  • Weights & Biases для логирования.

Шаги:

  1. Загрузить датасет MS MARCO (train queries + passages + qrels).
  2. Для каждого обучающего запроса отобрать top-50 документов через BM25.
  3. Выбрать оттуда 1 релевантный (по qrels) и 3 нерелевантных с наивысшим BM25-скорингом — это hard negatives.
  4. Взять предобученную модель cross-encoder/ms-marco-MiniLM-L-6-v2 (отличный старт).
  5. Создать конкатенации (query, passage) с маской.
  6. Обучить с MarginRankingLoss (margin=0.2), batch size 16, learning rate 2e-5, 3 эпохи.
  7. Валидировать на dev-сете: метрика MRR@10 или nDCG@10.

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

  • После обучения модель будет давать более высокие оценки для релевантных документов, чем для hard negatives.
  • На dev-сете MRR@10 вырастет на 5–15% по сравнению с предобученной версией (если fine-tuning сделан на домене).
  • Понимание pipeline: retriever → reranker → final selection.
  • Воспроизводимый код на GitHub (можно выложить в портфолио).

Связь с другими вопросами

ВопросТема
45Этапы ретрива и ранжирования в RAG

Навигация

  • Предыдущий: 969
  • Следующий: 971
  • Индекс: 00. Индекс разборов