Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

API RESTful

Oltre alle API gRPC, TensorFlow ModelServer supporta anche API RESTful. Questa pagina descrive questi endpoint API e un end-to-end esempio consumato.

La richiesta e la risposta sono un oggetto JSON. La composizione di questo oggetto dipende dal tipo di richiesta o dal verbo. Vedere le sezioni specifiche dell'API di seguito per i dettagli.

In caso di errore, tutte le API restituiranno un oggetto JSON nel corpo della risposta con error come chiave e il messaggio di errore come valore:

{
  "error": <error message string>
}

API dello stato del modello

Questa API segue da vicino l'API ModelService.GetModelStatus ModelService.GetModelStatus. Restituisce lo stato di un modello nel ModelServer.

URL

GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]

L'inclusione di /versions/${VERSION} o /labels/${LABEL} è facoltativa. Se lo stato omesso per tutte le versioni viene restituito nella risposta.

Formato della risposta

In caso di esito positivo, restituisce una rappresentazione JSON del GetModelStatusResponse GetModelStatusResponse.

Model Metadata API

Questa API segue da vicino l'API gRPC PredictionService.GetModelMetadata . Restituisce i metadati di un modello nel ModelServer.

URL

GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]/metadata

L'inclusione di /versions/${VERSION} o /labels/${LABEL} è facoltativa. Se omessi, i metadati del modello per l'ultima versione vengono restituiti nella risposta.

Formato della risposta

In caso di esito positivo, restituisce una rappresentazione JSON del GetModelMetadataResponse GetModelMetadataResponse.

Classify and Regress API

Questa API segue da vicino i metodi Classify e Regress dell'API gRPC PredictionService .

URL

POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:(classify|regress)

L'inclusione di /versions/${VERSION} o /labels/${LABEL} è facoltativa. Se omesso viene utilizzata l'ultima versione.

Formato richiesta

Il corpo della richiesta per le classify e regress API deve essere un oggetto JSON formattato come segue:

{
  // Optional: serving signature to use.
  // If unspecifed default serving signature is used.
  "signature_name": <string>,

  // Optional: Common context shared by all examples.
  // Features that appear here MUST NOT appear in examples (below).
  "context": {
    "<feature_name3>": <value>|<list>
    "<feature_name4>": <value>|<list>
  },

  // List of Example objects
  "examples": [
    {
      // Example 1
      "<feature_name1>": <value>|<list>,
      "<feature_name2>": <value>|<list>,
      ...
    },
    {
      // Example 2
      "<feature_name1>": <value>|<list>,
      "<feature_name2>": <value>|<list>,
      ...
    }
    ...
  ]
}

<value> è un numero JSON (intero o decimale) o una stringa e <list> è un elenco di tali valori. Vedere la sezione Codifica di valori binari di seguito per i dettagli su come rappresentare un valore binario (flusso di byte). Questo formato è simile ai protos ClassificationRequest e RegressionRequest gRPC. Entrambe le versioni accettano un elenco di oggetti di Example .

Formato della risposta

Una richiesta di classify restituisce un oggetto JSON nel corpo della risposta, formattato come segue:

{
  "result": [
    // List of class label/score pairs for first Example (in request)
    [ [<label1>, <score1>], [<label2>, <score2>], ... ],

    // List of class label/score pairs for next Example (in request)
    [ [<label1>, <score1>], [<label2>, <score2>], ... ],
    ...
  ]
}

<label> è una stringa (che può essere una stringa vuota "" se il modello non ha un'etichetta associata al punteggio). <score> è un numero decimale (virgola mobile).

La richiesta di regress restituisce un oggetto JSON nel corpo della risposta, formattato come segue:

{
  // One regression value for each example in the request in the same order.
  "result": [ <value1>, <value2>, <value3>, ...]
}

<value> è un numero decimale.

Gli utenti dell'API gRPC noteranno la somiglianza di questo formato con i protos ClassificationResponse e RegressionResponse .

Predict API

Questa API segue da vicino l'API gRPC PredictionService.Predict .

URL

POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:predict

L'inclusione di /versions/${VERSION} o /labels/${LABEL} è facoltativa. Se omesso viene utilizzata l'ultima versione.

Formato richiesta

Il corpo della richiesta per l'API di predict deve essere formattato come oggetto JSON come segue:

{
  // (Optional) Serving signature to use.
  // If unspecifed default serving signature is used.
  "signature_name": <string>,

  // Input Tensors in row ("instances") or columnar ("inputs") format.
  // A request can have either of them but NOT both.
  "instances": <value>|<(nested)list>|<list-of-objects>
  "inputs": <value>|<(nested)list>|<object>
}

Specifica dei tensori di input in formato riga.

Questo formato è simile al PredictRequest PredictRequest dell'API gRPC e all'API di previsione CMLE . Utilizzare questo formato se tutti i tensori di input denominati hanno la stessa dimensione 0 . In caso contrario, utilizza il formato a colonne descritto di seguito.

Nel formato riga, gli input vengono codificati nella chiave delle istanze nella richiesta JSON.

Quando è presente un solo input denominato, specificare il valore della chiave dell'istanza come valore dell'input:

{
  // List of 3 scalar tensors.
  "instances": [ "foo", "bar", "baz" ]
}

{
  // List of 2 tensors each of [1, 2] shape
  "instances": [ [[1, 2]], [[3, 4]] ]
}

I tensori sono espressi naturalmente in notazioni annidate poiché non è necessario appiattire manualmente l'elenco.

Per più input denominati, ogni elemento dovrebbe essere un oggetto contenente la coppia nome input / valore tensore, uno per ogni input denominato. Ad esempio, la seguente è una richiesta con due istanze, ciascuna con un set di tre tensori di input denominati:

{
 "instances": [
   {
     "tag": "foo",
     "signal": [1, 2, 3, 4, 5],
     "sensor": [[1, 2], [3, 4]]
   },
   {
     "tag": "bar",
     "signal": [3, 4, 1, 2, 5]],
     "sensor": [[4, 5], [6, 8]]
   }
 ]
}

