Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

172 строки
11 KiB
Markdown

# LR3 Создание сервиса предсказаний
## Цель
Создать микросервис предсказаний моделью ML, создать его docker-образ и запустить сервис в контейнере.
## Задание
1. Активировать виртуальное окружение. Установить библиотеки `fastapi`, `uvicorn`, не забыв обновить `requirements.txt`.
2. Запустить mlflow, убедиться, что доступны экспериметы, прогоны и модели, сделанные в ЛР2.
3. Создать директорию `./services`, в ней еще одну директорию `ml_service`, и в ней основной файл `main.py`.
```
my_proj
|_____ .venv_my_proj
|_____ .git
|_____ data
| |___ ...
|
|_____ eda
| |___ ...
|
|_____ research
| |___ ...
|
|_____ services
| |___ ml_service
| |___main.py
|
|_____ .gitignore
|_____ README.md
|_____ requirements.txt
```
4. В созданном файле создать экземпляр `FastAPI-приложения`, сделать обработку GET-запросов к корню приложения `/`, выдавая в ответ на запрос словарь `{"Hello": "World"}`
> В ходе работы с файлами `.py` будут создаваться директории `__pycache__`, в которых хранятся скомпилированные байт-код модули `.pyc`. Эти папки коммитить не нужно. Добавьте правило в `.gitignore`.
5. Запустить сервер `uvicorn` и убедиться, что сервис обрабатывает запросы к корню, пройдя на страницу `http://localhost:8000/docs` и выполнив тестовый запрос.
6. Создать endpoint `/api/prediction` выдачи предсказания для объекта. Endpoint будет обрабатывает POST-запросы, принимая в качестве URL-параметра идентификатор объекта `item_id`, а в теле запроса (body) все признаки объекта, необходимые для подачи на вход модели и выдачи предсказания. Возвращать будет словарь из двух объектов - `item_id` - тот же идентификатор объекта, и `predict` - предсказанное значение.
7. Запустить сервер `uvicorn` и убедиться, что сервис обрабатывает запросы к `/api/prediction`, пройдя на страницу `http://localhost:8000/docs` и выполнив тестовый запрос к этому endpoint-у. Если сервис работает правильно, то вы должны увидеть ответ такой структуры:
```
Response body
{
"item_id": 123,
"price": 0.7637315626006276
}
```
8. В директории `./services` создать директорию `models`, в которой будет храниться обученная модель, а также скрипт по ее получению из mlflow. Создать скрипт `get_model.py`
```
my_proj
|_____ .venv_my_proj
|_____ .git
|_____ data
| |___ ...
|
|_____ eda
| |___ ...
|
|_____ research
| |___ ...
|
|_____ services
| |___ ml_service
| | |___main.py
| |___models
| |___get_model.py
| |___model.pkl # Появится после выполнения следующего пункта
|
|_____ .gitignore
|_____ README.md
|_____ requirements.txt
```
9. Сформировать скрипт `get_model.py`, который должен подключаться к mlflow, выгружать модель по её run_id и сохранять ее в файл `model.pkl`.
10. В GUI MLFlow скопировать run_id production-модели, указать его в скрипте. Запустить скрипт и убедиться, что в директории `./services/models` появился файл `model.pkl`.
11. В директории `ml_service` создать файл `api_handler.py` и в нем описать класс-обработчик запросов к API `FastAPIHandler`.
Класс должен иметь метод `__init__` в котором загружается модель из файла `/model.pkl`, и метод `predict`, возвращающий предсказание.
12. Доработать основной модуль сервиса и класс-обработчик таким образом, чтобы сервис предсказывал значения для любого произвольного объекта, параметры которого передаются в теле запроса. Убедиться в корректности работы. Остановить сервис.
13. В папке `ml_service` создать файл `requirements.txt`, в который записать те зависимости, которые необходимы для работы сервиса.
> Данный файл - не то же самое, что `requirements.txt` в корневой директории проекта. Данный файл будет использоваться для сборки образа, поэтому должен содержать только необходимые зависимости и их версии. Виртуальное окружение на хостовой машине по-прежнему нужно устанавливать из файла в корневой директории.
> Проще всего заполнить этот `requirements.txt`, пройдясь по файлам в папке и выписав все импорты. Абсолютно точно на этом этапе в зависимости нужно добавить `fastapi`, `uvicorn`, `pandas`, `pickle4`.
```
my_proj
|_____ .venv_my_proj
...
|
|_____ services
| |___ ml_service
| | |___main.py
| | |___api_handler.py
| | |___Dockerfile
| | |___requirements.txt # новый файл, созданный на этом шаге
| |___models
| |___get_model.py
| |___model.pkl
|
|_____ .gitignore
|_____ README.md
|_____ requirements.txt # старый файл, созданный в ЛР1
```
14. В папке `ml_service` cформировать `Dockerfile`
Образ должен собираться Из базового образа `python:3.11-slim` по следующим шагам:
* Скопировать содержимое текущей директории в директорию `/ml_service` в контейнере
* Сделать директорию `/models` доступной снаружи контейнера
* Сделать `/ml_service` рабочей директорией
* Выполнить установку всех зависимостей из файла `requirements.txt`
* Указать, что порт 8000 должен быть доступен снаружи контейнера
* Финальная команда - запуск сервера. Необходимо явно указать адрес хоста `"0.0.0.0"` и порта `"8000"`, на которых будет запускаться сервер.
Состав директорий проекта на данном шаге должен выглядеть следуюшим образом:
```
my_proj
|_____ .venv_my_proj
|_____ .git
|_____ data
| |___ ...
|
|_____ eda
| |___ ...
|
|_____ research
| |___ ...
|
|_____ services
| |___ ml_service
| | |___main.py
| | |___api_handler.py
| | |___Dockerfile
| | |___requirements.txt
| |___models
| |___get_model.py
| |___model.pkl
|
|_____ .gitignore
|_____ README.md
|_____ requirements.txt
```
15. Собрать образ, дать ему понятное название и указав что это первая версия образа.
Команду по сборке образа записать в конец `Dockerfile`, добавив значок комментария `#`.
> В рамках это ЛР мы будем создавать первую версию нашего сервиса. Даже если вы несколько раз пересобираете образ, что-то меняя или добавляя в него, в этой ЛР все равно указывайте первую версию.
> Версия указывается через двоеточие после названия образа. Например, для указания 3й версии образа: `my_super_image:3`
16. Запустить контейнер из образа. Команду по запуску контейнера записать в конец `Dockerfile`, добавив значок комментария `#`.
> При запуске не забыть указать, какой хостовый порт должен быть связанным с портом 8000 внутри контейнера.
> Указать, что хостовая директория ../models должна быть связана с одноименной директорией в контейнере. Поскольку мы собираем образ из директории `ml_service`, а интересующая директория с моделью `models` находится на уровень выше, то путь до нее можно указать так: `$(pwd)/../models`. Здесь `$(pwd)` (print working directory) - утилита командной строки, которая выводит полный путь до текущей директории. Через двоеточие от хостовой директории нужно указать соответствующий volume внутри контейнера. Полный агрумент будет выглядеть так: `$(pwd)/../models:/models`
17. Убедиться, что контейнер работает, отправив запрос в сервис. Добиться работоспособности сервиса.
18. Актуализировать файл README:
* добавить описание разработанного сервиса: краткое описание файлов в папке ml_service, models.
* Указать команды для создания образа и запуска контейнера.
* Указать, как можно проверить работоспособность сервиса, включив пример тела запроса.