Reranking in RAG: two-stage retrieval (bi-encoder recall -> cross-encoder precision). Three scenarios: 1) two-stage cross-encoder rerank pipeline (Cohere Rerank-3, BGE-v2-m3) over top-100 candidates from hybrid (dense+BM25+RRF) retrieval, sorting to top-10 for LLM context; 2) recall@10 lift comparison without rerank vs with rerank; 3) LLM-as-reranker for high-stakes medical/legal Q&A. ADR on cross-encoder vs LLM-rerank cost/quality tradeoff.
"Bi-encoder выбрасывает 99% мусора. Cross-encoder упорядочивает оставшийся 1%. LLM-rerank рассуждает о близких кандидатах. Три разных задачи — три разных инструмента."
Vector search (bi-encoder) — это recall-машина. За 8ms она достаёт top-50 кандидатов из миллионов чанков, но ранжирует их по cosine similarity между независимо посчитанными эмбеддингами query и документа. Модель не видит query и doc вместе — она видит две точки в 1536-мерном пространстве и считает угол. Этого достаточно чтобы отделить относящееся к делу от полностью левого, но недостаточно чтобы упорядочить близкие кандидаты по реальной релевантности.
Симптомы которые лечатся reranking:
Cross-encoder делает один transformer forward pass на каждую пару (query, doc) — модель видит оба текста в одном контексте, через self-attention находит пересечения и отдаёт один scalar score. Это в 100-1000 раз дороже одного similarity-сравнения, поэтому работает только на маленьком candidate set (top-50-100 от первой стадии).
Стандартный production lift: +20-40% nDCG@10, recall@5 поднимается с 65% до 88% на типичном RAG eval. Цена — +100-200ms latency и +$2 на 1000 запросов (Cohere) или $540/мес GPU (self-host BGE).
Две стадии retrieval — это не "ещё один шаг", это две принципиально разные архитектуры с разными ограничениями:
| Bi-encoder (Stage 1) | Cross-encoder (Stage 2) | LLM-as-reranker (Stage 3, опц.) | |
|---|---|---|---|
| Что считает | sim(emb(q), emb(d)) | score(transformer(q ⊕ d)) | listwise rank(q, [d1..dN]) |
| Видит query+doc вместе? | Нет | Да (по парам) | Да (весь список) |
| Latency на top-50 | 8ms (предвычислено) | 50-200ms | 1-3s |
| Cost на 1K запросов | $0.05 (Pinecone) | $2 (Cohere) | $20-100 (Claude/GPT-4) |
| Когда уместен | всегда первый stage | top-50-100 для precision | high-stakes / eval generation |
| Главный failure | recall@5 ~60% на long-tail | domain mismatch без fine-tune | position bias, nondeterminism |
Аналогия: bi-encoder это поиск в библиотечном каталоге по жанру — быстро отсекаешь 99% книг, но среди оставшихся 50 нужно ещё пролистать корешки. Cross-encoder — пролистал корешки и сравнил каждую с запросом. LLM-rerank — попросил библиотекаря-эксперта посмотреть на 50 книг разом и упорядочить с обоснованием.
Ключевая интуиция: bi-encoder теряет информацию необратимо. Когда query и doc независимо превращены в векторы, любой нюанс взаимодействия (например, "lock-striping" в query ↔ "internal segmentation" в doc) растворяется в усреднённой проекции. Cross-encoder не теряет — query токены реально аттендят к doc токенам.
Три группы:
Stage 1: recall — параллельный hybrid retrieval.
vectordb (HNSW dense ANN, top-50) — семантическое сходство, ловит синонимы и парафразы.bm25 (sparse inverted index, top-50) — точные термины, имена, аббревиатуры, редкие слова которых не было в training corpus эмбеддера.rrf (Reciprocal Rank Fusion) — объединяет два списка через score = Σ 1/(60+rank_i), дедуплицирует, отдаёт top-100 уникальных.Stage 2: rerank — выбор precision-движка.
cross-encoder (Cohere Rerank-3 / BGE-v2-m3) — production default, pairwise scoring.llm-rerank (Claude/GPT-4, listwise) — опциональный третий tier для high-stakes.Generation — llm синтезирует ответ из top-10 контекста.
ADR-001 на ноде cross-encoder зафиксирован выбор между тремя путями (no-rerank / cross-encoder / LLM-rerank), trade-offs и условия применения каждого.
1. TWO-STAGE — bi-encoder recall + cross-encoder precision. Production-default. Параллельный fan-out на vector DB и BM25, RRF-fusion, cross-encoder скорит 100 пар, отрезает top-10, в LLM. Латентность ~200ms p99, lift nDCG@10 +20-40%.
2. COMPARE — без rerank vs с rerank. Один и тот же запрос идёт двумя путями. PATH A показывает как top-10 от чистого ANN кучкуется тематически и пропускает правильный чанк (rank=43). PATH B показывает как hybrid+rerank поднимает тот же чанк до rank=2. Видна цена ошибки.
3. LLM RERANK — listwise reasoning. Medical Q&A где accuracy важнее latency. Top-50 кандидатов отдаются Claude/GPT-4 с промптом "rank by clinical relevance". LLM рассуждает контекстуально (нюанс "atypical presentation in diabetic women" ловится), но 1.5s latency и три failure-mode: position bias, nondeterminism, context-window cap. Заканчивается tournament-паттерном: bi-encoder top-200 → cross-encoder top-20 → LLM top-5.
ADR-001 на ноде cross-encoder — Cross-encoder rerank vs LLM-as-reranker vs no-rerank.
Контекст: после bi-encoder retrieval top-50-100 — выбор как переранжировать в top-3-10 для LLM context.
Три варианта:
Решение: default — cross-encoder rerank на top-50-100 для production RAG. Cohere Rerank-3 если ok managed (zero ops, multilingual из коробки), self-host BGE при >30K queries/day (crossover к экономии). LLM-rerank только для (a) high-stakes ответов где accuracy >> latency, (b) eval/golden-set генерации для тренировки cross-encoder, (c) когда top-K близки по similarity и нужен listwise reasoning. Не использовать LLM-rerank в interactive chat — 2s = death UX. Skip rerank entirely если top-K уже малый (<10), recall@5 на eval >95% без rerank, или latency budget <100ms total.
Если выбран cross-encoder — обязательно eval (nDCG@10, MRR) до и после, иначе платишь latency без подтверждённого lift. Rerank top-1000 — антипаттерн, экспоненциальная стоимость; sweet spot top-50-100.
max(rerank_scores) < threshold, у тебя нет релевантного ответа. Не подсовывай LLM шум — отдай "no relevant information found" честно.