分享方式:


使用 Azure Machine Learning 推斷 HTTP 伺服器偵錯評分指令碼

Azure Machine Learning 推斷 HTTP 伺服器是 Python 套件,可將評分函式公開為 HTTP 端點,並將 Flask 伺服器程式碼和相依性包裝成單一套件。 伺服器包含在 預先建置用於推斷的 Docker 映像 中,以供藉由 Azure Machine Learning 部署模型時使用。 單獨使用套件,即可在本機部署模型以供生產環境使用,並在本機開發環境中輕鬆驗證評分 (入口) 指令碼。 如果評分指令碼發生問題,伺服器會傳回錯誤和錯誤的位置。

此伺服器也可以用於在持續整合和部署管線中建立驗證閘道。 例如,您可使用候選的指令碼啟動伺服器,並針對本機端點執行測試套件。

本文支援想要在本機使用推斷伺服器偵錯的開發人員,並說明如何在 Windows 上使用推斷伺服器與線上端點。

必要條件

若要使用 Azure Machine Learning 推斷 HTTP 伺服器進行本機偵錯,您的設定必須包含下列元件:

  • Python 3.8 或更新版本
  • Anaconda

Azure Machine Learning 推斷 HTTP 伺服器會在 Windows 和 Linux 作業系統上執行。

探索線上端點的本機偵錯選項

藉由在本機偵錯端點,再部署至雲端,您可以更早在程式碼和組態中攔截錯誤。 若要在本機偵錯端點,您有幾個選項,包括:

本文說明如何在 Windows 上使用 Azure Machine Learning 推斷 HTTP 伺服器。

下表提供案例的概觀,可協助您選擇最佳選項:

案例 推斷 HTTP 伺服器 本機端點
更新本機 Python 環境,而「不需」重建 Docker 映像 No
更新評分指令碼 Yes Yes
更新部署設定 (部署、環境、程式碼、模型) No Yes
整合 Microsoft Visual Studio Code (VS Code) 偵錯工具 Yes Yes

當您在本機執行推斷 HTTP 伺服器時,可以專注於偵錯評分指令碼,而不需考慮部署容器組態。

安裝 azureml-inference-server-http 套件

若要安裝 azureml-inference-server-http 套件,請執行下列命令:

python -m pip install azureml-inference-server-http

注意

若要避免套件衝突,請在虛擬環境中安裝推斷 HTTP 伺服器。 您可以使用 pip install virtualenv 命令來啟用組態的虛擬環境。

在本機對評分指令碼進行偵錯

若要在本機偵錯評分指令碼,您有數個選項可用來測試伺服器行為:

使用虛擬評分指令碼測試伺服器行為

  1. 建立名為 server_quickstart 的目錄來保存您的檔案:

    mkdir server_quickstart
    cd server_quickstart
    
  2. 若要避免套件衝突,請建立虛擬環境,例如 myenv,並加以啟用:

    python -m virtualenv myenv
    

    注意

    在 Linux 上,執行 source myenv/bin/activate 命令來啟動虛擬環境。

    測試伺服器之後,您可以執行 deactivate 命令來停用 Python 虛擬環境。

  3. pypi 摘要安裝 azureml-inference-server-http 套件:

    python -m pip install azureml-inference-server-http
    
  4. 建立您的入口指令碼。 下列範例會建立基本入口指令碼,並將它儲存至名為 score.py 的檔案:

    echo -e "import time def init(): \n\t time.sleep(1) \n\n def run(input_data): \n\t return {"message":"Hello, World!"}" > score.py
    
  5. 使用 azmlinfsrv 命令啟動伺服器,並將 score.py 檔案設定為入口指令碼:

    azmlinfsrv --entry_script score.py
    

    注意

    伺服器裝載於 0.0.0.0,這表示它會接聽主電腦的所有 IP 位址。

  6. 使用 curl 公用程式將評分要求傳送至伺服器:

    curl -p 127.0.0.1:5001/score
    

    伺服器會張貼下列回應:

    {"message": "Hello, World!"}
    
  7. 測試之後,選取 Ctrl + C 以終止伺服器。

現在,您可以使用 azmlinfsrv --entry_script score.py 命令再次執行伺服器,以修改評分指令碼檔案 (score.py) 並測試您的變更。

與 Visual Studio Code 整合

