AI-инжиниринг

Advanced RAG: hybrid search, re-ranking, query expansion, self-RAG

Цели урока

  • Понять почему naive RAG ломается на реальных данных и как диагностировать проблему
  • Реализовать hybrid search (BM25 + dense vectors) с Reciprocal Rank Fusion
  • Интегрировать cross-encoder reranking через Cohere или sentence-transformers
  • Применять query transformation: HyDE (Gao 2022), multi-query, step-back prompting
  • Освоить self-RAG и contextual compression для критичных доменов

Предварительные знания

  • RAG pipeline, pgvector, embeddings
  • RAG Fundamentals

Базовый RAG находит похожий текст. Advanced RAG находит правильный ответ. Разница - precision@5: базовый 60-70%, с reranking + hybrid search 85-92%. Это граница между "работает" и "можно продавать". Notion AI перешёл от naive RAG к hybrid + reranking - hallucination rate упал на 40%. Perplexity строит свой поиск на этих же принципах и делает 100M+ запросов в месяц.

  • Perplexity AI - hybrid search + re-ranking как core технологии поиска, 100M+ запросов/месяц
  • Notion AI - переход от naive RAG к hybrid + reranking снизил hallucination rate на 40%
  • Bloomberg GPT - domain-specific re-ranking для финансовых документов с терминологией
  • Abridge и Nabla (медицинские AI) - self-RAG для верификации каждого утверждения перед показом врачу
  • Anthropic Contextual Retrieval (2024) - комбинация BM25 + embeddings + contextual chunk summaries снижает пропуски на 67%

От Lewis 2020 до Contextual Retrieval 2024

**Lewis et al. 2020 (Facebook AI Research)** - оригинальный RAG paper: DPR encoder + BART generator, первый раз показано что retrieval + generation работает лучше чем pure LM на knowledge-intensive tasks. **Khattab et al. 2020 - ColBERT** - late interaction: вместо одного embedding на документ - матрица токен-embeddings, MaxSim для scoring. Точнее bi-encoder, быстрее cross-encoder. **Gao et al. 2022 - HyDE**: hypothetical document embedding как pre-retrieval трансформация, +5-10% recall на BEIR benchmark. **Anthropic Contextual Retrieval 2024**: BM25 + embeddings + LLM-generated chunk context (каждый chunk обогащается summary его места в документе) - снижение failed retrievals на 67%.

Где ломается Naive RAG

Naive RAG на демо выдаёт 95% accuracy - 10 тестовых вопросов, идеальные чанки, удобные запросы. Production - 55% на реальных пользователях. Первая мысль: поменять модель. Неверно. GPT-4 не поможет, если контекст не найден. Проблема всегда в retrieval.

СценарийПроблема Naive RAGПример
Keyword mismatchVector search не находит exact termsЗапрос "ошибка 500 при оплате" - документ содержит "PaymentGatewayException", embedding не совпадает
Сложный вопросОдин embedding не может выразить multi-hop query"Как связаны лимиты rate-limit и стоимость API?" - нужны chunks из разных разделов
Неточный retrievalTop-5 chunks содержат 2 релевантных и 3 шумовыхLLM отвлекается на нерелевантные chunks и даёт размытый ответ
Ambiguous queryПользователь спрашивает неточно"Как настроить авторизацию?" - OAuth? JWT? API keys? RBAC?

Advanced RAG - это три слоя хирургии вокруг поиска. Не замена, а надстройка:

  1. **Pre-retrieval** - улучшить запрос до поиска (query transformation, HyDE от Gao et al. 2022)
  2. **Retrieval** - улучшить сам поиск (BM25 + dense hybrid, multi-query с RRF)
  3. **Post-retrieval** - отфильтровать результаты (cross-encoder reranking, contextual compression)

Каждый слой добавляется независимо. Hybrid search - всегда. Re-ranking - когда precision важнее latency. HyDE - когда вопросы короткие и неоднозначные. Комбинация всех трёх - Contextual Retrieval (Anthropic, 2024), снижение пропусков на 67%.

