gRPC API 외에도 TensorFlow ModelServer는 RESTful API도 지원합니다. 이 페이지에서는 이러한 API 엔드포인트와 사용법에 대한 엔드투엔드 예제를 설명합니다.
요청과 응답은 JSON 개체입니다. 이 개체의 구성은 요청 유형이나 동사에 따라 다릅니다. 자세한 내용은 아래 API 관련 섹션을 참조하세요.
오류가 발생하는 경우 모든 API는 error
키로, 오류 메시지를 값으로 사용하여 응답 본문에 JSON 개체를 반환합니다.
{
"error": <error message string>
}
모델 상태 API
이 API는 ModelService.GetModelStatus
gRPC API를 밀접하게 따릅니다. ModelServer에서 모델의 상태를 반환합니다.
URL
GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]
/versions/${VERSION}
또는 /labels/${LABEL}
포함하는 것은 선택 사항입니다. 생략된 경우 모든 버전의 상태가 응답에 반환됩니다.
응답 형식
성공하면 GetModelStatusResponse
protobuf의 JSON 표현을 반환합니다.
모델 메타데이터 API
이 API는 PredictionService.GetModelMetadata
gRPC API를 밀접하게 따릅니다. ModelServer에서 모델의 메타데이터를 반환합니다.
URL
GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]/metadata
/versions/${VERSION}
또는 /labels/${LABEL}
포함하는 것은 선택 사항입니다. 생략하면 최신 버전의 모델 메타데이터가 응답으로 반환됩니다.
응답 형식
성공하면 GetModelMetadataResponse
protobuf의 JSON 표현을 반환합니다.
분류 및 회귀 API
이 API는 PredictionService
gRPC API의 Classify
및 Regress
메서드를 밀접하게 따릅니다.
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>
그러한 값의 목록입니다. 이 형식은 gRPC의 ClassificationRequest
및 RegressionRequest
proto와 유사합니다. 두 버전 모두 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>
10진수(부동 소수점) 숫자입니다.
regress
요청은 응답 본문에 다음과 같은 형식의 JSON 개체를 반환합니다.
{
// One regression value for each example in the request in the same order.
"result": [ <value1>, <value2>, <value3>, ...]
}
<value>
은 10진수입니다.
gRPC API 사용자는 이 형식이 ClassificationResponse
및 RegressionResponse
proto와 유사하다는 것을 알게 될 것입니다.
예측 API
이 API는 PredictionService.Predict
gRPC 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>
}
행 형식으로 입력 텐서를 지정합니다.
이 형식은 gRPC API 및 CMLE 예측 API 의 PredictRequest
proto와 유사합니다. 모든 명명된 입력 텐서의 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]] ]
}
목록을 수동으로 평면화할 필요가 없기 때문에 Tensor는 중첩 표기법으로 자연스럽게 표현됩니다.
여러 명명된 입력의 경우 각 항목은 각 명명된 입력에 대해 하나씩 입력 이름/텐서 값 쌍을 포함하는 객체일 것으로 예상됩니다. 예를 들어, 다음은 각각 3개의 명명된 입력 텐서 세트가 있는 두 개의 인스턴스가 있는 요청입니다.
{
"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번째 차원( 인스턴스 목록에 두 개의 객체가 있으므로 위의 예에서는 2 개 )을 갖는 것으로 암시적으로 가정됩니다. 서로 다른 0번째 차원을 갖는 명명된 입력이 있는 경우 아래에 설명된 열 형식을 사용하십시오.
열 형식으로 입력 텐서를 지정합니다.
명명된 개별 입력의 0번째 차원이 동일하지 않거나 보다 간결한 표현을 원하는 경우 이 형식을 사용하여 입력 텐서를 지정합니다. 이 형식은 gRPC Predict
요청의 inputs
필드와 유사합니다.
열 형식에서는 입력이 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 매핑
RESTful API는 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 값은 10진수입니다. |
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)을 기반으로 하는 하드웨어에서 실행되는 모델로 전송되면 값은 다음과 같습니다. 1435774380
32비트 부동 소수점 숫자로 정확하게 표현될 수 없기 때문에 기본 하드웨어에 의해 자동으로 1435774336
으로 변환됩니다. 일반적으로 제공에 대한 입력은 학습과 동일한 분포여야 하므로 학습 시 동일한 전환이 발생했기 때문에 일반적으로 문제가 되지 않습니다. 그러나 전체 정밀도가 필요한 경우에는 원하는 정밀도를 처리하거나 클라이언트 측 검사를 고려할 수 있는 모델의 기본 데이터 유형을 사용해야 합니다.
바이너리 값 인코딩
JSON은 UTF-8 인코딩을 사용합니다. 바이너리(예: 이미지 바이트)여야 하는 입력 기능 또는 텐서 값이 있는 경우 데이터를 Base64로 인코딩하고 다음과 같이 b64
키로 사용하는 JSON 객체에 캡슐화 해야 합니다 .
{ "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 ]
}
]
}
(엄격한) 표준을 준수하는 JSON 파서는 구문 분석 오류로 이를 거부합니다(실제 숫자와 혼합된 NaN
및 Infinity
토큰으로 인해). 코드에서 요청/응답을 올바르게 처리하려면 이러한 토큰을 지원하는 JSON 파서를 사용하세요.
NaN
, Infinity
, -Infinity
토큰은 proto3 , Python JSON 모듈 및 JavaScript 언어로 인식됩니다.
예
우리는 장난감 half_plus_3 모델을 사용하여 REST API가 실제로 작동하는 모습을 볼 수 있습니다.
REST API 엔드포인트로 ModelServer 시작
git 저장소 에서 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 엔드포인트를 내보냅니다(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 ...
ModelServer에 대한 REST API 호출 수행
다른 터미널에서 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)" }
$