Как стать автором
Поиск
Написать публикацию
Обновить

ReLLaX: как научить большие языковые модели понимать долгосрочное поведение пользователей

Уровень сложностиСредний
Время на прочтение16 мин
Количество просмотров213

Всем привет! Меня зовут Никита Горячев. Сейчас работаю в качестве Senior Machine Learning Engineer в WB Tech - занимаюсь исследованиями в рекомендациях и LLM. До этого работал в МТС и Сбере, где тоже занимался рекомендашками. Написал книгу про LLMOps и RAG, также сейчас пишу книгу про вывод Speech AI моделей в прод. Хочу поделиться разбором интересной статьи, которую нашел у коллег из Китая! 

1. Введение

Рекомендательные системы давно стали частью нашей повседневной цифровой жизни. Каждый день мы сталкиваемся с ними, даже не задумываясь: Netflix предлагает новый сериал, Spotify подбирает плейлист, Ozon подсовывает товары «вам может понравиться». Всё это работает благодаря алгоритмам, которые анализируют последовательности наших действий — что мы смотрели, что покупали, что добавляли в избранное. Но история развития этих алгоритмов интересна тем, что в ней очень наглядно видна эволюция от простых методов к сложным моделям, и на каждом этапе возникали ограничения.

Первые подходы были просты: коллаборативная фильтрация и матричные разложения. Они позволяли находить пользователей со схожими интересами и предлагать им похожие объекты. Но такие методы видели только факт взаимодействия «пользователь–объект» и игнорировали порядок действий. Представьте человека, который годами смотрел супергеройские фильмы, но пару раз включил романтическую комедию для разнообразия. Для классической модели это всё сольётся в «средний вкус», без понимания динамики.

Затем появились последовательные модели: рекуррентные сети (RNN, LSTM, GRU), а позже трансформеры. Они смогли учитывать порядок и контекст, замечать, что интересы меняются во времени. Если раньше пользователь смотрел комедии, а потом резко переключился на боевики, модель фиксировала этот сдвиг. Казалось, проблема решена. Но оказалось, что у этих методов есть два слабых места: во-первых, они плохо масштабируются на длинных историях, а во-вторых, требуют тонкой настройки и много инженерных ухищрений.

Когда на сцену вышли Large Language Models (LLMs), исследователи загорелись идеей: а что если просто подать модели всю историю пользователя в текстовом виде? Ведь LLM умеют держать в контексте десятки тысяч токенов и демонстрируют потрясающую способность находить сложные связи. Мы могли бы сказать: «Пользователь посмотрел фильм X, потом фильм Y, затем купил товар Z…» — и модель должна бы сделать выводы. На первый взгляд, это выглядело как «серебряная пуля».

Но на практике вскрылась ключевая проблема, которую авторы статьи называют lifelong sequential behavior incomprehension — непонимание долгосрочного последовательного поведения. Казалось бы, если модель может держать в контексте 32 тысячи токенов, она должна прекрасно справляться с длинными историями. Реальность другая: LLM перегружается, теряется в шуме и не умеет выделять действительно значимые сигналы. В длинном списке событий важное тонет в случайном.

Пример здесь показателен. У пользователя 500 просмотренных фильмов, среди которых 100 боевиков, 50 комедий и 10 мюзиклов. Мы подаём LLM весь этот список. Вместо того чтобы сосредоточиться на главной закономерности («человек любит боевики»), модель «усредняет» и предлагает что-то случайное. Даже наличие большого контекста не спасает — модель не учится правильно его использовать.

Таким образом стало ясно: просто увеличивать длину контекста — это не решение. Важно структурировать данные, помогать модели выделять главное и правильно адаптировать её под задачу. Именно из этого понимания родилась идея ReLLaX (Retrieval-enhanced Large Language Models Plus). Авторы предложили рассматривать проблему комплексно и оптимизировать LLM сразу на трёх уровнях: на уровне данных (умное извлечение релевантных частей истории пользователя), на уровне подсказок (добавление знаний из классических рекомендательных моделей) и на уровне параметров (улучшенная адаптация через CFLoRA). Вместо того чтобы заставлять LLM бездумно «переваривать» всё подряд, ReLLaX создаёт правильные условия: подсовывает ей только важное, снабжает экспертными подсказками и дообучает так, чтобы модель начинала действительно понимать долгосрочное поведение пользователей.

