Как сравнивать эмбеддинги запросов и товаров для поиска релевантных кандидатов
Что проверяют
Понимаете ли вы, как устроен отбор кандидатов в двухэтапном поиске: сначала быстро достать сотни объектов из миллионов, потом аккуратно их ранжировать. Следом обычно спрашивают, как это масштабировать и как оценить качество отбора.
Как отвечать
Начните с архитектуры: запрос и товар кодируются в векторы, чаще всего двухбашенной моделью (two-tower, bi-encoder), где башни обучены так, чтобы релевантные пары оказывались рядом. Эмбеддинги товаров считаются заранее, запрос кодируется онлайн.
Дальше метрика близости:
- скалярное произведение: то, что обычно оптимизирует модель при обучении с in-batch негативами. Длина вектора тоже несёт сигнал, например популярность товара;
- косинусное сходство: скалярное произведение нормированных векторов. После L2-нормализации косинус, dot product и евклидово расстояние дают один и тот же порядок;
- евклидово расстояние: уместно, если модель учили с ним, например с triplet loss.
Главное правило: метрика поиска совпадает с той, на которой училась модель.
Затем поиск. Полный перебор точен, но на миллионах товаров дорог, поэтому берут приближённый поиск (ANN): графовый индекс HNSW, IVF с квантованием в Faiss, ScaNN, векторные базы вроде Qdrant, Milvus или pgvector в PostgreSQL. Параметры поиска (ef у HNSW, nprobe у IVF) задают компромисс между полнотой и задержкой.
Качество отбора меряют recall@K на отложенных парах «запрос, покупка», а сам ANN сверяют с точным перебором. Отобранные кандидаты уходят в ранжирующую модель: кросс-энкодер или градиентный бустинг с фичами цены, наличия и истории пользователя.
Где спотыкаются
Смешивают метрики: модель учили на dot product, а в индекс кладут нормированные векторы и ищут по косинусу. Порядок меняется, recall падает, и без офлайн-оценки этого никто не замечает.
Сравнивают векторы из разных моделей или разных версий одной модели. После переобучения эмбеддинги всех товаров нужно пересчитать, иначе запрос и каталог живут в разных пространствах.
Считают близость векторов итоговой релевантностью. Эмбеддинг хорош для отбора, но не знает про наличие, цену и свежесть; без ранжирования и фильтров выдача получается похожей, но бесполезной.