Перейти к содержанию

Что такое рекомендательная система🔗

Рекомендательная система - это инструмент, основанный на методах машинного обучения, для показа пользователю наиболее релевантного для него товара. Система позволяет решать различные бизнес-задачи: увеличивать количество продаж, повышать конверсию, средний чек, удержание, LTV и другие показатели игрового проекта.

В зависимости от набора рекомендованных предметов и таргетной аудитории, рекомендательная система может:

  • подбирать персональные офферы и наборы
  • показывать рекомендованные предметы без скидки для увеличения продаж неакционных предметов
  • настраивать игровой магазин по релевантности для каждого пользователя
  • создавать баланс между показами рекламы и продажей предметов в зависимости от профиля игрока
  • противодействовать оттоку игроков путем подбора оптимального предложения или подарка в нужный момент времени.

Алгоритм работы с командой RecSys🔗

Шаги🔗

  1. Формализация бизнес-задачи.
  2. Проверка различных моделей и выбор лучшей из них.
  3. Проведение A/B теста модели.
  4. Оценка экономической эффективности.
  5. Запуск в Production.
  6. Поддержка и мониторинг после внедрения.

Что будет нужно от проекта🔗

  1. Инициализирующая встреча: выбор задачи, целевой аудитории, бизнес метрики.
  2. Формирование списка предметов для рекомендаций, при необходимости заведение предметов в платежной системе.
  3. Интеграция игры и API рекомендательной системы.
  4. Консультация по логам игры и механикам.
  5. В некоторых случаях требуется добавление логирования дополнительных событий (например, показ и покупка оффера).

Данные🔗

Игровые логи🔗

Для составления профилей по пользователям и предметам для создания рекомендаций используются игровые логи, хранящиеся в едином хранилище - игровом DWH.

Игровые логи, хранящиеся в игровых базах в DWH в свободном формате, преобразуются силами команды RecSys в унифицированный формат данных, понятный рекомендательной платформе.

Базово, используются следующие игровые события:

  • Лог траты/получения игровой валюты
  • Лог добавления/удаления предмета из инвентаря
  • Лог получения уровня
  • Лог боя
  • Лог показа/клика/покупки предложения/предмета от Рекомендательной системы

Также потребуются следующие логи, если не было интегрировано MRGS SDK:

  • Лог логина/логаута
  • Лог регистрации в игре
  • Лог покупки

Общий формат логов🔗

Поле Тип Обязательное Типовой Кастомный Комментарии
eventName string Y задается по умолчанию определяется создателем лога название лога
eventTime unixtime Y обязательное поле - может быть клиентским или серверным
userId string Y обязательное поле - id персонажа из игры
mygamesUserId string - -
sessionId string - - id игровой сессии (нужно договориться с аналитиками как ее определять)
deviceId string - -
ip string - -
idfa string - -
idfv string - -
systemVersion string - -
country string Y обязательное поле -
language string Y обязательное поле -
level int - -
abTestGroup string - - Группа при AB-тестировании
serverName string - - Сервер к которому подключен игрок
environment string - - "dev-стенд, тестовый, игровой"
appVersion string Application version
mrgsSdkVersion string
appBuild string Application build number
value float Какое-нибудь значение
objectId string Логи currencyChange, inventoryChange
transactionId string Логи currencyChange, inventoryChange
amt float Лог currencyChange
currency string Лог currencyChange
cnt int Лог inventoryChange
stage string Лог playMatch
result string Лог playMatch
offerId string Логи recsysOfferView, recsysOfferClick, recsysOfferPurchase id предмета/пака в офере
eventType string Логи recsysOfferView, recsysOfferClick, recsysOfferPurchase Тип лога recsysOffer
customString_1 string кастомные данные Кастомный лог
customString_2 string кастомные данные Кастомный лог
customString_3 string кастомные данные Кастомный лог
customString_4 string кастомные данные Кастомный лог
customString_5 string кастомные данные Кастомный лог
customString_6 string кастомные данные Кастомный лог
customString_7 string кастомные данные Кастомный лог
customString_8 string кастомные данные Кастомный лог
customString_9 string кастомные данные Кастомный лог
customString_10 string кастомные данные Кастомный лог
customString_11 string кастомные данные Кастомный лог
customString_12 string кастомные данные Кастомный лог
customString_13 string кастомные данные Кастомный лог
customString_14 string кастомные данные Кастомный лог
customString_15 string кастомные данные Кастомный лог
customString_16 string кастомные данные Кастомный лог
customString_17 string кастомные данные Кастомный лог
customString_18 string кастомные данные Кастомный лог
customString_19 string кастомные данные Кастомный лог
customString_20 string кастомные данные Кастомный лог
customInt_1 int кастомные данные Кастомный лог
customInt_2 int кастомные данные Кастомный лог
customInt_3 int кастомные данные Кастомный лог
customInt_4 int кастомные данные Кастомный лог
customInt_5 int кастомные данные Кастомный лог
customInt_6 int кастомные данные Кастомный лог
customInt_7 int кастомные данные Кастомный лог
customInt_8 int кастомные данные Кастомный лог
customInt_9 int кастомные данные Кастомный лог
customInt_10 int кастомные данные Кастомный лог
customFloat_1 float кастомные данные Кастомный лог
customFloat_2 float кастомные данные Кастомный лог
customFloat_3 float кастомные данные Кастомный лог
customFloat_4 float кастомные данные Кастомный лог
customFloat_5 float кастомные данные Кастомный лог
customFloat_6 float кастомные данные Кастомный лог
customFloat_7 float кастомные данные Кастомный лог
customFloat_8 float кастомные данные Кастомный лог
customFloat_9 float кастомные данные Кастомный лог
customFloat_10 float кастомные данные Кастомный лог

