Condividi tramite


Eseguire il debug degli script di assegnazione dei punteggi con il server HTTP di inferenza di Azure Machine Learning

Il server HTTP di inferenza di Azure Machine Learning è un pacchetto Python che espone la funzione di punteggio come endpoint HTTP ed esegue il wrapping del codice e delle dipendenze del server Flask in un pacchetto singolare. Il server è incluso nelle immagini Docker predefinite per l'inferenza usate durante la distribuzione di un modello con Azure Machine Learning. Usando il pacchetto da solo, è possibile distribuire il modello in locale per la produzione e convalidare facilmente lo script di assegnazione dei punteggi (voce) in un ambiente di sviluppo locale. Se si verifica un problema con lo script di assegnazione dei punteggi, il server restituisce un errore e il percorso dell'errore.

Il server può essere usato per creare controlli di convalida in una pipeline di integrazione e distribuzione continue. Ad esempio, è possibile avviare il server con lo script candidato ed eseguire il gruppo di test sull'endpoint locale.

Questo articolo supporta gli sviluppatori che vogliono usare il server di inferenza per eseguire il debug in locale e descrive come usare il server di inferenza con endpoint online in Windows.

Prerequisiti

Per usare il server HTTP di inferenza di Azure Machine Learning per il debug locale, la configurazione deve includere i componenti seguenti:

  • Python 3.8 o versioni successive
  • Anaconda

Il server HTTP di inferenza di Azure Machine Learning viene eseguito nei sistemi operativi basati su Windows e Linux.

Esplorare le opzioni di debug locale per gli endpoint online

Eseguendo il debug degli endpoint in locale prima della distribuzione nel cloud, è possibile rilevare gli errori nel codice e nella configurazione in precedenza. Per eseguire il debug degli endpoint in locale, sono disponibili diverse opzioni, tra cui:

Questo articolo descrive come usare il server HTTP di inferenza di Azure Machine Learning in Windows.

La tabella seguente offre una panoramica degli scenari che consentono di scegliere l'opzione più adatta

Scenario Server HTTP di inferenza Endpoint locale
Aggiornare l'ambiente Python locale senza ricompilare l'immagine Docker No
Aggiornare lo script di assegnazione dei punteggi
Aggiornare le configurazioni di distribuzione (distribuzione, ambiente, codice, modello) No
Integrare il debugger di Microsoft Visual Studio Code (VS Code)

Quando si esegue il server HTTP di inferenza in locale, è possibile concentrarsi sul debug dello script di assegnazione dei punteggi senza preoccupazioni per le configurazioni del contenitore di distribuzione.

Installare il pacchetto azureml-inference-server-http

Per installare il pacchetto azureml-inference-server-http, eseguire il comando seguente:

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

Nota

Per evitare conflitti di pacchetti, installare il server HTTP di inferenza in un ambiente virtuale. È possibile usare il comando pip install virtualenv per abilitare gli ambienti virtuali per la configurazione.

Eseguire il debug dello script di assegnazione dei punteggi in locale

Per eseguire il debug dello script di assegnazione dei punteggi in locale, sono disponibili diverse opzioni per testare il comportamento del server:

  • Provare uno script di assegnazione dei punteggi fittizi.
  • Usare Visual Studio Code per eseguire il debug con il pacchetto azureml-inference-server-http.
  • Eseguire uno script di assegnazione dei punteggi, un file di modello e un file di ambiente effettivi dal repository di esempi.

