MAATRIX / Блог / Reranker-модели: зачем они нужны в RAG

Reranker-модели: зачем они нужны в RAG

Reranker-модели: зачем они нужны в RAG

MAATRIX

Векторный поиск находит вроде бы похожие фрагменты, а модель отвечает мимо вопроса — знакомая картина, если вы уже собрали RAG и он «вроде работает, но как-то не очень». Причина часто не в эмбеддере и не в чанкинге, а в том, что косинусное сходство — не то же самое, что релевантность вопросу. Reranker — вторая модель, которая пересматривает уже найденных кандидатов и расставляет их заново, ближе к тому, что человек назвал бы «действительно по делу». Разбираемся, почему это работает, когда окупается и как встроить в свой пайплайн.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Почему одного векторного поиска часто недостаточно

Векторный поиск в RAG устроен так: вопрос и каждый чанк документа превращаются в вектор (эмбеддинг), а «похожесть» между ними считается как косинусное расстояние. Это быстро — по индексу из миллиона векторов ответ приходит за миллисекунды — но у самой идеи есть системное ограничение.

Эмбеддер кодирует чанк и вопрос независимо друг от друга, ничего не зная про пару целиком. Он видит «в этом тексте примерно такие темы» и «в этом вопросе примерно такие темы», а дальше просто сравнивает два облака смысла. Из-за этого возникают предсказуемые перекосы:

  • Длинные общие фрагменты обгоняют точные. Абзац, который поверхностно касается пяти тем сразу, может оказаться «ближе» к вопросу, чем короткий фрагмент, отвечающий на него буквально одним предложением.
  • Синонимы и парафраз путают модель. «Как отменить подписку» и «правила расторжения договора» семантически близки, но первое — вопрос пользователя, второе — юридический раздел, который на него не отвечает по сути.
  • Порядок топ-N ненадёжен именно в верхней части. Разница в косинусном сходстве между 1-м и 5-м местом часто минимальна — доли процента, — а смысловая разница между этими фрагментами может быть огромной.

На практике это значит: если вы отдаёте модели top-4–5 фрагментов напрямую, релевантный ответ нередко лежит на 7–8 месте и просто не попадает в контекст. Модель честно отвечает по тому, что ей дали, — и дают ей не то.

Если вы ещё не поднимали сам RAG-пайплайн — с чанкингом, эмбеддингом и диагностикой поиска, — это описано в статье как поднять RAG по своим документам на сервере. Reranker имеет смысл добавлять поверх уже работающей базовой схемы, а не вместо неё.

Как работает reranker: вторая модель поверх кандидатов

Ключевая разница между эмбеддером и reranker-моделью — в архитектуре, а не в размере или «качестве вообще».

Эмбеддер (bi-encoder) кодирует текст и вопрос раздельно, заранее, в отрыве друг от друга — поэтому его векторы можно посчитать один раз и сложить в индекс, а поиск свести к быстрому сравнению чисел. Это и даёт скорость на больших базах.

Reranker (обычно cross-encoder) устроен иначе: он получает пару «вопрос + конкретный фрагмент» одновременно и пропускает их через модель вместе, с полным вниманием между всеми токенами обоих текстов. На выходе — не вектор, а одно число: скор релевантности именно этой пары. Модель буквально «читает» вопрос и фрагмент рядом и оценивает, отвечает ли второе на первое.

Это точнее почти всегда, но дороже: пересчитать так придётся каждую пару отдельно, и посчитать заранее, как с эмбеддингами, нельзя — фрагмент не знает вопроса заранее. Поэтому cross-encoder не используют для поиска по всей базе (это было бы N сравнений на миллион документов), а применяют только к уже отобранным кандидатам — обычно 10–50 штук после первого прохода векторным поиском.

Отсюда и название «reranker»: модель не ищет, она пересортировывает то, что уже нашли.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Qdrant

Практическая схема: retrieve top-20, rerank в top-5

Рабочая связка, которая закрывает большинство случаев:

  1. Retrieve. Векторный поиск по базе (Qdrant, Chroma и т. п.) возвращает top-20 кандидатов по косинусному сходству. На этом этапе важна полнота — не бойтесь взять с запасом, cross-encoder всё равно отфильтрует лишнее.
  2. Rerank. Все 20 пар «вопрос + фрагмент» прогоняются через cross-encoder, каждая получает скор релевантности. Кандидаты сортируются заново по этому скору.
  3. Truncate. В промпт модели уходят только top-5 (иногда top-3–8, в зависимости от бюджета контекста) — уже пересортированных фрагментов.
