TensorFlow ModelServer, gRPC API'lerine ek olarak RESTful API'lerini de destekler. Bu sayfada, bu API uç noktaları ve kullanımla ilgili uçtan uca bir örnek açıklanmaktadır.
İstek ve yanıt bir JSON nesnesidir. Bu nesnenin bileşimi, istek türüne veya fiile bağlıdır. Ayrıntılar için aşağıdaki API'ye özgü bölümlere bakın.
Hata durumunda, tüm API'ler yanıt gövdesinde anahtar olarak error
ve değer olarak hata mesajıyla birlikte bir JSON nesnesi döndürür:
{
"error": <error message string>
}
Model durumu API'sı
Bu API, ModelService.GetModelStatus
gRPC API'sini yakından takip eder. ModelServer'da bir modelin durumunu döndürür.
URL
GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]
/versions/${VERSION}
veya /labels/${LABEL}
dahil etmek isteğe bağlıdır. Atlanırsa, yanıtta tüm sürümler için durum döndürülür.
Yanıt formatı
Başarılı olursa, GetModelStatusResponse
protobuf'un bir JSON temsilini döndürür.
Model Meta Veri API'sı
Bu API, PredictionService.GetModelMetadata
gRPC API'sini yakından takip eder. ModelServer'daki bir modelin meta verilerini döndürür.
URL
GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]/metadata
/versions/${VERSION}
veya /labels/${LABEL}
dahil etmek isteğe bağlıdır. Atlanırsa, en son sürüm için model meta verileri yanıtta döndürülür.
Yanıt formatı
Başarılı olursa, GetModelMetadataResponse
protobuf'un bir JSON temsilini döndürür.
Sınıflandırma ve Gerileme API'sı
Bu API, PredictionService
gRPC API'sinin Classify
ve Regress
yöntemlerini yakından takip eder.
URL
POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:(classify|regress)
/versions/${VERSION}
veya /labels/${LABEL}
dahil etmek isteğe bağlıdır. Atlanırsa en son sürüm kullanılır.
İstek biçimi
classify
ve regress
API'leri için istek gövdesi, aşağıdaki şekilde biçimlendirilmiş bir JSON nesnesi olmalıdır:
{
// 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>
bir JSON numarası (tam veya ondalık), JSON dizesi veya ikili verileri temsil eden bir JSON nesnesidir (ayrıntılar için aşağıdaki İkili değerleri kodlama bölümüne bakın). <list>
bu tür değerlerin bir listesidir. Bu biçim, gRPC'nin ClassificationRequest
ve RegressionRequest
protokollerine benzer. Her iki sürüm de Example
nesnelerin listesini kabul eder.
Yanıt formatı
Bir classify
isteği, yanıt gövdesinde aşağıdaki şekilde biçimlendirilmiş bir JSON nesnesi döndürür:
{
"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>
bir dizedir (modelin puanla ilişkilendirilmiş bir etiketi yoksa ""
boş bir dize olabilir). <score>
ondalık (kayan noktalı) bir sayıdır.
regress
isteği, yanıt gövdesinde aşağıdaki şekilde biçimlendirilmiş bir JSON nesnesi döndürür:
{
// One regression value for each example in the request in the same order.
"result": [ <value1>, <value2>, <value3>, ...]
}
<value>
bir ondalık sayıdır.
gRPC API kullanıcıları, bu formatın ClassificationResponse
ve RegressionResponse
protokolleri ile benzerliğini fark edeceklerdir.
Tahmin API'sı
Bu API, PredictionService.Predict
gRPC API'sini yakından takip eder.
URL
POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:predict
/versions/${VERSION}
veya /labels/${LABEL}
dahil etmek isteğe bağlıdır. Atlanırsa en son sürüm kullanılır.
İstek biçimi
predict
API'si için istek gövdesi, aşağıdaki şekilde biçimlendirilmiş JSON nesnesi olmalıdır:
{
// (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>
}
Giriş tensörlerini satır biçiminde belirtme.
Bu biçim, gRPC API'sinin PredictRequest
protokolüne ve CMLE tahmin API'sine benzer. Adlandırılmış tüm giriş tensörleri aynı 0. boyuta sahipse bu biçimi kullanın. Aksi takdirde, aşağıda daha sonra açıklanan sütun biçimini kullanın.
Satır biçiminde, girişler, JSON isteğindeki örnekler anahtarına anahtarlanır.
Yalnızca bir adlandırılmış giriş olduğunda, örnekler anahtarının değerini girişin değeri olarak belirtin:
{
// List of 3 scalar tensors.
"instances": [ "foo", "bar", "baz" ]
}
{
// List of 2 tensors each of [1, 2] shape
"instances": [ [[1, 2]], [[3, 4]] ]
}
Listeyi manuel olarak düzleştirmeye gerek olmadığından, tensörler doğal olarak iç içe gösterimde ifade edilir.
Birden çok adlandırılmış giriş için, her öğenin, adlandırılmış her giriş için bir tane olmak üzere giriş adı/tensör değeri çiftini içeren bir nesne olması beklenir. Örnek olarak, aşağıda her biri üç adlandırılmış giriş tensörü kümesine sahip iki örneğe sahip bir istek yer almaktadır:
{
"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]]
}
]
}
Adlandırılmış her girişin ("etiket", "sinyal", "sensör") dolaylı olarak aynı 0. boyuta sahip olduğu varsayılır ( örnek listesinde iki nesne olduğu için yukarıdaki örnekte iki tane ). Farklı 0'ıncı boyuta sahip girişleri adlandırdıysanız, aşağıda açıklanan sütun biçimini kullanın.
Giriş tensörlerini sütun biçiminde belirtme.
Adlandırılmış girişler aynı 0'ıncı boyuta sahip değilse veya daha kompakt bir temsil istiyorsanız, giriş tensörlerinizi belirtmek için bu formatı kullanın. Bu biçim, gRPC Predict
isteğinin inputs
alanına benzer.
Sütun biçiminde, girişler, JSON isteğindeki giriş anahtarına yazılır.
Girişler anahtarının değeri, tek bir giriş tensörü veya giriş adının tensörlere eşlenmesi olabilir (doğal iç içe formlarında listelenmiştir). Her girdi rastgele bir şekle sahip olabilir ve yukarıda açıklanan satır formatının gerektirdiği şekilde aynı 0'ıncı boyutu (diğer bir deyişle yığın boyutu) paylaşması gerekmez.
Önceki örneğin sütunlu gösterimi aşağıdaki gibidir:
{
"inputs": {
"tag": ["foo", "bar"],
"signal": [[1, 2, 3, 4, 5], [3, 4, 1, 2, 5]],
"sensor": [[[1, 2], [3, 4]], [[4, 5], [6, 8]]]
}
}
Girişlerin bir JSON nesnesi olduğunu ve liste benzeri örnekler olmadığını unutmayın (satır gösteriminde kullanılır). Ayrıca, daha önce açıklanan satır biçiminde yapılan ayrı satırlara açmanın aksine, tüm adlandırılmış girdiler birlikte belirtilir. Bu, temsili kompakt hale getirir (ancak belki daha az okunabilir).
Yanıt formatı
predict
isteği, yanıt gövdesinde bir JSON nesnesi döndürür.
Satır biçimindeki bir isteğin yanıtı aşağıdaki gibi biçimlendirilmiştir:
{
"predictions": <value>|<(nested)list>|<list-of-objects>
}
Modelin çıktısı yalnızca bir adlandırılmış tensör içeriyorsa, ad ve predictions
anahtar eşlemelerini bir skaler veya liste değerleri listesine atlarız. Model, birden çok adlandırılmış tensör çıkarırsa, bunun yerine, yukarıda bahsedilen satır biçimindeki talebe benzer şekilde, bir nesne listesi çıktısı alırız.
Sütun biçimindeki bir isteğin yanıtı aşağıdaki şekilde biçimlendirilmiştir:
{
"outputs": <value>|<(nested)list>|<object>
}
Modelin çıktısı yalnızca bir adlandırılmış tensör içeriyorsa, adı atlarız ve anahtar outputs
bir skaler veya liste değerleri listesine çıkarırız. Model, birden çok adlandırılmış tensör çıktısı verirse, bunun yerine bir nesne çıktısı alırız. Bu nesnenin her anahtarı, adlandırılmış bir çıkış tensörüne karşılık gelir. Biçim, yukarıda belirtilen sütun biçimindeki talebe benzer.
İkili değerlerin çıktısı
TensorFlow, ikili olmayan ve ikili diziler arasında ayrım yapmaz. Hepsi DT_STRING
türündedir. Adlarında sonek olarak _bytes
olan adlandırılmış tensörlerin ikili değerlere sahip olduğu kabul edilir. Bu tür değerler, aşağıdaki ikili değerlerin kodlanması bölümünde açıklandığı gibi farklı şekilde kodlanır.
JSON eşlemesi
RESTful API'leri, JSON'da standart bir kodlamayı destekleyerek, sistemler arasında veri paylaşımını kolaylaştırır. Desteklenen türler için, kodlamalar aşağıdaki tabloda tür bazında açıklanmıştır. Aşağıda listelenmeyen türlerin desteklenmediği ima edilmektedir.
TF Veri Türü | JSON Değeri | JSON örneği | notlar |
---|---|---|---|
DT_BOOL | doğru yanlış | doğru yanlış | |
DT_STRING | sicim | "Selam Dünya!" | DT_STRING ikili baytları temsil ediyorsa (örneğin, seri hale getirilmiş görüntü baytları veya protobuf), bunları Base64'te kodlayın. Daha fazla bilgi için bkz . İkili değerleri kodlama . |
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 | sayı | 1, -10, 0 | JSON değeri ondalık bir sayı olacaktır. |
DT_FLOAT, DT_DOUBLE | sayı | 1.1, -10.0, 0, NaN , Infinity | JSON değeri bir sayı veya özel belirteç değerlerinden biri olacaktır - NaN , Infinity ve -Infinity . Daha fazla bilgi için JSON uyumluluğuna bakın. Üs gösterimi de kabul edilir. |
Kayan Nokta Hassasiyeti
JSON, tek bir sayı veri türüne sahiptir. Böylece kesinlik kaybıyla sonuçlanan bir girdi için bir değer sağlamak mümkündür. Örneğin, x
girişi bir float
veri türüyse ve {"x": 1435774380}
girişi, IEEE 754 kayan nokta standardına (örn. Intel veya AMD) dayalı donanım üzerinde çalışan modele gönderilirse, değer 1435774380
, 32 bitlik bir kayan nokta sayısında tam olarak temsil edilemediğinden, temel donanım tarafından sessizce 1435774336
dönüştürülebilir. Tipik olarak, sunma girdileri eğitimle aynı dağılımda olmalıdır, bu nedenle eğitim sırasında aynı dönüşümler gerçekleştiği için bu genellikle sorunlu olmaz. Bununla birlikte, tam kesinliğin gerekli olması durumunda, modelinizde istenen kesinliği işleyebilecek ve/veya istemci tarafı denetimi dikkate alabilen temel bir veri türü kullandığınızdan emin olun.
İkili değerleri kodlama
JSON, UTF-8 kodlamasını kullanır. İkili olması gereken giriş özelliğine veya tensör değerlerine sahipseniz (görüntü baytları gibi), verileri Base64 ile kodlamanız ve aşağıdaki gibi anahtar olarak b64
sahip bir JSON nesnesine kapsüllemeniz gerekir :
{ "b64": <base64 encoded string> }
Bu nesneyi bir giriş özelliği veya tensörü için bir değer olarak belirleyebilirsiniz. Aynı biçim, çıktı yanıtını da kodlamak için kullanılır.
image
(ikili veri) ve caption
özelliklerine sahip bir sınıflandırma talebi aşağıda gösterilmiştir:
{
"signature_name": "classify_objects",
"examples": [
{
"image": { "b64": "aW1hZ2UgYnl0ZXM=" },
"caption": "seaside"
},
{
"image": { "b64": "YXdlc29tZSBpbWFnZSBieXRlcw==" },
"caption": "mountains"
}
]
}
JSON uyumluluğu
Birçok özellik veya tensör değeri, kayan nokta sayılarıdır. Sonlu değerlerin (örn. 3.14, 1.0 vb.) dışında, bunlar NaN
ve sonlu olmayan ( Infinity
ve -Infinity
) değerlere sahip olabilir. Ne yazık ki JSON spesifikasyonu ( RFC 7159 ) bu değerleri tanımıyor (JavaScript spesifikasyonu tanısa da).
Bu sayfada açıklanan REST API, istek/yanıt JSON nesnelerinin bu tür değerlere sahip olmasına izin verir. Bu, aşağıdaki gibi isteklerin geçerli olduğu anlamına gelir:
{
"example": [
{
"sensor_readings": [ 1.0, -3.14, Nan, Infinity ]
}
]
}
Standartlarla uyumlu (katı) bir JSON ayrıştırıcısı, bunu bir ayrıştırma hatasıyla reddeder ( NaN
ve Infinity
belirteçlerinin gerçek sayılarla karışması nedeniyle). Kodunuzdaki istekleri/yanıtları doğru şekilde işlemek için bu belirteçleri destekleyen bir JSON ayrıştırıcı kullanın.
NaN
, Infinity
, -Infinity
belirteçleri proto3 , Python JSON modülü ve JavaScript dili tarafından tanınır.
Örnek
REST API'lerini çalışırken görmek için toy half_plus_three modelini kullanabiliriz.
ModelServer'ı REST API bitiş noktasıyla başlatın
half_plus_three
modelini git deposundan indirin:
$ mkdir -p /tmp/tfserving
$ cd /tmp/tfserving
$ git clone --depth=1 https://github.com/tensorflow/serving
ModelServer'ı çalıştırmak için Docker'ı kullanacağız. ModelServer'ı sisteminize yerel olarak kurmak istiyorsanız, bunun yerine kurmak için kurulum talimatlarını izleyin ve REST API uç noktasını dışa aktarmak için ModelServer'ı --rest_api_port
seçeneğiyle başlatın (Docker kullanırken buna gerek yoktur).
$ 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'a REST API çağrıları yapın
Farklı bir terminalde, REST API çağrıları yapmak için curl
aracını kullanın.
Modelin durumunu aşağıdaki gibi alın:
$ 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
araması aşağıdaki gibi görünür:
$ 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]
}
Ve bir regress
çağrısı aşağıdaki gibi görünür:
$ 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
, varsayılan olmayan bir imza adında kullanılabilir ve açıkça belirtilmelidir. Yanlış bir istek URL'si veya gövdesi, bir HTTP hata durumu döndürür.
$ 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)" }
$