Пользователь спрашивает "ошибка при деплое", но документация описывает проблему как "DeploymentFailedException in CI/CD pipeline". Naive RAG не находит ответ. Какая это проблема?

Hybrid Search: BM25 + dense vectors

Два мира - два провала в одиночку. Vector search находит "как уменьшить задержку" рядом с "latency optimization" - семантика работает. Но спроси "ошибка E-4012" - embedding не знает что это за код. BM25 (TF-IDF на стероидах) найдёт E-4012 мгновенно, но не поймёт что "уменьшить задержку" и "optimize latency" - одно и то же.

МетодСильные стороныСлабые стороны
Vector (semantic)"Как уменьшить задержку?" → находит "latency optimization"Пропускает exact terms: "ошибка E-4012"
BM25 (keyword)Точное совпадение: "E-4012" → находит документ с этим кодомНе понимает синонимы: "уменьшить задержку" ≠ "latency"
Hybrid (BM25 + dense)Комбинирует: семантику + ключевые словаНужна настройка весов (alpha)

Склеивает два мира **Reciprocal Rank Fusion (RRF)** - не усредняет scores (они несопоставимы), а объединяет ранжирования. Документ на 1-м месте в BM25 и на 3-м в vector получает больше, чем тот что стоит на 10-м в обоих:

Реализация hybrid search с pgvector + PostgreSQL full-text search:

Параметр **alpha** подбирается эмпирически. Для технической документации (много кодов ошибок, имён API) - alpha 0.3-0.4 (больший вес keyword). Для общих вопросов - alpha 0.6-0.7 (больший вес semantic). Perplexity использует похожий баланс - это core их технологии поиска.

Больше chunks = лучше recall

Больше chunks = хуже precision, перегруженный reranker и больше шума в контексте

Можно взять top-100 вместо top-20 и recall формально вырастет - нужный документ попадёт в выборку. Но cross-encoder reranker перегружается: он делает forward pass для каждой пары (query, doc), и 100 пар вместо 20 - это +400ms latency. Плюс LLM получает контекст с шумом и начинает отвлекаться. Оптимальный диапазон - 15-25 кандидатов для reranker, 3-7 для финального контекста.

В hybrid search параметр alpha = 0.3 означает...

Re-ranking: cross-encoder и Cohere Rerank

Hybrid search вернул top-20 документов. Но ранжирование всё ещё грубое - cosine similarity между embedding запроса и embedding документа не учитывает тонкие смысловые связи. Bi-encoder кодирует query и doc независимо: они никогда не "видят" друг друга до момента сравнения.

Cross-encoder - другая архитектура. Query и document подаются вместе как один вход, модель делает полный attention между каждым токеном запроса и каждым токеном документа. Это медленно, но точно:

Bi-encoder (embedding)Cross-encoder (reranker)
Как работаетQuery и doc кодируются отдельно, сравниваются cosine similarityQuery и doc подаются вместе, модель выдаёт relevance score
СкоростьБыстро - doc уже закодирован, сравнение мгновенноеМедленно - нужен forward pass для каждой пары
ТочностьХорошаяЗначительно лучше - модель видит оба текста одновременно
МасштабМиллионы документовTop-20-50 кандидатов (post-retrieval)

Паттерн **retrieve-and-rerank** - стандарт production RAG. Широкая сеть на этапе retrieval, точный фильтр на этапе reranking:

Cohere Rerank - 1 доллар за 1000 запросов (каждый до 100 документов). Для self-hosted варианта - **bge-reranker-v2-m3** от BAAI (sentence-transformers), запускается на GPU через Hugging Face Inference. На CPU с 20 документами - около 300ms.

Почему cross-encoder точнее bi-encoder для ранжирования?

Query Transformation: HyDE, Multi-Query, Step-back

