API RESTful

Além gRPC APIs TensorFlow ModelServer também suporta APIs RESTful. Esta página descreve estes parâmetros API e um fim-de-final exemplo do uso.

A solicitação e a resposta são um objeto JSON. A composição deste objeto depende do tipo de solicitação ou verbo. Consulte as seções específicas da API abaixo para obter detalhes.

Em caso de erro, todas as APIs irá retornar um objeto JSON no corpo da resposta com error como chave ea mensagem de erro como o valor:

{
  "error": <error message string>
}

API de status do modelo

Esta API segue de perto a ModelService.GetModelStatus API gRPC. Ele retorna o status de um modelo no ModelServer.

URL

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

Incluindo /versions/${VERSION} ou /labels/${LABEL} é opcional. Se o status omitido para todas as versões for retornado na resposta.

Formato de resposta

Se for bem sucedido, retorna uma representação JSON de GetModelStatusResponse protobuf.

API de metadados de modelo

Esta API segue de perto a PredictionService.GetModelMetadata API gRPC. Ele retorna os metadados de um modelo no ModelServer.

URL

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

Incluindo /versions/${VERSION} ou /labels/${LABEL} é opcional. Se omitidos, os metadados do modelo para a versão mais recente são retornados na resposta.

Formato de resposta

Se for bem sucedido, retorna uma representação JSON de GetModelMetadataResponse protobuf.

Classificar e regredir API

Esta API segue de perto os Classify e Regress métodos de PredictionService gRPC API.

URL

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

Incluindo /versions/${VERSION} ou /labels/${LABEL} é opcional. Se omitido, a versão mais recente é usada.

Formato de solicitação

O corpo da solicitação para os classify e regress APIs deve ser um objeto JSON formatado como se 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> é um número JSON (inteiro ou decimal), string JSON, ou um objeto JSON que representa dados binários (ver a valores binária Codificação seção abaixo para detalhes). <list> é uma lista de tais valores. Este formato é semelhante ao do gRPC ClassificationRequest e RegressionRequest protos. Ambas as versões lista de aceitar Example objetos.

Formato de resposta

Um classify pedido devolve um objecto JSON no corpo da resposta, formatado como se 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> é uma string (que pode ser uma cadeia vazia "" se o modelo não tem um rótulo associado à pontuação). <score> é um número decimal (ponto flutuante).

A regress pedido devolve um objecto JSON no corpo da resposta, formatado como se segue:

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

<value> é um número decimal.

Usuários de gRPC API vai notar a semelhança deste formato com ClassificationResponse e RegressionResponse protos.

API de previsão

Esta API segue de perto a PredictionService.Predict API gRPC.

URL

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

Incluindo /versions/${VERSION} ou /labels/${LABEL} é opcional. Se omitido, a versão mais recente é usada.

Formato de solicitação

O corpo da solicitação para predict API deve ser objeto JSON formatado como 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>
}

Especificando tensores de entrada em formato de linha.

Este formato é semelhante ao PredictRequest proto de gRPC API eo CMLE prever API . Utilize este formato se todos os tensores de entrada nomeados têm o mesmo 0-th dimensão. Caso contrário, use o formato colunar descrito mais adiante.

No formato de linha, entradas têm formatos especiais para chave de casos no pedido JSON.

Quando há apenas uma entrada nomeada, especifique o valor de instâncias chave para ser o valor da entrada:

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

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

Os tensores são expressos naturalmente em notação aninhada, pois não há necessidade de achatar manualmente a lista.

Para várias entradas nomeadas, espera-se que cada item seja um objeto contendo o par nome de entrada/valor do tensor, um para cada entrada nomeada. Como exemplo, a seguir está uma solicitação com duas instâncias, cada uma com um conjunto de três tensores de entrada nomeados:

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

Note-se, cada entrada de chamada ( "tag", "sinal", "sensor") é assumida implicitamente têm mesmo 0-th dimensão (duas no exemplo acima, uma vez que existem dois objectos na lista de exemplos). Se você nomeou entradas com dimensão 0 diferente, use o formato colunar descrito abaixo.

Especificando tensores de entrada em formato de coluna.

Use este formato para especificar seus tensores de entrada, se as entradas nomeadas individuais não tiverem a mesma dimensão 0 ou você quiser uma representação mais compacta. Este formato é semelhante ao inputs campo do gRPC Predict pedido.

No formato de colunas, as entradas têm formatos especiais para entradas de chave no pedido JSON.

O valor de chave entradas podem quer um único tensor de entrada ou um mapa de entrada de nome tensores (listadas na sua forma aninhada natural). Cada entrada pode ter uma forma arbitrária e não precisa compartilhar a mesma dimensão 0 (também conhecida como tamanho do lote) conforme exigido pelo formato de linha descrito acima.

A representação colunar do exemplo anterior é a seguinte:

