Векторный поиск
| Задача | найти k векторов, ближайших к вектору запроса |
|---|---|
| Точный поиск | полный перебор (kNN) |
| Приближённый поиск | ANN — HNSW, IVF, DiskANN, ScaNN |
| Сжатие | продуктовая (PQ), скалярная и бинарная квантизация |
| Метрики качества | recall@k, задержка, память |
| Библиотеки | FAISS, hnswlib, ScaNN |
| Хранилища | pgvector, Qdrant, Milvus, Weaviate, Elasticsearch, OpenSearch |
Векторный поиск — поиск объектов по близости их векторных представлений. Тексты, изображения или товары заранее превращаются в эмбеддинги — векторы, в которых похожие по смыслу объекты расположены рядом. Запрос тоже превращается в вектор, и система находит k ближайших к нему векторов в коллекции. В отличие от поиска по ключевым словам, векторный поиск находит «машину» по запросу «автомобиль» и правильный раздел документации по вопросу, сформулированному своими словами.
Векторный поиск — центральная часть RAG, рекомендательных систем, поиска по изображениям и обнаружения дубликатов.
Точный и приближённый поиск
Точный поиск (kNN) сравнивает запрос со всеми векторами коллекции. Он прост и гарантирует правильный результат, но время растёт линейно: миллион векторов размерности 1024 — это миллиард умножений на каждый запрос. Для тысяч и десятков тысяч векторов этого достаточно, особенно на GPU.
Приближённый поиск ближайших соседей (ANN) использует индексы, которые проверяют лишь малую часть коллекции. Он находит почти всех настоящих соседей — доля найденных называется полнотой (recall@k) — но работает в сотни и тысячи раз быстрее. На практике полнота 95–99% при задержке в миллисекунды — обычный компромисс.
Основные алгоритмы
| Метод | Идея | Сильные стороны | Слабые стороны |
|---|---|---|---|
| HNSW | многоуровневый граф «тесного мира»: поиск спускается от дальних связей к ближним[1] | высокая полнота и скорость, добавление на лету | много памяти, долгое построение |
| IVF | векторы разбиты на кластеры, поиск только в ближайших | быстро строится, экономнее по памяти | полнота зависит от числа просматриваемых кластеров |
| PQ (продуктовая квантизация) | вектор делится на части, каждая кодируется номером ближайшего центроида[3] | сжатие в десятки раз | потеря точности, нужен пересчёт лучших кандидатов |
| DiskANN | граф, хранимый на SSD | миллиарды векторов на одном сервере | сложнее в эксплуатации |
| ScaNN | анизотропная квантизация от Google[4] | высокая скорость на CPU | меньше интеграций |
Библиотека FAISS от Meta реализует большинство этих методов и их комбинации, например IVF+PQ, на CPU и GPU.[2] Сравнивать алгоритмы на одинаковых данных позволяет открытый набор тестов ANN-Benchmarks.[6]
Пример
import faiss
import numpy as np
d = 768 # размерность эмбеддингов
xb = np.random.rand(100_000, d).astype("float32")
faiss.normalize_L2(xb) # для косинусного сходства
index = faiss.IndexHNSWFlat(d, 32, faiss.METRIC_INNER_PRODUCT) # 32 связи на узел
index.hnsw.efConstruction = 200
index.add(xb)
q = np.random.rand(1, d).astype("float32")
faiss.normalize_L2(q)
index.hnsw.efSearch = 64 # больше — точнее, но медленнее
scores, ids = index.search(q, 5) # 5 ближайших соседей
В продакшене индекс обычно живёт не в памяти скрипта, а в хранилище: в PostgreSQL через расширение pgvector или в специализированной векторной базе.
Фильтрация
Реальные запросы почти всегда сочетают смысловую близость с условиями: «документы этого клиента», «товары в наличии дешевле 5000 рублей», «статьи после 2024 года». Есть два наивных подхода — отфильтровать после поиска (рискуя получить пустой результат) или до поиска (теряя преимущества индекса). Современные системы поддерживают фильтрацию прямо во время обхода индекса; при выборе хранилища стоит проверять именно поиск с фильтрами на своих данных.
Гибридный поиск и переранжирование
Эмбеддинги хорошо передают общий смысл, но слабо работают с точными совпадениями: номерами ошибок, артикулами, именами функций, редкими терминами. Поэтому распространён гибридный поиск: параллельно выполняются векторный и полнотекстовый поиск (BM25), а списки объединяются, например методом обратного рангового слияния (RRF), где документ получает сумму величин 1 / (60 + ранг) из каждого списка.[5]
Затем лучшие 50–100 кандидатов можно переранжировать более точной, но медленной моделью (cross-encoder, reranker), которая читает запрос и документ вместе. Эта двухэтапная схема — быстрый отбор и точная сортировка — стандарт качественного поиска.
Практические советы
- Используйте одну и ту же модель эмбеддингов для документов и запросов; при смене модели переиндексируйте всё.
- Качество поиска чаще определяется подготовкой данных — нарезкой на фрагменты (Чанкинг документов), очисткой и метаданными, — чем выбором алгоритма индекса.
- Меряйте полноту на своём наборе запросов с известными правильными ответами, а не только скорость.
- Начинайте с простого: точный поиск или pgvector; специализированная инфраструктура нужна на десятках миллионов векторов.
См. также
- Эмбеддинг
- pgvector и векторные БД
- RAG (генерация с дополнением поиском)
- Чанкинг документов
- Индекс (базы данных)
Источники
- Yu. Malkov, D. Yashunin — Efficient and robust approximate nearest neighbor search using HNSW graphs (2016)
- J. Johnson, M. Douze, H. Jégou — Billion-scale similarity search with GPUs (FAISS, 2017)
- H. Jégou, M. Douze, C. Schmid — Product Quantization for Nearest Neighbor Search (IEEE TPAMI, 2011)
- R. Guo et al. — Accelerating Large-Scale Inference with Anisotropic Vector Quantization (ScaNN, 2019)
- G. Cormack et al. — Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods (SIGIR 2009)
- ANN-Benchmarks