Пользователь пишет "почему не работает деплой". Четыре слова. Embedding этих четырёх слов - точка в vector space, маленькая и плохо направленная. Реальный ответ - многостраничный документ с богатым словарём. Расстояние между точкой-вопросом и облаком-документом огромное. Query transformation меняет саму точку до поиска.

HyDE - Hypothetical Document Embedding

Идея Gao et al. (2022): не ищи по embedding запроса - сгенерируй **гипотетический ответ** и ищи по его embedding. Гипотетический ответ написан в стиле документации, богатый терминами, длинный - embedding такого текста гораздо ближе к реальным документам в vector space.

Multi-Query - разбить вопрос на подзапросы

Step-back Prompting - обобщить вопрос

Вместо конкретного "почему NestJS middleware не ловит ошибки async?" - сначала спросить "как работает error handling в NestJS middleware?". Более общий запрос находит фундаментальные документы, которые содержат ответ на конкретный вопрос как частный случай.

HyDE хорош для Q&A по документации - вопросы короткие, документы длинные. Multi-Query - для сложных аналитических вопросов с несколькими аспектами. Step-back - для вопросов "почему X не работает?" где причина в принципе, не в деталях. На практике в RAPTOR и Contextual Retrieval (Anthropic 2024) комбинируются все три.

HyDE (Hypothetical Document Embedding) ищет по embedding...

Self-RAG и Contextual Compression

Что если пользователь спрашивает "сколько будет 2+2?" - зачем вообще делать retrieval? И что если из найденных 5 chunks только один реально релевантен - зачем отдавать все пять в контекст? **Self-RAG** - паттерн где модель сама принимает оба решения: нужен ли поиск, и что из найденного использовать.

Self-RAG: модель как критик

  1. LLM получает вопрос и решает: нужен ли retrieval? (некоторые вопросы модель знает и без базы)
  2. Если да - retrieval, получить chunks
  3. LLM оценивает каждый chunk: релевантен? Полезен для ответа?
  4. Генерация ответа только на основе одобренных chunks
  5. LLM оценивает финальный ответ: подтверждён контекстом? Полезен пользователю?

Contextual Compression

Chunk на 500 токенов найден - но ответ на вопрос спрятан в 2 предложениях из 20. Остальные 18 - шум, который занимает context window и сбивает модель. **Contextual compression** (LangChain popularized, Anthropic Contextual Retrieval 2024) извлекает только нужное.

Self-RAG и compression добавляют extra LLM calls. В production это +200-500ms latency и +0.001-0.01 доллара за запрос. Использовать когда accuracy критичнее скорости - медицинские, юридические, финансовые чатботы. Abridge и Nabla применяют именно это для верификации каждого утверждения.

Contextual compression в RAG решает проблему...

RAG Fusion и Parent Document Retriever

RAG Fusion

RAG Fusion комбинирует Multi-Query и RRF в единый pipeline. Генерируется несколько вариантов запроса, каждый ищет отдельно, результаты объединяются через Reciprocal Rank Fusion. Идея: одна формулировка вопроса - одна точка в vector space. Четыре формулировки - четыре точки, покрывающие больше пространства.

Parent Document Retriever

Маленькие chunks - точный retrieval, плохой контекст. Большие chunks - плохой retrieval, хороший контекст. Классический trade-off. **Parent Document Retriever** разрезает его пополам: хранит маленькие chunks для поиска (128 токенов), большие parent chunks для контекста (1024 токена). Ищет по маленьким, отдаёт большие.

Сводка всех advanced RAG техник и когда их применять:

ТехникаКогда использоватьOverhead
Hybrid SearchВсегда - baseline для production+10ms (SQL query)
Re-rankingКогда precision важнее latency+200ms, 0.001/query
HyDEQ&A по документации+300ms, 0.001/query
Multi-QueryСложные аналитические вопросы+300ms, 0.001/query
RAG FusionМаксимальный recall, критичная accuracy+500ms, 0.003/query
Self-RAGМедицина, юриспруденция, финансы+500ms, 0.005/query
Parent Doc RetrieverДлинные документы с контекстом+5ms (другая схема данных)
Contextual CompressionОграниченный context window+200ms, 0.001/query

