documentation/pages/mlcmp.md

13 KiB
Raw Blame History

MLComponent

Компонент MLComponent позволяет создать сервис для синхронной обработки запросов пользователей.

MLComponent подходит для быстрых вычислений, в частности запуска предобученной модели машинного обучения на небольшой выборке данных. Например, распознавание объекта на одном изображении, классификация таблицы текстовых данных. Если алгоритм работает за доли секунды, то он подходит как основа для MLComponent.

На основе образа Docker, указанного в манифесте MLComponent, создаётся контейнер. В него устанавливается системная библиотека платформы, которая создаёт веб-сервис. При получении запроса от пользователя веб-сервис вызывает функцию inference, указанную в манифесте MLComponent, и передаёт вывод функции пользователю.

Для добавления MLComponent к модулю разработчику нужно:

  • Реализовать функцию, на основе которой будет создан веб-сервис.
  • Добавить в модуль манифест компонента MLComponent
  • Добавить в модуль манифест компонента APIComponent для обращения к MLComponent

Также в модуле уже должен присутствовать хотя бы один компонент DataBox и соответствующий ему APIComponent.

Функция inference

Для работы MLComponent нужно реализовать функцию со следующим интерфейсом:

def inference(parameters: List[Dict[str, Any]],
              inputs: List[Dict[str, Any]],
              output_fields: List[Dict[str, Any]],
              model_key: str,
              model: Any = None) -> Tuple[List[Dict[str, Any]], Any]:

Входные параметры:

  • parameters - список пар [name, value], произвольных параметров примитивных типов.
  • inputs - список входных данных, где каждый элемент - это словарь. Ключи словаря:
    • name - название, произвольная строка, используется в коде модуля. Например, "image".
    • datatype - тип входных данных, одна из строк "FP32", "FP64", "INT32", "FILE", "str".
    • content_type - тип содержимого файла, если тип входной переменной datatype - это "FILE".
    • data - строка с путём к входному файлу или одномерный список входных данных соответствующего типа.
    • shape - размерность входной переменной как массива, применимо даже к файлам (не размер файла в файловой системе).
  • output_fields - список выходных данных, где каждый элемент - это словарь. Ключи словаря:
    • name - название, произвольная строка, используется в коде модуля. Например, "prediction".
    • datatype - тип выходных данных, одна из строк "FP32", "FP64", "INT32", "FILE", "str".
    • content_type - тип содержимого файла, если тип выходной переменной datatype - это "FILE".
    • data - строка с путём к выходному файлу или одномерный список выходных данных соответствующего типа.
    • shape - размерность выходной переменной как массива, применимо даже к файлам (не размер файла в файловой системе).
  • model_key - строка, по которой можно загрузить модель (обычно путь).
  • model - объект модели, с помощью которого проводится инференс.

Функция выводит tuple из двух объектов:

  • список выходных данных, где каждый элемент - это словарь. Ключи словаря:
    • name - название, произвольная строка, используется в коде модуля. Например, "prediction".
    • datatype - тип выходных данных, одна из строк "FP32", "FP64", "INT32", "FILE", "str".
    • content_type - тип содержимого файла, если тип выходной переменной datatype - это "FILE".
    • data - строка с путём к выходному файлу или одномерный список выходных данных соответствующего типа.
    • shape - размерность выходной переменной как массива, применимо даже к файлам (не размер файла в файловой системе).
  • объект модели, который можно передать в следующий вызов функции как аргумент model.

Формат самих входных данных, которые передаются в аргументе inputs при вызове функции, должен быть указан в docstring-спецификации.

def inference(parameters: List[Dict[str, Any]],
              inputs: List[Dict[str, Any]],
              output_fields: List[Dict[str, Any]],
              model_key: str,
              model: Any = None) -> Tuple[List[Dict[str, Any]], Any]:

Манифесты

Пример манифеста ML-компонента.

apiVersion: "unified-platform.cs.hse.ru/v1"
kind: MLComponent
metadata:
  name: somename-mlcmp
  namespace: pu-username-pa-bm99