{
 "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, entradas é um objecto JSON e não como uma lista de ocorrências (usado na representação de linha). Além disso, todas as entradas nomeadas são especificadas juntas, em vez de desenrolá-las em linhas individuais feitas no formato de linha descrito anteriormente. Isso torna a representação compacta (mas talvez menos legível).

Formato de resposta

A predict de solicitação retorna um objeto JSON no corpo da resposta.

Um pedido em formato de linha tem resposta formatado como segue:

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

Se a saída do modelo contém apenas um tensor chamado, omitimos o nome e predictions chave mapeia para uma lista de valores escalares ou lista. Se o modelo gerar vários tensores nomeados, geramos uma lista de objetos, semelhante à solicitação no formato de linha mencionado acima.

Um pedido em formato de colunas tem resposta formatado como segue:

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

Se a saída do modelo contém apenas um tensor chamado, omitimos o nome e outputs chave mapeia para uma lista de valores escalares ou lista. Se o modelo gerar vários tensores nomeados, em vez disso, geramos um objeto. Cada chave deste objeto corresponde a um tensor de saída nomeado. O formato é semelhante ao da solicitação em formato de coluna mencionado acima.

Saída de valores binários

O TensorFlow não faz distinção entre strings não binárias e binárias. Todos são DT_STRING tipo. Tensores nomeados que têm _bytes como um sufixo em seu nome são considerados como tendo valores binários. Tais valores são codificados de forma diferente, tal como descrito no codificando valores binários secção abaixo.

Mapeamento JSON

As APIs RESTful suportam uma codificação canônica em JSON, facilitando o compartilhamento de dados entre sistemas. Para tipos suportados, as codificações são descritas tipo por tipo na tabela abaixo. Tipos não listados abaixo estão implícitos como não suportados.

Tipo de dados TF Valor JSON Exemplo JSON Notas
DT_BOOL verdadeiro falso verdadeiro falso
DT_STRING corda "Olá Mundo!" Se DT_STRING representa bytes binárias (por exemplo, bytes de imagem serializados ou protobuf), codificam estes em base64. Veja Encoding valores binários para mais informações.
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 número 1, -10, 0 O valor JSON será um número decimal.
DT_FLOAT, DT_DOUBLE número 1.1, -10.0, 0, NaN , Infinity Valor JSON será um número ou um dos valores de token especiais - NaN , Infinity , e -Infinity . Veja JSON conformidade para mais informações. A notação de expoente também é aceita.

Precisão de ponto flutuante

JSON tem um único tipo de dados de número. Assim, é possível fornecer um valor para uma entrada que resulte em perda de precisão. Por exemplo, se a entrada x é um float tipo de dados, e a entrada {"x": 1435774380} é enviado para o modelo rodando em hardware baseado no IEEE 754 padrão de ponto flutuante (por exemplo, Intel ou AMD), então o valor será silenciosamente ser convertido pelo hardware underyling para 1435774336 desde 1435774380 não pode ser exactamente representados em um número de ponto flutuante de 32-bits. Normalmente, as entradas para veiculação devem ter a mesma distribuição do treinamento, portanto, isso geralmente não será problemático porque as mesmas conversões ocorreram no momento do treinamento. No entanto, caso seja necessária precisão total, certifique-se de usar um tipo de dados subjacente em seu modelo que possa lidar com a precisão desejada e/ou considere a verificação do lado do cliente.

Codificando valores binários

JSON usa codificação UTF-8. Se você tem valores de recurso ou tensores de entrada que precisam ser binário (como a imagem bytes), você deve Base64 codificar os dados e encapsulá-lo em um objeto JSON ter b64 como a chave da seguinte forma:

{ "b64": <base64 encoded string> }

Você pode especificar esse objeto como um valor para um recurso ou tensor de entrada. O mesmo formato também é usado para codificar a resposta de saída.

Um pedido de classificação com image (dados binários) e caption características é mostrado abaixo:

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

Conformidade JSON

Muitos valores de recurso ou tensor são números de ponto flutuante. Além de valores finitos (por exemplo, 3,14, 1,0, etc.) estes podem ter NaN e não-finito ( Infinity e -Infinity valores). Infelizmente a especificação JSON ( RFC 7159 ) não reconhece esses valores (embora a especificação JavaScript faz).

A API REST descrita nesta página permite que objetos JSON de solicitação/resposta tenham esses valores. Isso implica que solicitações como a seguinte são válidas:

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

Um (rigorosas) padrões JSON compatível analisador vai rejeitar este com um erro de análise (devido a NaN e Infinity fichas misturado com números reais). Para lidar corretamente com solicitações/respostas em seu código, use um analisador JSON que dê suporte a esses tokens.

NaN , Infinity , -Infinity símbolos são reconhecidos pelo proto3 , Python JSON módulo ea linguagem JavaScript.

Exemplo

Podemos usar o brinquedo half_plus_three modelo para ver APIs descanso em ação.

Inicie o ModelServer com o endpoint da API REST

Baixe o half_plus_three modelo de repositório git :

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

Usaremos o Docker para executar o ModelServer. Se você deseja instalar ModelServer nativamente em seu sistema, siga as instruções de configuração para instalar em vez disso, e iniciar o ModelServer com --rest_api_port opção de endpoint exportação API REST (isto não é necessário quando se utiliza 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 ...

Faça chamadas de API REST para ModelServer

Em um terminal diferente, use a curl ferramenta para fazer chamadas de API REST.

Obtenha o status do modelo da seguinte maneira:

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

A predict chamada ficaria da seguinte forma:

$ 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 uma regress de chamadas é o seguinte:

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

Note, regress está disponível em um nome de assinatura não-padrão e deve ser especificado explicitamente. Um URL ou corpo de solicitação incorreto retorna um status de erro 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)" }
$