Qdrant - Vector Database
Гибридный поиск
Dense поиск пропускает точные термины. Sparse не понимает синонимы. Hybrid объединяет лучшее - и именно его используют production системы в Elastic, Weaviate и Qdrant для достижения лучшего recall.
- **Документация и knowledge base:** 'pandas 2.1 merge bug' - sparse находит версию, dense находит семантически близкие баг-репорты
- **E-commerce:** 'красные Nike кроссовки размер 42' - sparse по артикулу, dense по описанию
- **Медицинский поиск:** код МКБ-10 + описание симптомов - sparse для кодов, dense для клинического смысла
Предварительные знания
Зачем гибридный поиск: слабости dense и sparse
**Dense-only поиск** (обычные embeddings) хорошо понимает семантику, но пропускает точные совпадения по ключевым словам. Запрос «CVE-2024-1234» или «numpy v1.26.3» - dense модель не знает этих конкретных строк и вернёт семантически близкое, но не точное.
| Подход | Сильные стороны | Слабые стороны |
|---|---|---|
| Dense (embeddings) | Семантика, синонимы, перефразировки | Пропускает точные термины, версии, имена |
| Sparse (BM25/SPLADE) | Точные совпадения по ключевым словам | Нет семантики, не понимает синонимы |
| Hybrid (dense + sparse) | Семантика + точные термины | Чуть сложнее настройки, нужна обе модели |
**Практические сценарии для hybrid search:** поиск по технической документации (термины + семантика), e-commerce поиск (артикул + описание), медицинские базы (коды МКБ + симптомы), юридические документы (номера статей + смысл).
Пользователь ищет «React hooks useState tutorial для beginners». Какой подход лучше всего справится?
RRF Fusion: как объединяем результаты
**Reciprocal Rank Fusion (RRF)** - алгоритм слияния ранкингов из нескольких источников. Не нужно нормализовать score (у dense и sparse разные шкалы), нужны только позиции в ранкинге.
**Почему RRF лучше простого усреднения score?** Dense score - косинусное сходство [0,1]. Sparse score - BM25 или dot product [0, +∞]. Нельзя просто сложить. RRF работает только с позициями - универсален для любых источников.
| Метод fusion | Как работает | Плюсы | Минусы |
|---|---|---|---|
| RRF (Reciprocal Rank Fusion) | 1/(k + rank) для каждого источника | Не требует нормализации, robust | Игнорирует разрыв между score |
| Weighted sum | α×score_dense + β×score_sparse | Учитывает величину score | Нужна нормализация и подбор α, β |
| Dbsf (Distribution-Based) | Нормализация по распределению | Хороший баланс | Сложнее реализация |
Документ A на 1-м месте в dense, на 20-м в sparse. Документ B на 5-м в обоих списках. Кто выше по RRF (k=60)?
Query API с prefetch: новый подход Qdrant
**Query API** - новый unified API в Qdrant v1.7+, заменяет отдельные search/recommend/discover. Ключевая фича - `prefetch`: выполнить несколько поисков параллельно, затем объединить результаты через fusion.
**Как настроить коллекцию для hybrid search:** нужны оба вектора в одной точке - dense (named vector «text») и sparse (named sparse vector «text-sparse»).
**prefetch limit vs финальный limit:** prefetch должен быть больше финального. Правило: prefetch limit = 3-5× финального. При финальном limit=10 используйте prefetch limit=20-50. RRF нужны кандидаты для ранжирования.
В query API вы установили prefetch limit: 5 и финальный limit: 10. Что произойдёт?
Практика: полный pipeline гибридного поиска
**Полный pipeline hybrid search** требует две модели: dense embedding модель (OpenAI, sentence-transformers) и sparse модель (SPLADE, BM25). Разберём конкретный пример.
**FastEmbed + Qdrant:** Qdrant разработал FastEmbed - быструю Python-библиотеку для генерации dense и sparse векторов. Поддерживает SPLADE++ для production sparse embeddings. Работает локально без API-вызовов.
В вашем hybrid search dense поиск возвращает отличные результаты, а sparse - мусор (неправильная токенизация). Как изменится итоговый ranking через RRF?
Ключевые идеи
- **Dense-only** пропускает точные термины; **sparse-only** не понимает семантику - hybrid решает оба случая
- **RRF** объединяет ранкинги через 1/(k+rank) - не требует нормализации score
- **Query API + prefetch** - современный подход: несколько поисков → fusion → финальный результат
- **prefetch limit** должен быть в 3-5× больше финального limit
- В production: FastEmbed (SPLADE++) для sparse, OpenAI/sentence-transformers для dense
- Помните hook? Production системы используют hybrid - теперь вы знаете почему и как
Что дальше
Hybrid search настроен. Следующий шаг - работа с несколькими векторами на одну точку.
- Named Vectors — Несколько векторов (текст + изображение) в одной точке
- Фильтрация по payload — Добавить фильтры к hybrid search для ещё точнее поиска
- Sparse векторы — Подробнее о SPLADE и BM25 в Qdrant
Вопросы для размышления
- Для какого из ваших текущих проектов имеет смысл hybrid search? Где dense-only не справляется?
- Как выбрать prefetch limit? Какие trade-offs между памятью, скоростью и качеством?
- Если нужно добавить третий источник (например, title-only dense), как изменится prefetch конфигурация?