271 lines
14 KiB
Markdown
271 lines
14 KiB
Markdown
|
||
# Работа с фреймворком, обзор основных компонентов
|
||
|
||
- [Работа с фреймворком, обзор основных компонентов](#работа-с-фреймворком-обзор-основных-компонентов)
|
||
- [Модули](#модули)
|
||
- [Структура базового модуля](#структура-базового-модуля)
|
||
- [Репозиторий](#репозиторий)
|
||
- [Образ Docker](#образ-docker)
|
||
- [DataBox](#databox)
|
||
- [MLComponent](#mlcomponent)
|
||
- [ExperimentPipeline](#experimentpipeline)
|
||
- [APIComponent](#apicomponent)
|
||
- [Общие элементы компонентов](#общие-элементы-компонентов)
|
||
|
||
|
||
## Модули
|
||
|
||
Фреймворк работает с тремя типами модулей:
|
||
|
||
1. Базовый модуль - приложение, которое решает прикладную задачу.
|
||
2. MLOps-модуль - библиотека или набор подпрограмм, которые модифицируют работу базового модуля.
|
||
3. Модуль данных - набор данных, оформленный в соответствии с интерфейсом, который поддерживается фреймворком.
|
||
|
||
Основной тип модулей, которые развёртываются на фреймворке - базовые.
|
||
|
||
|
||
## Структура базового модуля
|
||
|
||
Базовый модуль состоит из нескольких частей, в совокупности формирующих приложение.
|
||
|
||
- Git-репозиторий
|
||
- Программный код, решающий прикладную задачу
|
||
- Интерфейс взаимодействия с фреймворком
|
||
- Компоненты модуля
|
||
- MLComponent
|
||
- ExperimentPipeline
|
||
- APIComponent
|
||
- DataBox
|
||
- Системные компоненты, подключающие модуль к фреймворку
|
||
- Secret
|
||
- Repository
|
||
- PlatformApp
|
||
- Образы Docker
|
||
|
||
|
||
Связь компонентов модуля:
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
%% External APIs
|
||
MLAPI[API ML-компонента]
|
||
PipeAPI-General[Общий API пайплайнов]
|
||
PipeAPI1[API первого пайплайна]
|
||
PipeAPI2[API второго пайплайна]
|
||
FileAPI[Файловый API]
|
||
|
||
|
||
%% S3 Infrastructure
|
||
S3Storage[(S3 Хранилище)]
|
||
FileAPI <---> S3Box-UserData[S3 Box: Данные пользователей]
|
||
FileAPI <---> S3Box-ModelWeights[S3 Box: Веса моделей]
|
||
S3Box-UserData --> S3Storage
|
||
|
||
%% ML Component Section
|
||
subgraph ML-Component["ML Component"]
|
||
direction LR
|
||
MLService[ML Service]
|
||
end
|
||
|
||
MLAPI <--> ML-Component
|
||
ML-Component --> S3Box-UserData
|
||
ML-Component --> S3Box-ModelWeights
|
||
S3Box-ModelWeights --> S3Storage
|
||
|
||
%% Pipeline Sections
|
||
subgraph Pipeline1["Pipeline 1"]
|
||
direction LR
|
||
Pipeline1Service1[Pipeline 1 запуск 1]
|
||
Pipeline1Service2[Pipeline 1 запуск 2]
|
||
end
|
||
subgraph Pipeline2["Pipeline 2"]
|
||
direction LR
|
||
Pipeline2Service1[Pipeline 2 запуск 1]
|
||
end
|
||
|
||
PipeAPI1 --> Pipeline1
|
||
PipeAPI2 --> Pipeline2
|
||
PipeAPI-General --> Pipeline1
|
||
PipeAPI-General --> Pipeline2
|
||
|
||
Pipeline1 --> S3Box-UserData
|
||
Pipeline2 --> S3Box-UserData
|
||
|
||
```
|
||
|
||
|
||
|
||
## Репозиторий
|
||
|
||
Репозиторий развернутого модуля содержит:
|
||
|
||
- Исходный код проекта
|
||
- Зависимости проекта, по которым можно воссоздать виртуальную среду для работы с ним
|
||
- Dockerfile
|
||
- Папку с манифестами (файлами YAML) компонентов модуля
|
||
|
||
Пример репозитория:
|
||
|
||
```
|
||
/mymodule
|
||
├── app
|
||
│ ├── api-files.yaml
|
||
│ ├── api-mlcmp-foo.yaml
|
||
│ ├── api-pipeline-bar.yaml
|
||
│ ├── api-pipeline-foo.yaml
|
||
│ ├── api-pipelines.yaml
|
||
│ ├── mlcmp-foo.yaml
|
||
│ ├── pipeline-bar.yaml
|
||
│ ├── pipeline-foo.yaml
|
||
│ └── s3-box.yaml
|
||
├── myapp
|
||
│ ├── __init__.py
|
||
│ ├── inference.py
|
||
│ ├── config.py
|
||
│ ├── settings.py
|
||
│ └── util.py
|
||
├── tests
|
||
│ ├── data
|
||
│ │ ├── img
|
||
│ │ │ ├── 0.json
|
||
│ │ │ ├── 0.png
|
||
│ │ │ ├── 1.json
|
||
│ │ │ ├── 1.png
|
||
│ │ └── test_model.joblib
|
||
│ ├── __init__.py
|
||
│ └── test_inference.py
|
||
├── .dockerignore # данные в tests для локальных запусков не включаются в образ
|
||
├── .gitignore
|
||
├── gpu-pipeline.dockerfile
|
||
├── README.md
|
||
├── requirements.txt
|
||
└── service.dockerfile
|
||
```
|
||
|
||
|
||
## Образ Docker
|
||
|
||
Docker-образ должен быть собран с помощью файла Dockerfile из репозитория модуля.
|
||
|
||
Образ должен содержать только основную программу, включая интерфейс взаимодействия с фреймворком, и зависимости, необходимые для её запуска. Образ должен быть основан на `-slim` версии базового образа Python, если не требуется иное.
|
||
|
||
В образе не должно быть лишних данных, таких как:
|
||
|
||
- папка `.git`
|
||
- данные для тестов
|
||
- веса ИИ-моделей
|
||
- артефакты сборки
|
||
|
||
Данные файлы рекомендуется сразу добавить в .gitignore для упрощения работы.
|
||
|
||
Необходимые для работы данные нужно загружать через файловое хранилище S3:
|
||
|
||
- Для [MLComponent](./mlcmp.md) - через пункты манифеста `modelPath` и `modelBox`.
|
||
- Для [ExperimentPipeline](./pipeline.md) - через входную переменную, к которой прописан полный путь в `mountFrom`.
|
||
|
||
## DataBox
|
||
|
||
Компонент [DataBox](./databox.md) позволяет модулю использовать файловое хранилище S3. В одном модуле может быть несколько компонентов, отвечающих за разные виды данных. Например, данные конечных пользователей модуля (загруженные для расчётов файлы) и данные разработчика модуля (веса моделей ИИ).
|
||
|
||
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
User[Пользователь]
|
||
User <--> FileAPI
|
||
S3Box-UserData --> S3Storage
|
||
|
||
subgraph Module["Модуль"]
|
||
direction TB
|
||
|
||
FileAPI["Файловый API
|
||
.../files/userbox/run_inputs/data.txt"]
|
||
subgraph Container["Контейнер Docker"]
|
||
Filesystem["Файловая система
|
||
/home/user/data/myfile.txt"]
|
||
end
|
||
S3Box-UserData
|
||
S3Box-ModelWeights
|
||
end
|
||
|
||
|
||
Filesystem <--Монтирование в '/home/user/data/'--> S3Box-UserData[S3 Box: Данные пользователей]
|
||
Filesystem <--Монтирование в '/home/weights/data/'--> S3Box-ModelWeights[S3 Box: Веса моделей]
|
||
|
||
FileAPI <---> S3Box-UserData["S3 Box 'userbox': Данные пользователей"]
|
||
FileAPI <---> S3Box-ModelWeights["S3 Box 'weights': Веса моделей"]
|
||
S3Box-ModelWeights --> S3Storage
|
||
|
||
S3Storage[("S3 Хранилище
|
||
userbox/USERNAME/file_groups/run_inputs/data.txt")]
|
||
|
||
```
|
||
|
||
## MLComponent
|
||
|
||
[MLComponent](./mlcmp.md) - это компонент, который позволяет создать сервис синхронной обработки вычислительных запросов.
|
||
|
||
Код MLComponent обязательно должен содержать функцию, написанную на языке Python, с заранее определённым интерфейсом ("функция inference"). В неё передаются данные из запроса пользователя, а так же готовая модель машинного обучения, определённая в манифесте MLComponent.
|
||
|
||
Разработчик указывает, среди прочего:
|
||
|
||
- Docker-образ компоненты, который содержит код функции inference
|
||
- Путь к Python-модулю функции inference в Docker-контейнере
|
||
- Путь в Docker-контейнере, по которому можно загрузить модель ИИ
|
||
- Настройки запуска Docker-контейнера: лимиты ресурсов, переменные окружения и т.д.
|
||
- Детали подключения файлового хранилища S3 к файловой системе контейнера
|
||
- Какие компоненты DataBox используются
|
||
- Соответствие путей в файловом хранилище S3 и путей в файловой системе контейнера
|
||
|
||
|
||
## ExperimentPipeline
|
||
|
||
Компонент [ExperimentPipeline](./pipeline.md) ("пайплайн") позволяет создать сервис для асинхронной обработки запросов пользователей.
|
||
|
||
В пайплайнах важной частью кода разработчика является описание Docker-контейнера. Взаимодействие контейнера с фреймворком организуется через файловую систему и переменные окружения. Входные и выходные данные монтируются в файловую систему контейнера, и локальные пути к ним передаются в контейнер как переменные окружения. Таким образом, порядок работы контейнера:
|
||
|
||
- Считать переменные окружения, получить пути к входным данным и к папкам для размещения выходных данных.
|
||
- Считать данные, используя полученные пути к входным данным
|
||
- Произвести вычисления
|
||
- Сохранить результаты, используя полученные пути для размещения выходных данных
|
||
|
||
Компонент ExperimentPipeline позволяет организовывать вычисления в несколько этапов, каждый из которых запускается со своим набором входных и выходных данных. Каждый контейнер соответствует одному этапу.
|
||
|
||
В самом манифесте ExperimentPipeline разработчик, помимо прочего, указывает:
|
||
|
||
- Docker-образ, который будет запускаться
|
||
- В том числе настройки запуска - переменные окружения, лимиты ресурсов
|
||
- Входные и выходные переменные этапов
|
||
- Могут указываться детали их подключения - путь к файловом хранилище S3, путь в файловой системе контейнера
|
||
- Детали подключения файлового хранилища S3 к файловой системе контейнера
|
||
- Какие компоненты DataBox используются
|
||
- Соответствие путей в файловом хранилище S3 путям в файловой системе контейнера по умолчанию
|
||
|
||
## APIComponent
|
||
|
||
Компонент APIComponent предоставляет доступ к элементам модуля через API. Есть четыре основных вида компонентов APIComponent:
|
||
|
||
1. Файловый API
|
||
2. API пайплайнов в целом
|
||
3. API отдельного MLComponent
|
||
4. API отдельного ExperimentPipeline
|
||
|
||
Первые три вида APIComponent определяются похожим образом, и с точки зрения разработчика отличаются добавлением соответствующего поля в манифест.
|
||
|
||
APIComponent отдельного ExperimentPipeline определяет всю структуру взаимодействия с соответствующим пайплайном через API, то есть входные и выходные переменные, их типы данных и описания.
|
||
|
||
## Общие элементы компонентов
|
||
|
||
Манифесты компонентов имеют следующую структуру:
|
||
|
||
```yaml
|
||
apiVersion: "unified-platform.cs.hse.ru/v1"
|
||
kind: <Тип>
|
||
metadata:
|
||
name: <Название компонента>
|
||
namespace: <Название приложения>
|
||
spec:
|
||
<Содержимое компонента>
|
||
```
|
||
|
||
Все компоненты в репозитории являются частью одного и того же приложения, поэтому значение поля `metadata.namespace` у всех компонентов в одном репозитории должно совпадать.
|