Лог траты/получения игровой валюты🔗

когда пишется: в момент списания/начисления внутриигровой валюты

eventName: "currency_change"

endpoint:

топик:

Специальные поля:

поле тип обязательное комментарий
objectId string Y объект взаимодействия, цель траты валюты - название/id, купленного предмета, если пишется в момент траты, если в момент получения, то поле отвечает за источник получения валюты
transactionId string N
amt float Y (количество потраченной валюты, отрицательное, если происходит списание, положительное, если начисление
currency string Y тип потраченной валюты: "gold", "crystals"
custom* при необходимости

Лог добавления/удаления предмета из инвентаря🔗

когда пишется: в момент добавления/удаления предмета в инвентарь персонажа

eventName: "inventory_change"

endpoint:

топик:

Специальные поля:

поле тип обязательное комментарий
objectId string Y id добавляемого/удаляемого предмета
cnt int Y количество таких предметов, положительное, если добавляется предмет, отрицательное, если удаляется
custom* при необходимости

Лог получения уровня🔗

когда пишется: в момент обновления уровня персонажа

eventName: "level_gain"

endpoint:

топик:

Специальные поля:

поле тип обязательное комментарий
level int Y какой уровень получен
custom* при необходимости

Лог боя🔗

когда пишется: в момент старта/окончания либо другого важного момента боя

eventName: "play_match"

endpoint:

топик:

Специальные поля:

поле тип обязательное комментарий
stage string N примеры: start, end - момент боя, в котором этот лог пишется
result string Y примеры: win, lose, leave, draw - результат боя
custom* при необходимости

Лог показа/клика/покупки предложения от Рекомендательной системы🔗

когда пишется: в момент просмотра баннера с рекомендациями/ клика по баннеру с рекомендациями и переходе к покупке/ в момент покупки

eventName: "recsys_offer"

endpoint:

топик:

Специальные поля:

поле тип обязательное комментарий
offerId string Y id предложения из конфига с офферами/предметами, которые участвуют в рекомендациях (offerId)
eventType string Y тип события view, click или purchase
custom* при необходимости

Предметы🔗

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

Возможны 2 сценария:

  1. Проект сам определяет список предметов, доступных рекомендательной системе.
  2. Команда RecSys проводит исследование и выбирает набор предметов либо предлагает набор сгенерированных предметов (бандлы либо базовые предметы с немного измененными характеристиками).

Сбор данных для обучения🔗

В некоторых случаях, когда запускаются новые предметы или предметы были показаны ранее на специфической аудитории, и накопленные исторические логи показов не могут быть использованы для решения текущей задачи, первое время происходят рандомные показы предметов с целью накопить достаточно статистики по показам для обучения. Обычно этот период занимает от 1 до 3 недель и осуществляется через стандартную схему интеграции с проектом.

Тестирование🔗

Тестирование функционала🔗

Тестирование функционала может быть разделено на несколько частей:

  1. Тестирование получения ответа рекомендаций по пользователю от API RecSys - на стороне проекта. Базовый подход: на стороне RecSys заводятся в тестовом или продовом API тестовые id пользователей и тестовые рекомендации, которые могут быть рандомными предметами из списка либо покрывать определённые use cases, по договорённости с проектом. Проект запрашивает рекомендации по данным тестовым пользователям и проверяет ответы на соответствие ожиданиям.
  2. Тестирование показа/начисления офферов внутри игры - проводится на стороне проекта, RecSys проверяет логирование показов и покупок в хранилище.
  3. Тестирование раздачи A/B тестов, модели - на стороне команды RecSys.

A/B🔗

Разбиение пользователей на группы для A/B тестирования осуществляется на стороне RecSys. Механизм раздачи A/B теста позволяет раскатить эксперимент на разный объем аудитории и гибко перезапускать эксперименты, а также проводить несколько экспериментов одновременно. Все данные по разбиениям сохраняются в исторические таблицы, что позволяет при необходимости легко воспроизвести результаты. Все решения о внедрении рекомендательной системы осуществляются через статистику путем расчета результатов A/B теста и наблюдения статистически значимых изменений.

Интеграция🔗

Получение рекомендаций для пользователя🔗

GET /projects/{project_id}/user/{user_id}/recommendations

Параметры запроса:

Параметр Тип Обязательно Описание
project_id string да Идентификатор проекта для которого происходит загрузка рекомендаций
user_id string да Id пользователя

Пример запроса и ответа:

Запрос

GET /projects/test/user/1605632/recommendations

Ответ

200 OK

{
  "items:": [
    {
      "id": "123",
      "is_mrgs_show": true,
      "is_transaction": false,
      "images": {
          "landscape" : {
              "img_2400" : "https://localhost/image%20test_2400.png",
              "img_800" : "https://localhost/image%20test_800.png",
              "hash_2400" : "abcdefghigklmnopqrstuvwxyz123456",
              "hash_800" : "abcdefghigklmnopqrstuvwxyz123456"           
          },
          "portrait" : {
              "img_2400" : "https://localhost/image%20test_2400.png",
              "img_800" : "https://localhost/image%20test_800.png",
              "hash_2400" : "abcdefghigklmnopqrstuvwxyz123456",
              "hash_800" : "abcdefghigklmnopqrstuvwxyz123456"
          }
      }
        }
  ]
}

Авторизация🔗

Чтобы осуществлять запросы на получение рекомендаций к API, нужна базовая авторизация для проекта/студии. Без авторизации API на все запросы будет отвечать 422 ошибкой.

Чтобы авторизоваться, нужно добавить в запрос пользователя и пароль, которые передаются игровому проекту разработчиками Рекомендательной системы. Для тестового и продового API имя пользователя и пароль могут отличаться.

Адреса API🔗

Игровой сервер напрямую обращается к продакшн или тестовому API Рекомендательной системы.

Production API: https://recsys.my.games

QA API: https://api-test.recsys.pvt

Формат ошибок🔗

Общий формат ответа для 422 ошибок:

Параметр Тип Обязательно Описание
code string да Код ошибки
text string нет Описание ошибки
context array нет Дополнительная информация по конкретной ошибке

Ответ

HTTP/1.1 422 Unprocessable Entity for url: https://api-test.recsys.pvt/projects/test/user/105240266041/recommendations/feature/0 
Connection: keep-alive
Content-Length: 180
Content-Type: application/json
Keep-Alive: 5

{
  "code": "recommendation_not_found",
  "text": "Recommendation for 105240266041 not found",
  "context": {
    "user_id": "105240266041"
  }
}

В случае непредвиденной ошибки вернется ответ со статусом 500.

Интеграция на клиенте🔗

Для отправки необходимых событий нужно воспользоваться классом MRGSRecommendations в одноименном модуле MRGS. Все объекты событий можно создать через фабрику MRGSRecSysEvent, либо через стандартный конструктор класса, отвечающего за событие.

Примеры отправки событий:

// Log of spending/receiving game currency
var currencyChangeEvent = MRGSRecSysEvent.CurrencyChange("item_id", "transaction_id", 123.4f, "gold");
// Event sending
MRGSRecommendations.Instance.TrackEvent(currencyChangeEvent);

// Log of adding/removing an item from inventory
MRGSRecommendations.Instance.TrackEvent(MRGSRecSysEvent.InventoryChange("item_id", -123));

// Log of getting level
MRGSRecommendations.Instance.TrackEvent(MRGSRecSysEvent.LevelGain(555));

// Battle log
MRGSRecommendations.Instance.TrackEvent(MRGSRecSysEvent.PlayMatch("start", "win"));

// Log of showing/click/purchase of the offer of the recommendation system
MRGSRecommendations.Instance.TrackEvent(MRGSRecSysEvent.OfferAction("some_offer_id", MRGSRecSysEvent.ActionTypeView));
MRGSRecommendations.Instance.TrackEvent(MRGSRecSysEvent.OfferAction("some_offer_id", MRGSRecSysEvent.ActionTypeClick));
MRGSRecommendations.Instance.TrackEvent(MRGSRecSysEvent.OfferAction("some_offer_id", MRGSRecSysEvent.ActionTypePurchase));
// Log of spending/receiving game currency
MRGSRecSysEvent* ev = [MRGSRecSysEvent currencyChangeWithObjectId:@"item_id" transactionId:@"transaction_id" amount:123.4f currency:@"gold"];
// Event sending
[[MRGSRecommendations sharedInstance] trackEvent:ev];

// Log of adding/removing an item from inventory
[[MRGSRecommendations sharedInstance] trackEvent:[MRGSRecSysEvent inventoryChangeWithObjectId:@"item_id" count:-123]];

// Log of getting level
[[MRGSRecommendations sharedInstance] trackEvent:[MRGSRecSysEvent levelGain:555]];

// Battle log
[[MRGSRecommendations sharedInstance] trackEvent:[MRGSRecSysEvent playMatchWithStage:@"start" result:@"win"]];

// Log of showing/click/purchase of the offer of the recommendation system
[[MRGSRecommendations sharedInstance] trackEvent:[MRGSRecSysEvent offerActionWithOfferId:@"some_offer_id" actionType:kMRGSRecSysOfferActionView]];
[[MRGSRecommendations sharedInstance] trackEvent:[MRGSRecSysEvent offerActionWithOfferId:@"some_offer_id" actionType:kMRGSRecSysOfferActionClick]];
[[MRGSRecommendations sharedInstance] trackEvent:[MRGSRecSysEvent offerActionWithOfferId:@"some_offer_id" actionType:kMRGSRecSysOfferActionPurchase]];
import games.my.mrgs.recsys.MRGSRecSysEvent;
import games.my.mrgs.recsys.MRGSRecSysEvents;
import games.my.mrgs.recsys.MRGSRecommendations;

// Log of spending/receiving game currency
final MRGSRecSysEvent currencyChangeEvent = new MRGSRecSysEvents.CurrencyChangeEvent("item_id", "transaction_id", 123.4f, "gold");
// Event sending
MRGSRecommendations.getInstance().trackEvent(currencyChangeEvent);

// Log of adding/removing an item from inventory
MRGSRecommendations.getInstance().trackEvent(new MRGSRecSysEvents.InventoryChangeEvent("item_id", -123));

// Log of getting level
MRGSRecommendations.getInstance().trackEvent(new MRGSRecSysEvents.LevelGainEvent(555));

// Battle log
MRGSRecommendations.getInstance().trackEvent(new MRGSRecSysEvents.PlayMatchEvent("start", "win"));

// Log of showing/click/purchase of the offer of the recommendation system
MRGSRecommendations.getInstance().trackEvent(new MRGSRecSysEvents.OfferActionEvent("some_offer_id", MRGSRecSysEvent.ACTION_TYPE_VIEW));
MRGSRecommendations.getInstance().trackEvent(new MRGSRecSysEvents.OfferActionEvent("some_offer_id", MRGSRecSysEvent.ACTION_TYPE_CLICK));
MRGSRecommendations.getInstance().trackEvent(new MRGSRecSysEvents.OfferActionEvent("some_offer_id", MRGSRecSysEvent.ACTION_TYPE_PURCHASE));

Дополнительные параметры к событиям🔗

С версии MRGS 6.4.0 можно добавить дополнительные параметры к событиям. Вы можете добавлять к ним поля из унифицированных логов, такие как customString1-20, level, customFloat и другие.

var ev = MRGSRecSysEvent.LevelGain(555);
ev.AddCustomParams(new Dictionary<string, object>()
{
    {"test_param_1", "testStr"},
    {"customFloat_1", 123.456f},
});
MRGSRecommendations.Instance.TrackEvent.TrackEvent(ev);
MRGSRecSysEvent* event = [MRGSRecSysEvent levelGain:555];
[event addCustomParams:@{
    @"test_param_1": @"testStr",
    @"customFloat_1" : @(123.456f)
}];
[[MRGSRecommendations sharedInstance] trackEvent:event];
import games.my.mrgs.recsys.MRGSRecommendations;
import games.my.mrgs.recsys.MRGSRecSysEvent;
import games.my.mrgs.recsys.MRGSRecSysEvents;

final MRGSRecSysEvent event = MRGSRecSysEvents.LevelGainEvent(555);
event.putParam("test_param_1", "testStr");
event.putParam("customFloat_1", 123.456f);
MRGSRecommendations.getInstance().trackEvent(event);

Последнее обновление: 2023-10-20
Дата создания: 2020-12-15