Комментарии 22
Спасибо, интересно!
Добрый день. У меня появилась идея для вашего поиска. Можно как-нибудь выделить одно слово, чтобы в выдаче были только товары, где это слово встречается, а других товаров не было бы видно. Предлагаю, например, заключить нужное слово в кавычки.
Приветствую! Ты имеешь в виду что-то похожее на уточнение запроса в google?
У нас были когда-то идеи в эту сторону --- а-ля предоставить пользователю больше управляемости поиском. Но, кажется, этой функцией будут пользоваться, дай бог, 0.1% юзеров (я был бы в их числе, да...).
Сейчас мы двигаемся в сторону того, чтобы пользователю нужно было приложить минимум усилий для нахождения нужного товара. Не всегда это получается... Но мы точно на верном пути)
P.S. Насколько мне не изменяет память, предлагаемый тобой функционал раньше был в поиске Авито. Вопрос: пользовались ли юзеры им? Ребята из Авито, если вы тут, то, может, подскажите пару интересных фактов про статистику использования?
интересно, а у вас есть репа на hf где можно какие-то открытые варианты обученной модели и открытые сеты данных посмотреть? (амазон например делится подобными данными)
Привет! Такого нет, и мы в целом даже не задумывались об этом. Можно будет поднять этот вопрос с руководством)
Тут добавлю, что идея с выложенным датасетом мне нравится. Сейчас не хватает поисковых или рекомендательных датасетов, которые состоят из десятков или сотен миллионов документов. Да, Яндекс выкладывал свой рекомендательный датасет по музыки, но он со всем не NLP-й.
Про веса моделей всё сложнее, так как без наших данных они в целом не особо применимы. По нашим наблюдениям, модели очень чувствительны к тому, на чём они обучаются и на чём инферятся. И при публикации весов без наших данных вы, скорее всего, не сможете получить адекватную работу модели, что вызовет очень много вопросов к нам)
Привет, статья интересная, очень крутые технологии! Спасибо, что поделились!
Можно ли писать запросы типа такого, когда ищешь не что-то конкретное, а чтобы ИИ порекомендовал что-нибудь? Запрос: подбери подарок на день рождения для мальчика 10 лет в пределах 10к рублей и не машинка?
Прикольно, интересно, что прирост «самый большой» за 4 года.
Типа, если бы раньше был только текстовый поиск (с бизнес-правилами), то никаких новых токенов QP бы не сгенерила, т.к. все токены, по которым мы документ находили, уже являются токенами документа. А получается, что все новые токены — это попытка тыкнуть в ретро и сказать: «На самом деле семантический ANN просто "находил" эти слова, давайте добавим их в индекс».
При этом понятно, что находил он дофига слов, и не все из них к клику/добавлению в корзину приводили, т.е. мы как бы так дообучаемся + интерпретируем одновременно.
P.S. Когда я начинал писать этот комментарий, я обратил внимание только на «интерпретируем»-часть, мне показалось странным, что прирост получился самый большой. Пока писал — понял, что мы ещё и дообучаемся всё-таки, ведь выбираем только те слова запроса, где часто кликали. И из странного оно стало просто интересным.
Получается, QP — способ избавиться от ANN в проде, сохранив его семантику, но только ту часть, которая реально работала
Привет! Пару моментов:
1) У нас никогда не было ANN в проде в поисковой части. Как верно было сказано в одном из замечаний, ANN был только в рекламной части.
2) QP генерирует новые токены. За счёт огромного количества данных обучаются неочевидные паттерны, расширяется лексикон документа.
Возможно, я тут немного не понял твой ход мыслей, поэтому ответ мог получиться не самым понятным)
Да, я ошибся. Я подумал, что этот метод прикольно решает такой кейс:
Есть какой-то семантический поиск на векторах в проде;
Вот пользователь по запросу «Корова» нашёл «Отличное молоко»;
Мы это заметили в логах и добавили токен «корова» к айтемам, вектора которых близки к «Отличному молоку»;
После этого векторный поиск можно убрать.
Ну и в этой схеме казалось, что без векторного поиска она не имеет смысла: «корова» найдётся только там, где этот токен уже есть. Но я не учёл, что будут айтемы, похожие по эмбедингу на «коровьи», но без самого слова — и их мы как раз добавим через логи.
Спасибо за статью и ответ :)
Спасибо @anton39reg за отличную статью! Очень компетентный анализ проблемы!
Привет.
А можете пожалуйста вот тут пояснить
> И последнее: обучение на кросс-энтропию избавляет нас от проблемы многих ранжирующих лоссов — подбор hard negatives.
почему такое обучение решает проблему подбора HN и в чем тут, собственно, проблема?
Привет! Про проблему с hard negatives обычно пишут в куче статей по metric learning. Можно посмотреть какие-нибудь лекции --- там сто процентов будет освещаться этот вопрос)
Если попытаться объяснить на пальцах:
Слишком простой негатив (например, случайный из батча) несёт мало нового сигнала, когда уже есть более-менее обученная модель. Поэтому нужно извиваться и набирать негативы более умно. В том же SPLADE/ColBERT негативы на одном из этапов майнятся за счёт сортировки документов по BM25 и каким-то магическим эвристикам. Следующим этапом подбора негативов может стать предыдущая обученная модель. То есть новая модель учится на примерах старой модели + какие-то магические эвристики. Во всей этой истории главная проблема в том, что ты не можешь адекватно и быстро оценивать полученные негативы и доверяешься уже какой-то существующей, более "простой" модели. Поэтому может получиться как хорошо, так и плохо) А чтобы обучить хорошую ранжирующую модель, которой можно было бы доверять и дистиллировать, нужны хорошие негативы. И тут у нас получается замкнутый круг.
В нашем подходе мы просим как-то приблизить распределение, что сильно проще для модели с точки зрения обучения и не требует сбора таргета негативов. Тебе просто не нужно сравнивать два документа относительно какого-то якоря. Можно, конечно, попробовать понижать вероятность "шумных" токенов, но это какие-то синтетические изменения, которые портят чистый пользовательский сигнал и ведут к непредсказуемым последствиям.
т.е. под кросс-энтропией здесь понимается K-L Дивергенция?
https://en.wikipedia.org/wiki/Kullback–Leibler_divergence#Cross_entropy
Супер статья, спасибо, а такой вопрос: как я понимаю, используемый токенизатор является +- стандартным, где пробел не является символом
Не думали ли делать что-то типа https://github.com/google/sentencepiece, где у тебя обучение на сырых данных и токенами могут быть как раз последовательности типа "type c" / "apple iphone" / "зубная щетка"?
Привет! У нас по дефолту идёт разбиение по пробелу, да. Вариант с SentencePiece или Byte-Level BPE пока не дотащили до АБ-теста. Такой токенизатор как раз рассматривали как первый подход к N-граммам) Как пример, они выучивали что-то типа: ["ноутбук 15.6", "картины по номерам", "наволочки 70x70", ...].
Когда пользователь вводит запрос, запрос разбивается на
query partsпри помощи токенизатора. Затем отправляется обычный запрос в обратный индекс, построенный на основе предсказанныхquery parts
Подскажите, а как выполняется обработка опечаток в таком подходе?
Привет!
Все исправления опечаток применяются при построении запроса в индекс другой командой. То есть на самом деле механизм чуть более сложный, чем я описал. При построении запроса нужно: учесть все фильтры, применить опечаточник, токенизировать запрос, учесть min should match и qp idf эвристику и т.д.
Про детальную работу опечаточника я не подскажу, глядишь, ребята когда-нибудь тоже доберутся написать статью про это!
Здравствуйте. Как вы решаете проблему морфологии?
В Query Prediction Ozon модель предсказывает токены запросов на основе BPE-токенизатора - покрывает ли это полноценно русскую морфологию (падежи, времена, множественное число), или требуется дополнительная лемматизация для поиска товаров вроде 'беговые кроссовки' vs 'кроссовки для бега'?
Приветствую!
Можно сказать, что проблема морфологии решается за счёт эвристики min should match. Она позволяет учитывать не все токены запроса при получении ответа из индекса. Таким образом, падежи, времена, множественное число могут просто не учитываться при ответе. Поэтому получается «естественная» лемматизация.
Тут нужно детальнее смотреть на отдельные примеры: сколько токенов запроса сматчились в документе, какое влияние оказали суффиксы и приставки на финальный скор.
Скажите я правильно резюмирую вашу статью?
Статья описывает эволюцию системы Query Prediction (QP) в Ozon: от ANN к гибридному подходу на базе обратного индекса и нейросетей для улучшения поиска товаров.
Исходная проблема
Раньше использовали ANN (Approximate Nearest Neighbors) для семантического поиска, но это работало плохо на хвостовых запросах (редкие, длинные фразы вроде сленга или описаний). Масштаб Ozon (миллиарды запросов) требовал скорости и точности.
Путь перехода
Перешли на классический поиск по обратному индексу (Elasticsearch-like) с предсказанием вероятных запросов для товаров.
Обучили BERT-like модель (QP-модель) на логах: вход — описание товара, выход — топ-50 токенов запросов (BPE-токенизатор, 65К словарь из реальных поисков).
Индексация: для каждого товара сохраняют предсказанные токены; поиск — матчинг запроса с этими токенами + ранжирование.
Итоговый результат
QP покрывает 80%+ запросов лучше ANN, особенно на long-tail; скорость — миллисекунды. Планы: N-граммы, морфология, персонализация. Отказ от ANN упростил систему и повысил релевантность (метрика: добавления в корзину).
---
Скажите у вас только одна метрика качества поиска "добавление в корзину" или есть более хитрые типа "холостых сессий", "доуточнение поиска" и т.д.?
Query Prediction, или как мы отказались от ANN и полюбили обратный индекс