モデル サービス グリッド: クラウド ネイティブでのモデル サービス管理

モデル サービス メッシュは、分散環境で機械学習モデル サービスをデプロイおよび管理するために使用されるアーキテクチャ パターンです。複数のモデル サービスを管理、展開、スケジュールするためのスケーラブルで高性能なインフラストラクチャを提供し、モデルの展開、バージョン管理、ルーティング、推論リクエストの負荷分散をより適切に処理します。

モデル サービス グリッドの中心的な考え方は、モデルをスケーラブルなサービスとしてデプロイし、グリッドを通じてこれらのサービスを管理およびルーティングすることで、モデル サービスの管理と運用を簡素化することです。モデル サービスを統合されたスケーラブルなユニットに抽象化することで、モデルのデプロイ、拡張、バージョン管理が容易になります。また、モデル サービスの高可用性と信頼性を確保するために、ロード バランシング、自動スケーリング、障害回復などのいくつかのコア機能も提供します。

実際の推論リクエストの負荷に基づいてモデルを自動的にスケーリングおよび負荷分散できるため、効率的なモデル推論が可能になります。モデル サービス グリッドは、モデル サービスのトラフィックをより適切に制御および管理するためのトラフィック セグメンテーション、A/B テスト、グレースケール パブリッシングなどの高度な機能も提供し、異なるモデル バージョンの切り替えやロールバックを簡単に行うことができます。また、動的ルーティングもサポートしており、モデル タイプ、データ形式、その他のメタデータなどの要求のプロパティに基づいて、要求を適切なモデル サービスにルーティングできます。

Alibaba Cloud Service Grid ASM は、モデルのデプロイとバージョン管理、推論リクエストのルーティングと負荷分散をより適切に処理するために、複数のモデル サービスを管理、デプロイ、およびスケジュールするためのスケーラブルで高性能のモデル サービス グリッドの基本機能を提供します。モデル サービス メッシュを使用することで、開発者は機械学習モデルをより簡単にデプロイ、管理、拡張できると同時に、さまざまなビジネス ニーズを満たす高可用性、復元力、柔軟性を提供できます。

01 マルチモデル推論サービスにモデルサービスグリッドを使用する

モデル サービス グリッドは、KServe ModelMesh に基づいて実装されており、大容量、高密度、頻繁に変更されるモデルのユース ケース向けに最適化されており、モデルをメモリにインテリジェントにロードまたはアンロードして、応答性と計算のバランスをとることができます。

モデル サービス メッシュは次の機能を提供します。

  • キャッシュ管理
  • ポッドは、分散型最長未使用 (LRU) キャッシュとして管理されます。
  • 使用頻度と現在のリクエスト量に基づいて、モデルのコピーをロードおよびアンロードします。
  • スマートな配置と読み込み
  • モデルの配置は、ポッド間のキャッシュの経過時間とリクエストの負荷によってバランスがとれます。
  • キューを使用してモデルの同時読み込みを処理し、ランタイム トラフィックへの影響を最小限に抑えます。
  • 弾性
  • 失敗したモデルのロードは、別の Pod で自動的に再試行されます。
  • 操作性の良さ
  • ローリング モデルの更新を自動的かつシームレスに処理します。

以下は導入モデルの例であり、利用の前提条件については[1]を参照してください。

1.1 ストレージ宣言PVCの作成

ACK クラスターで、次の YAML を使用してストレージ宣言 my-models-pvc を作成します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: my-models-pvc
  namespace: modelmesh-serving
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: alibabacloud-cnfs-nas
  volumeMode: Filesystem

次に、次のコマンドを実行します。

kubectl get pvc -n modelmesh-serving

次のような期待される結果が得られます。

NAME STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS            AGE
my-models-pvc    Bound    nas-379c32e1-c0ef-43f3-8277-9eb4606b53f8   1Gi        RWX            alibabacloud-cnfs-nas   2h

1.2 PVCにアクセスするためのPodの作成

新しい PVC を使用するには、それをボリュームとして Kubernetes ポッドにマウントする必要があります。次に、このポッドを使用してモデル ファイルを永続ボリュームにアップロードできます。

pvc-access ポッドをデプロイし、「my-models-pvc」を指定して、先ほどリクエストした PVC を宣言するように Kubernetes コントローラーに依頼しましょう。