Testare il comportamento del server con script di assegnazione dei punteggi fittizi

  1. Creare una directory denominata server_quickstart in cui inserire i file:

    mkdir server_quickstart
    cd server_quickstart
    
  2. Per evitare conflitti di pacchetti, creare un ambiente virtuale come myenv e attivarlo:

    python -m virtualenv myenv
    

    Nota

    In Linux eseguire il comando source myenv/bin/activate per attivare l'ambiente virtuale.

    Dopo aver testato il server, è possibile eseguire il comando deactivate per disattivare l'ambiente virtuale Python.

  3. Installare il pacchetto azureml-inference-server-http dal feed pypi:

    python -m pip install azureml-inference-server-http
    
  4. Creare lo script di immissione. L'esempio seguente crea uno script di immissione di base e lo salva in un file denominato 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. Avviare il server con il comando azmlinfsrv e impostare il file score.py come script di immissione:

    azmlinfsrv --entry_script score.py
    

    Nota

    Il server è ospitato in 0.0.0.0, il che significa che è in ascolto di tutti gli indirizzi IP del computer di hosting.

  6. Inviare una richiesta di assegnazione di punteggio al server tramite l'utilità curl:

    curl -p 127.0.0.1:5001/score
    

    Il server invia la risposta seguente:

    {"message": "Hello, World!"}
    
  7. Dopo il test, selezionare CTRL+C per terminare il server.

È ora possibile modificare lo script di assegnazione dei punteggi (score.py) e testare le modifiche eseguendo di nuovo il server con il comando azmlinfsrv --entry_script score.py.

Eseguire l'integrazione con Visual Studio Code

Per usare VS Code e l'Estensione Python per il debug con il pacchetto azureml-inference-server-http, è possibile usare le modalità Avvia e Allega.

  • Per Modalità di avvio configurare il file launch.json in VS Code e avviare il server HTTP di inferenza di Azure Machine Learning in VS Code:

    1. Avviare VS Code e aprire la cartella contenente lo script (score.py).

    2. Aggiungere la configurazione seguente al file launch.json per tale area di lavoro in VS Code:

      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. Avviare la sessione di debug in VS Code selezionando Esegui>Avvia debug o usando il tasto di scelta rapida F5.

  • Per Modalità di collegamento: avviare il server HTTP di inferenza di Azure Machine Learning in una finestra di comando e usare VS Code con l'estensione Python per connettersi al processo:

    Nota

    Per Linux, installare prima di tutto il pacchetto gdb eseguendo il comando sudo apt-get install -y gdb.

    1. Aggiungere la configurazione seguente al file launch.json per tale area di lavoro in VS Code:

      launch.json

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "name": "Python: Attach using Process Id",
                  "type": "python",
                  "request": "attach",
                  "processId": "${command:pickProcess}",
                  "justMyCode": true
              }
          ]
        }
      
    2. In una finestra di comando avviare il server HTTP di inferenza usando il comando azmlinfsrv --entry_script score.py.

    3. Avviare la sessione di debug in VS Code:

      1. Selezionare Esegui>Avvia debug o usare il tasto di scelta rapida F5.

      2. Nella finestra di comando visualizzare i log dal server di inferenza e individuare l'ID processo del comando azmlinfsrv (non il gunicorn):

        Screenshot che mostra una finestra di comando che mostra i log dal server HTTP di inferenza e l'ID processo del comando azmlinfsrv evidenziato.

      3. Nel debugger di VS Code immettere l'ID processo del comando azmlinfsrv.

        Se non viene visualizzata la selezione del processo di VS Code, è possibile immettere manualmente l'ID processo nel campo processId del file launch.json per tale area di lavoro.

Per entrambe le modalità, è possibile impostare punti di interruzione ed eseguire il debug dello script in modo dettagliato.

Usare un esempio end-to-end