Вот в этом и заключается главный сдвиг мышления: дело не в том, сколько данных мы дадим модели, а в том, как именно мы их организуем и встроим в её работу.

# Пример: даже если у пользователя очень длинная история,
# важно выбрать релевантные действия, а не просто последние.
# SUBR делает именно это — ищет семантически близкие объекты.

def subr_retrieve(user_history_item_ids, target_item_id, k=50):
    index, user_vecs = build_user_index(user_history_item_ids, item_vecs)
    q = item_vecs[iid2idx[target_item_id]][None, :]
    sim, I = index.search(q, min(k, len(user_history_item_ids)))
    selected = [user_history_item_ids[i] for i in I[0]]
    sims = sim[0].tolist()
    return selected, sims

Именно этот взгляд на задачу — от классической статистики через последовательные модели к LLM и их ограничениям — подводит нас к пониманию, почему ReLLaX стал важным шагом вперёд. Он показывает: чтобы LLM работали в рекомендациях, нужно не «заставлять» их потреблять больше, а научить их думать правильнее.

2. Основные компоненты ReLLaX

Итак, если мы согласились с тем, что LLM сами по себе не способны по-настоящему понимать долгосрочное поведение пользователей, возникает вопрос: что же с этим делать? Авторы ReLLaX предложили мыслить «полным стеком» и работать сразу на трёх уровнях — данных, подсказок и параметров модели. Это не три изолированных трюка, а единая архитектура, где каждый слой усиливает другой.

Первый уровень — работа с самими данными. В стандартных системах для обучения берут последние N действий пользователя: посмотрел он десять фильмов, именно их и передаём в модель. Но на самом деле последние действия не всегда отражают главное. Человек может всю жизнь быть фанатом боевиков, а вчера случайно включить комедию. Если в модель попадёт только эта «поверхностная» активность, она сделает неверный вывод. ReLLaX решает это через метод Semantic User Behavior Retrieval (SUBR). Идея в том, что мы смотрим на целевой объект — например, фильм, который хотим порекомендовать, — и ищем в истории пользователя именно те действия, которые семантически ближе всего к этому объекту. Для фильма Marvel это будут другие боевики, даже если они были просмотрены несколько месяцев назад. Таким образом контекст, который мы подаём LLM, получается фокусированным, очищенным от случайного шума.

def subr_retrieve(user_history_item_ids, target_item_id, k=50):
    index, user_vecs = build_user_index(user_history_item_ids, item_vecs)
    q = item_vecs[iid2idx[target_item_id]][None, :]
    sim, I = index.search(q, min(k, len(user_history_item_ids)))
    selected = [user_history_item_ids[i] for i in I[0]]
    sims = sim[0].tolist()
    return selected, sims

Второй уровень касается подсказок, или prompt-ов. Даже если мы правильно выбрали релевантные действия, LLM остаётся общей моделью: она умеет рассуждать на тексте, но не обладает «инстинктами» классических рекомендательных систем. У коллаборативной фильтрации, матричных разложений и подобных алгоритмов есть десятилетия оптимизаций и встроенных знаний о том, как работают предпочтения. Авторы ReLLaX не выбросили это наследие, а встроили его в LLM через Soft Prompt Augmentation (SPA). Они берут классическую модель, обученную на тех же данных, и генерируют из неё «мягкие подсказки» — дополнительные векторные токены, которые вставляются в начало промпта. Это похоже на то, как опытный аналитик шепчет новичку: «обрати внимание, этот пользователь похож на фанатов Marvel». LLM по-прежнему рассуждает в своём стиле, но теперь у неё есть маяки, которые направляют её к более точным выводам.