kubectl apply  -n modelmesh-serving  -f - <<EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: "pvc-access"
spec:
  containers:
    - name: main
      image: ubuntu
      command: ["/bin/sh", "-ec", "sleep 10000"]
      volumeMounts:
        - name: "my-pvc"
          mountPath: "/mnt/models"
  volumes:
    - name: "my-pvc"
      persistentVolumeClaim:
        claimName: "my-models-pvc"
EOF

pvc-access ポッドが実行されていることを確認します。

kubectl get pods -n modelmesh-serving | grep pvc-access

次のような期待される結果が得られます。

pvc-access 1/1     Running

1.3 モデルを永続ボリュームに保存する

次に、AI モデルをストレージ ボリュームに追加する必要があります。scikit-learn でトレーニングされた MNIST 手書き数字文字認識モデルを使用します。mnist-svm.joblib モデル ファイルのコピーは、kserve/modelmesh-minio-examples リポジトリ [2] からダウンロードできます。

次のコマンドを使用して、mnist-svm.joblib モデル ファイルを pvc-access ポッドの /mnt/models フォルダーにコピーします。

kubectl -n modelmesh-serving cp mnist-svm.joblib pvc-access:/mnt/models/

次のコマンドを実行して、モデルが正常にロードされたことを確認します。

kubectl -n modelmesh-serving exec -it pvc-access -- ls -alr /mnt/models/

次のようなものが得られるはずです。

-rw-r--r-- 1 501 staff 344817 Oct 30 11:23 mnist-svm.joblib

1.4 推論サービスのデプロイ

次に、sklearn-mnist 推論サービスをデプロイする必要があります。

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: sklearn-mnist
  namespace: modelmesh-serving
  annotations:
    serving.kserve.io/deploymentMode: ModelMesh
spec:
  predictor:
    model:
      modelFormat:
        name: sklearn
      storage:
        parameters:
          type: pvc
          name: my-models-pvc
        path: mnist-svm.joblib

数十秒後 (イメージのプル速度に応じて)、新しい推論サービス sklearn-mnist の準備が整います。

次のコマンドを実行します。

kubectl get isvc -n modelmesh-serving

次のような期待される結果が得られます。

NAME URL                  READY
sklearn-mnist   grpc://modelmesh-serving.modelmesh-serving:8033   True

1.5 推論サービスの実行

これで、curl を使用して推論リクエストを sklearn-mnist モデルに送信できるようになりました。配列形式の要求されたデータは、分類されるデジタル画像スキャンの 64 ピクセルのグレースケール値を表します。

MODEL_NAME="sklearn-mnist"
ASM_GW_IP="ASM网关IP地址"
curl -X POST -k "http://${ASM_GW_IP}:8008/v2/models/${MODEL_NAME}/infer" -d '{"inputs": [{"name": "predict", "shape": [1, 64], "datatype": "FP32", "contents": {"fp32_contents": [0.0, 0.0, 1.0, 11.0, 14.0, 15.0, 3.0, 0.0, 0.0, 1.0, 13.0, 16.0, 12.0, 16.0, 8.0, 0.0, 0.0, 8.0, 16.0, 4.0, 6.0, 16.0, 5.0, 0.0, 0.0, 5.0, 15.0, 11.0, 13.0, 14.0, 0.0, 0.0, 0.0, 0.0, 2.0, 12.0, 16.0, 13.0, 0.0, 0.0, 0.0, 0.0, 0.0, 13.0, 16.0, 16.0, 6.0, 0.0, 0.0, 0.0, 0.0, 16.0, 16.0, 16.0, 7.0, 0.0, 0.0, 0.0, 0.0, 11.0, 13.0, 12.0, 1.0, 0.0]}}]}'

JSON 応答は次のようになります。スキャンされた数値は「8」であると推測されます。

{
"modelName": "sklearn-mnist__isvc-3c10c62d34",
 "outputs": [
  {
   "name": "predict",
   "datatype": "INT64",
   "shape": [
    "1",
    "1"
   ],
   "contents": {
    "int64Contents": [
     "8"
    ]
   }
  }
 ]
}

02 モデル サービス メッシュを使用してモデル ランタイムをカスタマイズする

モデル サービス メッシュ (略して ModelMesh) は、大容量、高密度、頻繁に変更されるモデル推論サービスの展開と運用向けに最適化されており、モデルをメモリにインテリジェントにロードまたはアンロードして、モデル間の最適なバランスを確保できます。応答性とコンピューティング。

