Использование Python FastApi, действий Github и Vue.js.

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

Требования

Прежде чем двигаться дальше, вам потребуется установить в вашей среде следующий инструмент:

  • Аккаунт AWS
  • AWS CLI
  • Аккаунт Github
  • Python 3.7 или выше
  • модель scikit-learn, обученная и сериализованная на этапе предварительной обработки (с использованием pickle)

Понимание архитектуры решения

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

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

Модель машинного обучения хранится в корзине s3. Он загружается работником, который является функцией Lambda, когда сообщение, содержащее данные прогноза, помещается в очередь SQS клиентом через шлюз API / конечную точку Lambda REST.

Когда рабочий завершает задание прогнозирования, он помещает результат в таблицу DynamoDb для доступа. Наконец, клиент запрашивает результат прогнозирования через конечную точку API, которая будет читать таблицу DynamoDb для получения результата.

Как видите, мы делегируем работу по загрузке и прогнозированию работнику и не интегрируем модель в REST API. Это связано с тем, что для загрузки и прогнозирования модели может потребоваться много времени. Поэтому мы управляем ими асинхронно благодаря добавлению очереди SQS и таблицы DynamoDb.

Как развернута инфраструктура?

Можно настроить инфраструктуру через консоль AWS, но здесь мы будем использовать действие Github, которое я написал, которое позволит нам развернуть модель без необходимости управлять развертыванием инфраструктуры, за исключением корзины s3.

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

Мы не будем здесь обсуждать, как писать действия GitHub или как использовать бессерверную структуру.

Настройка проекта

Я буду использовать поэзию для настройки структуры проекта и управления зависимостями, не стесняйтесь адаптировать ее, если вы хотите использовать pip с виртуальной средой.

  1. Создайте новый проект с poetry new <name_of_project>
  2. cd в созданную папку
  3. Выполните следующую команду, чтобы установить зависимости проекта: poetry add pandas scikit-learn pydantic typer boto3

4. Создайте app.py файл в папке <your_package_name> в корневом каталоге.

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

Создание небольшого интерфейса командной строки для настройки s3

Для обеспечения воспроизводимости мы напишем простой интерфейс командной строки с Typer, который построен поверх Click. Если вы не знакомы с интерфейсом командной строки, я написал сообщение, в котором рассматриваются некоторые основные концепции создания интерфейса командной строки.



Давайте посмотрим на код для создания интерфейса командной строки.

Первые две команды позволяют нам создавать и удалять ведро s3. Важно отметить, что сегмент создается с управлением версиями. Управление версиями дает нам возможность загружать разные версии одной и той же модели, а затем обновлять воркер для обслуживания версии по нашему выбору.

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

Наконец, последняя команда позволит нам обновить идентификатор версии модели, обслуживаемой API.

Теперь давайте добавим интерфейс командной строки к нашим поэтическим сценариям, откроем pyproject.tomlfile и добавим внизу следующие строки:

[tool.poetry.scripts]
cli = "<package_name>.app:app"

Затем проверьте, все ли работает с poetry run cli, у вас должно получиться что-то вроде:

Usage: cli [OPTIONS] COMMAND [ARGS]...
Options:
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.
--help                          Show this message and exit.
Commands:
  create-bucket
  delete-bucket
  list-objects
  upload
  update-lambda

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

  1. poetry run cli create-bucket <bucket-name-to-be-created>
  2. poetry run cli upload <bucket-name> <path_to_your_model> --tag 1.0
  3. poetry run cli list-objects <bucket-name>, который должен напечатать что-то вроде следующего:
Key: <your_model>.pickle
VersionId: 11j3aXER32C7exuanDNKvOea0FxJwXg
IsLatest: True 
LastModified: 2020-09-11 09:38:46+00:00 
Tag: [{'Key': 'Version', 'Value': '1.0'}]

Теперь, когда наша модель хранится на s3, нам нужно определить класс, который отображает нашу схему данных.

Создание схемы проверки

Поскольку действие GitHub использует FastApi под капотом, нам нужно предоставить класс для метода post, который будет обрабатывать данные, которые клиент отправит для прогнозирования. Благодаря определению этого класса FastApi выполнит проверку отправленных данных за нас.

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

И вот мой соответствующий файл validation.py с классом PredictionData:

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

Примечание. Класс должен называться PredictionData.

Тестирование модели

Наш набор тестов будет написан с помощью pytest, нам нужно установить его как зависимость разработчика с помощью следующей команды: poetry add pytest --dev

В папке tests создайте файл test_model.py и поместите следующие тесты:

Набор тестов сначала гарантирует, что написанный нами класс валидации может быть инициализирован необработанными данными. Затем он проверяет, является ли модель экземпляром класса конвейера scikit learn. Наконец, он гарантирует, что наша модель может предсказать необработанные данные.

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

Теперь запустите набор тестов с poetry run pytest -v, если все прошло хорошо, вы должны увидеть следующий результат:

tests/test_model.py::test_version PASSED                                                                                                                          [ 25%]
tests/test_model.py::test_init_prediction_data PASSED                                                                                                             [ 50%]
tests/test_model.py::test_is_pipeline PASSED                                                                                                                      [ 75%]
tests/test_model.py::test_prediction PASSED                                                                                                                       [100%]

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

Написание формы веб-приложения

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