La procedura seguente esegue il server in locale con file di esempio (script di assegnazione dei punteggi, file di modello e ambiente) dal repository di esempio di Azure Machine Learning. Per altri esempi su come usare i file di esempio, vedere Distribuire e assegnare un punteggio a un modello di Machine Learning usando un endpoint online.

  1. Clonare il repository di esempio:

    git clone --depth 1 https://github.com/Azure/azureml-examples
    cd azureml-examples/cli/endpoints/online/model-1/
    
  2. Creare e attivare un ambiente virtuale con conda:

    In questo esempio il pacchetto azureml-inference-server-http viene installato automaticamente. Il pacchetto è incluso come libreria dipendente del pacchetto azureml-defaults nel file conda.yml:

    # 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. Esaminare lo script di assegnazione dei punteggi:

    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. Eseguire il server HTTP di inferenza specificando lo script di assegnazione dei punteggi e il file del modello:

    La directory del modello specificata nel parametro model_dir è definita come variabile AZUREML_MODEL_DIR e recuperata nello script di assegnazione dei punteggi.

    In questo caso, si specifica la directory corrente ./ poiché la sottodirectory viene specificata nello script di assegnazione dei punteggi come model/sklearn_regression_model.pkl.

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

    Quando il server viene avviato e richiamato correttamente lo script di assegnazione dei punteggi, viene aperto log di avvio. In caso contrario, il log mostra i messaggi di errore.

  5. Testare lo script di assegnazione dei punteggi con dati di esempio:

    Aprire un'altra finestra di comando e andare alla stessa directory di lavoro in cui si esegue il comando.

    Usare l'utilità curl per inviare una richiesta di esempio al server e ricevere un risultato di assegnazione dei punteggi:

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

    Quando non sono presenti problemi nello script di assegnazione dei punteggi, lo script restituisce il risultato dell'assegnazione dei punteggi. In caso di problemi, è possibile provare ad aggiornare lo script di assegnazione dei punteggi e avviare di nuovo il server per testare lo script aggiornato.

Esaminare le route del server

Il server HTTP di inferenza è in ascolto sulla porta 5001 per impostazione predefinita nelle route seguenti:

Nome Itinerario
Probe di attività 127.0.0.1:5001/
Punteggio 127.0.0.1:5001/score
OpenAPI (swagger) 127.0.0.1:5001/swagger.json

Esaminare i parametri del server

Il server HTTP di inferenza accetta i parametri seguenti:

Parametro Richiesto Default Description
entry_script Vero N/D Identifica il percorso relativo o assoluto dello script di assegnazione dei punteggi.
model_dir Falso N/D Identifica il percorso relativo o assoluto della directory che contiene il modello usato per l'inferenza.
port Falso 5001 Specifica la porta di servizio del server.
worker_count Falso 1 Fornisce il numero di thread di lavoro per l'elaborazione delle richieste simultanee.
appinsights_instrumentation_key Falso N/D Fornisce la chiave di strumentazione per Application Insights in cui sono pubblicati i log.
access_control_allow_origins Falso N/D Abilita CORS per le origini specificate, in cui più origini sono separate da una virgola (,), ad esempio microsoft.com, bing.com.

Esplorare l'elaborazione delle richieste del server

La procedura seguente spiega come il server HTTP di inferenza di Azure Machine Learning (azmlinfsrv) gestisce le richieste in ingresso:

  1. Un wrapper dell'interfaccia della riga di comando di Python si trova intorno allo stack di rete del server e viene usato per avviare il server.

  2. Un client invia una richiesta al server.

  3. Il server invia la richiesta tramite il server Web Server Gateway Interface (WSGI), che invia la richiesta a un'app ruolo di lavoro Flask:

  4. L'app ruolo di lavoro Flask gestisce la richiesta, che include il caricamento dello script di immissione e le eventuali dipendenze.

  5. Lo script di immissione riceve la richiesta. Lo script di immissione esegue una chiamata di inferenza al modello caricato e restituisce una risposta:

Diagramma che mostra come il server HTTP di inferenza elabora le richieste in ingresso.

Esplorare i log del server

Esistono due modi per ottenere i dati di log per il test del server HTTP di inferenza:

  • Eseguire il pacchetto azureml-inference-server-http in locale e visualizzare l'output dei log.
  • Usare gli endpoint online e visualizzare i log dei contenitori. Il log per il server di inferenza è denominato Server HTTP di inferenza di Azure Machine Learning <versione>.

Nota