ModelMesh は、デフォルトで次のモデル サーバー実行環境を統合します。

  • NVIDIA のサーバーである Triton Inference Server は、TensorFlow、PyTorch、TensorRT、ONNX などのフレームワークに適しています。
  • MLServer は Seldon の Python ベースのサーバーで、SKLearn、XGBoost、LightGBM などのフレームワークに適しています。
  • OpenVINO Model Server、Intel OpenVINO や ONNX などのフレームワーク用の Intel のサーバー。
  • TorchServe は、eager モードを含む PyTorch モデルをサポートします。

これらのモデル サーバーが特定の要件を満たすことができない場合 (たとえば、推論用のカスタム ロジックを処理する必要がある場合、またはモデルで上記のサポート リストにないフレームワークが必要な場合)、拡張サポート用にサービス ランタイムをカスタマイズできます。

詳細については[3]を参照してください。

03 大規模言語モデルLLMのサービス提供

Large Language Model (LLM) は、GPT-3、GPT-4、PaLM、PaLM2 など、数億のパラメーターを持つニューラル ネットワーク言語モデルを指します。以下に、大規模言語モデル LLM のサービスを提供する方法について説明します。

使用の前提条件の詳細については、[4] を参照してください。

3.1 カスタム ランタイムの構築

HuggingFace LLM に構成を調整するためのプロンプトを提供するカスタム ランタイムを構築します。この例のデフォルト設定は、事前に構築されたカスタム ランタイム イメージと事前に構築されたプロンプト チューニング構成です。

3.1.1 MLServer MLModelを継承したクラスの実装

kfp-tekton/samples/peft-modelmesh-pipeline ディレクトリ [5] にある peft_model_server.py ファイルには、HuggingFace LLM にプロンプ​​ト調整構成を提供する方法に関するすべてのコードが含まれています。

以下の _load_model 関数は、PEFT プロンプト調整構成用に事前トレーニングされた LLM モデルを選択することを示しています。トークナイザーもモデルの一部として定義されているため、ユーザーが入力をテンソル バイトに前処理する必要なく、推論リクエストの生の文字列入力をエンコードおよびデコードするために使用できます。

from typing import List

from mlserver import MLModel, types
from mlserver.codecs import decode_args

from peft import PeftModel, PeftConfig
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import os

class PeftModelServer(MLModel):
    async def load(self) -> bool:
        self._load_model()
        self.ready = True
        return self.ready

    @decode_args
    async def predict(self, content: List[str]) -> List[str]:
        return self._predict_outputs(content)

    def _load_model(self):
        model_name_or_path = os.environ.get("PRETRAINED_MODEL_PATH", "bigscience/bloomz-560m")
        peft_model_id = os.environ.get("PEFT_MODEL_ID", "aipipeline/bloomz-560m_PROMPT_TUNING_CAUSAL_LM")
        self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, local_files_only=True)
        config = PeftConfig.from_pretrained(peft_model_id)
        self.model = AutoModelForCausalLM.from_pretrained(config.base_model_name_or_path)
        self.model = PeftModel.from_pretrained(self.model, peft_model_id)
        self.text_column = os.environ.get("DATASET_TEXT_COLUMN_NAME", "Tweet text")
        return

    def _predict_outputs(self, content: List[str]) -> List[str]:
        output_list = []
        for input in content:
            inputs = self.tokenizer(
                f'{self.text_column} : {input} Label : ',
                return_tensors="pt",
            )
            with torch.no_grad():
                inputs = {k: v for k, v in inputs.items()}
                outputs = self.model.generate(
                    input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"], max_new_tokens=10, eos_token_id=3
                )
                outputs = self.tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)
            output_list.append(outputs[0])
        return output_list

3.1.2 Dockerイメージのビルド

モデル クラスを実装した後、その依存関係 (MLServer を含む) を ServingRuntime リソースをサポートするイメージにパッケージ化する必要があります。イメージをビルドするには、次の Dockerfile を参照してください。

# TODO: choose appropriate base image, install Python, MLServer, and
# dependencies of your MLModel implementation
FROM python:3.8-slim-buster
RUN pip install mlserver peft transformers datasets
# ...