若要使用 VS Code 和 Python 擴充功能 偵錯 azureml-inference-server-http 套件,您可以使用 啟動和附加模式

  • 針對 啟動模式,在 VS Code 中設定 launch.json 檔案,並在 VS Code 中啟動 Azure Machine Learning 推斷 HTTP 伺服器:

    1. 啟動 VS Code,然後開啟包含指令碼 (score.py) 的資料夾。

    2. 將下列組態新增至 VS Code 中該工作區的 launch.json 檔案:

      launch.json

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "name": "Debug score.py",
                  "type": "python",
                  "request": "launch",
                  "module": "azureml_inference_server_http.amlserver",
                  "args": [
                      "--entry_script",
                      "score.py"
                  ]
              }
          ]
        }
      
    3. 選取 [執行>開始偵錯] 或使用鍵盤快速鍵 F5,在 VS Code 中啟動偵錯工作階段。

  • 對於 附加模式,請在命令視窗中啟動 Azure Machine Learning 推斷 HTTP 伺服器,並使用 VS Code 搭配 Python 擴充功能以附加至進程:

    注意

    針對 Linux,請先執行 sudo apt-get install -y gdb 命令來安裝 gdb 套件。

    1. 將下列組態新增至 VS Code 中該工作區的 launch.json 檔案:

      launch.json

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "name": "Python: Attach using Process Id",
                  "type": "python",
                  "request": "attach",
                  "processId": "${command:pickProcess}",
                  "justMyCode": true
              }
          ]
        }
      
    2. 在命令視窗中,使用 azmlinfsrv --entry_script score.py 命令啟動推斷 HTTP 伺服器。

    3. 在 VS Code 中啟動偵錯工作階段:

      1. 選取 [執行>開始偵錯] 或使用鍵盤快速鍵 F5。

      2. 在命令視窗中,檢視推斷伺服器的記錄,並找出 azmlinfsrv 命令的進程識別碼 (而非 gunicorn):

        顯示命令視窗的螢幕擷取畫面,其中顯示來自推斷 HTTP 伺服器的記錄,以及醒目提示 azmlinfsrv 命令的進程識別碼。

      3. 在 VS Code 偵錯工具中,輸入 azmlinfsrv 命令的進程識別碼。

        如果您沒有看到 VS Code 進程選擇器,您可以在該工作區 launch.json 檔案的 processId 欄位中手動輸入進程識別碼。

針對這兩種模式,您可以設定 斷點 並逐步偵錯指令碼。

使用端對端範例

下列程式會在本機執行伺服器,使用來自 Azure Machine Learning 範例存放庫的 範例檔案 (評分指令碼、模型檔案和環境)。 如需如何使用這些範例檔案的更多範例,請參閱 使用線上端點部署和評分機器學習模型

  1. 複製範例存放庫:

    git clone --depth 1 https://github.com/Azure/azureml-examples
    cd azureml-examples/cli/endpoints/online/model-1/
    
  2. 使用 conda 建立並啟用虛擬環境:

    在此範例中,會自動安裝 azureml-inference-server-http 套件。 套件會包含在 conda.yml 檔案中作為 azureml-defaults 套件的相依程式庫:

    # Create the environment from the YAML file
    conda env create --name model-env -f ./environment/conda.yml
    # Activate the new environment
    conda activate model-env
    
  3. 檢閱評分指令碼:

    onlinescoring/score.py

    import os
    import logging
    import json
    import numpy
    import joblib
    
    
    def init():
        """
        This function is called when the container is initialized/started, typically after create/update of the deployment.
        You can write the logic here to perform init operations like caching the model in memory
        """
        global model
        # AZUREML_MODEL_DIR is an environment variable created during deployment.
        # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
        # Please provide your model's folder name if there is one
        model_path = os.path.join(
            os.getenv("AZUREML_MODEL_DIR"), "model/sklearn_regression_model.pkl"
        )
        # deserialize the model file back into a sklearn model
        model = joblib.load(model_path)
        logging.info("Init complete")
    
    
    def run(raw_data):
        """
        This function is called for every invocation of the endpoint to perform the actual scoring/prediction.
        In the example we extract the data from the json input and call the scikit-learn model's predict()
        method and return the result back
        """
        logging.info("model 1: request received")
        data = json.loads(raw_data)["data"]
        data = numpy.array(data)
        result = model.predict(data)
        logging.info("Request processed")
        return result.tolist()
    
  4. 指定評分指令碼和模型檔案,以執行推斷 HTTP 伺服器:

    model_dir 參數中指定的模型目錄是使用 AZUREML_MODEL_DIR 變數來定義,並在評分指令碼中擷取。

    在此情況下,您會將目前目錄指定為 ./,因為評分指令碼中將子目錄指定為 model/sklearn_regression_model.pkl

    azmlinfsrv --entry_script ./onlinescoring/score.py --model_dir ./
    

    當伺服器啟動並成功叫用評分指令碼時,範例 啟動記錄檔 會開啟。 否則,記錄檔會顯示錯誤訊息。

  5. 使用範例資料測試評分指令碼:

    開啟另一個命令視窗,並變更為執行命令的相同工作目錄。

    使用 curl 公用程式將範例要求傳送至伺服器,並接收評分結果:

    curl --request POST "127.0.0.1:5001/score" --header "Content-Type:application/json" --data @sample-request.json
    

    當您的評分指令碼中沒有任何問題時,指令碼會傳回評分結果。 如果發生問題,您可以嘗試更新評分指令碼,然後再次啟動伺服器來測試更新過的指令碼。