Nota, si presume implicitamente che ogni ingresso denominato ("tag", "segnale", "sensore") abbia la stessa dimensione 0 ( due nell'esempio precedente, poiché ci sono due oggetti nell'elenco delle istanze ). Se sono stati denominati input che hanno una dimensione 0-esima diversa, utilizzare il formato a colonne descritto di seguito.

Specifica dei tensori di input in formato colonna.

Utilizzare questo formato per specificare i tensori di input, se i singoli input con nome non hanno la stessa dimensione 0 o si desidera una rappresentazione più compatta. Questo formato è simile al campo di inputs della richiesta gRPC Predict .

Nel formato a colonne, gli input sono codificati nella chiave di input nella richiesta JSON.

Il valore per la chiave di input può essere un singolo tensore di input o una mappa del nome di input per i tensori (elencati nella loro forma nidificata naturale). Ogni input può avere una forma arbitraria e non è necessario condividere la stessa dimensione 0-esima (ovvero la dimensione del batch) come richiesto dal formato di riga descritto sopra.

La rappresentazione a colonne dell'esempio precedente è la seguente:

{
 "inputs": {
   "tag": ["foo", "bar"],
   "signal": [[1, 2, 3, 4, 5], [3, 4, 1, 2, 5]],
   "sensor": [[[1, 2], [3, 4]], [[4, 5], [6, 8]]]
 }
}

Nota, gli input sono un oggetto JSON e non un elenco come istanze (utilizzato nella rappresentazione di riga). Inoltre, tutti gli input denominati vengono specificati insieme, invece di srotolarli in singole righe nel formato di riga descritto in precedenza. Questo rende la rappresentazione compatta (ma forse meno leggibile).

Formato della risposta

La richiesta di predict restituisce un oggetto JSON nel corpo della risposta.

Una richiesta in formato riga ha la risposta formattata come segue:

{
  "predictions": <value>|<(nested)list>|<list-of-objects>
}

Se l'output del modello contiene un solo tensore denominato, omettiamo il nome e la chiave delle predictions mappati a un elenco di valori scalari o di elenco. Se il modello restituisce più tensori denominati, restituiamo invece un elenco di oggetti, simile alla richiesta in formato riga menzionata sopra.

Una richiesta in formato colonnare ha la risposta formattata come segue:

{
  "outputs": <value>|<(nested)list>|<object>
}

Se l'output del modello contiene un solo tensore denominato, omettiamo il nome e outputs le mappe chiave a un elenco di valori scalari o di elenco. Se il modello restituisce più tensori denominati, viene invece restituito un oggetto. Ogni chiave di questo oggetto corrisponde a un tensore di output denominato. Il formato è simile alla richiesta in formato colonna menzionata sopra.

Output di valori binari

TensorFlow non distingue tra stringhe non binarie e binarie. Tutti sono di tipo DT_STRING . I tensori denominati che hanno _bytes come suffisso nel loro nome sono considerati avere valori binari. Tali valori sono codificati in modo diverso come descritto nella sezione relativa alla codifica dei valori binari di seguito.

Mappatura JSON

Le API RESTful supportano una codifica canonica in JSON, semplificando la condivisione dei dati tra i sistemi. Per i tipi supportati, le codifiche sono descritte tipo per tipo nella tabella seguente. Si presume che i tipi non elencati di seguito non siano supportati.

Tipo di dati TF Valore JSON Esempio JSON Appunti
DT_BOOL vero falso vero falso
DT_STRING corda "Ciao mondo!" Se DT_STRING rappresenta byte binari (ad es. Byte immagine serializzati o protobuf), codificali in Base64. Per ulteriori informazioni, vedere Codifica di valori binari .
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 numero 1, -10, 0 Il valore JSON sarà un numero decimale.
DT_FLOAT, DT_DOUBLE numero 1.1, -10.0, 0, NaN , Infinity Il valore JSON sarà un numero o uno dei valori speciali del token: NaN , Infinity e -Infinity . Vedi Conformità JSON per maggiori informazioni. È accettata anche la notazione esponente.

