GRPC API'lerine ek olarak TensorFlow ModelServer RESTful API'lerini de destekler. Bu sayfada bu API uç noktaları ve kullanıma ilişkin 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 özel bölümlere bakın.
Hata durumunda, tüm API'ler yanıt gövdesinde anahtar olarak error
ve değer olarak hata mesajı içeren bir JSON nesnesi döndürür:
{
"error": <error message string>
}
Model durumu API'si
Bu API, ModelService.GetModelStatus
gRPC API'sini yakından takip eder. ModelServer'daki bir modelin durumunu döndürür.
URL'si
GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]
/versions/${VERSION}
veya /labels/${LABEL}
ın dahil edilmesi isteğe bağlıdır. Cevapta tüm sürümlerin atlanmış durumu döndürülür.
Yanıt formatı
Başarılı olursa GetModelStatusResponse
protobuf'un JSON temsilini döndürür.
Model Meta Veri API'si
Bu API, PredictionService.GetModelMetadata
gRPC API'sini yakından takip eder. ModelServer'daki bir modelin meta verilerini döndürür.
URL'si
GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]/metadata
/versions/${VERSION}
veya /labels/${LABEL}
ın dahil edilmesi isteğe bağlıdır. Atlanırsa, yanıtta en son sürümün model meta verileri döndürülür.
Yanıt formatı
Başarılı olursa GetModelMetadataResponse
protobuf'un JSON temsilini döndürür.
API'yi Sınıflandır ve Regresyonla
Bu API, PredictionService
gRPC API'sinin Classify
ve Regress
yöntemlerini yakından takip eder.
URL'si
POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:(classify|regress)
/versions/${VERSION}
veya /labels/${LABEL}
ın dahil edilmesi isteğe bağlıdır. Atlanırsa en son sürüm kullanılır.
Talep formatı
classify
ve regress
API'lerine ilişkin istek gövdesi, aşağıdaki gibi 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ıdır (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 gibi 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 (eğer modelin puanla ilişkilendirilmiş bir etiketi yoksa boş bir dize ""
olabilir). <score>
ondalık (kayan nokta) bir sayıdır.
regress
isteği, yanıt gövdesinde aşağıdaki gibi 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>
ondalık bir sayıdır.
GRPC API kullanıcıları bu formatın ClassificationResponse
ve RegressionResponse
protokolleriyle benzerliğini fark edeceklerdir.
API'yi tahmin et
Bu API, PredictionService.Predict
gRPC API'sini yakından takip eder.
URL'si
POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:predict
/versions/${VERSION}
veya /labels/${LABEL}
ın dahil edilmesi isteğe bağlıdır. Atlanırsa en son sürüm kullanılır.
Talep formatı
predict
API'sine ilişkin istek gövdesi aşağıdaki gibi 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'ıncı boyuta sahipse bu formatı kullanın. Değilse, aşağıda daha sonra açıklanan sütunlu formatı kullanın.
Satır biçiminde girişler, JSON isteğindeki örnek anahtarına anahtarlanır.
Yalnızca bir adlandırılmış giriş olduğunda, örnek anahtarının değerini girişin değeri olacak şekilde 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österimle ifade edilir.
Birden fazla adlandırılmış giriş için, her öğenin, her adlandırılmış giriş için bir tane olmak üzere, giriş adı/tensör değeri çiftini içeren bir nesne olması beklenir. Örnek olarak, her biri üç adlandırılmış giriş tensöründen oluşan iki örnek içeren bir istek aşağıda verilmiştir:
{
"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]]
}
]
}
Her adlandırılmış girişin ("etiket", "sinyal", "sensör") dolaylı olarak aynı 0'ıncı boyuta sahip olduğunun varsayıldığını unutmayın ( örnek listesinde iki nesne olduğundan yukarıdaki örnekte iki ). 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 formatında belirtme.
Bireysel adlandırılmış girişler aynı 0'ıncı boyuta sahip değilse veya daha kompakt bir gösterim istiyorsanız, giriş tensörlerinizi belirtmek için bu formatı kullanın. Bu biçim, gRPC Predict
isteğinin inputs
alanına benzer.
Sütunlu formatta girişler, JSON isteğindeki giriş anahtarına anahtarlanır.
Giriş anahtarının değeri, tek bir giriş tensörü veya giriş adının tensörlere haritası (doğal iç içe formlarında listelenmiştir) olabilir. Her giriş isteğe bağlı bir şekle sahip olabilir ve yukarıda açıklanan satır formatının gerektirdiği gibi aynı 0'ıncı boyutu (başka bir deyişle parti boyutunu) paylaşmaya gerek duymaz.
Ö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 örneklere benzer bir liste olmadığını (satır gösteriminde kullanılan) unutmayın. Ayrıca, adlandırılmış tüm girişler, daha önce açıklanan satır formatında yapılan ayrı ayrı satırlara dönüştürülmesinin aksine, birlikte belirtilir. Bu, gösterimi 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 şekilde biçimlendirilmiştir:
{
"predictions": <value>|<(nested)list>|<list-of-objects>
}
Modelin çıktısı yalnızca bir adlandırılmış tensör içeriyorsa, skaler veya liste değerleri listesine isim ve predictions
anahtar eşlemelerini çıkarırız. Model birden fazla adlandırılmış tensör çıktısı veriyorsa, bunun yerine yukarıda bahsedilen satır formatındaki isteğe 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 haritaları bir skaler veya liste değerleri listesine outputs
. Model birden fazla adlandırılmış tensör çıktısı veriyorsa 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 isteğe benzer.
İkili değerlerin çıkışı
TensorFlow, ikili olmayan ve ikili dizeler arasında ayrım yapmaz. Hepsi DT_STRING
türündedir. Adında sonek olarak _bytes
bulunan 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'ler JSON'da kanonik 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 edilir.
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 (örn. serileştirilmiş görüntü baytları veya protobuf), bunları Base64'te kodlayın. Daha fazla bilgi için İkili değerleri kodlama konusuna bakın. |
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 | sayı | 1, -10, 0 | JSON değeri ondalık sayı olacaktır. |
DT_FLOAT, DT_DOUBLE | sayı | 1.1, -10.0, 0, NaN , Infinity | JSON değeri bir sayı veya özel simge değerlerinden biri olacaktır ( NaN , Infinity ve -Infinity . Daha fazla bilgi için JSON uyumluluğuna bakın. Üslü gösterim de kabul edilir. |
Kayan Nokta Hassasiyeti
JSON tek sayı veri türüne sahiptir. Böylece, hassasiyet kaybıyla sonuçlanan bir girdi için bir değer sağlamak mümkündür. Örneğin, x
girişi float
bir veri türüyse ve {"x": 1435774380}
girişi IEEE 754 kayan nokta standardını temel alan donanım üzerinde çalışan modele (örn. Intel veya AMD) gönderilirse, bu durumda değer şu şekilde olacaktır: 1435774380
32 bitlik bir kayan nokta sayısında tam olarak temsil edilemediğinden, temeldeki donanım tarafından sessizce 1435774336
dönüştürülebilir. Genellikle, hizmete yönelik girdilerin eğitimle aynı dağılımda olması gerekir; dolayısıyla aynı dönüşümler eğitim zamanında da gerçekleştiğinden bu genellikle sorun yaratmaz. Bununla birlikte, tam hassasiyetin gerekli olması durumunda, modelinizde istenen hassasiyeti işleyebilecek ve/veya istemci tarafı kontrolünü dikkate alabilecek 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ği veya tensör değerleriniz varsa (görüntü baytları gibi), verileri Base64 ile kodlamanız ve bunu anahtar olarak b64
sahip bir JSON nesnesine aşağıdaki gibi kapsüllemeniz gerekir :
{ "b64": <base64 encoded string> }
Bu nesneyi bir giriş özelliği veya tensör için değer olarak belirtebilirsiniz. Aynı format, çıktı yanıtını kodlamak için de kullanılır.
image
(ikili veri) ve caption
özelliklerine sahip bir sınıflandırma isteği aşağıda gösterilmektedir:
{
"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. Bunlar sonlu değerlerin dışında (örneğin 3.14, 1.0 vb.) NaN
ve sonlu olmayan ( Infinity
ve -Infinity
) değerlere sahip olabilirler. Ne yazık ki JSON spesifikasyonu ( RFC 7159 ) bu değerleri TANIMIYOR (ancak JavaScript spesifikasyonu öyle).
Bu sayfada açıklanan REST API, istek/yanıt JSON nesnelerinin bu tür değerlere sahip olmasına olanak tanır. Bu, aşağıdaki gibi isteklerin geçerli olduğu anlamına gelir:
{
"example": [
{
"sensor_readings": [ 1.0, -3.14, Nan, Infinity ]
}
]
}
(Katı) standartlarla uyumlu 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). Kodunuzda istekleri/yanıtları doğru şekilde işlemek için bu belirteçleri destekleyen bir JSON ayrıştırıcısı kullanın.
NaN
, Infinity
, -Infinity
tokenları proto3 , Python JSON modülü ve JavaScript dili tarafından tanınır.
Örnek
REST API'lerini çalışırken görmek için oyuncak half_plus_third modelini kullanabiliriz.
ModelServer'ı REST API uç 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 yüklemek istiyorsanız, bunun yerine 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 bu gerekli değildir).
$ 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": ""
}
}
]
}
Bir predict
çağrısı aşağıdaki gibi görünecektir:
$ 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 mevcut olduğunu ve açıkça belirtilmesi gerektiğini unutmayın. 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)" }
$