檢閱伺服器路由

推斷 HTTP 伺服器預設會在連接埠 5001 上接聽下列路由:

名稱 路由
活躍度探查 127.0.0.1:5001/
分數 127.0.0.1:5001/score
OpenAPI (swagger) 127.0.0.1:5001/swagger.json

檢閱伺服器參數

推斷 HTTP 伺服器接受下列參數:

參數 必要 預設 描述:
entry_script True N/A 識別評分指令碼的相對或絕對路徑。
model_dir False N/A 識別保存用於推斷之模型的目錄相對或絕對路徑。
port False 5001 指定伺服器的連接埠。
worker_count False 1 提供處理同時要求的背景工作線程數目。
appinsights_instrumentation_key False N/A 提供發佈記錄之 Application Insights 的檢測金鑰。
access_control_allow_origins False N/A 針對指定的原點啟用 CORS,其中多個來源是以逗號分隔,例如 microsoft.com, bing.com

探索伺服器要求處理

下列步驟示範 Azure Machine Learning 推斷 HTTP 伺服器 (azmlinfsrv) 如何處理傳入要求:

  1. Python CLI 包裝函式位於伺服器的網路堆疊周圍,可用來啟動伺服器。

  2. 用戶端會將要求傳送至伺服器。

  3. 伺服器會透過 Web 伺服器閘道介面 (WSGI) 伺服器傳送要求,將要求分派給 Flask 背景工作應用程式:

  4. Flask 背景工作應用程式會處理要求,其中包括載入入口指令碼和任何相依性。

  5. 您的入口指令碼會收到要求。 入口指令碼會向載入的模型提出推斷呼叫並傳回回應:

此圖顯示推斷 HTTP 伺服器如何處理傳入要求。

探索伺服器記錄

有兩種方式可取得推斷 HTTP 伺服器測試的記錄資料:

  • 在本機執行 azureml-inference-server-http 套件,並檢視記錄輸出。
  • 使用線上端點並檢視 容器記錄。 推斷伺服器的記錄會命名為 Azure Machine Learning 推斷 HTTP 伺服器 <版本>

注意

記錄格式自 0.8.0 版以來已變更。 如果您的記錄檔使用與預期不同的樣式,請將 azureml-inference-server-http 套件更新為最新版本。

檢視啟動記錄

伺服器啟動時,記錄會顯示初始伺服器設定,如下所示:

Azure Machine Learning Inferencing HTTP server <version>

Server Settings
---------------
Entry Script Name: <entry_script>
Model Directory: <model_dir>
Worker Count: <worker_count>
Worker Timeout (seconds): None
Server Port: <port>
Application Insights Enabled: false
Application Insights Key: <appinsights_instrumentation_key>
Inferencing HTTP server version: azmlinfsrv/<version>
CORS for the specified origins: <access_control_allow_origins>

Server Routes
---------------
Liveness Probe: GET   127.0.0.1:<port>/
Score:          POST  127.0.0.1:<port>/score

<logs>

例如,當您依照 端對端範例 啟動伺服器時,記錄會顯示如下:

Azure Machine Learning Inferencing HTTP server v0.8.0

Server Settings
---------------
Entry Script Name: /home/user-name/azureml-examples/cli/endpoints/online/model-1/onlinescoring/score.py
Model Directory: ./
Worker Count: 1
Worker Timeout (seconds): None
Server Port: 5001
Application Insights Enabled: false
Application Insights Key: None
Inferencing HTTP server version: azmlinfsrv/0.8.0
CORS for the specified origins: None

