Масштаб и ANN-поиск

Урок объясняет, как рекомендовать среди миллионов товаров за миллисекунды с помощью приближённого поиска ближайших соседей.

ANN (Approximate Nearest Neighbors) — приближённый поиск ближайших к запросу векторов, который жертвует крошечной долей точности ради колоссального ускорения по сравнению с полным перебором.

Проблема масштаба

Two-tower и контентные модели свели рекомендацию к поиску ближайших товарных эмбеддингов к эмбеддингу пользователя. Но точный поиск (посчитать близость со всеми миллионами товаров и отсортировать) на каждый запрос слишком дорог. Если каталог — 10 миллионов товаров, а запросов — десятки тысяч в секунду, полный перебор просто не уложится в бюджет задержки.

import math

def cosine(a, b):
    num = sum(x*y for x, y in zip(a, b))
    na = math.sqrt(sum(x*x for x in a)); nb = math.sqrt(sum(y*y for y in b))
    return num / (na * nb) if na and nb else 0.0

# наивный (точный) поиск: считаем близость со ВСЕМИ товарами
query = [0.2, 0.9, 0.1]
items = {
    "i1": [0.1, 0.8, 0.2], "i2": [0.9, 0.1, 0.1],
    "i3": [0.2, 0.85, 0.15], "i4": [0.3, 0.3, 0.9],
}
scores = sorted(((cosine(query, v), k) for k, v in items.items()), reverse=True)
print("Топ-2 (точный перебор):", [k for _, k in scores[:2]])

Вывод:

Топ-2 (точный перебор): ['i3', 'i1']

На четырёх товарах это мгновенно. На десяти миллионах — нет: сложность линейна по размеру каталога.

Идея ANN

ANN строит специальную структуру-индекс, которая позволяет находить почти-ближайших, не сравнивая запрос со всеми. Главные семейства:

  • HNSW (графы малого мира) — навигация по слоям графа, где каждый шаг приближает к цели. Очень быстрый и точный, индустриальный фаворит.
  • IVF (инвертированные списки) — каталог заранее разбит на кластеры; ищем только в нескольких ближайших кластерах, а не во всём.
  • PQ (product quantization) — сжимает векторы, чтобы экономить память и ускорять сравнение.

Цена — приближённость: иногда настоящий ближайший сосед может быть пропущен. Но на практике потеря качества ничтожна, а ускорение — в сотни и тысячи раз.

Связь с векторными БД

Эти индексы — ровно та технология, что лежит в основе векторных баз данных (учебник «RAG и векторные БД»): FAISS, HNSWlib, а также Qdrant, Milvus, pgvector. Рекомендатель и RAG-поиск решают одну инженерную задачу — «найди ближайшие векторы быстро». Поэтому генерацию кандидатов в больших системах часто реализуют именно как запрос к векторной БД.

Как работает под капотом

Индекс строят офлайн из всех товарных эмбеддингов и периодически пересобирают при обновлении каталога/модели. Онлайн приходит эмбеддинг пользователя, индекс возвращает top-N приближённых соседей за единицы миллисекунд независимо от размера каталога (логарифмическая, а не линейная сложность у графовых методов). Параметры индекса (например, число проверяемых соседей) дают регулируемый компромисс «скорость ↔ точность».

Частые ошибки

  • Полный перебор на масштабе. Линейный поиск не выживает на миллионах товаров; нужен ANN-индекс.
  • Гнаться за 100% recall ANN. Последние проценты точности стоят непропорционально дорого; обычно достаточно ~95–99%.
  • Забыть про пересборку индекса. Устаревший индекс не содержит новых товаров — они выпадают из кандидатов.

Итоги

  • На масштабе точный перебор по каталогу невозможен — выручает ANN.
  • HNSW, IVF и PQ находят почти-ближайших на порядки быстрее.
  • Это та же технология, что в векторных БД (FAISS, Qdrant, pgvector).
  • Параметры индекса задают компромисс между скоростью и точностью.
Проверьте себя
1. Зачем в больших рекомендательных системах нужен ANN-поиск?
AЧтобы повысить точность до 100%
BПолный перебор по миллионам товаров слишком дорог; ANN находит почти-ближайших на порядки быстрее
CЧтобы отказаться от эмбеддингов
DЧтобы хранить меньше товаров
2. Как ANN-поиск связан с векторными базами данных?
AНикак не связан
BЭто одна и та же технология поиска ближайших векторов (HNSW, IVF), лежащая в основе FAISS, Qdrant, pgvector
CВекторные БД не используют ANN
DANN работает только с текстом