Создание систем рекомендаций по видеоиграм с использованием FastAPI, PostgreSQL и Render: Часть 1

Автор: Дмитрий Иванов [Команда P9X]

~8 минут чтения

Введение

Включение приложения для генерации интеллектуальных предложений для пользователя, эффективной сортировки релевантного контента. В этой статье мы создаём и развёртываем динамическую систему рекомендаций видеоигр, используя PostgreSQL, FastAPI и Render, чтобы рекомендовать новые игры на основе тех, с которыми пользователь взаимодействовал. Цель — предоставить чёткий пример того, как можно построить автономную систему рекомендаций, которую затем можно интегрировать во фронтенд-систему или другое приложение.

Для этого проекта мы используем данные о видеоиграх, доступные через API Steams, но это можно легко заменить любыми другими данными о продуктах. Основные шаги будут одинаковыми. Мы рассмотрим, как хранить эти данные в базе данных, векторизовать теги игр, генерировать оценки сходства на основе игр, с которыми пользователь взаимодействовал, и возвращать ряд соответствующих рекомендаций. В конце статьи мы развернём эту систему рекомендаций как веб-приложение с помощью FastAPI, чтобы всякий раз, когда пользователь взаимодействует с новой игрой, мы могли динамически генерировать и сохранять новый набор рекомендаций для этого пользователя.

Используемые инструменты

  • PostgreSQL
  • FastAPI
  • Docker
  • Render

Интересующиеся репозиторием на GitHub могут найти его здесь.

Содержание

Из-за объёма этого проекта он разделён на две части. Первая часть охватывает настройку и теорию, лежащую в основе этого проекта (шаги 1–5, показанные ниже), а вторая часть посвящена развёртыванию. Если вы ищете вторую часть, она находится здесь.

Часть 1

  1. Обзор набора данных
  2. Общая архитектура системы
  3. Настройка базы данных
  4. Настройка FastAPI
  • Модели
  • Маршруты
  1. Создание конвейера подобия

  2. Развёртывание базы данных PostgreSQL на Render

  3. Развёртывание приложения FastAPI как веб-приложения Render

  • Докеризация нашего приложения
  • Отправка образа Docker в DockerHub
  • Извлечение из DockerHub в Render

Обзор набора данных

Набор данных для этого проекта содержит данные о топ-~2000 играх из API steamworks. Эти данные бесплатны и лицензированы для личного и коммерческого использования в соответствии с условиями обслуживания. Существует ограничение в 200 запросов в 5 минут, из-за которого мы работали только с подмножеством данных. Условия обслуживания можно найти здесь.

Обзор данных игр

Большинство полей относительно описательны; ключевая вещь, которую следует отметить, — это уникальный идентификатор продукта — appid. Помимо этого набора данных, у нас есть ещё несколько дополнительных таблиц, которые мы подробно рассмотрим ниже; наиболее важная для нашей системы рекомендаций — таблица тегов игр, которая содержит значения appid, сопоставленные с каждым тегом, связанным с игрой (стратегия, RPG, карточная игра и т. д.). Они были взяты из поля categories, показанного в обзоре данных, а затем преобразованы в таблицу game_tags, чтобы для каждого сочетания appip:category была уникальная строка.

Архитектура

Для нашей системы рекомендаций мы будем использовать базу данных PostgreSQL с уровнем доступа и обработки данных FastAPI, который позволит нам добавлять или удалять игры из списка игр пользователя. Пользователи, вносящие изменения в свою игровую библиотеку через POST-запрос к FastAPI, также запускают конвейер рекомендаций, используя функцию FastAPI Background Tasks, которая будет запрашивать их список понравившихся игр из базы данных, вычислять оценку сходства с непонравившимися играми и обновлять таблицу user_recommendation новыми играми пользователя.

Настройка базы данных

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

  • Таблица Game: содержит базовые данные об играх для каждой уникальной игры в нашей базе данных.
  • Таблица User: таблица пользователей, содержащая пример информации.
  • Таблица User_Game: содержит сопоставление между всеми играми, которые пользователь «понравился»; эта таблица является одной из базовых таблиц, используемых для генерации рекомендаций, фиксируя, в какие игры заинтересован пользователь.
  • Таблица Game_Tags: содержит сопоставление appid:game_tag, где game tag может быть чем-то вроде «стратегия», «RPG», «комедия», описательный тег, отражающий суть игры. Для каждого appid сопоставлено несколько тегов.
  • Таблица User_Recommendation: это наша целевая таблица, которая будет обновляться нашим конвейером. Каждый раз, когда пользователь взаимодействует с новой игрой, наш конвейер рекомендаций будет запускаться и генерировать новую серию рекомендаций для этого пользователя, которая будет храниться здесь.