question → vector search (Qdrant) → top-20 candidates
top-20 → cross-encoder rerank (пара question+chunk → score)
top-20 sorted by score → top-5 → LLM prompt

Числа 20 и 5 не догма, а отправная точка. Логика их выбора простая:

  • Top-K на retrieve должен быть достаточно широким, чтобы туда почти наверняка попал правильный ответ — иначе reranker просто нечего пересортировывать. Если ваша база разнородная (много похожих по теме, но разных по сути документов), берите 30–50.
  • Top-N после rerank должен помещаться в контекст модели с запасом на системный промпт и историю диалога, и не должен размывать внимание модели лишним. Пять фрагментов — разумный дефолт для большинства LLM с контекстом в десятки тысяч токенов; для очень коротких контекстов может быть оправдано 3, для длинных — 8–10.

Проверить это на глаз почти невозможно — нужен тестовый набор вопросов с известными правильными фрагментами и метрика попадания правильного фрагмента в top-N до и после rerank. Без такого замера легко получить обратный эффект: reranker «на глаз» иногда ухудшает выдачу на конкретных доменных текстах.

Какие reranker-модели существуют

Разброс — от лёгких открытых моделей до платных API. Ориентировочная картина на конец 2026 года:

Модель / сервисТипГде крутитсяОсобенность
BAAI/bge-reranker-base, bge-reranker-largecross-encoderлокально (CPU/GPU)открытая, хорошо работает на русском и английском вместе с bge-эмбеддерами
BAAI/bge-reranker-v2-m3cross-encoderлокальномультиязычная, легче интегрировать в пайплайн на нескольких языках
sentence-transformers/ms-marco-MiniLMcross-encoderлокально (лёгкая)компактная, быстрая на CPU, в основном под английский
Cohere RerankAPIоблакоплатный, без своей инфраструктуры, минимальная задержка на интеграцию
Jina Rerankerлокально / APIоба вариантаесть открытые веса, есть облачный API

Открытые cross-encoder-модели из семейства BAAI и sentence-transformers запускаются через библиотеку sentence-transformers или FlagEmbedding и не требуют GPU для небольших объёмов — на CPU reranking 20 пар обычно укладывается в разумное время для интерактивного ответа, хотя точная скорость зависит от модели, длины фрагментов и железа: здесь я намеренно не называю цифры «токенов в секунду» — измерьте на своих данных, у вас будет иначе.

Если вы уже считаете эмбеддинги на CPU без GPU, добавление reranker того же класса обычно укладывается в тот же бюджет железа — подробнее про расчёт нагрузки есть в статье как считать эмбеддинги на CPU без GPU.

Когда reranker оправдан, а когда избыточен

Reranker — не обязательный компонент любого RAG, это оптимизация под конкретную ситуацию.

Стоит добавлять, когда:

  • база большая (десятки тысяч фрагментов и больше) и в топ-N векторного поиска регулярно попадает «почти похожее», а не точный ответ;
  • цена ошибки высокая — юридические, медицинские, финансовые ответы, где неточная выдача стоит дороже, чем лишние 100–300 мс на запрос;
  • вопросы пользователей формулируются иначе, чем текст документов (разговорный язык против канцелярита в источниках) — именно здесь эмбеддер чаще всего промахивается;
  • вы уже проверили базовый RAG на тестовом наборе и видите, что нужный фрагмент есть в top-20, но не входит в top-5 без reranker.

Скорее избыточен, когда:

  • база маленькая (сотни фрагментов) — там векторный поиск и так почти всегда находит нужное в топе, а выигрыш от rerank статистически не заметен;
  • задержка критичнее точности — например, чат в реальном времени, где 200–500 мс дополнительной обработки заметны пользователю, а цена неточного ответа невысока;
  • документы однородные и узкотематические (одна база — одна тема), там косинусное сходство и так хорошо разделяет релевантное от нерелевантного;
  • у вас пока нет способа измерить, помог ли reranker — добавлять компонент, эффект которого не с чем сравнить, обычно не стоит того.

