API RESTful

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

En plus des API GRPC tensorflow ModelServer prend également en charge les API RESTful. Cette page décrit ces points d'extrémité API et un bout en bout par exemple sur l' utilisation.

La demande et la réponse sont un objet JSON. La composition de cet objet dépend du type de requête ou du verbe. Voir les sections spécifiques à l'API ci-dessous pour plus de détails.

En cas d'erreur, toutes les API renvoient un objet JSON dans le corps de réponse avec error comme la clé et le message d'erreur comme la valeur:

{
  "error": <error message string>
}

API d'état du modèle

Cette API suit de près l' ModelService.GetModelStatus API GRPC. Il renvoie l'état d'un modèle dans le ModelServer.

URL

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

Y compris /versions/${VERSION} ou /labels/${LABEL} est facultative. En cas d'omission, le statut de toutes les versions est renvoyé dans la réponse.

Format de réponse

En cas de succès, retourne une représentation JSON de GetModelStatusResponse protobuf.

API de métadonnées de modèle

Cette API suit de près l' PredictionService.GetModelMetadata API GRPC. Il renvoie les métadonnées d'un modèle dans le ModelServer.

URL

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

Y compris /versions/${VERSION} ou /labels/${LABEL} est facultative. En cas d'omission, les métadonnées de modèle pour la dernière version sont renvoyées dans la réponse.

Format de réponse

En cas de succès, retourne une représentation JSON de GetModelMetadataResponse protobuf.

API de classification et de régression

Cette API suit de près les Classify et Regress méthodes de PredictionService API GRPC.

URL

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

Y compris /versions/${VERSION} ou /labels/${LABEL} est facultative. En cas d'omission, la dernière version est utilisée.

Format de la demande

Le corps de la demande pour les classify et regress API doit être un objet JSON formaté comme suit:

{
  // 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> est un numéro de JSON (entier ou décimal), chaîne JSON, ou un objet JSON qui représente des données binaires (voir les valeurs binaires d' encodage section ci - dessous pour les détails). <list> est une liste de ces valeurs. Ce format est similaire à de GRPC ClassificationRequest et RegressionRequest les Protos. Les deux versions acceptent la liste des Example de objets.

Format de réponse

A classify demande retourne un objet JSON dans le corps de la réponse formatée comme suit:

{
  "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> est une chaîne (qui peut être une chaîne vide "" si le modèle ne dispose pas d' une étiquette associée à la partition). <score> est un nombre décimal (virgule flottante).

La regress requête retourne un objet JSON dans le corps de la réponse formatée comme suit:

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

<value> est un nombre décimal.

Les utilisateurs de l' API GRPC remarquerez la similitude de ce format avec ClassificationResponse et RegressionResponse Protos.

API de prédiction

Cette API suit de près l' PredictionService.Predict API GRPC.

URL

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

Y compris /versions/${VERSION} ou /labels/${LABEL} est facultative. En cas d'omission, la dernière version est utilisée.

Format de la demande

Le corps de demande de predict l' API doit être objet JSON formaté comme suit:

{
  // (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>
}

Spécification des tenseurs d'entrée au format de ligne.

Ce format est similaire à PredictRequest proto de l' API GRPC et CMLE prédire API . Utilisez ce format si tous les tenseurs d'entrée nommés ont la même dimension 0-ème. Si ce n'est pas le cas, utilisez le format en colonnes décrit plus loin ci-dessous.

Dans le format de ligne, les entrées sont calées à des instances clé dans la demande JSON.

Quand il n'y a qu'une seule entrée nommée, spécifiez la valeur des instances clés pour la valeur de l'entrée:

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

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

Les tenseurs sont exprimés naturellement en notation imbriquée puisqu'il n'est pas nécessaire d'aplatir manuellement la liste.

Pour plusieurs entrées nommées, chaque élément doit être un objet contenant une paire nom d'entrée/valeur de tenseur, un pour chaque entrée nommée. À titre d'exemple, voici une requête avec deux instances, chacune avec un ensemble de trois tenseurs d'entrée nommés :

{
 "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]]
   }
 ]
}

Remarque, chaque entrée nommée ( « tag », « capteur » « signal ») est supposé implicitement avoir la même dimension 0-ème (deux dans l' exemple ci - dessus, il y a deux objets dans la liste des cas). Si vous avez nommé des entrées qui ont une dimension 0 différente, utilisez le format en colonnes décrit ci-dessous.

Spécification des tenseurs d'entrée au format colonne.

Utilisez ce format pour spécifier vos tenseurs d'entrée, si les entrées nommées individuelles n'ont pas la même dimension 0 ou si vous souhaitez une représentation plus compacte. Ce format est similaire à inputs domaine de la GRPC Predict demande.

Dans le format colonnaire, les entrées sont calées aux entrées clé dans la demande JSON.

La valeur de clé entrées peut soit un tenseur d'entrée unique ou une carte du nom d'entrée tenseurs ( voir la liste dans leur forme naturelle imbriquée). Chaque entrée peut avoir une forme arbitraire et n'a pas besoin de partager la même dimension 0 (c'est-à-dire la taille du lot) comme requis par le format de ligne décrit ci-dessus.

La représentation en colonnes de l'exemple précédent est la suivante :

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

Remarque, les entrées est un objet JSON et non une liste comme des cas (utilisé dans la représentation de la ligne). De plus, toutes les entrées nommées sont spécifiées ensemble, au lieu de les dérouler dans des lignes individuelles dans le format de ligne décrit précédemment. Cela rend la représentation compacte (mais peut-être moins lisible).

Format de réponse

La predict demande renvoie un objet JSON dans le corps de réponse.

Une demande en format de ligne a réponse formatée comme suit:

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