Мы собираемся использовать действие GitHub, которое я написал, который использует vue-form-generator под капотом для создания формы, предоставляя ей файл конфигурации. Создайте form.yml файл в корневом каталоге проекта.

В начале файла у нас есть первый блок, содержащий 3 ключа:

  1. title: строка, представляющая заголовок веб-приложения.
  2. units: строка, представляющая единицу результата прогноза.
  3. главная: список объектов, которые будут отображаться content внутри поля на главной странице.

Примечание. Для строковой переменной вам нужно будет добавить строку в одинарные кавычки.

Затем у нас есть fieldsproperty под schemakey, который представляет собой список объектов. Для каждого объекта мы определяем тип. Например, в моем form.yml я использовал select с некоторыми предоставленными значениями, которые нужно будет выбрать пользователю. Вам нужно будет проверить документацию vue-form-generator, чтобы увидеть все доступные параметры ввода, которые вы хотите использовать для сопоставления полей данных.

Примечания.
Настройте поля в том же порядке, который вы определили в своем validation.py.

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

Написание рабочего процесса GitHub

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

Секреты предназначены для хранения конфиденциальной информации, такой как пароли или ключи API. В нашем случае нужны следующие секреты:

  1. AWS_ACCESS_KEY
  2. AWS_KEY_ID
  3. ACCESS_TOKEN

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

Вам нужно будет выбрать области, в которых вы хотите предоставить этот токен, обязательно установите флажок repo, чтобы иметь возможность развернуть форму на странице GitHub.

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

После того, как вы настроили все секреты, вы можете создать дерево каталогов .github/worflows внутри корневой папки вашего проекта, которое будет содержать следующий main.yml файл.

Примечание. Обратите внимание на отступы, вы можете использовать этот инструмент, чтобы выявлять ошибки.

onkey определяет, когда запускать развертывание, в моем случае каждый раз, когда выполняется нажатие на главную ветку, действие будет выполняться. Затем в env key мы определяем конфигурацию AWS как переменные среды.

Наконец, мы определяем одно задание из 4 шагов:

  1. Первый использует действия / проверку, чтобы клонировать наше репо внутри бегуна, здесь виртуальная машина ubuntu
  2. Затем мы вызываем действие для развертывания модели обучения scikit. Благодаря ключу with мы указываем:
  • Название ведра
  • Ключ модели
  • Идентификатор версии модели, отображаемой в REST API.
  • Название службы
  • Этапы развертывания.

Примечания:
Вы можете добавить worker_timeout:"<time_in_seconds>" на шаге api в качестве входных данных, чтобы установить другой тайм-аут для Lambda worker, отвечающего за загрузку и сделав прогноз по умолчанию равным 10 секундам.

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

3. Затем мы используем другое действие GitHub для создания нашего веб-приложения из form.yml, оно использует выходные данные предыдущего шага для получения конечной точки API.

4. Наконец, мы используем последнее действие GitHub для развертывания нашего созданного веб-приложения на странице GitHub.

Развертывание решения

Прежде чем запускать действие, давайте проверим, что структура папок в порядке, если вы использовали поэзию, у вас должно получиться что-то вроде этого:

Примечание: затененные имена не передаются в git.

Теперь, когда наш рабочий процесс настроен, нам нужно запустить действие с помощью git push <remote_name> master

Затем перейдите в репозиторий GitHub и выберите Действия на ленте выбора под именем вашего каталога. Щелкните имя своего коммита, чтобы увидеть, как идет процесс развертывания.

Если все прошло нормально: перейдите на http://<your_github_name>.github.io/<your_repo_name>/#/, вы должны увидеть домашнюю страницу.

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

Взаимодействие через конечную точку FAST API

Адрес конечной точки API можно найти в журнале действия GitHub, щелкнув на шаге «Остаточное развертывание API» или в консоли AWS в службе шлюза API.

Конечная точка предоставляет две услуги:

  1. POST - ‹your_adress› / ‹stage› / api / прогноз, который принимает данные, как определено в raw_data в нашем наборе тестов, и возвращает prediction_id
  2. GET - ‹your_adress› / ‹stage› / api / pred / ‹prediction_id›, которые возвращают результат предсказания.

Обновление модели

Теперь представим, что вы хотите развернуть вторую версию той же модели, потому что вы ее улучшили. Это как действовать:

  1. запустите тестовый костюм для новой версии с peotry run pytest
  2. загрузите новую модель в s3 с помощью poetry run cli <bucket-name> <path_to_your_model> --tag 2.0
  3. получить идентификатор новой версии загруженной модели с помощью: poetry run cli list-objects <bucket-name>
  4. обновите лямбда-функцию с помощью poetry run cli update-lambda <lambda-name> <version_id>

Рабочая функция Lambda теперь обслуживает обновленную модель через ту же конечную точку API. Это позволяет не развертывать весь стек заново.

Удаление стека

Если вы хотите удалить все развернутые сервисы, вы можете перейти в консоль AWS и выбратьcloudformation service. В списке стеков вы увидите service_name, который вы определили в файле рабочего процесса. Выберите его и удалите.

Заключение

В этом посте мы увидели, как бессерверные сервисы AWS использовались для развертывания модели. Благодаря действиям GitHub развертывание модели автоматизировано, и с ней можно взаимодействовать программно или через простое веб-приложение. Также возможно обновить модель без повторного развертывания стека.

Спасибо за чтение. Мы будем благодарны за любые конструктивные отзывы, предложения или улучшения кода.

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