В дополнении к КПГРАМ 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)" }
$