Общая архитектура модели: генеративный encoder-decoder трансформер. На входе описание пользователя, на выходе semantic ids - специальные рекомендательные токены. Вообще специализированная токенизация - важная часть мультмодальных LLM. В рекомендациях была впервые введена в TIGER. В OneRec реализуется собственная модификация токенизации, о которой поговорим в другой раз.
Encoder-decoder не очень частый выбор для рекомендательных трансформеров. Мы в команде последние несколько лет применяли encoder (bidirectional attention, все входы видят друг друга). Сейчас, с появлением Argus, стали использовать decoder (авторегрессивный, каждый токен видит только своё прошлое). Обычно в рекомендациях используется impression level обучение - количество обучающих сэмплов равно числу запросов за рекомендацией. Подход с каузальной маской позволяет "сжимать" большое число сэмплов в один, уменьшая сложность обучения с
O(n^3) до O(n^2), где n - число событий на пользователя (эффект хорошо описан в Actions...).Выбор архитектуры, похоже, продиктован 2 соображениями: облегчением инференса и несовпадением форматов входа и выхода.
В encoder используется
ffw_hidden_dim = 2 * hidden_dim. Такой выбор параметров я встречаю первый раз. В оригинальном Attention Is All You Need использовали 4, сейчас чаще всего встречается 2/3 × 4 (LLaMA: Open and Efficient Foundation Language Models). В 0.9b версии добавляют MoE в decoder, а в 2.6b ещё и в encoder. Концепция MoE, которая уже довольно широко применяется в LLM, мне видится перспективной, будем обязательно пробовать. Наличие MoE у самых больших версий OneRec дополнительно объясняет некоторое затухание scaling law, которое прослеживается на их графиках.Вход и выход модели значительно отличаются. Если на выходе semantic ids, то на входе события описываются целым набором фич. Мы формируем входы в трансформер похожим способом (Personalized Transformer-based Ranking for e-Commerce at
Yandex). В OneRec сжимают историю через несколько маршрутов: 20 самых свежих соыбтий, 256 позитивных, а также 100000 longterm, которые предварительно кластеризуются в 2000, а затем сжимаются в 128 с помощью QFormer (идея вдохновлена TWIN V2 от тех же Kuaishou).
Оба подхода вносят inductive bias и не очень сильно мне нравятся, в долгосрочной перспективе хочется от них уйти.
Представление событий в виде набора фич делает наш "токен" очень "богатым", а хотелось бы просто разделить задачу на максимально примитивные кусочки и позволить модели "правильно" их скомбинировать: item-action схема из Actions..., context-item-action из Argus и Semantic ids двигают модель именно в таком направлении.
Набор событий в историю позволяет использовать техники сжатия (в авторегрессивном формате применить их не получится), однако возвращает обучение в impression level, значительно замедляя тренировку. Побороть несовпадение входа и выхода можно с помощью каких-нибудь interleaved схем (Sparse Meets Dense: Unified Generative Recommendations with Cascaded Sparse-Dense Representations). Поддержать же длинный контекст в проде тяжело. Не только из-за долгого инференса, но и из-за значительных проблем на уровне хранилища и процессинга.
Интересный факт, который расходится с моей интуицией: авторы утверждают, что события на входе в трансформер можно описывать только с помощью semantic ids, отказавшись от стандартных sparse ids и больших матриц эмбеддингов для документов. У трансформера "память" находится в feed-forward слоях (Transformer Feed-Forward Layers Are Key-Value Memories), которых, как мне казалось, не должно хватать с учётом пока ещё скромных размеров модели. На наших внутренних замерах результат предварительно подтверждается, но будем перепроверять.