Начало работы с FastAPI

Теперь, когда у нас есть база данных, настроенная и заполненная, нам нужно создать методы для доступа, обновления и удаления данных, используя FastAPI. FastAPI позволяет нам легко создавать стандартизированные (и быстрые) API для взаимодействия с нашей базой данных.

Модели FastAPI

Часть FastAPI нашего проекта основана на двух основных файлах: models.py, в котором определены модели данных, с которыми мы будем взаимодействовать (игры, пользователи и т. д.), и main.py, в котором определяется наше фактическое приложение FastAPI и содержатся наши маршруты.

Настройка маршрутов FastAPI

После того как мы определили наши модели, мы можем создать методы для взаимодействия с этими моделями и запроса данных из базы данных (GET), добавления данных в базу данных (POST) или удаления данных из базы данных (DELETE). Ниже приведён пример того, как мы можем определить запрос GET для нашей модели игры.

Создание конвейера рекомендаций

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

Построение конвейера рекомендаций

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

Привязка конвейера рекомендаций к FastAPI

Представьте, что у нас есть служба рекомендаций, которая будет обновлять нашу таблицу user_recommendation. Мы хотим убедиться, что эта служба вызывается всякий раз, когда пользователь обновляет свои предпочтения. Мы можем реализовать это в несколько шагов, как показано ниже; сначала мы определяем функцию generate_recommendations_background, эта функция отвечает за подключение к нашей базе данных, запуск конвейера сходства и закрытие соединения. Затем нам нужно убедиться, что это вызывается, когда пользователь делает POST-запрос (т. е. «нравится» новой игре); для этого мы просто добавляем вызов функции в конце нашей функции create_user_game POST-запроса.

Создание конвейера рекомендаций

Теперь, когда мы понимаем, как наш конвейер сходства может быть запущен, когда пользователь обновляет свои понравившиеся игры, пришло время погрузиться в механику того, как работает конвейер рекомендаций. Наш конвейер рекомендаций хранится в similarity_pipeline.py и содержит наш класс UserRecommendationService, который мы показали, как импортировать и создать экземпляр выше. Этот класс содержит серию вспомогательных функций, которые в конечном итоге вызываются в методе generate_recommendations_for_user.

  1. Извлечение игр пользователя: чтобы генерировать похожие игровые рекомендации, нам нужно извлечь игры, которые пользователь уже добавил в свою игровую корзину. Это делается с помощью нашей вспомогательной функции fetch_user_games.
  2. Извлечение игровых тегов: чтобы сравнить игры, нам нужен параметр для сравнения, и этим параметром являются теги, связанные с каждой игрой (стратегия, настольная игра и т. д.). Чтобы извлечь тег игры: сопоставление, мы вызываем нашу функцию fetch_all_game_tags, которая возвращает теги для всех игр в нашей базе данных.
  3. Векторизация игровых тегов: чтобы сравнить сходство между играми A и B, нам сначала нужно векторизовать игровые теги с помощью нашей функции create_game_vectors.
  4. Создание вектора пользователя: после того как мы создали вектор, представляющий каждую игру, нам нужен агрегированный вектор пользователя для сравнения. Чтобы добиться этого, мы используем нашу функцию create_user_vector.
  5. Расчёт сходства: мы используем векторы, созданные на шагах 3 и 4, в нашем calculate_user_recommendations, который вычисляет оценку сходства по косинусу в диапазоне от 0 до 1 и измеряет сходство между каждой игрой и совокупностью игр пользователя.
  6. Удаление старых рекомендаций: прежде чем мы заполним нашу таблицу user_recommendations новыми рекомендациями для пользователя, мы сначала должны удалить старые с помощью delete_existing_recommendations.
  7. Заполнение новыми рекомендациями: после удаления старых рекомендаций мы заполняем новые с помощью save_recommendations.

Завершение

В этой статье мы рассмотрели, как настроить базу данных PostgreSQL и приложение FastAPI для запуска системы рекомендаций игр. Однако мы ещё не рассмотрели, как развернуть эту систему на облачном сервисе, чтобы другие могли с ней взаимодействовать. Во второй части, посвящённой именно этому, читайте далее в Части 2.