21 KiB
Сложный пайплайн (mldev)
MLDev - программное обеспечение, упрощающее запуск воспроизводимых вычислительных экспериментов.
С помощью MLDev можно создавать более сложные вычислительные эксперименты (пайплайны) для использования на фреймворке, а также более удобно работать с обычными пайплайнами.
Принцип работы с фреймворком при помощи MLDev:
- Разработчик создаёт манифест эксперимента, аналогичный манифесту пайплайна.
- На основе манифеста эксперимента с помощью mldev автоматически генерируется манифест пайплайна и собираются docker-образы.
- Разработчик добавляет сгенерированный манифест пайплайна и docker-образы к модулю как при обычном создании пайплайна.
- Подготовка элементов mldev
- config.yaml
- stages.py
- experiment-unip-pipeline.yaml
- unip-pipeline.yaml
- MLOps-модули
Подготовка элементов mldev
В примере далее рассматривается следующая структура файлов, относящихся к MLDev.
experiments
├── .mldev
│ ├── config.yaml
│ └── stages.py
├── experiment-unip-pipeline.yaml
└── unip-pipeline.yaml
config.yaml
- настройки MLDev, такие как параметры запуска, уровень логирования и шаблон названия docker-образов.stages.py
- загрузка используемых компонентов MLDev с помощью выраженияimport
.experiment-unip-pipeline.yaml
- mldev-пайплайн сборки эксперимента, запускаемый разработчиком.unip-pipeline.yaml
- основной пайплайн, используется пайплайном сборки для построения вычислительного эксперимента.
config.yaml
Пример содержимого config.yaml
:
logger:
level: DEBUG
extras:
base: mldev.experiment_objects
containers: mldev_containers.containers
environ:
IMAGE_TAG_TEMPLATE: 'platform-reg.stratpro.hse.ru/myproject/${name}:${revision}'
UNIP_MLDEV_PIPELINE_OUTPUT: ./build/pipelines
EXPERIMENT_FILE: ./experiments/unip-pipeline.yaml
FORCE_RUN: True
logger.level
- уровень логирования,DEBUG
,INFO
илиERROR
.extras
- дополнительные модули MLDev, необходимые для взаимодействия с фреймворком.environ
- переменные окруженияIMAGE_TAG_TEMPLATE
- шаблон названия образа Docker.${name}
будет автоматически заменено на название этапа из файла эксперимента, а${revision}
- на короткий хэш последнего коммита в репозитории проектаUNIP_MLDEV_PIPELINE_OUTPUT
- путь, куда будет сохранён сгенерированный манифест пайплайна для фреймворкаEXPERIMENT_FILE
- файл с вычислительным экспериментомFORCE_RUN
- параметр, заставляющий MLDev собирать эксперимент заново, даже если не найдено изменений с прошлой сборки
stages.py
Пример файла stages.py
:
from mldev_containers import ContainerStage, StageCode, StageVar
from unip.mldev_pipeline.unip_pipeline import UnipPipeline
from unip.mldev_pipeline.dataloader import StageSrc
UnipPipeline
,StageCode
,StageVar
,ContainerStage
- классы компонентов, необходимых для работы с пайплайнамиStageSrc
- класс подключения модуля данных
Аналогично модулю данных в примере, для подключения других специализированных этапов, таких как подключение к суперкомпьютеру cHARISMa и автоматическая генерация отчёта об эксперименте, необходимо добавлять соответствующие классы в stages.py
.
experiment-unip-pipeline.yaml
В этом файле определяется небольшой вычислительный эксперимент MLDev, в результате которого должен быть собран полноценный эксперимент из файла unip-pipeline.yaml
.
Здесь определяются параметры запуска и переменные окружения полноценного эксперимента, а также добавляются вспомогательные команды.
Пример файла experiment-unip-pipeline.yaml
pipeline: !GenericPipeline
runs:
- !BasicStage
name: experiment
env:
PYTHONPATH: './experiments/.mldev'
MLDEV_CONFIG_PATH: './experiments/.mldev/config.yaml'
PIP_EXTRA_INDEX_URL: '${env.PIP_EXTRA_INDEX_URL}'
script:
- mkdir -p ./build/containers
- mkdir -p ./build/pipelines
- rm -rf ./build/containers/*
- rm -rf ./build/pipelines/*
- mldev run pipeline -f ./experiments/unip-pipeline.yaml
pipeline: !GenericPipeline
- указывает, что это объект классаGenericPipeline
- стандартный пайплайн библиотеки MLDev, не относящийся к фреймворку.runs
- список этапов, которые будут выполнены в ходе выполнения пайплайна GenericPipeline!BasicStage
- указывает, что текущий этап - это объект классаBasicStage
, стандартного класса этапа пайплайна в MLDev.name: experiment
- имя этапа. Не используется далееenv:
- переменные окружения, с которыми запускается этап сборки полноценного пайплайна,PYTHONPATH
- чтобы модули MLDev, импортированные в файлеstages.py
были загружены, нужно указать в PYTHONPATH путь к папке с этим файлом. В данном примере,./experiments/.mldev
MLDEV_CONFIG_PATH
- путь к используемому в полноценном эксперименте файлу настроек MLDev.PIP_EXTRA_INDEX_URL
- дополнительные индексы для установки пакетов Python. Используются для установки пакетов фреймворка, которые не размещены в индексе PyPI. Значение'${env.PIP_EXTRA_INDEX_URL}'
означает, что переменная окруженияPIP_EXTRA_INDEX_URL
копирует содержимое такой же переменной из среды, которая запускает эксперимент.
script
= команды, которые выполяются в текущем этапеexperiment
. В данном примере это создание папок./build/containers
и./build/pipelines
, удаление их содержимого и запуск сборки полноценного пайплайна.
unip-pipeline.yaml
Этот файл полностью описывает вычислительный эксперимент, аналогично компоненту ExperimentPipeline
.
UnipPipeline
Основной объект вычислительного эксперимента, который должен быть определён в файле unip-pipeline.yaml
- это объект pipeline:!UnipPipeline
со следующей структурой:
pipeline: !UnipPipeline
name: my-project
namespace: pu-username-pa-appname
variables:
- name: preparation_data
- name: internal_state
- name: user_report
runs:
- *container_stage_prepare
- *container_stage_complete
connected_boxes:
- name: user-box
path: /userdata/
default: true
mount_s3_box:
s3_box_name: users
name: my-project
- имя, которое будет использовано далее при генерации имени компонентаExperimentPipeline
.namespace
- пространство имён приложения, аналогично с остальными манифестами компонентов.variables
- список переменных, которые используются во всех этапах, вместе взятых. АналогичноExperimentPipeline
. Для каждой переменной помимо поляname
можно указать поляpath
(точка монтирования в контейнере) иmountFrom
(DataBox и точка монтирования в хранилище S3).runs
- список этапов пайплайна. В примере - ссылки на отдельно определённые компоненты.connected_boxes
- раздел, полностью аналогичный такому же разделу вExperimentPipeline
- определение связанных компонентовDataBox
, указание пути монтирования по умолчанию и внутреннего имени DataBox, которое используется в этом файле далее. В отличие отExperimentPipeline
, где используется camelCase, здесь используется snake_case.
ContainerStage
Отдельный этап пайплайна UnipPipeline
- это ContainerStage
. Такой этап соответствует этапу ExperimentPipeline
.
container_stage_prepare: !ContainerStage &container_stage_prepare
name: my-prepare
base_image: platform-reg.stratpro.hse.ru/my_org/myproject-prepare:718e2b0
stage: *stage_prepare
build:
<<: *build
code: *code
env:
MY_CUSTOM_FLAG: "True"
resource_limits:
cpu: "1"
memory: 500M
container_stage_prepare: !ContainerStage &container_stage_prepare
:container_stage_prepare:
- корень объекта этапа!ContainerStage
- класс, на основе которого будет создан этап&container_stage_prepare
- имя, по которому на этот этап можно ссылаться. Это имя используется вUnipPipeline
my-prepare
- название этапа. Используется как название этапа вExperimentPipeline
и в названии Docker-образаbase_image
- образ Docker, на основе которого будет создан этап. Это может быть как стандартный образ видаpython:3.11.10-slim-bullseye
, так и образ, загруженный в реестр фреймворка видаplatform-reg.stratpro.hse.ru/my_org/myproject-prepare:718e2b0
.stage: *stage_prepare
- объект видаBasicStage
, в котором определяются входные, выходные данные и точка входа, запускающая вычисления.build
- параметры сборки Docker-образа, здесь определяются отдельным объектом.code
- объект типаStageCode
, который определяет устанавливаемые черезrequirements.txt
зависимости, а также файл с исходным кодом проекта, добавляемые в контейнер.env
- набор произвольных переменных окружения, которые будут установлены при запуске контейнера.resource_limits
- лимиты ресурсов в терминах Kubernetes, аналогичноExperimentPipeline
.
build
В данном определении используется несколько ссылок на внешние объекты. Объект build
имеет структуру
build_params: &build
root: .
output: build/containers
Это означает, что корнем сборки Docker-контейнера выступает корень репозитория, а сгенерированные скрипты сборки и Dockerfile-ы появятся в папке build/containers
в репозитории.
code
Объект StageCode
имеет структуру
code: !StageCode &code
requirements: ./requirements.txt
src:
- ./myproject/
- ./my_static_config.json
- ./.mldev/
- ./experiments/unip-pipeline-paper.yaml
- Это объект типа
StageCode
, на который далее можно ссылаться по имениcode
. requirements
- файл с зависимостями, который будет скопировать в контейнер и использован для установки зависимостейsrc
- список файлов или папок, которые будут скопированы в рабочую директорию контейнера. По умолчанию это/unip
.
Объект StageCode
предполагает единый проект, даже если в его рамках запускаются разные файлы. Если несколько контейнеров объединяются в один пайплайн с разными StageCode
, то в результате сгенерируется несколько объектов ExperimentPipeline
, составляющих цепочку запуска.
BasicStage
Объект BasicStage
определяет входные, выходные данные этапа пайплайна, а также точку входа.
stage_prepare: !BasicStage &stage_prepare
name: stage_prepare
inputs:
- !StageVar
name: preparation_data
path: ./data/preparation
outputs:
- !StageVar
name: internal_state
script:
- python src/prepare.py
stage_prepare: !BasicStage &stage_prepare
- аналогично предыдущим компонентам, объектstage_prepare
классаBasicStage
, на который можно ссылаться какstage_prepare
.name
- название этапаinputs
- список входных переменных!StageVar
- переменная типаStageVar
. Это обычный тип переменных по умолчанию, аналогичный переменнымExperimentPipeline
.name
- название переменной, используется далее в пайплайне и в контейнере.path
- путь монтирования переменной внутри контейнера. Если передан относительный путь, он рассчитывается от рабочей директории контейнера -/unip
.
outputs
- аналогичноinputs
script
- точка входа в этап эксперимента.- При этом точкой входа в контейнер будет команда MLDev
mldev run stage_prepare -f /unip/experiments/unip-pipeline.yaml
, а уже запущенный ей процесс выполнит команду из поляscript
.
- При этом точкой входа в контейнер будет команда MLDev
Сборка пайплайна
Запуск сборки
Чтобы запустить сборку пайплайна нужно выполнить следующие условия:
- В
PATH
доступна командаmldev
. Например, в используемой виртуальной среде установлен пакет Pythonmldev
. - В переменной окружения
PIP_EXTRA_INDEX_URL
указаны ссылки на используемые реестры пакетов Python фреймворка с указанием рекизитов.
Дополнительные индексы пакетов Python указываются в формате
export PIP_EXTRA_INDEX_URL="https://my_username:mypassword_or_token_abcdef1234@platform-forgejo.stratpro.hse.ru/api/packages/MY_ORG/pypi/simple https://my_username:mypassword_or_token_abcdef1234@platform-forgejo.stratpro.hse.ru/api/packages/ANOTHER_ORG/pypi/simple"
Общий набор команд для сборки эксперимента mldev может быть примерно такой:
cd /home/my_username/MLOPS/my_project/
export PIP_EXTRA_INDEX_URL="https://my_username:mypassword_or_token_abcdef1234@platform-forgejo.stratpro.hse.ru/api/packages/MY_ORG/pypi/simple https://my_username:mypassword_or_token_abcdef1234@platform-forgejo.stratpro.hse.ru/api/packages/ANOTHER_ORG/pypi/simple"
source venv/bin/activate
mldev run -f experiments/experiment-unip-pipeline-paper.yaml
После завершения сборки в корневой папке проекта должна появиться следующая структура:
/build
├── containers
│ ├── my-complete.dockerfile
│ ├── my-complete.dockerignore
│ ├── my-complete.sh
│ ├── my-prepare.dockerfile
│ ├── my-prepare.dockerignore
│ └── my-prepare.sh
└── pipelines
└── my-project-qzv828.yaml
Здесь в containers
хранятся файлы, используемые для сборки контейнеров отдельных этапов, а в pipelines
- сгенерированный манифест ExperimentPipeline
. Сами собранные образы этапов должны быть доступны в Docker, например, видны в команде docker images
.
Подключение к базовому модулю
Чтобы подключить сгенерированный манифест ExperimentPipeline
к фреймворку, следует его переименовать, изменить в содержимом манифеста поле name
на желаемое название пайплайна и поместить манифест в папку app
в репозитории.
Компонент APIComponent
не генерируется при сборке пайплайна MLDev, его нужно создать вручную.
Собранные образы Docker нужно загрузить в репозиторий образов в Harbor.
Разделение на несколько пайплайнов
ExperimentPipeline
поддерживает последовательный запуск нескольких пайплайнов - подробнее здесь.
Во время сборки эксперимента через MLDev этапы с разными объектами StageCode
считаются достаточно сильно отличными друг от друга. Такие этапы разделяются в отдельные объекты ExperimentPipeline
и связываются через continueWith
.
MLOps-модули
MLOps-модули фреймворка и некоторые другие дополнительные возможности работают за счёт замены стандартных классов ContainerStage
, BasicStage
и StageVar
на свои варианты.
Например:
CharismaStage
вместоContainerStage
позволяет отправить вычислительную задачу на суперкомпьютер cHARISMa.StageSrc
вместоStageVar
позволяет использовать данные из модуля данных.Report
вместоBasicStage
позволяет сгенерировать отчёт о проведённом вычислительном эксперименте.