master
Родитель
3d81a62189
Сommit
17eb8952a6
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -0,0 +1,171 @@
|
|||||||
|
# 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.
|
||||||
|
* Указать команды для создания образа и запуска контейнера.
|
||||||
|
* Указать, как можно проверить работоспособность сервиса, включив пример тела запроса.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче