Привет! Меня зовут Алексей Мельников, я продакт в KION (онлайн-кинотеатр от МТС Digital), занимаюсь фичами, связанными с искусственным интеллектом. 

Весной мы писали о фиче пропуска титров. Судя по карме, статья хабровчанам понравилась и это мотивировало нас на написание серии материалов, посвященных другой фиче – автоплею фильмов. Ниже я расскажу, как и зачем мы реализовали эту фичу и что у нее под капотом.

Autoplay позволяет не бросать еще «теплого» зрителя во время просмотра и предлагать ему новый фильм сразу после окончания предыдущего. Система рекомендаций сама подбирает контент, наиболее похожий на тот, что смотрит зритель. Новый фильм запускается в автоматическом режиме при наступлении титров, если пользователь бездействует.

Когда начинаются титры – мы уводим их в pip в левый нижний угол экрана и на бэке показываем постер следующего похожего фильма. В правой нижней части экрана показываем кнопки Следующий фильм и Смотреть титры. И если пользователь бездействует n секунд (этот параметр настраивается) – включаем следующий похожий фильм. Как это выглядит – показываю ниже:

Дизайн функции автоплей в онлайн кинотеатре Kion
Дизайн функции автоплей в онлайн кинотеатре Kion
Анимация фичи автоплей
Анимация фичи автоплей

Почему мы внедрили эту фичу?

Предпосылок для создания Autoplay было две:

  • мы созрели с точки зрения бэка и научились работать с i2i – item to item, подробно об этом ниже;

  • мы боремся не только с конкурентами, но и за внимание зрителя, который в момент окончания фильма решает, чем ему заняться дальше. Поспать? Погулять? Или посмотреть еще один фильм? Autoplay как раз подталкивает зрителя к дальнейшему просмотру.

А что под капотом?

Об этом подробно рассказывает Глеб Волохов, ведущий ML-разработчик KION:

Для стабильной и надежной работы ML-решений в продакшене необходимы:

  • полное версионирование моделей;

  • возможность быстро откатиться до какой-то конкретной версии модели (например, предыдущей);

  • контроль и хранение истории онлайн и оффлайн – метрик качества;

  • полная повторяемость пайплайнов в любой момент времени;

  • удобство и простота разработки для датасаентистов, а также их независимость от бэкенд разработчиков.

Также очень желательно максимально исключить человеческий фактор на всех этапах деплоя.

При построении системы, отвечающей всем нашим требованиям, в качестве центрального компонента был выбран MLFlow. Используя все возможности MLFlow, мы построили полностью автоматический пайплайн, в котором присутствуют следующие компоненты:

  • MLFlow – центральный компонент, отвечающий за отслеживание экспериментов, метрик, регистрацию моделей, а также, после небольшой доработки, выступающий инициатором автоматической раскатки моделей;

  • Gitlab репозиторий c dvc (mldatasets) – этот репозиторий используется для хранения датасетов для обучения и их версионирования;

  • Vanga – микросервис для моделей, обеспечивающий унифицированное API для работы с моделями;

  • MLTrainer – микросервис, который запускает модели учиться, принимает решение о раскатке и раскатывает новую версию модели в продакшен;

  • Ailflow – распространенное решение для выстраивания etl-процессов, в нашем случае даги периодически собирают датасеты для обучения и складывают в соответствующий репозиторий, анализируют нужно ли какую-то из моделей поучить и в случае успеха инициируют запуск нашего MLTrainer;

  • Telegram-чат – используется для информирования.

Схема взаимодейсвия компонентов
Схема взаимодейсвия компонентов

Остановимся на каждом из компонентов подробнее: 

MLFlow

В MLFlow используется бэкенд – postgres 14.0, хранилище для артефактов – S3. Для того, чтобы обеспечить дальнейшую автоматическую раскатку зарегистрированных в MLFlow моделей, на таблицу в БД postgres, отвечающую за регистрацию моделей, были повешены сигналы, которые отлавливаются специальным сервисом. В зависимости от того, в какое состояние с точки зрения MLFlow переходит зарегистрированная модель, – вешаются хуки.

