# Работа с фреймворком, обзор основных компонентов - [Работа с фреймворком, обзор основных компонентов](#работа-с-фреймворком-обзор-основных-компонентов) - [Модули](#модули) - [Структура базового модуля](#структура-базового-модуля) - [Репозиторий](#репозиторий) - [Образ 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` у всех компонентов в одном репозитории должно совпадать.