REST-API

В дополнении к КПГРАМ APIs TensorFlow ModelServer также поддерживает RESTful API. Эта страница описывает эти API конечные точки и конец в конец пример по использованию.

Запрос и ответ - это объект JSON. Состав этого объекта зависит от типа запроса или глагола. Подробности см. В разделах, посвященных конкретным API, ниже.

В случае ошибки, все интерфейсы будут возвращать объект JSON в теле ответа с error в качестве ключа и сообщений об ошибке в качестве значения:

{
  "error": <error message string>
}

API статуса модели

Этот API внимательно следит за ModelService.GetModelStatus API КПГР. Он возвращает статус модели на ModelServer.

URL

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

В том числе /versions/${VERSION} или /labels/${LABEL} не является обязательным. Если опущено, в ответе возвращается статус для всех версий.

Формат ответа

В случае успеха возвращает представление JSON из GetModelStatusResponse Protobuf.

API метаданных модели

Этот API внимательно следит за PredictionService.GetModelMetadata API КПГР. Он возвращает метаданные модели в ModelServer.

URL

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

В том числе /versions/${VERSION} или /labels/${LABEL} не является обязательным. Если опущено, в ответе возвращаются метаданные модели для последней версии.

Формат ответа

В случае успеха возвращает представление JSON из GetModelMetadataResponse Protobuf.

API классификации и регрессии

Этот API внимательно следит за Classify и Regress методы PredictionService КПГР API.

URL

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

В том числе /versions/${VERSION} или /labels/${LABEL} не является обязательным. Если не указано иное, используется последняя версия.

Формат запроса

Тело запроса для classify и regress API , должно быть объект JSON , отформатированный следующим образом :