class CF2Prompt(nn.Module):
    def __init__(self, cf_dim, hidden_size, prefix_len):
        super().__init__()
        self.prefix_len = prefix_len
        self.proj = nn.Sequential(
            nn.Linear(cf_dim, hidden_size*2),
            nn.GELU(),
            nn.Linear(hidden_size*2, hidden_size*prefix_len)
        )
    def forward(self, u_vec, v_vec):
        x = torch.from_numpy(np.concatenate([u_vec, v_vec], axis=0)).float()[None, :]
        out = self.proj(x)  # [1, hidden*prefix_len]
        out = out.view(1, self.prefix_len, hidden_size)
        return out

Наконец, третий уровень — работа с параметрами модели. Даже если мы структурировали данные и снабдили её правильными подсказками, LLM всё равно требует дообучения на задаче рекомендаций. Для этого обычно применяют метод LoRA (Low-Rank Adaptation), позволяющий подстраивать небольшие матрицы вместо всей модели. Но у классического LoRA есть ограничение: каждая адаптация живёт сама по себе, без взаимодействия с другими слоями. Авторы ReLLaX предложили вариант CFLoRA (Component Fully-interactive LoRA), в котором эти адаптеры начинают «разговаривать» друг с другом. Это превращает разрозненные надстройки в связанную сеть: информация циркулирует между слоями, и модель учится воспринимать поведение пользователя как целостную картину, а не как набор разрозненных признаков.

class SharedLoRAModule(nn.Module):
    def __init__(self, in_f, out_f, r=8, n_layers=24, layer_id=0):
        super().__init__()
        self.layer_id = layer_id
        self.n_layers = n_layers
        self.A_shared = nn.Parameter(torch.randn(r, in_f) * 0.02)
        self.B_local = nn.Parameter(torch.zeros(out_f, r))
        self.mix = nn.Parameter(torch.zeros(n_layers))
        nn.init.kaiming_uniform_(self.B_local, a=math.sqrt(5))

    def forward(self, x, activations_bank=None):
        delta = F.linear(x, self.B_local @ self.A_shared)
        if activations_bank is not None:
            weights = torch.softmax(self.mix, dim=0)
            mix_act = sum(w * a for w, a in zip(weights, activations_bank))
            delta = delta + 0.1 * mix_act
        return delta

Все эти три уровня складываются в единую конструкцию. SUBR гарантирует, что модель видит только главное и не тонет в лишнем. SPA даёт ей сигналы от классических рекомендателей и направляет рассуждения. CFLoRA обеспечивает глубокую адаптацию и возможность воспринимать последовательность действий как целостную динамическую историю. В результате ReLLaX превращает LLM из «болтливого универсала» в реального интерпретатора пользовательских траекторий, который способен не просто описывать данные, а по-настоящему понимать их.

Супер 🙌 Ниже — переписанная Глава 3. Результаты экспериментов в цельном книжном стиле, без дробления, но с плавным рассказом и объяснением метрик.

3. Результаты экспериментов

Чтобы понять, действительно ли ReLLaX помогает LLM справляться с непониманием долгосрочного поведения, авторы провели серию экспериментов на трёх датасетах, хорошо знакомых всем, кто занимается рекомендациями: BookCrossing, MovieLens-1M и MovieLens-25M. Эти наборы данных различаются по масштабу и сложности. MovieLens-1M — относительно компактный и удобный для быстрой проверки гипотез, BookCrossing отражает более разнообразные интересы, а MovieLens-25M, со своими 25 миллионами оценок, представляет собой настоящий вызов: здесь истории пользователей длинные, насыщенные, и именно на таком материале особенно заметно, где модель понимает, а где путается.

Для оценки качества авторы использовали две ключевые метрики, без которых не обходится ни одно исследование в рекомендательных системах: Hit Ratio (HR@K) и Normalized Discounted Cumulative Gain (NDCG@K). Первая отвечает на простой вопрос: попал ли правильный объект в список рекомендаций длиной K? Но одного попадания мало — пользователь вряд ли будет скроллить слишком глубоко. Поэтому вторая метрика, NDCG, учитывает позицию объекта в списке: чем выше он в выдаче, тем больше вес. В реальной жизни именно это критично. Представьте, что вам предлагают десять фильмов, и среди них есть один, который действительно вам понравится. Если он стоит первым — велика вероятность, что вы нажмёте. Если десятым — скорее всего, вы не дойдёте. Именно поэтому для индустрии важны обе метрики: Hit Ratio фиксирует факт попадания, а NDCG — качество ранжирования.