Codifica di valori binari

JSON utilizza la codifica UTF-8. Se hai una funzione di input o valori tensoriali che devono essere binari (come i byte dell'immagine), devi codificare i dati in Base64 e incapsularli in un oggetto JSON con b64 come chiave come segue:

{ "b64": <base64 encoded string> }

È possibile specificare questo oggetto come valore per una funzione di input o un tensore. Lo stesso formato viene utilizzato anche per codificare la risposta di output.

Di seguito viene mostrata una richiesta di classificazione con image (dati binari) e caption :

{
  "signature_name": "classify_objects",
  "examples": [
    {
      "image": { "b64": "aW1hZ2UgYnl0ZXM=" },
      "caption": "seaside"
    },
    {
      "image": { "b64": "YXdlc29tZSBpbWFnZSBieXRlcw==" },
      "caption": "mountains"
    }
  ]
}

Conformità JSON

Molti valori di caratteristiche o tensori sono numeri in virgola mobile. A parte i valori finiti (es. 3.14, 1.0 ecc.) Questi possono avere valori NaN e non finiti ( Infinity e -Infinity ). Sfortunatamente la specifica JSON ( RFC 7159 ) NON riconosce questi valori (sebbene la specifica JavaScript lo faccia).

L'API REST descritta in questa pagina consente agli oggetti JSON di richiesta / risposta di avere tali valori. Ciò implica che le richieste come la seguente sono valide:

{
  "example": [
    {
      "sensor_readings": [ 1.0, -3.14, Nan, Infinity ]
    }
  ]
}

Un parser JSON conforme agli standard (rigorosi) lo rifiuterà con un errore di analisi (a causa di token NaN e Infinity mescolati con numeri effettivi). Per gestire correttamente le richieste / risposte nel codice, utilizza un parser JSON che supporti questi token.

-Infinity token NaN , Infinity , -Infinity sono riconosciuti da proto3 , dal modulo Python JSON e dal linguaggio JavaScript.

Esempio

Possiamo usare il modello giocattolo half_plus_three per vedere le API REST in azione.

Avvia ModelServer con l'endpoint dell'API REST

Scarica il modello half_plus_three dal repository git :

$ mkdir -p /tmp/tfserving
$ cd /tmp/tfserving
$ git clone --depth=1 https://github.com/tensorflow/serving

Useremo Docker per eseguire ModelServer. Se desideri installare ModelServer in modo nativo sul tuo sistema, segui le istruzioni di configurazione per installare invece e avvia ModelServer con --rest_api_port opzione --rest_api_port per esportare l'endpoint dell'API REST (non è necessario quando si utilizza Docker).

$ cd /tmp/tfserving
$ docker pull tensorflow/serving:latest
$ docker run --rm -p 8501:8501 \
    --mount type=bind,source=$(pwd),target=$(pwd) \
    -e MODEL_BASE_PATH=$(pwd)/serving/tensorflow_serving/servables/tensorflow/testdata \
    -e MODEL_NAME=saved_model_half_plus_three -t tensorflow/serving:latest
...
.... Exporting HTTP/REST API at:localhost:8501 ...

Effettua chiamate API REST a ModelServer

In un terminale diverso, utilizza lo strumento curl per effettuare chiamate API REST.

Ottieni lo stato del modello come segue:

$ curl http://localhost:8501/v1/models/saved_model_half_plus_three
{
 "model_version_status": [
  {
   "version": "123",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}

Una chiamata di predict avrebbe il seguente aspetto:

$ curl -d '{"instances": [1.0,2.0,5.0]}' -X POST http://localhost:8501/v1/models/saved_model_half_plus_three:predict
{
    "predictions": [3.5, 4.0, 5.5]
}

E una chiamata di regress il seguente aspetto:

$ curl -d '{"signature_name": "tensorflow/serving/regress", "examples": [{"x": 1.0}, {"x": 2.0}]}' \
  -X POST http://localhost:8501/v1/models/saved_model_half_plus_three:regress
{
    "results": [3.5, 4.0]
}

Nota, regress è disponibile con un nome di firma non predefinito e deve essere specificato in modo esplicito. Un URL o un corpo della richiesta errato restituisce uno stato di errore HTTP.

$ curl -i -d '{"instances": [1.0,5.0]}' -X POST http://localhost:8501/v1/models/half:predict
HTTP/1.1 404 Not Found
Content-Type: application/json
Date: Wed, 06 Jun 2018 23:20:12 GMT
Content-Length: 65

{ "error": "Servable not found for request: Latest(half)" }
$