

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 為 SageMaker AI 多模型端點建置自有容器
<a name="build-multi-model-build-container"></a>

請參閱以下各節了解如何針對多模型端點使用自有容器及相依性。

**Topics**
+ [在 CPU 支援的執行個體為多模型端點提供自有相依性](#build-multi-model-container-cpu)
+ [在 GPU 支援的執行個體為多模型端點提供自有相依性](#build-multi-model-container-gpu)
+ [運用 SageMaker AI 推論工具組](#multi-model-inference-toolkit)
+ [多模型端點的自訂容器合約](mms-container-apis.md)

## 在 CPU 支援的執行個體為多模型端點提供自有相依性
<a name="build-multi-model-container-cpu"></a>

如預先建置的容器映像都無法滿足您的需求，您可建置自有容器來搭配 CPU 支援的多模型端點使用。

Amazon SageMaker AI 部署的自訂 Amazon Elastic Container Registry (Amazon ECR) 映像應遵守[具託管服務的自訂推論程式碼](your-algorithms-inference-code.md)所述的基本合約，該合約會規範 SageMaker AI 如何與執行您自有推斷程式碼的 Docker 容器進行互動。若是能夠並行載入並為多個模型提供服務的容器，則會有必須遵從的額外 API 和行為。這份額外的合約包含了載入、列出、取得和取消載入模型的 API，以及另一個調用模型的 API。也有 API 必須遵守的不同錯誤情境行為。若要表示容器符合額外的要求，您可以將下列命令新增到 Docker 檔案：

```
LABEL com.amazonaws.sagemaker.capabilities.multi-models=true
```

SageMaker AI 也會將環境變數插入到容器中

```
SAGEMAKER_MULTI_MODEL=true
```

如果您要為序列推論管道建立多模型端點，則 Docker 檔案必須具有多模型和序列推論管道所需的標籤。如需序列資訊管道的詳細資訊，請參閱[使用推論管道執行即時預測](inference-pipeline-real-time.md)。

為協助您實作自訂容器的這些要求，提供下列兩個程式庫：
+ [多模型伺服器](https://github.com/awslabs/multi-model-server)是一種可為機器學習模型提供服務的開放原始碼架構，可安裝於容器中以提供符合新多模型端點容器 API 要求的前端。它可提供多模型端點所需的 HTTP 前端和模型管理功能，以將多個模型託管於單一容器內、動態地將模型載入到容器中及從中取消載入模型，以及在指定的載入模型上執行推斷。它還提供了隨插即用的後端，支援隨插即用的自訂後端處理常式，可讓您實作自己的演算法。
+ [SageMaker AI 推論工具組](https://github.com/aws/sagemaker-inference-toolkit)是使用組態和設定來引導多模型伺服器的程式庫，以使其與 SageMaker AI 多模型端點相容。也可讓您根據不同的情境需求調校重要效能參數，例如每個模型的工作者數量。

## 在 GPU 支援的執行個體為多模型端點提供自有相依性
<a name="build-multi-model-container-gpu"></a>

針對採用由 GPU 支援執行個體的多模型端點，多模型伺服器與 SageMaker AI 推論工具組程式庫目前不支援其運用自有容器 (BYOC) 功能。

若要使用由 GPU 支援的執行個體建立多模型端點，您可利用 SageMaker AI 支援的 [NVIDIA Triton 推論伺服器](https://docs.aws.amazon.com/sagemaker/latest/dg/triton.html)，並搭配 [NVIDIA Triton 推論容器](https://github.com/aws/deep-learning-containers/blob/master/available_images.md#nvidia-triton-inference-containers-sm-support-only)。若要採用自有相依性，您可採用 SageMaker AI 支援的 [NVIDIA Triton 推論伺服器](https://docs.aws.amazon.com/sagemaker/latest/dg/triton.html)來建置自有容器，做為 Docker 檔案的基礎映像：

```
FROM 301217895009.dkr.ecr.us-west-2.amazonaws.com/sagemaker-tritonserver:22.07-py3
```

**重要**  
若要用於 GPU 支援的多模型端點，具 Triton 推論伺服器的容器是唯一支援的容器。

## 運用 SageMaker AI 推論工具組
<a name="multi-model-inference-toolkit"></a>

**注意**  
SageMaker AI 推論工具組僅支援 CPU 支援的多模型端點。SageMaker AI 推論工具組目前不支援 GPU 支援的多模型端點。

[支援的多模型端點適用演算法、架構與執行個體](multi-model-support.md) 列出支援多模型端點的預先建置容器。如果你想要使用其他任何架構或演算法，則需要建置容器。最簡單的做法是運用 [SageMaker AI 推論工具組](https://github.com/aws/sagemaker-inference-toolkit)來擴展現有預先建置的容器。SageMaker AI 推論工具組是多模型伺服器 (MMS) 的實作，可讓您建立可在 SageMaker AI 部署的端點。如需示範如何設定及部署可在 SageMaker AI 支援多模型端點之自訂容器的範例筆記本，請參閱[多模型端點 BYOC 範例筆記本](https://github.com/awslabs/amazon-sagemaker-examples/tree/master/advanced_functionality/multi_model_bring_your_own)。

**注意**  
SageMaker AI 推論工具組僅支援 Python 模型處理常式。如果您想要以其他任何語言來實作處理常式，則必須建置您自己的容器，以實作其他多模型端點 API。如需相關資訊，請參閱[多模型端點的自訂容器合約](mms-container-apis.md)。

**使用 SageMaker AI 推論工具組來擴展容器**

1. 建立模型處理常式。MMS 需要模型處理常式，這是一個 Python 檔案，其中實作函式來預處理、從模型取得預測，以及在模型處理常式中處理輸出。如需模型處理常式的範例，請參閱範例筆記本中的 [model\$1handler.py](https://github.com/awslabs/amazon-sagemaker-examples/blob/master/advanced_functionality/multi_model_bring_your_own/container/model_handler.py)。

1. 匯入推論工具組，並使用其 `model_server.start_model_server` 函式來啟動 MMS。下列範例來自範例筆記本中的 `dockerd-entrypoint.py` 檔案。請注意，呼叫 `model_server.start_model_server` 會傳遞上一個步驟中描述的模型處理常式：

   ```
   import subprocess
   import sys
   import shlex
   import os
   from retrying import retry
   from subprocess import CalledProcessError
   from sagemaker_inference import model_server
   
   def _retry_if_error(exception):
       return isinstance(exception, CalledProcessError or OSError)
   
   @retry(stop_max_delay=1000 * 50,
          retry_on_exception=_retry_if_error)
   def _start_mms():
       # by default the number of workers per model is 1, but we can configure it through the
       # environment variable below if desired.
       # os.environ['SAGEMAKER_MODEL_SERVER_WORKERS'] = '2'
       model_server.start_model_server(handler_service='/home/model-server/model_handler.py:handle')
   
   def main():
       if sys.argv[1] == 'serve':
           _start_mms()
       else:
           subprocess.check_call(shlex.split(' '.join(sys.argv[1:])))
   
       # prevent docker exit
       subprocess.call(['tail', '-f', '/dev/null'])
       
   main()
   ```

1. 在 `Dockerfile` 中，複製第一個步驟中的模型處理常式，並將上一個步驟中的 Python 檔案指定為 `Dockerfile` 中的進入點。下列幾行來自範例筆記本中使用的 [Dockerfile](https://github.com/awslabs/amazon-sagemaker-examples/blob/master/advanced_functionality/multi_model_bring_your_own/container/Dockerfile)：

   ```
   # Copy the default custom service file to handle incoming data and inference requests
   COPY model_handler.py /home/model-server/model_handler.py
   
   # Define an entrypoint script for the docker image
   ENTRYPOINT ["python", "/usr/local/bin/dockerd-entrypoint.py"]
   ```

1. 建置並註冊容器。範例筆記本中有下列殼層指令碼，可建置容器，並上傳到您 AWS 帳戶的 Amazon Elastic Container Registry 儲存庫：

   ```
   %%sh
   
   # The name of our algorithm
   algorithm_name=demo-sagemaker-multimodel
   
   cd container
   
   account=$(aws sts get-caller-identity --query Account --output text)
   
   # Get the region defined in the current configuration (default to us-west-2 if none defined)
   region=$(aws configure get region)
   region=${region:-us-west-2}
   
   fullname="${account}.dkr.ecr.${region}.amazonaws.com/${algorithm_name}:latest"
   
   # If the repository doesn't exist in ECR, create it.
   aws ecr describe-repositories --repository-names "${algorithm_name}" > /dev/null 2>&1
   
   if [ $? -ne 0 ]
   then
       aws ecr create-repository --repository-name "${algorithm_name}" > /dev/null
   fi
   
   # Get the login command from ECR and execute it directly
   $(aws ecr get-login --region ${region} --no-include-email)
   
   # Build the docker image locally with the image name and then push it to ECR
   # with the full name.
   
   docker build -q -t ${algorithm_name} .
   docker tag ${algorithm_name} ${fullname}
   
   docker push ${fullname}
   ```

現在，您可以使用此容器在 SageMaker AI 部署多模型端點。

**Topics**
+ [在 CPU 支援的執行個體為多模型端點提供自有相依性](#build-multi-model-container-cpu)
+ [在 GPU 支援的執行個體為多模型端點提供自有相依性](#build-multi-model-container-gpu)
+ [運用 SageMaker AI 推論工具組](#multi-model-inference-toolkit)
+ [多模型端點的自訂容器合約](mms-container-apis.md)

# 多模型端點的自訂容器合約
<a name="mms-container-apis"></a>

若要處理多個模型，容器必須支援一組可讓 Amazon SageMaker AI 與容器進行溝通的 API，以視需要載入、列出、取得和取消載入模型。`model_name` 會用於新的 API 集，做為金鑰輸入參數。客戶容器應使用 `model_name` 做為對應金鑰來追蹤已載入的模型。此外，`model_name` 是不透明的識別符，且未必是傳遞到 `InvokeEndpoint` API 的 `TargetModel` 參數的值。`InvokeEndpoint` 請求中的原始 `TargetModel` 值會傳遞到 API 中的容器，做為可用於記錄用途的 `X-Amzn-SageMaker-Target-Model` 標題。

**注意**  
GPU 支援執行個體的多模型端點目前僅支援 SageMaker AI 的 [NVIDIA Triton 推論伺服器容器](https://docs.aws.amazon.com/sagemaker/latest/dg/triton.html)。此容器已經實作如下定義的合同。客戶可直接搭配使用此容器與多模型 GPU 端點，無需進行任何額外工作。

您可於容器為 CPU 支援的多模型端點設定下列 API。

**Topics**
+ [Load Model API](#multi-model-api-load-model)
+ [List Model API](#multi-model-api-list-model)
+ [Get Model API](#multi-model-api-get-model)
+ [Unload Model API](#multi-model-api-unload-model)
+ [調用模型 API](#multi-model-api-invoke-model)

## Load Model API
<a name="multi-model-api-load-model"></a>

指示容器將主體 `url` 欄位中現有的特定模型載入到客戶容器記憶體中，並使用獲派的 `model_name` 進行追蹤。載入模型後，容器應該已準備就緒，可使用此 `model_name` 為推斷請求提供服務。

```
POST /models HTTP/1.1
Content-Type: application/json
Accept: application/json

{
     "model_name" : "{model_name}",
     "url" : "/opt/ml/models/{model_name}/model",
}
```

**注意**  
若已載入 `model_name`，此 API 應傳回 409。凡是由於記憶體或任何其他資源不足而無法載入模型時，此 API 皆應傳回 507 HTTP 狀態碼給 SageMaker AI，接著它會發起取消載入未使用的模型以重新取得。

## List Model API
<a name="multi-model-api-list-model"></a>

傳回已載入到客戶容器的記憶體的模型清單。

```
GET /models HTTP/1.1
Accept: application/json

Response = 
{
    "models": [
        {
             "modelName" : "{model_name}",
             "modelUrl" : "/opt/ml/models/{model_name}/model",
        },
        {
            "modelName" : "{model_name}",
            "modelUrl" : "/opt/ml/models/{model_name}/model",
        },
        ....
    ]
}
```

此 API 也支援分頁。

```
GET /models HTTP/1.1
Accept: application/json

Response = 
{
    "models": [
        {
             "modelName" : "{model_name}",
             "modelUrl" : "/opt/ml/models/{model_name}/model",
        },
        {
            "modelName" : "{model_name}",
            "modelUrl" : "/opt/ml/models/{model_name}/model",
        },
        ....
    ]
}
```

SageMaker AI 不需要提供值給 `next_page_token` 即可在一開始呼叫列出模型 API。如果回應中傳回了 `nextPageToken` 欄位，則會提供該欄位做為後續 List Models 呼叫中 `next_page_token` 的值。若未傳回 `nextPageToken`，則表示沒有其他要傳回的模型。

## Get Model API
<a name="multi-model-api-get-model"></a>

這是 `model_name` 實體上的簡易讀取 API。

```
GET /models/{model_name} HTTP/1.1
Accept: application/json

{
     "modelName" : "{model_name}",
     "modelUrl" : "/opt/ml/models/{model_name}/model",
}
```

**注意**  
若未載入 `model_name`，此 API 應傳回 404。

## Unload Model API
<a name="multi-model-api-unload-model"></a>

指示 SageMaker AI 平台引導客戶容器從記憶體中取消載入模型。這會根據平台在開始載入新模型程序時的判斷，發起移出候選模型。當此 API 傳回回應時，佈建到 `model_name` 的資源應由容器重新取得。

```
DELETE /models/{model_name}
```

**注意**  
若未載入 `model_name`，此 API 應傳回 404。

## 調用模型 API
<a name="multi-model-api-invoke-model"></a>

從提供的特定 `model_name` 提出預測請求。SageMaker AI 執行時期 `InvokeEndpoint` 請求支援利用 `X-Amzn-SageMaker-Target-Model` 做為新標題，這會採用針對調用指定模型的相對路徑。SageMaker AI 系統會將 `CreateModel` API 呼叫提供的字首與模型的相對路徑加以結合，藉此建構模型的絕對路徑。

```
POST /models/{model_name}/invoke HTTP/1.1
Content-Type: ContentType
Accept: Accept
X-Amzn-SageMaker-Custom-Attributes: CustomAttributes
X-Amzn-SageMaker-Target-Model: [relativePath]/{artifactName}.tar.gz
```

**注意**  
若未載入 `model_name`，此 API 應傳回 404。

此外，在 GPU 執行個體，如 `InvokeEndpoint` 因記憶體或其他資源不足而失敗，則此 API 應將 507 HTTP 狀態碼傳回給 SageMaker AI，然後啟動卸載未使用模型以便進行回收。