Если сомневаетесь — разверните reranker необязательным флагом в своём пайплайне и сравните ответы на одном и том же тестовом наборе вопросов с ним и без. Часто выясняется, что для конкретной базы выигрыш есть только на определённом классе вопросов, а не везде.

Как встроить reranker в пайплайн на сервере

Если векторная база уже поднята (например, Qdrant — как это сделать, описано в статье как установить и настроить Qdrant на VPS), добавление reranker — это дополнительный шаг между поиском и сборкой промпта, без изменений в самой базе.

Минимальный пример на Python с sentence-transformers:

from sentence_transformers import CrossEncoder
from qdrant_client import QdrantClient

client = QdrantClient(url="http://localhost:6333")
reranker = CrossEncoder("BAAI/bge-reranker-base")

def search_with_rerank(question, top_k_retrieve=20, top_n_final=5):
    # 1. Retrieve: обычный векторный поиск
    hits = client.search(
        collection_name="docs",
        query_vector=embed(question),  # ваша функция эмбеддинга
        limit=top_k_retrieve,
    )
    candidates = [h.payload["text"] for h in hits]

    # 2. Rerank: пары "вопрос + фрагмент" через cross-encoder
    pairs = [[question, text] for text in candidates]
    scores = reranker.predict(pairs)

    # 3. Пересортировка и обрезка до top_n_final
    ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
    return [text for text, score in ranked[:top_n_final]]

Несколько практических деталей, которые легко упустить:

  • Reranker и эмбеддер — разные модели, менять их местами нельзя. Эмбеддер отвечает за скорость поиска по всей базе, reranker — за точность на малой выборке кандидатов.
  • Длина фрагмента имеет значение. Cross-encoder обрабатывает вопрос и фрагмент как одну последовательность, поэтому у него есть лимит токенов на пару — обычно 512. Слишком длинные чанки будут обрезаны, и часть текста не попадёт в оценку.
  • Батчинг ускоряет rerank. Вместо цикла по одной паре прогоняйте весь список сразу через predict() — реализации cross-encoder используют батч эффективнее.
  • Кэшировать нечего. В отличие от эмбеддингов документов, которые считаются один раз и хранятся в индексе, reranker считает скор заново для каждой новой пары — закладывайте это время в бюджет ответа.
  • Мониторьте, что реально меняется после rerank. Если top-1 почти всегда совпадает с top-1 до rerank, компонент не даёт эффекта на вашей базе — стоит сменить модель или вернуться к обычному векторному поиску.

Если у вас RAG собран не с нуля, а на готовой платформе вроде AnythingLLM, встроить произвольный cross-encoder в её пайплайн retrieve может быть не так прямолинейно, как в собственном коде — прежде чем внедрять reranker, стоит понять, где именно у вас теряется точность: подробнее об устройстве векторной базы под RAG — в статье как поднять векторную базу для RAG на сервере.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Qdrant

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Reranker заменяет векторный поиск?

Нет. Он работает только поверх уже найденных кандидатов — прогнать всю базу через cross-encoder на каждый запрос было бы слишком медленно на сколько-нибудь большом объёме данных.

Нужен ли GPU для reranker?

Не обязательно. Небольшие cross-encoder-модели (base-размера) справляются на CPU с разумной задержкой для 10–20 кандидатов; для большого потока запросов или тяжёлых моделей GPU ускорит работу, но это вопрос нагрузки, а не обязательное требование.

Можно ли использовать reranker вместо переранжирования top-K, а сразу как основной поиск?

Технически можно построить полный перебор через cross-encoder на маленькой базе (сотни документов), но с ростом базы это быстро упирается в линейный рост времени — отсюда и двухэтапная схема retrieve→rerank.

Насколько сильно reranker меняет качество ответов?

Зависит от базы и вопросов — на некоторых доменах эффект заметный (нужный фрагмент чаще попадает в топ), на однородных узких базах разница может быть минимальной. Единственный надёжный способ узнать — замерить на своём тестовом наборе вопросов, а не полагаться на общие оценки из чужих бенчмарков.

Есть ли смысл ставить reranker, если у меня и так всего 4 фрагмента в топе?

Обычно нет — если top-4 из векторного поиска и так стабильно релевантны на ваших вопросах, добавлять ступень пересортировки незачем. Reranker решает проблему, когда top-4 или top-5 без него часто мимо.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.