Если в naive RAG ответы плохие - надо просто добавить больше документов в индекс. Чем больше corpus, тем лучше retrieval.

Качество retrieval упирается не в размер corpus, а в формулировку запроса и распределение релевантности. Hybrid search, re-ranking и query transformation бьют рост corpus в 3-5 раз чаще, чем сам corpus.

Интуиция от классических SQL/full-text баз: больше данных - точнее ответ. В RAG обратное: чем больше документов, тем выше вероятность, что наивный векторный поиск утонет в семантических близнецах и пропустит точное вхождение. Решает не объём, а ансамбль методов поверх одной и той же базы.

Parent Document Retriever ищет по маленьким chunks, но возвращает большие parent chunks. Зачем?

Больше chunks = лучше recall, можно брать top-100

Больше chunks = хуже precision, перегруженный reranker, больше шума в контексте

Recall формально растёт - нужный документ почти наверняка попадёт в top-100. Но cross-encoder делает forward pass для каждой пары (query, doc): 100 пар вместо 20 = +400ms. А главное - LLM получает контекст с шумом: 80 нерелевантных chunks среди 20 нужных и начинает галлюцинировать или давать размытые ответы. Оптимум: retrieve 15-25 кандидатов, rerank до 5-7, в контекст - не больше 5.

Ключевые выводы

  • Naive RAG ломается на keyword mismatch, сложных вопросах и ambiguous queries - проблема всегда в retrieval, не в модели
  • Hybrid search (BM25 + dense + RRF) - обязательный baseline для production, покрывает keyword mismatch без latency overhead
  • Cross-encoder reranking (sentence-transformers, Cohere) даёт +15-20% precision на top-5: модель видит query и doc вместе
  • HyDE (Gao 2022) ищет по embedding гипотетического ответа - для коротких вопросов по длинным документам
  • Self-RAG + contextual compression - для медицины, юриспруденции, финансов где hallucination недопустима
  • Contextual Retrieval (Anthropic 2024): BM25 + embeddings + chunk context summaries - 67% снижение пропусков

Вопросы для размышления

  • В каком из четырёх сценариев провала Naive RAG (keyword mismatch, multi-hop, noisy retrieval, ambiguous query) пострадает продукт больше всего в конкретном проекте?
  • Hybrid search добавляет +10ms, reranking +200ms, HyDE +300ms. Какой бюджет latency разумен для конкретного use case - и какую комбинацию выбрать?
  • Self-RAG добавляет ~5 LLM calls на один пользовательский запрос. При каком сценарии accuracy стоит этой цены?

Что дальше

Retrieval настроен, но его качество критически зависит от того, как разбиты документы. Chunking strategy - следующий рычаг оптимизации.

  • Chunking стратегии — Как правильно нарезать документы - fixed, recursive, semantic chunking
  • Conversation Memory — RAG в контексте чатбота - как совмещать retrieval с историей разговора
  • Evaluation — Как системно измерять качество RAG pipeline на golden datasets

Связанные уроки

  • aie-12-rag-fundamentals — Базовый RAG - фундамент для advanced техник
  • aie-09-embeddings — Dense retrieval строится на embedding quality
  • aie-10-vector-databases — HNSW-индекс Qdrant критичен для hybrid search
  • aie-14-chunking-strategies — Правильный chunking удваивает precision advanced RAG
  • prob-04-bayes — Reranking - posterior update поверх prior retrieval
  • ml-52-search-ranking — Cross-encoder reranking из search ranking теории
  • db-26-caching
  • db-28-search
Advanced RAG: hybrid search, re-ranking, query expansion, self-RAG

0

1

Войти