使用 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 作業系統上執行。
探索線上端點的本機偵錯選項
藉由在本機偵錯端點,再部署至雲端,您可以更早在程式碼和組態中攔截錯誤。 若要在本機偵錯端點,您有幾個選項,包括:
- Azure Machine Learning 推斷 HTTP 伺服器
- 本機端點
本文說明如何在 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
命令來啟用組態的虛擬環境。
在本機對評分指令碼進行偵錯
若要在本機偵錯評分指令碼,您有數個選項可用來測試伺服器行為:
- 嘗試虛擬評分指令碼。
- 使用 Visual Studio Code 搭配 azureml-inference-server-http 套件進行偵錯。
- 從我們的 範例存放庫 執行實際的評分指令碼、模型檔案和環境檔案。
使用虛擬評分指令碼測試伺服器行為
建立名為 server_quickstart 的目錄來保存您的檔案:
mkdir server_quickstart cd server_quickstart
若要避免套件衝突,請建立虛擬環境,例如 myenv,並加以啟用:
python -m virtualenv myenv
注意
在 Linux 上,執行
source myenv/bin/activate
命令來啟動虛擬環境。測試伺服器之後,您可以執行
deactivate
命令來停用 Python 虛擬環境。從 pypi 摘要安裝
azureml-inference-server-http
套件:python -m pip install azureml-inference-server-http
建立您的入口指令碼。 下列範例會建立基本入口指令碼,並將它儲存至名為 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
使用
azmlinfsrv
命令啟動伺服器,並將 score.py 檔案設定為入口指令碼:azmlinfsrv --entry_script score.py
注意
伺服器裝載於 0.0.0.0,這表示它會接聽主電腦的所有 IP 位址。
使用
curl
公用程式將評分要求傳送至伺服器:curl -p 127.0.0.1:5001/score
伺服器會張貼下列回應:
{"message": "Hello, World!"}
測試之後,選取 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 伺服器:
啟動 VS Code,然後開啟包含指令碼 (score.py) 的資料夾。
將下列組態新增至 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" ] } ] }
選取 [執行>開始偵錯] 或使用鍵盤快速鍵 F5,在 VS Code 中啟動偵錯工作階段。
對於 附加模式,請在命令視窗中啟動 Azure Machine Learning 推斷 HTTP 伺服器,並使用 VS Code 搭配 Python 擴充功能以附加至進程:
注意
針對 Linux,請先執行
sudo apt-get install -y gdb
命令來安裝gdb
套件。將下列組態新增至 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 } ] }
在命令視窗中,使用
azmlinfsrv --entry_script score.py
命令啟動推斷 HTTP 伺服器。在 VS Code 中啟動偵錯工作階段:
選取 [執行>開始偵錯] 或使用鍵盤快速鍵 F5。
在命令視窗中,檢視推斷伺服器的記錄,並找出
azmlinfsrv
命令的進程識別碼 (而非gunicorn
):在 VS Code 偵錯工具中,輸入
azmlinfsrv
命令的進程識別碼。如果您沒有看到 VS Code 進程選擇器,您可以在該工作區 launch.json 檔案的
processId
欄位中手動輸入進程識別碼。
針對這兩種模式,您可以設定 斷點 並逐步偵錯指令碼。
使用端對端範例
下列程式會在本機執行伺服器,使用來自 Azure Machine Learning 範例存放庫的 範例檔案 (評分指令碼、模型檔案和環境)。 如需如何使用這些範例檔案的更多範例,請參閱 使用線上端點部署和評分機器學習模型。
複製範例存放庫:
git clone --depth 1 https://github.com/Azure/azureml-examples cd azureml-examples/cli/endpoints/online/model-1/
使用 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
檢閱評分指令碼:
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()
指定評分指令碼和模型檔案,以執行推斷 HTTP 伺服器:
model_dir
參數中指定的模型目錄是使用AZUREML_MODEL_DIR
變數來定義,並在評分指令碼中擷取。在此情況下,您會將目前目錄指定為 ./,因為評分指令碼中將子目錄指定為 model/sklearn_regression_model.pkl。
azmlinfsrv --entry_script ./onlinescoring/score.py --model_dir ./
當伺服器啟動並成功叫用評分指令碼時,範例 啟動記錄檔 會開啟。 否則,記錄檔會顯示錯誤訊息。
使用範例資料測試評分指令碼:
開啟另一個命令視窗,並變更為執行命令的相同工作目錄。
使用
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
) 如何處理傳入要求:
Python CLI 包裝函式位於伺服器的網路堆疊周圍,可用來啟動伺服器。
用戶端會將要求傳送至伺服器。
伺服器會透過 Web 伺服器閘道介面 (WSGI) 伺服器傳送要求,將要求分派給 Flask 背景工作應用程式:
Flask 背景工作應用程式會處理要求,其中包括載入入口指令碼和任何相依性。
您的入口指令碼會收到要求。 入口指令碼會向載入的模型提出推斷呼叫並傳回回應:
探索伺服器記錄
有兩種方式可取得推斷 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 伺服器的基本疑難排解秘訣。 若要針對線上端點進行疑難排解,請參閱 針對線上端點部署進行疑難排解。
確認已安裝的套件
請遵循下列步驟來解決已安裝套件的問題。
收集 Python 環境已安裝套件和版本的相關資訊。
確認環境檔案中指定的
azureml-inference-server-http
Python 套件版本是否符合啟動記錄中顯示的 Azure Machine Learning 推斷 HTTP 伺服器版本。在某些情況下,pip 相依性解析程式會安裝非預期的套件版本。 您可能需要執行
pip
來更正已安裝的套件和版本。如果您在環境中指定 Flask 或其相依性,請移除這些項目。
- 相依套件包括
flask
、jinja2
、itsdangerous
、werkzeug
、markupsafe
和click
。 flask
會列為伺服器套件中的相依性。 最佳方法是允許推斷伺服器安裝flask
套件。- 當推斷伺服器設定為支援新版 Flask 時,伺服器會在套件更新可用時自動接收套件更新。
- 相依套件包括
檢查伺服器版本
azureml-inference-server-http
伺服器套件會發行至 PyPI。 PyPI 頁面 (英文) 會列出變更記錄和所有舊版。
如果您使用舊版套件,請將您的設定更新為最新版本。 下表摘要說明穩定版本、常見問題和建議的調整:
套件版本 | 描述 | 問題 | 解決方案 |
---|---|---|---|
0.4.x | 包含在 20220601 或更早版本的訓練映像,以及從 .1.34 到 1.43 的 azureml-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-http
或azureml-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.43
或 azureml-inference-server-http~=0.4.13
項目,以暫時避免問題。 這些項目會指示伺服器使用 flask 1.0.x
安裝舊版。
在伺服器啟動期間出現 ImportError 或 ModuleNotFoundError
在伺服器啟動時,您可能會在特定模組上遇到 ImportError
或 ModuleNotFoundError
,例如 opencensus
、jinja2
、markupsafe
或 click
。 下列範例顯示錯誤訊息:
ImportError: cannot import name 'Markup' from 'jinja2'
當您使用不會將 Flask 相依性釘選到相容版本的伺服器 0.4.10 版或更早版本時,就會發生匯入和模組錯誤。 若要避免此問題,請安裝較新版本的伺服器。