{
  // 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> представляет собой число в формате JSON (целое или десятичное число), строка JSON или объект JSON , который представляет двоичные данные (см Кодирование двоичных значений раздел ниже). <list> список таких значений. Этот формат похож на КПГРЫ в ClassificationRequest и RegressionRequest Протос. Обе версии списка Example объектов.

Формат ответа

classify запрос возвращает объект JSON в теле ответа, в следующем формате:

{
  "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> является строкой (которая может быть пустой строкой "" , если модель не имеет метку , связанную со счетом). <score> является десятичной ( с плавающей точкой) числом.

regress запрос возвращает объект JSON в теле ответа, в следующем формате:

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

<value> является десятичным числом.

Пользователи КПГР API заметит сходство этого формата с ClassificationResponse и RegressionResponse Протос.

Прогнозирование API

Этот API внимательно следит за PredictionService.Predict API КПГР.

URL

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

В том числе /versions/${VERSION} или /labels/${LABEL} не является обязательным. Если не указано иное, используется последняя версия.

Формат запроса

Тело запрос predict API должен быть объект JSON в следующем формате:

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

Указание входных тензоров в строчном формате.

Этот формат похож на PredictRequest прото из КПГР API и CMLE предсказать API . Используйте этот формат , если все названные входные тензоры имеют одинаковый 0-го размера. В противном случае используйте столбчатый формат, описанный ниже.

В формате строки, входы сконструированы так, чтобы ключ экземпляров в запросе JSON.

Когда есть только один названный вход, указать значение экземпляров ключевых быть значением входного сигнала:

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

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

Тензоры естественным образом выражаются во вложенной нотации, поскольку нет необходимости вручную сглаживать список.

Для нескольких именованных входов каждый элемент должен быть объектом, содержащим пару имени входа / значения тензора, по одной для каждого именованного входа. В качестве примера ниже представлен запрос с двумя экземплярами, каждый из которых имеет набор из трех именованных входных тензоров:

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

Обратите внимание, каждый названный вход ( «метка», «Сигнал», «датчик») неявно предполагается , имеет то же 0-й размер (два в приведенном выше примере, так как есть два объекта в списке экземпляров). Если вы назвали входы, которые имеют другое 0-е измерение, используйте столбчатый формат, описанный ниже.

Указание входных тензоров в формате столбца.

Используйте этот формат, чтобы указать ваши входные тензоры, если отдельные именованные входы не имеют одинакового 0-го измерения или вам нужно более компактное представление. Этот формат аналогичен inputs поля КПГР Predict запрос.

В формате столбчатого, входы ключ к входам ключу в запросе JSON.

Значение ключа входов может либо один тензор входа или карта ввод имени тензорам (перечислено в их естественной форме вложенной). Каждый вход может иметь произвольную форму и не обязательно иметь одно и то же 0-е измерение (или размер пакета), как того требует формат строки, описанный выше.

Столбцовое представление предыдущего примера выглядит следующим образом:

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

Обратите внимание, входы представляет собой объект JSON , а не список , как экземпляры (используемый в представлении строки). Кроме того, все именованные входы указываются вместе, в отличие от их разворачивания в отдельные строки, выполненного в формате строки, описанном ранее. Это делает представление компактным (но, возможно, менее читаемым).

Формат ответа

predict запрос возвращает объект JSON в теле ответа.

Запрос в формате строки имеет отклик в следующем формате:

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

Если выход модели содержит только один названный тензор, мы опускаем имя и predictions ключ карты в список скалярных или список значений. Если модель выводит несколько именованных тензоров, вместо этого мы выводим список объектов, аналогично запросу в строковом формате, упомянутому выше.

Запрос в столбчатой формат имеет ответ следующий формат:

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

Если выход модели содержит только один названный тензор, мы опускаем имя и outputs ключ карты в список скалярных или список значений. Если модель выводит несколько именованных тензоров, вместо этого мы выводим объект. Каждому ключу этого объекта соответствует именованный выходной тензор. Формат аналогичен упомянутому выше запросу в формате столбца.

Вывод двоичных значений

TensorFlow не делает различий между небинарными и двоичными строками. Все они DT_STRING типа. Названные тензоры , которые имеют _bytes как суффикс в названии, считаются имеющими двоичные значения. Такие значения кодируются по- разному , как описаны в кодирующем двоичных значениях раздел ниже.

Сопоставление JSON

API-интерфейсы RESTful поддерживают каноническую кодировку в JSON, что упрощает обмен данными между системами. Для поддерживаемых типов кодировки описаны для каждого типа в таблице ниже. Подразумевается, что типы, не перечисленные ниже, не поддерживаются.

Тип данных TF Значение JSON Пример JSON Примечания
DT_BOOL правда, ложь правда, ложь
DT_STRING нить "Привет мир!" Если DT_STRING представляет собой двоичные байты (например , сериализованы байты изображения или Protobuf), кодировать их в Base64. См Кодирование двоичных значений для получения дополнительной информации.
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 номер 1, -10, 0 Значение JSON будет десятичным числом.
DT_FLOAT, DT_DOUBLE номер 1,1, -10,0, 0, NaN , Infinity Значение JSON будет число или один из специальных маркеров значений - NaN , Infinity и -Infinity . Смотрите JSON соответствия для получения дополнительной информации. Также допускается экспоненциальная запись.

Точность с плавающей запятой

JSON имеет единственный числовой тип данных. Таким образом, можно указать значение для ввода, которое приведет к потере точности. Например, если входной сигнал x представляет собой float тип данных, а вход {"x": 1435774380} отправляются модель работает на оборудовании на основе точечного стандарта с плавающим IEEE 754 (например , Intel или AMD), то значение будет автоматически конвертируют в underyling аппаратных средств к 1435774336 , так как 1435774380 не может быть точно представлено в 32-разрядное число с плавающей точкой. Как правило, входные данные для обслуживания должны иметь такое же распределение, как и для обучения, поэтому обычно это не будет проблемой, потому что такие же преобразования произошли во время обучения. Однако в случае, если требуется полная точность, обязательно используйте в своей модели базовый тип данных, который может обрабатывать желаемую точность и / или учитывать проверку на стороне клиента.

Кодирование двоичных значений

JSON использует кодировку UTF-8. Если у вас есть входные полнометражных или тензорные значения , которые должны быть бинарными (как байты изображения), вы должны Base64 кодирует данные и инкапсулировать его в объект JSON , имеющий b64 в качестве ключа следующим образом :

{ "b64": <base64 encoded string> }

Вы можете указать этот объект как значение для входного объекта или тензора. Тот же формат используется и для кодирования выходного ответа.

Запрос классификации с image (двоичные данные) и caption особенностей показан ниже:

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

Соответствие JSON

Многие значения признаков или тензорных значений представляют собой числа с плавающей запятой. Кроме конечных значений (например , 3.14, 1.0 и т.д.) они могут иметь NaN и нефинитные ( Infinity и -Infinity ) значение. К сожалению , спецификация JSON ( RFC 7159 ) , не признает эти значения (хотя спецификация JavaScript делает).

REST API, описанный на этой странице, позволяет объектам JSON запроса / ответа иметь такие значения. Это означает, что такие запросы, как следующий, действительны:

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

A (строгие) соответствуют стандартам JSON парсер будет отвергать это с ошибкой синтаксического анализа (из - за NaN и Infinity лексемы смешанной с фактическими номерами). Чтобы правильно обрабатывать запросы / ответы в вашем коде, используйте парсер JSON, который поддерживает эти токены.

NaN , Infinity , -Infinity маркеры распознаются proto3 , Python JSON и модуль JavaScript язык.

Пример

Мы можем использовать игрушку half_plus_three модель , чтобы увидеть API - интерфейсы REST в действии.

Запустите ModelServer с конечной точкой REST API

Скачать half_plus_three модель из мерзавца репозитория :

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

Мы будем использовать Docker для запуска ModelServer. Если вы хотите установить ModelServer изначально на вашей системе, следуйте инструкциям по --rest_api_port установке , чтобы установить вместо этого, и начать ModelServer с --rest_api_port возможностью экспорта REST API конечной точки (это не требуется при использовании Докер).

$ 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 ...

Выполнение вызовов REST API к ModelServer

В другом терминале, используйте curl инструмент , чтобы сделать REST API вызовов.

Получите статус модели следующим образом:

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

predict вызов будет выглядеть следующим образом :

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

И через regress вызов выглядит следующим образом :

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

Обратите внимание, regress доступен на имя подписи не по умолчанию и должны быть указаны в явном виде. Неправильный URL-адрес или тело запроса возвращает статус ошибки 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)" }
$