Azure Machine Learning 유추 HTTP 서버를 사용하여 채점 스크립트 디버깅

Azure Machine Learning 유추 HTTP 서버는 채점 함수를 HTTP 엔드포인트로 노출하고 Flask 서버 코드 및 종속성을 단일 패키지로 래핑하는 Python 패키지입니다. 이 패키지는 Azure Machine Learning을 사용하여 모델을 배포할 때 사용되는 유추를 위해 미리 빌드된 Docker 이미지에 포함되어 있습니다. 이 패키지만 사용하여 프로덕션을 위해 모델을 로컬로 배포할 수 있으며 로컬 개발 환경에서 채점(항목) 스크립트의 유효성을 쉽게 검사할 수 있습니다. 채점 스크립트에 문제가 있는 경우 서버는 오류와 오류 발생 위치를 반환합니다.

연속 통합 및 배포 파이프라인에서 유효성 검사 게이트를 만들 때에도 서버를 사용할 수 있습니다. 예를 들어 후보 스크립트를 사용하여 서버를 시작하고 로컬 엔드포인트에 대해 테스트 도구 모음을 실행할 수 있습니다.

이 문서에서는 주로 유추 서버를 사용하여 로컬로 디버그하려는 사용자를 대상으로 하지만, 온라인 엔드포인트에서 유추 서버를 사용하는 방법을 이해하는 데도 도움이 됩니다.

온라인 엔드포인트 로컬 디버깅

엔드포인트를 클라우드에 배포하기 전에 로컬로 디버깅하면 이전에 코드 및 구성에서 오류를 catch하는 데 도움이 될 수 있습니다. 엔드포인트를 로컬로 디버그하려면 다음을 사용할 수 있습니다.

이 문서에서는 Azure Machine Learning 유추 HTTP 서버를 중점적으로 다룹니다.

다음 표에서는 가장 적합한 시나리오를 선택하는 데 도움이 되는 시나리오의 개요를 제공합니다.

시나리오 유추 HTTP 서버 로컬 엔드포인트
Docker 이미지 다시 빌드 없이 로컬 Python 환경 업데이트 아니요
점수 매기기 스크립트 업데이트
배포 구성 업데이트(배포, 환경, 코드, 모델)
VS Code 디버거 통합

유추 HTTP 서버를 로컬로 실행하면 배포 컨테이너 구성의 영향을 받지 않고 채점 스크립트를 디버깅하는 데 집중할 수 있습니다.

필수 조건

  • 필요: Python >=3.8
  • Anaconda

Azure Machine Learning 유추 HTTP 서버는 Windows 및 Linux 기반 운영 체제에서 실행됩니다.

설치

참고 항목

패키지 충돌을 방지하려면 가상 환경에 서버를 설치합니다.

azureml-inference-server-http package를 설치하려면 cmd/터미널에서 다음 명령을 실행합니다.

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

로컬로 채점 스크립트 디버그

점수 매기기 스크립트를 로컬로 디버그하려면 더미 채점 스크립트를 사용하여 서버가 작동하는 방식을 테스트하거나, VS Code를 사용하여 azureml-inference-server-http 패키지로 디버그하거나, 예제 리포지토리의 실제 채점 스크립트, 모델 파일 및 환경 파일로 서버를 테스트할 수 있습니다.

더미 채점 스크립트를 사용하여 서버 동작 테스트

  1. 파일을 저장할 디렉터리를 만듭니다.

    mkdir server_quickstart
    cd server_quickstart
    
  2. 패키지 충돌을 방지하려면 가상 환경을 만들고 활성화합니다.

    python -m venv myenv
    source myenv/bin/activate
    

    테스트한 후 deactivate를 실행하여 Python 가상 환경을 비활성화합니다.

  3. pypi 피드에서 azureml-inference-server-http 패키지를 설치합니다.

    python -m pip install azureml-inference-server-http
    
  4. 항목 스크립트(score.py)를 만듭니다. 다음 예제에서는 기본 항목 스크립트를 만듭니다.

    echo '
    import time
    
    def init():
        time.sleep(1)
    
    def run(input_data):
        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!"}
    