Например, при переходе из состояния 'None' в состояние 'Staging' происходит валидация входных параметров и дальнейшая раскатка микросервиса, отвечающего за API к этой модели. При переходе в состояние 'Archived' модель прекращает свою работу в продакшен контуре. Все действия дублируются ботом в наш служебный чат. В том числе, если в процессе раскатки не прошла какая-то валидация, информация об ошибке будет отправлена в чатик, а модель будет автоматически возвращена в состояние 'None'.

Каждая модель оформляется в виде MLFlow-проекта и имеет два обязательных эндпоинта: train и test. Train – эндпоинт, необходимый для автоматического переобучения модели на новых данных. В качестве обязательных входных аргументов эндпоинт принимает версию датасета из репозитория mldatasets.

Это необходимо для  динамического влияния на версию данных, на которых мы хотим обучить нашу модель. Test – также принимает версию датасета и считает оффлайн-метрики, которые отслеживаются в MLFlow. Основываясь на метриках, наш автоматический тренер принимает решение, нужно ли новую версию модели выкатывать в продакшен. 

Каждая модель представляет собой набор кода и вспомогательной информации, необходимой датасаентистам. Все для работы хранится в отдельном репозитории, каждая модель в своей ветке. Такой подход к организации работы дал нам следующее:

  • в любой момент мы можем откатиться на предыдущую версию;

  • в процессе трекинга наших экспериментов в MLFlow регистрируется и версия коммита, что позволяет на всех этапах отслеживать, что версия модели и версия кода консистентны;

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

Так мы сделали из MLFlow-сервера единое место для хранения информации о моделях, которое не только любому клиенту может эту информацию предоставить, но и выступает инициатором выкатки и валидации входных данных: полноты и корректности для дальнейшего деплоя. 

Mldatasets

Mldatasets – это gitlab-репозиторий с dvc, для которого настроен в s3 bucket с expire – 30 дней. Для каждого проекта своя ветка, а датасеты собираются в него по расписанию дагами из airflow. Даги собирают данные из различных источников (clickhouse, mongo и так далее), предобрабатывают, агрегируют и помещают в нужную ветку. Так появляется единая точка входа для получения датасетов, они единообразны и уже предобработаны. Также получаем жесткую версионированность, что для нас критически важно.

Использование такого репозитория позволяет нам точно знать, на каких датасетах училась какая модель, и, в случае необходимости, где угодно повторить обучение или проанализировать состояние датасетов.

Vanga

Это микросервис, обеспечивающий унифицированное API для взаимодействия с моделями. Микросервис написан на fastapi, обертка на модель подключается как сабмодуль, необходимая версия для каждой конкретной модели берется из MLFlow вместе с некоторой необходимой для раскатки мета-информацией. Например, можно задать вот что: назначение модели (как i2i), персонализацию витрины, включен или выключен режим автотренировки моделей.

В рамках CI запускаются тесты и прочие проверки. Инициатором раскатки выступает хук, повешенный на MLFlow при переводе зарегистрированной в MLFlow модели из состояния 'None' в состояние 'Staging'. В случае неудачного прохождения тестов модель также автоматически переводится в состояние 'None', а сообщение с текстом об ошибке направляется в соответствующий чат.

Airflow

Бэкенд, который отдает для нашего кинотеатра рекомендации i2i забирает их из redis. Наполняется redis дагом, логика работы которого следующая:

  • узнать, какие модели для i2i находятся в состоянии 'Production' с соответствующей мета-информацией (куда делать запрос);

  • получить рекомендации от соответствующего экземпляра микросервиса Vanga;

  • сохранить в Redis.

Также именно даг по расписанию проверяет, есть ли претенденты на обучение, смотрит, кто из моделей еще не учился на актуальной версии датасетов и запускает mltrainer.

MLTrainer

Компонент, отвечающий за переобучение моделей, принятие решений о выкатке новой версии модели и перевод текущей версии в архив. Сервис развернут на собственных мощностях МТС Медиа, оборудованных видеокартами Nvidia Tesla V100.