Server Routes
---------------
Liveness Probe: GET   127.0.0.1:5001/
Score:          POST  127.0.0.1:5001/score

2022-12-24 07:37:53,318 I [32726] gunicorn.error - Starting gunicorn 20.1.0
2022-12-24 07:37:53,319 I [32726] gunicorn.error - Listening at: http://0.0.0.0:5001 (32726)
2022-12-24 07:37:53,319 I [32726] gunicorn.error - Using worker: sync
2022-12-24 07:37:53,322 I [32756] gunicorn.error - Booting worker with pid: 32756
Initializing logger
2022-12-24 07:37:53,779 I [32756] azmlinfsrv - Starting up app insights client
2022-12-24 07:37:54,518 I [32756] azmlinfsrv.user_script - Found user script at /home/user-name/azureml-examples/cli/endpoints/online/model-1/onlinescoring/score.py
2022-12-24 07:37:54,518 I [32756] azmlinfsrv.user_script - run() is not decorated. Server will invoke it with the input in JSON string.
2022-12-24 07:37:54,518 I [32756] azmlinfsrv.user_script - Invoking user's init function
2022-12-24 07:37:55,974 I [32756] azmlinfsrv.user_script - Users's init has completed successfully
2022-12-24 07:37:55,976 I [32756] azmlinfsrv.swagger - Swaggers are prepared for the following versions: [2, 3, 3.1].
2022-12-24 07:37:55,977 I [32756] azmlinfsrv - AML_FLASK_ONE_COMPATIBILITY is set, but patching is not necessary.

了解記錄資料格式

推斷 HTTP 伺服器的所有記錄,除了啟動器指令碼之外,會以下列格式呈現資料:

<UTC Time> | <level> [<pid>] <logger name> - <message>

項目包含下列元件:

  • <UTC Time>:該項目輸入至記錄檔的時間。
  • <pid>:與該項目相關聯的進程識別碼。
  • <level>:該項目 記錄層級 的第一個字元,例如 ERROR 的 E、INFO 的 I 等等。
  • <logger name>:與記錄項目相關聯的資源名稱。
  • <message>:記錄訊息的內容。

Python 中有六個層級的記錄會根據嚴重性指派數值:

記錄層級 數值
重要 50
ERROR 40
警告 30
INFO 20
DEBUG 10
NOTSET 0

針對伺服器問題進行疑難排解

下列各節提供 Azure Machine Learning 推斷 HTTP 伺服器的基本疑難排解秘訣。 若要針對線上端點進行疑難排解,請參閱 針對線上端點部署進行疑難排解

確認已安裝的套件

請遵循下列步驟來解決已安裝套件的問題。

  1. 收集 Python 環境已安裝套件和版本的相關資訊。

  2. 確認環境檔案中指定的 azureml-inference-server-http Python 套件版本符合啟動記錄中顯示的 Azure Machine Learning 推斷 HTTP 伺服器版本。

    在某些情況下,pip 相依性解析程式會安裝非預期的套件版本。 您可能需要執行 pip 來更正已安裝的套件和版本。

  3. 如果您在環境中指定 Flask 或其相依性,請移除這些項目。

    • 相依套件包括 flaskjinja2itsdangerouswerkzeugmarkupsafeclick
    • flask 會列為伺服器套件中的相依性。 最佳方法是允許推斷伺服器安裝 flask 套件。
    • 當推斷伺服器設定為支援新版 Flask 時,伺服器會在套件更新可用時自動接收套件更新。

檢查伺服器版本

azureml-inference-server-http 伺服器套件會發行至 PyPI。 PyPI 頁面會列出變更記錄和所有舊版。

如果您使用舊版套件,請將您的設定更新為最新版本。 下表摘要說明穩定版本、常見問題和建議的調整:

套件版本 描述 問題 解決方案
0.4.x 包含在 20220601 或更早版本的訓練映像,以及從 .1.341.43azureml-defaults 套件版本。 最新的穩定版本 0.4.13 對於早於 0.4.11 的伺服器版本,您可能會遇到 Flask 相依性問題,例如"can't import name Markup from jinja2" 儘可能升級至 0.4.13 版或 0.8.x 版 (最新版本)。
0.6.x 預安裝於推斷 20220516 及更早版本的映像。 最新的穩定版本為 0.6.1 N/A N/A
0.7.x 支援 Flask 2。 最新的穩定版本 0.7.7 N/A N/A
0.8.x 記錄格式已變更。 Python 3.6 支援已結束。 N/A N/A

