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 è un oggetto JSON. La composizione di questo oggetto dipende dal tipo o dal verbo della richiesta. Vedi le sezioni specifiche 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 di stato del modello

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

URL

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

Includere /versions/${VERSION} o /labels/${LABEL} è facoltativo. Se lo stato omesso per tutte le versioni viene restituito nella risposta.

Formato di risposta

In caso di successo, restituisce una rappresentazione JSON del GetModelStatusResponse protobuf GetModelStatusResponse.

API dei metadati del modello

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

URL

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

Includere /versions/${VERSION} o /labels/${LABEL} è facoltativo. Se omesso, i metadati del modello per l'ultima versione vengono restituiti nella risposta.

Formato di risposta

Se ha esito positivo, restituisce una rappresentazione JSON del GetModelMetadataResponse protobuf GetModelMetadataResponse.

API Classify and Regress

Questa API segue da vicino le Classify e Regress metodi di PredictionService gRPC API.

URL

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

Includere /versions/${VERSION} o /labels/${LABEL} è facoltativo. Se omessa viene utilizzata l'ultima versione.

Formato richiesta

Il corpo della richiesta per le API di classify e regress 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 stringa e <list> è un elenco di tali valori. Vedere la sezione Codifica dei 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 Example .

Formato di 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 protocolli ClassificationResponse e RegressionResponse .

API Predict

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

URL

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

Includere /versions/${VERSION} o /labels/${LABEL} è facoltativo. Se omessa viene utilizzata l'ultima versione.

Formato richiesta

Il corpo della richiesta per l'API di predict deve essere formattato 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 dell'API di previsione CMLE . Utilizzare questo formato se tutti i tensori di input con nome hanno la stessa dimensione 0 . In caso contrario, utilizzare il formato colonnare descritto più avanti.

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

Quando esiste solo un input denominato, specificare il valore della chiave di istanze 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 notazione nidificata poiché non è necessario appiattire manualmente l'elenco.

Per più input nominati, ogni elemento dovrebbe essere un oggetto contenente nome input / coppia valore tensore, uno per ciascun 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]]
   }
 ]
}
 

Si noti che ogni input denominato ("tag", "signal", "sensor") è implicitamente assunto avere la stessa dimensione 0 ( due nell'esempio sopra, poiché ci sono due oggetti nell'elenco delle istanze ). Se sono stati denominati input con diversa dimensione 0, utilizzare il formato colonna descritto di seguito.

Specifica dei tensori di input in formato colonna.

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

Nel formato colonnare, gli input sono codificati nella chiave 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 0-dimensione (ovvero dimensione batch) come richiesto dal formato di riga sopra descritto.

La rappresentazione colonnare 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, input è un oggetto JSON e non un elenco come istanze (usato nella rappresentazione di riga). Inoltre, tutti gli input nominati vengono specificati insieme, anziché srotolarli in singole righe eseguite nel formato di riga descritto in precedenza. Questo rende la rappresentazione compatta (ma forse meno leggibile).

Formato di risposta

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

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

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

Se l'output del modello contiene solo un tensore con nome, omettiamo il nome e le predictions mappe chiave in un elenco di valori scalari o di elenco. Se il modello genera più tensori con nome, viene invece generato un elenco di oggetti, simile alla richiesta nel formato di riga sopra menzionato.

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

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

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

Uscita di valori binari

TensorFlow non distingue tra stringhe non binarie e binarie. Tutti sono di tipo DT_STRING . I tensori nominati 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. I tipi non elencati di seguito implicano che non sono 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 esempio byte di immagine serializzati o protobuf), codificarli in Base64. Vedi Codifica dei valori binari per maggiori informazioni.
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 token speciali: NaN , Infinity e -Infinity . Vedi conformità JSON per maggiori informazioni. Anche la notazione esponente è accettata.

Codifica di valori binari

JSON utilizza la codifica UTF-8. Se si dispone di valori di caratteristiche o tensore di input che devono essere binario (come immagine byte), è necessario Base64 codificare i dati e incapsulare in un oggetto JSON avente b64 come la chiave come segue:

 { "b64": <base64 encoded string> }
 

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

Di seguito è mostrata una richiesta di classificazione con funzioni di 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 funzionalità o tensore sono numeri in virgola mobile. Oltre ai valori finiti (ad 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 riconosca).

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 dei token NaN e Infinity mescolati con i numeri effettivi). Per gestire correttamente richieste / risposte nel codice, utilizzare un parser JSON che supporti questi token.

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

Esempio

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

Avviare 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 si desidera installare ModelServer in modo nativo sul proprio sistema, seguire invece le istruzioni di installazione per installare e avviare ModelServer con --rest_api_port opzione --rest_api_port per esportare l'endpoint API REST (questo 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 ...
 

Effettuare chiamate API REST a ModelServer

In un altro terminale, utilizzare lo strumento curl per effettuare chiamate all'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 predict dovrebbe apparire come segue:

 $ 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 presenta come segue:

 $ 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 su un nome di firma non predefinito e deve essere specificato esplicitamente. Un URL o un corpo di 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)" }
$