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:
- Il server HTTP di inferenza di Azure Machine Learning
- Un endpoint locale
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 | Sì | No |
Aggiornare lo script di assegnazione dei punteggi | Sì | Sì |
Aggiornare le configurazioni di distribuzione (distribuzione, ambiente, codice, modello) | No | Sì |
Integrare il debugger di Microsoft Visual Studio Code (VS Code) | Sì | Sì |
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
Creare una directory denominata server_quickstart in cui inserire i file:
mkdir server_quickstart cd server_quickstart
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.Installare il pacchetto
azureml-inference-server-http
dal feed pypi:python -m pip install azureml-inference-server-http
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
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.
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!"}
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:
Avviare VS Code e aprire la cartella contenente lo script (score.py).
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" ] } ] }
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 comandosudo apt-get install -y gdb
.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 } ] }
In una finestra di comando avviare il server HTTP di inferenza usando il comando
azmlinfsrv --entry_script score.py
.Avviare la sessione di debug in VS Code:
Selezionare Esegui>Avvia debug o usare il tasto di scelta rapida F5.
Nella finestra di comando visualizzare i log dal server di inferenza e individuare l'ID processo del comando
azmlinfsrv
(non ilgunicorn
):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.
Clonare il repository di esempio:
git clone --depth 1 https://github.com/Azure/azureml-examples cd azureml-examples/cli/endpoints/online/model-1/
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 pacchettoazureml-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
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()
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 variabileAZUREML_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.
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:
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.
Un client invia una richiesta al server.
Il server invia la richiesta tramite il server Web Server Gateway Interface (WSGI), che invia la richiesta a un'app ruolo di lavoro Flask:
L'app ruolo di lavoro Flask gestisce la richiesta, che include il caricamento dello script di immissione e le eventuali dipendenze.
Lo script di immissione riceve la richiesta. Lo script di immissione esegue una chiamata di inferenza al modello caricato e restituisce una risposta:
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 esempioE
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.
Raccogliere informazioni su pacchetti e versioni installati per l'ambiente Python.
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.Se si specifica Flask o le relative dipendenze nell'ambiente, rimuovere questi elementi.
- I pacchetti dipendenti includono
flask
,jinja2
itsdangerous
,werkzeug
,markupsafe
, eclick
. flask
è elencato come dipendenza nel pacchetto del server. L'approccio migliore consiste nel consentire al server di inferenza di installare il pacchettoflask
.- 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.
- I pacchetti dipendenti includono
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
oazureml-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.