檢查套件相依性

azureml-inference-server-http 伺服器套件最相關的相依套件包括:

  • flask
  • opencensus-ext-azure
  • inference-schema

如果您在 Python 環境中指定 azureml-defaults 套件,則 azureml-inference-server-http 套件是相依套件。 相依性會自動安裝。

提示

如果您使用 Python SDK v1,且未在 Python 環境中明確指定 azureml-defaults 套件,SDK 可能會自動新增套件。 不過,套件工具版本會與 SDK 版本相對鎖定。 例如,如果 SDK 版本是 1.38.0,則會將 azureml-defaults==1.38.0 項目新增至環境的 pip 需求。

伺服器啟動期間出現 TypeError

您可能在伺服器啟動期間遇到下列 TypeError

TypeError: register() takes 3 positional arguments but 4 were given

  File "/var/azureml-server/aml_blueprint.py", line 251, in register

    super(AMLBlueprint, self).register(app, options, first_registration)

TypeError: register() takes 3 positional arguments but 4 were given

當您在 Python 環境中安裝 Flask 2,但您的 azureml-inference-server-http 套件版本不支援 Flask 2 時,就會發生此錯誤。 Flask 2 的支援適用於 azureml-inference-server-http 套件版本 0.7.0 和更新版本,以及azureml-defaults 套件版本 1.44 和更新版本。

  • 如果您未在 Azure Machine Learning Docker 映像中使用 Flask 2 套件,請使用最新版本的 azureml-inference-server-httpazureml-defaults 套件。

  • 如果您在 Azure Machine Learning Docker 映像中使用 Flask 2 套件,請確認映像組建版本為 2022 年 7 月 或更新版本。

    您可以在容器記錄中找到映像版本。 例如:

    2022-08-22T17:05:02,147738763+00:00 | gunicorn/run | AzureML Container Runtime Information
    2022-08-22T17:05:02,161963207+00:00 | gunicorn/run | ###############################################
    2022-08-22T17:05:02,168970479+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,174364834+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,187280665+00:00 | gunicorn/run | AzureML image information: openmpi4.1.0-ubuntu20.04, Materialization Build:20220708.v2
    2022-08-22T17:05:02,188930082+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,190557998+00:00 | gunicorn/run | 
    

    映像的建置日期會出現在 Materialization Build 標記法之後。 在上述範例中,映像版本為 20220708 或 2022 年 7 月 8 日。 此範例中的映像與 Flask 2 相容。

    如果您在容器記錄檔中看不到類似的訊息,您的映像已過期且應該更新。 如果您使用計算統一裝置架構 (CUDA) 映像,而且找不到較新的映像,請檢查您的映像是否已在 AzureML-Containers 中淘汰。 您可以找到已取代映像的指定取代項目。

    如果您使用伺服器搭配線上端點,您也可以在 Azure Machine Learning 工作室 [端點] 頁面上的 [記錄] 中找到記錄。

如果您使用 SDK v1 進行部署,且未在部署組態中明確指定映像,伺服器會套用 openmpi4.1.0-ubuntu20.04 套件與本機 SDK 工具組相符的版本。 不過,安裝的版本可能不是映像的最新可用版本。

針對 SDK 1.43 版,伺服器預設會安裝 openmpi4.1.0-ubuntu20.04:20220616 套件版本,但此套件版本與 SDK 1.43 不相容。 請確定您為部署使用最新的 SDK。

如果您無法更新映像,您可以在環境檔案中釘選 azureml-defaults==1.43azureml-inference-server-http~=0.4.13 項目,以暫時避免問題。 這些項目會指示伺服器使用 flask 1.0.x 安裝舊版。

在伺服器啟動期間出現 ImportError 或 ModuleNotFoundError

在伺服器啟動時,您可能會在特定模組上遇到 ImportErrorModuleNotFoundError,例如 opencensusjinja2markupsafeclick。 下列範例顯示錯誤訊息:

ImportError: cannot import name 'Markup' from 'jinja2'

當您使用未將 Flask 相依性釘選到相容版本的伺服器 0.4.10 版或更早版本時,就會發生匯入和模組錯誤。 若要避免此問題,請安裝較新版本的伺服器。