테스트한 후 Ctrl + C를 눌러 서버를 종료할 수 있습니다. 이제 채점 스크립트(score.py)를 수정하고 서버를 다시 실행하여 변경 내용을 테스트할 수 있습니다(azmlinfsrv --entry_script score.py).

Visual Studio Code와 통합하는 방법

VS Code(Visual Studio 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. VS Code에서 디버깅 세션을 시작합니다. "실행" -> "디버깅 시작"(또는 F5)을 선택합니다.

  • 연결 모드: 명령줄에서 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. CLI(azmlinfsrv --entry_script score.py)를 사용하여 유추 서버를 시작합니다.

    3. VS Code에서 디버깅 세션을 시작합니다.

      1. VS Code에서 "실행" -> "디버깅 시작"(또는 F5)을 선택합니다.
      2. CLI에 표시된 로그(유추 서버)를 사용하여 azmlinfsrv(gunicorn이 아님)의 프로세스 ID를 입력합니다. 서버의 프로세스 ID를 보여주는 CLI의 스크린샷.

      참고 항목

      프로세스 선택기가 표시되지 않으면 launch.jsonprocessId 필드에 프로세스 ID를 수동으로 입력합니다.

두 가지 방법 모두에서 중단점을 설정하고 단계별로 디버그할 수 있습니다.

엔드투엔드 예제

이 섹션에서는 예제 리포지토리에서 샘플 파일(채점 스크립트, 모델 파일 및 환경)을 사용하여 서버를 로컬로 실행합니다. 샘플 파일은 온라인 엔드포인트를 사용하여 기계 학습 모델 배포 및 채점에 대한 문서에서도 사용됩니다.

  1. 샘플 리포지토리를 복제합니다.

    git clone --depth 1 https://github.com/Azure/azureml-examples
    cd azureml-examples/cli/endpoints/online/model-1/
    
  2. conda를 사용하여 가상 환경을 만들고 활성화합니다. 이 예제에서는 다음과 같이 conda.yml에 있는 azureml-defaults 패키지의 종속 라이브러리로 포함되기 때문에 azureml-inference-server-http 패키지가 자동으로 설치됩니다.

    # 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. 채점 스크립트 및 모델 파일을 지정하여 유추 서버를 실행합니다. 지정된 모델 디렉터리(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
    

    채점 스크립트에 문제가 없는 경우 점수 매기기 결과가 반환됩니다. 문제가 발견되면 채점 스크립트를 업데이트하고 서버를 다시 시작하여 업데이트된 스크립트를 테스트할 수 있습니다.

서버 경로

서버가 이러한 경로에서 포트 5001(기본값)에서 수신 대기합니다.

이름 경로
활동성 프로브 127.0.0.1:5001/
점수 127.0.0.1:5001/점수
OpenAPI(Swagger) 127.0.0.1:5001/swagger.json

서버 매개 변수

다음 표에는 서버에서 허용하는 매개 변수가 나와 있습니다.

매개 변수 Required 기본값 설명
entry_script True 해당 없음 점수 매기기 스크립트의 상대 또는 절대 경로입니다.
model_dir False 해당 없음 추론에 사용되는 모델을 보유하고 있는 디렉터리의 상대 또는 절대 경로입니다.
port False 5001 서버의 서비스 포트입니다.
worker_count False 1 동시 요청을 처리할 작업자 스레드 수입니다.
appinsights_instrumentation_key False 해당 없음 로그가 게시될 Application Insights에 대한 계측 키입니다.
access_control_allow_origins False 해당 없음 지정된 원본에 대해 CORS를 사용하도록 설정합니다. 여러 원본을 ","로 구분합니다.
예: "microsoft.com, bing.com"

요청 흐름

다음 단계에서는 Azure Machine Learning 유추 HTTP 서버(azmlinfsrv)에서 들어오는 요청을 처리하는 방법을 설명합니다.

  1. Python CLI 래퍼는 서버의 네트워크 스택을 중심으로 하며 서버를 시작하는 데 사용됩니다.
  2. 클라이언트는 서버에 요청을 보냅니다.
  3. 요청이 수신되면 WSGI 서버를 거치며 작업자 중 하나로 발송됩니다.
    • GunicornLinux에서 사용됩니다.
    • WaitressWindows에서 사용됩니다.
  4. 그러면 요청이 Flask 앱에 의해 처리되고 항목 스크립트 및 종속성이 로드됩니다.
  5. 마지막으로 요청이 항목 스크립트에 전송됩니다. 그런 다음, 항목 스크립트는 로드된 모델에 대한 유추 호출을 수행하고 응답을 반환합니다.

HTTP 서버 프로세스의 다이어그램.

로그 이해

여기서는 Azure Machine Learning 유추 HTTP 서버의 로그를 설명합니다. azureml-inference-server-http를 로컬로 실행할 때 로그를 가져올 수 있고, 온라인 엔드포인트를 사용하는 경우 컨테이너 로그를 가져올 수 있습니다.

참고 항목

로깅 형식은 버전 0.8.0 이후에 변경되었습니다. 다른 스타일로 로그를 찾으면 azureml-inference-server-http 패키지를 최신 버전으로 업데이트합니다.

온라인 엔드포인트를 사용하는 경우 유추 서버의 로그는 Azure Machine Learning Inferencing HTTP server <version>으로 시작됩니다.

시작 로그

서버가 시작되면 서버 설정은 다음과 같이 로그에 의해 먼저 표시됩니다.

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.

로그 형식

유추 서버의 로그는 Python 패키지의 일부가 아니므로 시작 관리자 스크립트를 제외하고 다음 형식으로 생성됩니다.

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

여기서 <pid>는 프로세스 ID이고 <level>로깅 수준의 첫 번째 문자입니다. 즉, ERROR의 경우 E, INFO의 경우 I가 됩니다.

Python에는 6가지 수준의 로깅이 있으며 심각도와 관련된 숫자가 지정됩니다.

로깅 수준 숫자 값
위험 50
오류 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

문제 해결 가이드

이 섹션에서는 Azure Machine Learning 유추 HTTP 서버에 대한 기본적인 문제 해결 팁을 제공합니다. 온라인 엔드포인트 문제를 해결하려면 온라인 엔드포인트 배포 문제 해결도 참조하세요.

기본 단계

기본적인 문제 해결 단계는 다음과 같습니다.

  1. Python 환경에 대한 버전 정보를 수집합니다.
  2. 환경 파일에 지정된 azureml-inference-server-http python 패키지 버전이 시작 로그에 표시된 AzureML 유추 HTTP 서버 버전과 일치하는지 확인합니다. 경우에 따라 pip의 종속성 확인자가 예기치 않은 버전의 패키지를 설치하도록 합니다.
  3. 사용자 환경에서 Flask(및 해당 종속성)를 지정하는 경우 이를 제거합니다. 종속성에는 Flask, Jinja2, itsdangerous, Werkzeug, MarkupSafeclick이 포함됩니다. Flask는 서버 패키지에 종속성으로 나열되며, 서버에서 설치하도록 하는 것이 가장 좋습니다. 이렇게 하면 서버에서 새 버전의 Flask를 지원할 때 자동으로 가져옵니다.

서버 버전

서버 패키지 azureml-inference-server-http가 PyPI에 게시됩니다. PyPI 페이지에서 변경 로그와 이전의 모든 버전을 찾을 수 있습니다. 이전 버전을 사용하는 경우 최신 버전으로 업데이트합니다.

  • 0.4.x: 학습 이미지 ≤ 20220601azureml-defaults>=1.34,<=1.43에 번들로 제공되는 버전입니다. 0.4.13은 안정적인 마지막 버전입니다. 버전 0.4.11 이전의 서버를 사용하는 경우 jinja2에서 이름 Markup을 가져올 수 없는 것과 같은 Flask 종속성 문제가 나타날 수 있습니다. 가능한 경우 0.4.13 또는 0.8.x(최신 버전)로 업그레이드하는 것이 좋습니다.
  • 0.6.x: 유추 이미지에 사전 설치된 버전은 ≤ 20220516입니다. 안정적인 최신 버전은 0.6.1입니다.
  • 0.7.x: Flask 2를 지원하는 첫 번째 버전입니다. 안정적인 최신 버전은 0.7.7입니다.
  • 0.8.x: 로그 형식이 변경되고 Python 3.6 지원이 삭제되었습니다.

패키지 종속성

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인 경우 환경의 pip 요구 사항에 azureml-defaults==1.38.0이 추가됩니다.

자주 묻는 질문

1. 서버를 시작하는 동안 다음 오류가 발생했습니다.


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가 설치되어 있지만 Flask 2를 지원하지 않는 azureml-inference-server-http 버전을 실행하고 있습니다. Flask 2에 대한 지원은 azureml-defaults>=1.44에도 있는 azureml-inference-server-http>=0.7.0에 추가되었습니다.

  • AzureML Docker 이미지에서 이 패키지를 사용하지 않는 경우 최신 버전의 azureml-inference-server-http 또는 azureml-defaults를 사용합니다.

  • AzureML Docker 이미지와 함께 이 패키지를 사용하는 경우 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, Materializaton Build:20220708.v2
    2022-08-22T17:05:02,188930082+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,190557998+00:00 | gunicorn/run | 
    

    이미지의 빌드 날짜는 위의 예에서 20220708 또는 2022년 7월 8일인 "구체화 빌드" 뒤에 나타납니다. 이 이미지는 Flask 2와 호환됩니다. 컨테이너 로그에 이와 같은 배너가 표시되지 않으면 이미지가 오래된 것이므로 업데이트해야 합니다. CUDA 이미지를 사용 중이고 최신 이미지를 찾을 수 없는 경우 AzureML-Containers에서 이미지가 더 이상 사용되지 않는지 확인합니다. 그렇다면 대체 이미지를 찾을 수 있어야 합니다.

  • 온라인 엔드포인트가 있는 서버를 사용 중인 경우 Azure Machine Learning 스튜디오의 온라인 엔드포인트 페이지에 있는 '배포 로그'에서 로그를 찾을 수도 있습니다. SDK v1을 사용하여 배포하고 배포 구성에 이미지를 명시적으로 지정하지 않으면 기본적으로 로컬 SDK 도구 집합과 일치하는 openmpi4.1.0-ubuntu20.04 버전이 사용됩니다. 이 버전은 이미지의 최신 버전이 아닐 수 있습니다. 예를 들어 SDK 1.43은 기본적으로 호환되지 않는 openmpi4.1.0-ubuntu20.04:20220616을 사용합니다. 배포에 최신 SDK를 사용하고 있는지 확인합니다.

  • 어떤 이유로 이미지를 업데이트할 수 없는 경우 azureml-defaults==1.43 또는 azureml-inference-server-http~=0.4.13을 고정하여 일시적으로 문제를 피할 수 있습니다. 그러면 이전 버전 서버가 Flask 1.0.x로 설치됩니다.

2. 다음 메시지와 같이 시작하는 동안 모듈 opencensus, jinja2, MarkupSafe 또는 click에서 ImportError 또는 ModuleNotFoundError가 발생했습니다.

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

이전 버전(<= 0.4.10)의 서버는 Flask의 종속성을 호환 가능한 버전에 고정하지 않았습니다. 이 문제는 최신 버전의 서버에서 수정되었습니다.

다음 단계