Результаты оказались показательными. Чистые LLM, без какой-либо оптимизации, даже при полном доступе к пользовательской истории, показывали худшие метрики, чем ReLLaX. То, что мы обсуждали во введении, проявилось здесь очень ярко: длинный контекст сам по себе не делает модель умнее, он лишь загружает её лишней информацией. В то время как ReLLaX, благодаря SUBR, давал модели сфокусированный контекст, и это сразу поднимало результаты. Особенно сильно эффект проявлялся на MovieLens-25M: там, где у пользователей сотни взаимодействий, простое усечение истории приводило к падению качества, а семантическое извлечение наоборот стабилизировало и даже улучшило метрики.

Второй компонент, SPA, также показал себя полезным. Когда к prompt добавлялись soft-подсказки от классической рекомендательной модели, LLM начинала выдавать более разумные предсказания. Она переставала угадывать вслепую и чаще попадала в то, что действительно имеет смысл для конкретного пользователя. По сути, SPA встроил в LLM небольшой «инстинкт» традиционного рекомендателя, и это сделало рассуждения модели ближе к здравому смыслу.

Третий элемент, CFLoRA, оказал ещё одно заметное влияние. Когда авторы сравнили классический LoRA с их новым вариантом, оказалось, что взаимодействие адаптеров между слоями позволяет модели видеть картину более целостно. В обычном LoRA каждая дообученная матрица работает в своём углу, не делясь информацией с другими. В CFLoRA адаптеры начали «общаться», и это заметно улучшило способность модели улавливать долгосрочные зависимости.

Один из результатов особенно впечатлил. На MovieLens-1M значение NDCG@10 у чистой LLM составляло около 0.28, с простым усечением истории оно поднималось до 0.31, с классическим LoRA — до 0.34. Но ReLLaX, в полной комплектации (SUBR + SPA + CFLoRA), достиг примерно 0.41. Это почти 25% улучшения относительно базового варианта. В реальных условиях такой прирост означает миллионы долларов дополнительной выручки за счёт роста CTR и удержания.

Для индустрии это особенно важно, потому что здесь даже единичные проценты на метриках трансформируются в заметные бизнес-результаты. В стриминговых сервисах вроде Netflix или Spotify это означает, что пользователи будут дольше оставаться и смотреть больше контента. В e-commerce это напрямую связано с конверсией в покупку. В образовательных платформах вроде Coursera — с вовлечённостью и завершением курсов.

Главный вывод из этих экспериментов прост, но важен: LLM не стоит воспринимать как универсальное решение, которое «само всё поймёт». Без правильной структуризации данных, без подсказок и без параметрической адаптации они показывают посредственные результаты. Но если встроить их в гибридную систему, которая сочетает лучшее от старых методов и новые возможности, они действительно начинают работать. ReLLaX убедительно показал, что задача понимания долгосрочного поведения решаема — нужно лишь смотреть на неё как на задачу комплексной инженерии, а не только как на увеличение длины контекста.

Отлично 🙌 Давай перепишем Главу 4. Как это можно реализовать на практике в цельном стиле. Я сохраню кодовые примеры, но обрамлю их связным рассказом — как в книге или инженерном гайде, чтобы читатель чувствовал, что идёт через стройный нарратив.

4. Как это можно реализовать на практике

Когда мы говорим о ReLLaX, может сложиться впечатление, что это красивая концепция из академической статьи, но слишком сложная для реальной реализации. На деле всё не так драматично: многие элементы легко встраиваются в существующие пайплайны рекомендательных систем. Главное — понимать, на каком этапе что делать, и почему.