# The custom `MLModel` implementation should be on the Python search path
# instead of relying on the working directory of the image. If using a
# single-file module, this can be accomplished with:
COPY --chown=${USER} ./peft_model_server.py /opt/peft_model_server.py
ENV PYTHONPATH=/opt/

# environment variables to be compatible with ModelMesh Serving
# these can also be set in the ServingRuntime, but this is recommended for
# consistency when building and testing
ENV MLSERVER_MODELS_DIR=/models/_mlserver_models \
 MLSERVER_GRPC_PORT=8001 \
    MLSERVER_HTTP_PORT=8002 \
    MLSERVER_LOAD_MODELS_AT_STARTUP=false \
    MLSERVER_MODEL_NAME=peft-model

# With this setting, the implementation field is not required in the model
# settings which eases integration by allowing the built-in adapter to generate
# a basic model settings file
ENV MLSERVER_MODEL_IMPLEMENTATION=peft_model_server.PeftModelServer

CMD mlserver start ${MLSERVER_MODELS_DIR}

3.1.3 新しい ServingRuntime リソースを作成する

次のコード ブロックで YAML テンプレートを使用して、新しい ServingRuntime リソースを作成し、作成したばかりのイメージを指すことができます。

apiVersion: serving.kserve.io/v1alpha1
kind: ServingRuntime
metadata:
 name: peft-model-server
  namespace: modelmesh-serving
spec:
  supportedModelFormats:
    - name: peft-model
      version: "1"
      autoSelect: true
  multiModel: true
  grpcDataEndpoint: port:8001
  grpcEndpoint: port:8085
  containers:
    - name: mlserver
      image:  registry.cn-beijing.aliyuncs.com/test/peft-model-server:latest
      env:
        - name: MLSERVER_MODELS_DIR
          value: "/models/_mlserver_models/"
        - name: MLSERVER_GRPC_PORT
          value: "8001"
        - name: MLSERVER_HTTP_PORT
          value: "8002"
        - name: MLSERVER_LOAD_MODELS_AT_STARTUP
          value: "true"
        - name: MLSERVER_MODEL_NAME
          value: peft-model
        - name: MLSERVER_HOST
          value: "127.0.0.1"
        - name: MLSERVER_GRPC_MAX_MESSAGE_LENGTH
          value: "-1"
        - name: PRETRAINED_MODEL_PATH
          value: "bigscience/bloomz-560m"
        - name: PEFT_MODEL_ID
          value: "aipipeline/bloomz-560m_PROMPT_TUNING_CAUSAL_LM"
        # - name: "TRANSFORMERS_OFFLINE"
        #   value: "1" 
        # - name: "HF_DATASETS_OFFLINE"
        #   value: "1"   
      resources:
        requests:
          cpu: 500m
          memory: 4Gi
        limits:
          cpu: "5"
          memory: 5Gi
  builtInAdapter:
    serverType: mlserver
    runtimeManagementPort: 8001
    memBufferBytes: 134217728
    modelLoadingTimeoutMillis: 90000

次に、kubectl apply コマンドを使用して ServingRuntime リソースを作成すると、ModelMesh デプロイメントに新しいカスタム ランタイムが表示されます。

3.2 LLM サービスのデプロイ

新しく作成したランタイムを使用してモデルをデプロイするには、モデルを提供する InferenceService リソースを作成する必要があります。このリソースは、モデルを管理するために KServe と ModelMesh によって使用されるメイン インターフェイスであり、推論におけるモデルの論理エンドポイントを表します。

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: peft-demo
  namespace: modelmesh-serving
  annotations:
    serving.kserve.io/deploymentMode: ModelMesh
spec:
  predictor:
    model:
      modelFormat:
        name: peft-model
      runtime: peft-model-server
      storage:
        key: localMinIO
        path: sklearn/mnist-svm.joblib

前述のコード ブロックでは、InferenceService の名前は peft-demo で、そのモデル形式は peft-model として宣言されています。これは、前に作成したサンプル カスタム ランタイムで使用されているのと同じ形式です。オプションのフィールド ランタイムも渡され、ModelMesh に peft-model-server ランタイムを使用してこのモデルをデプロイするように明示的に指示されます。

3.3 推論サービスの実行

これで、curl を使用して、上でデプロイした LLM モデル サービスに推論リクエストを送信できるようになりました。