spec:
  image:
    existingImageName: example.com/lab-name/bm99-module-container-name:12ab345
  resourceLimits:
    cpu: 500m
    memory: 256M
  env:
    - name: CUSTOM_PARAMETER_1
      value: "3.14"
    - name: ANOTHER_PARAMETER
      value: "some_value"
  mlService:
    packageRegistryName: python-package-registry
    inference:
      fileExchange:
        fileBox: user-box
        inferenceFilesPath: /home/appname/users/tmp
      model:
        modelBox: model-box
        modelPath: /home/path/to/model.joblib
      entryPoint:
        pythonPath: .
        pythonFunction: modulename.predict.inference
  connectedBoxes:
    - name: model-box
      path: /home/path/to
      mountS3Box:
        subPath: users/developer/file_groups/models
        s3BoxName: mymodule-data-box
    - name: user-box
      copyS3Box:
        s3BoxName: users

Здесь,

  • metadata/name - название ML-компонента. Оно используется в API-компоненте и может использоваться в других обращениях к компоненту через kubernetes.
  • spec/image/existingImageName - название образа, из которого собирается ML-компонент. Этот образ был подготовлен в пункте 5.
  • spec/image/resourceLimits - ограничения по ресурсам для ML-компонента.
    • Ресурсы процессора cpu измеряются в ядрах. 500m - 500 миллиядер, то есть половина ядра процессора занята развёрнутым ML-компонентом.
    • Ресурсы оперативной памяти memory могут измеряться в мегабайтах, гигабайтах и других метриках памяти
    • Подробнее - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
  • spec/env - переменные окружения, передаваемые в контейнер. Вы можете вынести настройки контейнера в переменные окружения и задавать их в ML-компоненте, чтобы не нужно было изменять код и пересоздавать образ Docker с новыми значениями.
  • spec/mlService
    • packageRegistryName - название репозитория с пакетами Python, должно соответствовать "внешнему" названию из компонента приложения в пункте 7.6. Название может быть другим, главное - соответствие названий друг другу.
    • inference/fileExchange - соединение файловой системы контейнера (сервиса) и ящика S3 для обмена файлами.
      • fileBox - название ящика S3 для файлов пользователей.
        Должно соответствовать названию из пункта connectedBoxes ниже в этом файле, а не названию metadata/name из компонента DataBox.
      • inferenceFilesPath - путь, куда будут записываться создаваемые файлы внутри контейнера. К этому пути должны быть права доступа у пользователя контейнера. С этой папкой фреймворк взаимодействует автоматически, то есть лучше сделать уникальный путь, который нигде больше не используется.
    • inference/model - соединение файловой системы контейнера (сервиса) и ящика S3 для подключения модели расчётов.
      • modelBox - название ящика S3, где размещена модель.
        Должно соответствовать названию из пункта connectedBoxes ниже в этом файле, а не названию metadata/name из компонента DataBox.
      • modelPath - путь, по которому модель будет доступна внутри контейнера.
        Этот путь передаётся в функцию inference. Может быть папкой или файлом.
    • inference/entryPoint
      • pythonPath - относительный путь от корня репозитория к папке, которая будет добавлена в PYTHONPATH.
      • pythonFunction - имя функции-адаптера, включая имена промежуточных модулей.
  • spec/connectedBoxes - подключенные компоненты DataBox (ящики)
    • Первый ящик в примере используется для доступа к модели.
      • name - имя, по которому к ящику можно обращаться выше в пункте spec/mlService/inference/model/modelBox.
      • path - путь внутри контейнера, к которому монтируется ящик.
      • mountS3Box/s3BoxName - название компонента DataBox.
      • mountS3Box/subPath - путь внутри ящика, который монтируется к пути path.
        Здесь используется путь users/developer/file_groups/models как решение проблемы загрузки весов моделей и прочих данных в хранилище S3. При загрузке через файловый API от лица пользователя USER файлы загружаются по пути users/USER/file_groups/.... То есть в текущем примере веса можно загрузить от лица пользователя developer в папку models/, и через ML-компонент дать к ним доступ всем остальным пользователям.
    • Второй ящик в примере используеся для взаимодействия с пользователями
      • name - имя, по которому к ящику можно обращаться выше в пункте spec/mlService/inference/fileExchange/fileBox.
      • copyS3Box/s3BoxName - назание компонента DataBox.