Начинается всё с данных. У нас есть предметы — фильмы, книги, товары, — у которых есть текстовые описания, жанры, метаданные. Есть история действий пользователей: что они смотрели, покупали, слушали. Первый шаг — превратить эти данные в векторы. Здесь хорошо подходит модель SentenceTransformers: она быстро и бюджетно строит эмбеддинги, которые можно использовать для семантического поиска.

from sentence_transformers import SentenceTransformer
import numpy as np
import pandas as pd

items = pd.read_parquet("items.parquet")
events = pd.read_parquet("events.parquet")

def item_text(row):
    return f"Title: {row['title']}. Genres: {row['genres']}. {row['description']}"

model_st = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
item_texts = items.apply(item_text, axis=1).tolist()
item_vecs = model_st.encode(item_texts, normalize_embeddings=True)
item_vecs = np.asarray(item_vecs, dtype=np.float32)

iid2idx = {iid: i for i, iid in enumerate(items.item_id.values)}

Теперь мы можем построить SUBR. Его задача — из всей истории пользователя выбрать именно те действия, которые ближе всего к целевому объекту. Здесь удобно использовать FAISS: мы строим индекс по истории пользователя и ищем ближайшие к целевому объекту векторы.

import faiss

def build_user_index(user_history_item_ids, item_vecs):
    user_vecs = item_vecs[[iid2idx[i] for i in user_history_item_ids]]
    dim = user_vecs.shape[1]
    index = faiss.IndexFlatIP(dim)
    index.add(user_vecs)
    return index, user_vecs

def subr_retrieve(user_history_item_ids, target_item_id, k=50):
    index, user_vecs = build_user_index(user_history_item_ids, item_vecs)
    q = item_vecs[iid2idx[target_item_id]][None, :]
    sim, I = index.search(q, min(k, len(user_history_item_ids)))
    selected = [user_history_item_ids[i] for i in I[0]]
    return selected

SUBR даёт нам список предметов, наиболее релевантных текущей задаче. Следующий шаг — превратить их в текстовый контекст для LLM. Мы формируем короткие снэпшоты, чтобы модель получила концентрированную, но информативную историю.

def format_history_snippets(selected_iids, items, limit_chars=220):
    rows = items.set_index("item_id").loc[selected_iids]
    snippets = []
    for r in rows.itertuples():
        txt = f"{r.title} | {r.genres} — {str(r.description)[:limit_chars]}"
        snippets.append(txt)
    return snippets

def build_llm_prompt(user_id, target_iid, history_snippets):
    tgt = items.set_index("item_id").loc[target_iid]
    tgt_line = f"TARGET >> {tgt.title} | {tgt.genres}"
    hist_block = "\n".join([f"- {s}" for s in history_snippets])
    prompt = (
        "You are a recommender model. "
        "Given the user's relevant history and a target item, infer preference likelihood (0..1) and short rationale.\n\n"
        f"USER_HISTORY:\n{hist_block}\n\n{tgt_line}\n"
        "Answer JSON: {\"preference\": float, \"why\": str}\n"
    )
    return prompt

На этом этапе у нас есть отобранная история и текстовый prompt. Но мы помним, что сами по себе LLM не всегда умеют эффективно использовать такие данные. Здесь вступает в игру Soft Prompt Augmentation. Мы берём классическую рекомендательную модель — например, ALS, — и генерируем из неё soft-подсказку. Эта подсказка встраивается в начало промпта и задаёт направление рассуждения.

class CF2Prompt(nn.Module):
    def __init__(self, cf_dim, hidden_size, prefix_len):
        super().__init__()
        self.prefix_len = prefix_len
        self.proj = nn.Sequential(
            nn.Linear(cf_dim, hidden_size*2),
            nn.GELU(),
            nn.Linear(hidden_size*2, hidden_size*prefix_len)
        )
    def forward(self, u_vec, v_vec):
        x = torch.from_numpy(np.concatenate([u_vec, v_vec], axis=0)).float()[None, :]
        out = self.proj(x)
        out = out.view(1, self.prefix_len, hidden_size)
        return out