MODEL_NAME="peft-demo"
ASM_GW_IP="ASM网关IP地址"
curl -X POST -k http://${ASM_GW_IP}:8008/v2/models/${MODEL_NAME}/infer -d @./input.json

ここで、input.json はリクエスト データを表します。

{
 "inputs": [
        {
          "name": "content",
          "shape": [1],
          "datatype": "BYTES",
          "contents": {"bytes_contents": ["RXZlcnkgZGF5IGlzIGEgbmV3IGJpbm5pbmcsIGZpbGxlZCB3aXRoIG9wdGlvbnBpZW5pbmcgYW5kIGhvcGU="]}
        }
    ]
}

bytes_contents は、「毎日が新たな始まりであり、機会と希望に満ちています」という文字列の Base64 エンコードに対応します。

JSON 応答は次のようになります。スキャンされた数値は「8」であると推測されます。

{
"modelName": "peft-demo__isvc-5c5315c302",
 "outputs": [
  {
   "name": "output-0",
   "datatype": "BYTES",
   "shape": [
    "1",
    "1"
   ],
   "parameters": {
    "content_type": {
     "stringParam": "str"
    }
   },
   "contents": {
    "bytesContents": [
     "VHdlZXQgdGV4dCA6IEV2ZXJ5IGRheSBpcyBhIG5ldyBiaW5uaW5nLCBmaWxsZWQgd2l0aCBvcHRpb25waWVuaW5nIGFuZCBob3BlIExhYmVsIDogbm8gY29tcGxhaW50"
    ]
   }
  }
 ]
}

bytesContents の Base64 デコードされたコンテンツは次のとおりです。

Tweet text : Every day is a new binning, filled with optionpiening and hope Label : no complaint

これまでのところ、上記の大規模言語モデル LLM のモデル サービス リクエストが期待どおりの結果を得ていることがわかります。

04 まとめ

Alibaba Cloud Service Grid ASM は、モデルのデプロイとバージョン管理、推論リクエストのルーティングと負荷分散をより適切に処理するために、複数のモデル サービスを管理、デプロイ、およびスケジュールするためのスケーラブルで高性能のモデル サービス グリッドの基本機能を提供します。

ぜひお試しください: https://www.aliyun.com/product/servicemesh

関連リンク:

[1] 以下は導入モデルの一例ですので、ご利用の前提条件をご参照ください。

https://help.aliyun.com/zh/asm/user-guide/multi-model-inference-service-using-model-service-mesh?spm=a2c4g.11186623.0.0.7c4e6561k1qyJV#213af6d078xu7

[2] kserve/modelmesh-minio-examples ウェアハウス

https://github.com/kserve/modelmesh-minio-examples/blob/main/sklearn/mnist-svm.joblib

[3] 詳細はこちらをご参照ください。

https://help.aliyun.com/zh/asm/user-guide/customizing-the-model-runtime-using-the-model-service-mesh?spm=a2c4g.11186623.0.0.1db77614Vw96Eu

[4] ご利用の前提条件をご確認ください。

https://help.aliyun.com/zh/asm/user-guide/services-for-the-large- language-model-llm?spm=a2c4g.11186623.0.0.29777614EEBYWt#436fc73079euz

[5] kfp-tekton/samples/peft-modelmesh-pipeline 目录

https://github.com/kubeflow/kfp-tekton

著者: 王西寧

元のリンク

この記事は Alibaba Cloud のオリジナル コンテンツであり、許可なく複製することはできません。

有名なオープンソース プロジェクトの作者が躁状態で職を失った - 「オンラインでお金を求めている」 スターなし、修正なし 2023 年世界のエンジニアリング成果トップ 10 が発表: ChatGPT、Hongmeng オペレーティング システム、中国宇宙ステーション、その他の選ばれた ByteDance Google、2023 年に最も人気のある Chrome 拡張機能を発表学者 の倪光南氏: Xiaomi 携帯電話 BL のロックを解除するために、 輸入 HDD を国産 SSD に置き換えることを願っていますか? まず、Java プログラマーの面接の質問をします. Arm が 70 人以上の中国人エンジニアを解雇し、中国のソフトウェア ビジネスの再編を計画. OpenKylin 2.0 が明らかに | UKUI 4.10 ダブル ダイヤモンド デザイン、美しく高品質! Manjaro 23.1 リリース、コード名は「Vulcan」
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/yunqi/blog/10324103