MLTrainer запускает для модели эндпоинт train, затем test, собирает оффлайн метрики после текущего обучения и предыдущих N обучений активной модели, принимая решение нужно ли текущую версию модели перевести в 'Archived' и раскатить новую версию модели в продакшен. При проседании оффлайн метрик модель не катится в продакшен, а разработчик получает уведомление об этом с ссылкой на run в MLflow. 

Вся необходимая документация для работы датасаентистов оформлена при помощи Vuepress, что позволяет быстро найти информацию для работы. 

Основной стек: MLFlow, Gitlab CI/CD, Fastapi, TensorFlow, Postgres, S3, Vuepress   

Каким был фидбэк от юзеров?

Занимательным. Например, мы обнаружили, что некоторые пользователи, смотрят нон-стопом фильмы на смартфонах. Как мы это выяснили? У нас после просмотра 3 фильмов подряд всплывает сообщение:

Вопрос по окончании просмотра 3 фильмов подряд
Вопрос по окончании просмотра 3 фильмов подряд

И пользователи нажимают смотреть далее. Кстати, этот скрин сделал один из наших разработчиков во время путешествия, когда сам смотрел фильмы подряд без перерыва.

С точки зрения цифр мы получили следующие результаты:

Результаты АБ теста по автоплей фильмов, TVTU - Total View Time by User
Результаты АБ теста по автоплей фильмов, TVTU - Total View Time by User

После внедрения фичи мы увеличили один из наших ключевых показателей Total View Time Unique – количество минут смотрения в среднем на одного юзера. А еще мы увеличили среднюю длину сессии. 

При этом количество зрителей, которые досматривают рекомендованный контент, находится в пределах 30-40%.

Что дальше?

В будущем мы планируем протестировать гипотезу о том, что пользователю нужен выбор: несколько вариантов контента, которые он может смотреть.

Развитие фичи автоплей
Развитие фичи автоплей
Развитие фичи
Развитие фичи

Идея такая – давать ленту с контентом в виде рекомендаций похожих фильмов в момент появления титров. 

Кроме того мы планируем улучшать качество модели i2i и рекомендовать не только фильмы, но и сериалы.

Спасибо за внимание! Увидимся в KION!)

Комментарии (7)


  1. Rebeiro
    09.08.2022 16:13
    +4

    торренты наше все


  1. mihnik
    10.08.2022 07:57
    +5

    У меня одного ощущение, что мне рассказывают как меня, против моего желания, заставляют что-то делать(продолжать таращиться в телевизор, даже после окончания фильма), да ещё и при этом хвастаются этим, как большим научно-техническим достижением?

    Если что, я могу и сам кнопочку play нажать.


    1. akmelnikov Автор
      10.08.2022 09:41

      Добрый день, Николай. У вас, как у пользователя Кион, есть возможность не смотреть, то что вам предлагают, выйти из плеера и искать другой фильм самостоятельно. Технически статья про item 2 item рекомендации, которые используются во многих местах приложения, не только в автоплей.


  1. Zamuka
    10.08.2022 09:55
    +5

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


    1. akmelnikov Автор
      10.08.2022 11:49
      +1

      Добрый день. Да, такую функцию планируем реализовать.


    1. d583605
      10.08.2022 13:29

      Начинал читать статью с такими же мыслями и уже формулировал их для комментария. Остаётся только полностью с вами согласиться. Прекрасно понимаю зачем этот функционал присутствует и включен по умолчанию, и рад за компании, если это работает. Но не могу представить, что бы меня это заставило смотреть ещё одну серию и уж тем более ещё один фильм. Всё таки какие-то планы на следующие полтора часа у меня чаще все есть.


  1. Mike-M
    10.08.2022 12:51

    в момент окончания фильма решает, чем ему заняться дальше. Поспать? Погулять? Или посмотреть еще один фильм?
    IMHO, лучше поспать/погулять дать глазам отдохнуть.