Il formato di registrazione è cambiato dalla versione 0.8.0. Se il log usa uno stile differente da quello previsto, aggiornare il pacchetto azureml-inference-server-http alla versione più recente.

Visualizzare i log di avvio

All'avvio del server, i log mostrano le impostazioni iniziali del server come indicato di seguito:

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>

Ad esempio, quando si avvia il server seguendo l'esempio end-to-end, il log viene visualizzato come indicato di seguito:

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.

Informazioni sul formato dei dati di log

Tutti i log dal server HTTP di inferenza, ad eccezione dello script di avvio, presentano i dati nel formato seguente:

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

La voce è costituita dai componenti seguenti:

  • <UTC Time>: ora in cui la voce è stata immessa nel log.
  • <pid>: ID del processo associato alla voce.
  • <level>: primo carattere del livello di registrazione per la voce, ad esempio E per ERRORE, I per INFO e così via.
  • <logger name>: nome della risorsa associata alla voce di log.
  • <message>: contenuto del messaggio di log.

Esistono sei livelli di registrazione in Python con valori numerici assegnati in base alla gravità:

Livello di registrazione Valore numerico
CRITICAL 50
ERROR 40
AVVISO 30
INFORMAZIONI: 20
DEBUG 10
NOTSET 0

Risolvere i problemi del server

Le seguenti sezioni forniscono suggerimenti di base per la risoluzione dei problemi del server HTTP di inferenza di Azure Machine Learning. Per risolvere i problemi relativi agli endpoint online, vedere Risoluzione dei problemi di distribuzione degli endpoint online.

Controllare i pacchetti installati

Per risolvere problemi relativi ai pacchetti installati, seguire questa procedura.

  1. Raccogliere informazioni su pacchetti e versioni installati per l'ambiente Python.

  2. Assicurarsi che la versione del pacchetto Python azureml-inference-server-http specificata nel file di ambiente corrisponda alla versione del server HTTP di inferenza di Azure Machine Learning visualizzata nel log di avvio.

    In alcuni casi, il sistema di risoluzione delle dipendenze pip installa versioni impreviste del pacchetto. Potrebbe essere necessario eseguire pip per correggere i pacchetti e le versioni installati.

  3. Se si specifica Flask o le relative dipendenze nell'ambiente, rimuovere questi elementi.

    • I pacchetti dipendenti includono flask, jinja2 itsdangerous, werkzeug, markupsafe, e click.
    • flask è elencato come dipendenza nel pacchetto del server. L'approccio migliore consiste nel consentire al server di inferenza di installare il pacchetto flask.
    • Quando il server di inferenza è configurato per supportare le nuove versioni di Flask, il server riceve automaticamente gli aggiornamenti del pacchetto non appena diventano disponibili.

Controllare la versione del server

Il pacchetto server azureml-inference-server-http viene pubblicato in PyPI. La pagina PyPI elenca il log delle modifiche e tutte le versioni precedenti.

Se si usa una versione precedente del pacchetto, aggiornare la configurazione alla versione più recente. La tabella seguente riepiloga le versioni stabili, i problemi comuni e le modifiche consigliate:

Versione pacchetto Descrizione Problema Risoluzione
0.4.x In bundle nelle immagini di training datate 20220601 o precedenti e versioni del pacchetto azureml-defaults da .1.34 a 1.43. La versione stabile più recente è 0.4.13. Per le versioni del server precedenti a 0.4.11, è possibile che si verifichino problemi di dipendenza Flask, ad esempio "can't import name Markup from jinja2". Se possibile, eseguire l'aggiornamento alla versione 0.4.13 o 0.8.x, ovvero la versione più recente.
0.6.x Preinstallato nelle immagini di inferenza datate 20220516 e precedenti. La versione stabile più recente è 0.6.1. N/D N/D
0.7.x Supporta Flask 2. La versione stabile più recente è 0.7.7. N/D N/D
0.8.x Formato del log modificato. Il supporto di Python 3.6 è terminato. N/D N/D

Verificare le dipendenze del pacchetto