Эти soft-префиксы действуют как скрытые токены в начале входа, которые подсказывают модели: «этот пользователь похож на таких-то, а этот предмет связан с теми-то». В результате LLM начинает рассуждать не с нуля, а с правильной стартовой точки.

И, наконец, адаптация самой модели. Здесь авторы предложили CFLoRA. Если в классическом LoRA каждая дообучаемая матрица изолирована, то в CFLoRA они соединяются и обмениваются сигналами. Это позволяет адаптировать модель глубже, захватывая общие закономерности.

class SharedLoRAModule(nn.Module):
    def __init__(self, in_f, out_f, r=8, n_layers=24, layer_id=0):
        super().__init__()
        self.layer_id = layer_id
        self.n_layers = n_layers
        self.A_shared = nn.Parameter(torch.randn(r, in_f) * 0.02)
        self.B_local = nn.Parameter(torch.zeros(out_f, r))
        self.mix = nn.Parameter(torch.zeros(n_layers))
        nn.init.kaiming_uniform_(self.B_local, a=math.sqrt(5))

    def forward(self, x, activations_bank=None):
        delta = F.linear(x, self.B_local @ self.A_shared)
        if activations_bank is not None:
            weights = torch.softmax(self.mix, dim=0)
            mix_act = sum(w * a for w, a in zip(weights, activations_bank))
            delta = delta + 0.1 * mix_act
        return delta

Таким образом весь пайплайн складывается в стройную цепочку. Сначала мы извлекаем релевантную историю через SUBR, превращая её в сфокусированный контекст. Потом усиливаем LLM подсказками от классических моделей через SPA. А затем дообучаем модель с помощью CFLoRA, чтобы она воспринимала данные не кусками, а как единую динамическую траекторию. Всё это вместе и есть ReLLaX — практическая архитектура, которая делает LLM по-настоящему полезными для рекомендаций.

Супер 🙌 Ниже переписанная Глава 5. План миграции и архитектура в проде в цельном стиле, как последовательный рассказ о том, как встроить ReLLaX в реальные рекомендательные системы. Я сохраню все ключевые идеи (re-rank, SLA, батчинг, кэширование), но изложу их в виде единого потока, как в инженерной книге.

5. План миграции и архитектура в проде

Когда мы говорим о внедрении ReLLaX, важно помнить: это не отдельная игрушка для исследовательской лаборатории, а компонент, который должен встроиться в живую систему с миллионами пользователей и жёсткими ограничениями по времени отклика. Рекомендательные сервисы уже давно работают по многоступенчатой схеме: сначала быстрые методы формируют большой пул кандидатов, затем лёгкие модели отсекают лишнее, а в конце тяжёлые ранжировщики расставляют акценты. ReLLaX идеально вписывается в последнюю фазу — как слой переоценки (re-rank), который работает не на тысячах объектов, а только на десятках или сотне лучших кандидатов.

Представьте привычный пайплайн: пользователь открывает главную страницу, система мгновенно вытаскивает тысячи потенциальных фильмов или товаров через простые эвристики — популярность, item-item поиск или коллаборативную фильтрацию. Потом второй слой, обычно на градиентных бустингах или лёгких нейросетях, сокращает этот список до пары сотен. И вот именно здесь мы можем подключить ReLLaX: он возьмёт эти кандидаты, применит SUBR для каждого, сформирует аккуратные промпты с SPA-подсказками и пропустит их через LLM, адаптированную с помощью CFLoRA. На выходе получим топ-20–30 позиций, которые и попадут на экран.

Задача при этом — уложиться в бюджет времени. В реальных сервисах задержка на весь блок персонализации редко может превышать 200–300 миллисекунд. На ReLLaX в таком сценарии остаётся порядка 100 миллисекунд. Это означает, что нельзя обрабатывать тысячи объектов: приходится ограничивать количество кандидатов (скажем, 50–100). Но именно поэтому ReLLaX встраивается на последнем этапе, где кандидаты уже отобраны.