Si la sortie du modèle ne contient qu'un seul tenseur nommé, nous omettons le nom et les predictions clés des cartes à une liste de valeurs scalaires ou liste. Si le modèle génère plusieurs tenseurs nommés, nous affichons à la place une liste d'objets, similaire à la requête au format de ligne mentionnée ci-dessus.

Une demande en format colonnade a réponse formatée comme suit:

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

Si la sortie du modèle ne contient qu'un seul tenseur nommé, nous omettons le nom et les outputs clé cartes à une liste de valeurs scalaires ou liste. Si le modèle génère plusieurs tenseurs nommés, nous générons un objet à la place. Chaque clé de cet objet correspond à un tenseur de sortie nommé. Le format est similaire à la demande en format colonne mentionnée ci-dessus.

Sortie de valeurs binaires

TensorFlow ne fait pas la distinction entre les chaînes non binaires et binaires. Tous sont DT_STRING de type. Nommés tenseurs qui ont _bytes comme suffixe à leur nom sont considérés comme des valeurs binaires. De telles valeurs sont codées différemment , comme décrit dans le codage des valeurs binaires section ci - dessous.

Mappage JSON

Les API RESTful prennent en charge un encodage canonique en JSON, ce qui facilite le partage de données entre les systèmes. Pour les types pris en charge, les codages sont décrits type par type dans le tableau ci-dessous. Les types non répertoriés ci-dessous sont implicitement non pris en charge.

Type de données TF Valeur JSON Exemple JSON Remarques
DT_BOOL vrai faux vrai faux
DT_STRING chaîne de caractères "Bonjour le monde!" Si DT_STRING représente octets binaires (par exemple octets d'images en série ou en protobuf), encode en base64 ceux - ci. Voir codage des valeurs binaires pour plus d' informations.
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 numéro 1100 La valeur JSON sera un nombre décimal.
DT_FLOTTEUR, DT_DOUBLE numéro 1.1, -10,0, 0, NaN , Infinity Valeur JSON sera un numéro ou une des valeurs symboliques spéciales - NaN , Infinity et -Infinity . Voir conformité JSON pour plus d' informations. La notation d'exposant est également acceptée.

Précision à virgule flottante

JSON a un type de données numérique unique. Ainsi, il est possible de fournir une valeur pour une entrée qui entraîne une perte de précision. Par exemple, si l'entrée x est un float type de données, et l'entrée {"x": 1435774380} est envoyé au modèle en cours d' exécution sur le matériel basé sur la norme de virgule flottante IEEE 754 (par exemple Intel ou AMD), la valeur être converti en silence par le matériel à Sous - jacent 1435774336 depuis 1435774380 ne peut pas être exactement représenté dans un nombre à virgule flottante 32 bits. En règle générale, les entrées à diffuser doivent avoir la même distribution que l'entraînement. Cela ne posera donc généralement pas de problème, car les mêmes conversions se sont produites au moment de l'entraînement. Cependant, si une précision totale est nécessaire, veillez à utiliser un type de données sous-jacent dans votre modèle qui peut gérer la précision souhaitée et/ou envisager une vérification côté client.

Encodage des valeurs binaires

JSON utilise l'encodage UTF-8. Si vous avez des valeurs caractéristiques d' entrée ou tenseur qui ont besoin d'être binaire (comme octets image), vous devez base64 encoder les données et l' encapsuler dans un objet JSON ayant b64 comme la clé de la manière suivante:

{ "b64": <base64 encoded string> }

Vous pouvez spécifier cet objet comme valeur pour une entité ou un tenseur en entrée. Le même format est également utilisé pour coder la réponse de sortie.

Une demande de classification de l' image (données binaires) et caption caractéristiques est représentée ci - dessous:

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

Conformité JSON

De nombreuses valeurs de caractéristiques ou de tenseurs sont des nombres à virgule flottante. En dehors des valeurs finies (par exemple 3,14, 1,0 , etc.) ceux - ci peuvent avoir NaN et non finis ( Infinity et -Infinity valeurs). Malheureusement , la spécification JSON ( RFC 7 159 ) ne reconnaît pas ces valeurs (bien que la spécification JavaScript fait).

L'API REST décrite sur cette page permet aux objets JSON de requête/réponse d'avoir de telles valeurs. Cela implique que des requêtes comme la suivante sont valides :

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

Une des normes (strictes) analyseur de JSON compatible rejettera cela avec une erreur d'analyse ( en raison de NaN et Infinity jetons mélangés avec des chiffres réels). Pour gérer correctement les demandes/réponses dans votre code, utilisez un analyseur JSON qui prend en charge ces jetons.

NaN , Infinity , -Infinity jetons sont reconnus par proto3 , Python JSON module et le langage JavaScript.

Exemple

Nous pouvons utiliser le jouet half_plus_three modèle pour voir API REST en action.

Démarrez ModelServer avec le point de terminaison de l'API REST

Télécharger le half_plus_three modèle de référentiel git :

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

Nous utiliserons Docker pour exécuter le ModelServer. Si vous souhaitez installer ModelServer nativement sur votre système, suivez les instructions d'installation pour installer à la place, et démarrer le ModelServer avec --rest_api_port option pour l' exportation de point final API REST (ce n'est pas nécessaire lors de l' utilisation 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 ...

Faire des appels d'API REST à ModelServer

Dans un autre terminal, utilisez la curl outil pour faire des appels API REST.

Obtenez le statut du modèle comme suit :

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

Un predict appel se présente comme suit:

$ 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]
}

Et un regress des regards d'appel suit comme:

$ 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]
}

Remarque, regress est disponible sur un nom de signature non par défaut et doit être spécifié explicitement. Une URL ou un corps de requête incorrect renvoie un état d'erreur 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)" }
$