I pacchetti dipendenti più rilevanti per il pacchetto server azureml-inference-server-http includono:

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

Se è stato specificato il pacchetto azureml-defaults nell'ambiente Python, il pacchetto azureml-inference-server-http è un pacchetto dipendente. La dipendenza viene installata automaticamente.

Suggerimento

Se si usa Python SDK v1 e non si specifica in modo esplicito il pacchetto azureml-defaults nell'ambiente Python, l'SDK potrebbe aggiungere automaticamente il pacchetto. Tuttavia, la versione dello strumento per la creazione di pacchetti è bloccata rispetto alla versione dell'SDK. Ad esempio, se la versione dell'SDK è 1.38.0, la voce azureml-defaults==1.38.0 viene aggiunta ai requisiti pip dell'ambiente.

TypeError durante l'avvio del server

Durante l'avvio del server potrebbe verificarsi l'errore TypeError seguente:

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

Questo errore si verifica quando Flask 2 è installato nell'ambiente Python, ma la versione del pacchetto azureml-inference-server-http non supporta Flask 2. Il supporto per Flask 2 è disponibile nel pacchetto azureml-inference-server-http versione 0.7.0 e successive e nel pacchetto azureml-defaults versione 1.44 e successive.

  • Se non si usa il pacchetto Flask 2 in un'immagine Docker di Azure Machine Learning, usare la versione più recente del pacchetto azureml-inference-server-http o azureml-defaults

  • Se si usa il pacchetto Flask 2 in un'immagine Docker di Azure Machine Learning, assicurarsi che la versione della build dell'immagine sia luglio 2022 o successiva.

    È possibile trovare la versione dell'immagine nei log del contenitore. Ad esempio:

    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 | 
    

    La data di compilazione dell'immagine viene visualizzata dopo la notazione Materialization Build. Nell'esempio precedente la versione dell'immagine è 20220708 o 8 luglio 2022. L'immagine in questo esempio è compatibile con Flask 2.

    Se nel log del contenitore non viene visualizzato un messaggio simile, l'immagine non è aggiornata e deve essere aggiornata. Se si usa un'immagine Compute Unified Device Architecture (CUDA) e non è possibile trovare un'immagine più recente, verificare se l'immagine è deprecata in AzureML-Containers. È possibile trovare sostituzioni designate per le immagini deprecate.

    Se si usa il server con un endpoint online, è anche possibile trovare i log in Log nella pagina Endpoint nello studio di Azure Machine Learning.

Se si esegue la distribuzione con SDK v1 e non si specifica in modo esplicito un'immagine nella configurazione della distribuzione, il server applica il pacchetto openmpi4.1.0-ubuntu20.04 con una versione corrispondente al set di strumenti dell'SDK locale. Tuttavia, la versione installata potrebbe non essere la versione più recente disponibile dell'immagine.

Per SDK versione 1.43, il server installa la versione del pacchetto openmpi4.1.0-ubuntu20.04:20220616 per impostazione predefinita, ma questa versione del pacchetto non è compatibile con SDK 1.43. Assicurarsi di usare l'SDK più recente per la distribuzione.

Se non è possibile aggiornare l'immagine, è possibile evitare temporaneamente il problema aggiungendo le voci azureml-defaults==1.43 o azureml-inference-server-http~=0.4.13 nel file di ambiente. Queste voci indirizzano il server a installare la versione precedente con flask 1.0.x.

ImportError o ModuleNotFoundError durante l'avvio del server

È possibile che si verifichi un errore ImportError o ModuleNotFoundError in moduli specifici, tra cui opencensus, jinja2, markupsafe o click, durante l'avvio del server. L'esempio seguente mostra il messaggio di errore:

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

Gli errori di importazione e del modulo si verificano quando si usa la versione 0.4.10 o versioni precedenti del server che non consentono di aggiungere la dipendenza Flask a una versione compatibile. Per evitare il problema, installare una versione successiva del server.