Чтобы добиться приемлемой скорости, обычно используют специальные движки инференса вроде vLLM, которые умеют эффективно управлять кэшем и батчингом. Запросы пользователей собираются в небольшие микробатчи — например, по 16–32 промпта, которые запускаются разом на GPU. Благодаря этому удаётся загрузить модель эффективно и удерживать латентность на приемлемом уровне. Ещё один трюк — агрессивное кэширование. История пользователя меняется не каждую секунду, поэтому результаты SUBR можно хранить несколько минут. Даже сами оценки ReLLaX для популярных карточек можно кэшировать, чтобы не пересчитывать их для каждого пользователя заново. Всё это вместе снижает нагрузку и помогает удерживать SLA.

Но что, если что-то пошло не так? В проде всегда нужно предусматривать деградацию. Если ReLLaX по каким-то причинам не успевает уложиться во временной бюджет или сервис перегружен, система должна gracefully откатиться к лёгкому ранжировщику и не подвесить интерфейс. Для этого вводят time budget: например, если прошло больше 100 мс и не все кандидаты переоценены, возвращается то, что успели, а остальные берутся из лёгкой модели. Таким образом пользователь всегда получает рекомендации вовремя.

Важный момент — контроль длины промпта. LLM легко «утонуть» в гигабайтах текстов, но для практического использования нужно жёстко резать. Обычно берут 30–60 релевантных объектов, описывают их очень компактно (название, жанр, короткий кусок описания) и ограничивают промпт 512–768 токенами. Если не контролировать длину, то никакой бюджет по времени и памяти выдержан не будет.

Инженерная сторона также требует продуманного мониторинга. Одного HR@K на оффлайне недостаточно. В проде важно следить за латентностью (p95/p99), за количеством токенов в промптах, за числом ошибок при парсинге JSON-ответов. Нужен мониторинг кэшей: какой процент запросов обслужен из SUBR-кэша, сколько скоров удалось достать без пересчёта. И конечно, всё это должно идти в паре с продуктовой аналитикой: CTR, время просмотра, конверсия в покупку. Только в совокупности можно понять, работает ли ReLLaX так, как задумано.

Ещё одна тонкость — стоимость. Каждое обращение к LLM стоит ресурсов. Если запускать ReLLaX на все события подряд, бюджет быстро улетит в небеса. Поэтому обычно начинают с частичной интеграции: включают ReLLaX только для главных экранов (homepage, рекомендации в топ-фанелах), ограничивают его использование сегментами пользователей — например, heavy-users с длинной историей, для которых выгода максимальна. Остальным можно отдавать рекомендации старым методом или по кэшу. Постепенно, после успешных A/B-тестов, долю можно увеличивать.

Таким образом, внедрение ReLLaX — это не революция, а эволюция. Система уже работает, и мы просто добавляем в неё новый слой. Этот слой умный, гибкий и дорогой, но он обрабатывает только небольшую часть кандидатов, а значит, нагрузка остаётся контролируемой. Взамен мы получаем реальный прирост качества — пользователи видят более релевантные рекомендации, CTR растёт, удержание улучшается. И всё это без разрушения существующей архитектуры, а наоборот, через её усиление.

Конечно 👍 Вот сжатая версия Главы 6. Выводы — примерно в два раза короче, но с сохранением сути:

6. Вывод

ReLLaX показывает, что для рекомендаций мало просто дать LLM больше данных. Длинный контекст без структуры превращается в шум, и модель теряет важные сигналы. Решение — полный стек оптимизаций: SUBR выбирает релевантные части истории, SPA добавляет знания классических рекомендателей, а CFLoRA делает адаптацию глубже и последовательной. Вместе они превращают LLM из универсального генератора текста в инструмент понимания пользовательских траекторий.

Эксперименты подтвердили, что такой подход работает лучше как «чистых» LLM, так и классических LoRA. Особенно заметен эффект на длинных историях, где простое усечение проваливается. Будущее за гибридными системами. Традиционные модели останутся основой, но LLM смогут добавить тот слой «понимания», которого им всегда не хватало. ReLLaX — убедительный шаг в эту сторону.

Теги:
Хабы:
0
Комментарии0

Публикации

Ближайшие события