API RESTful

Selain gRPC API TensorFlow ModelServer juga mendukung API tenang. Halaman ini menjelaskan titik akhir API ini dan end-to-end contoh pada penggunaan.

Permintaan dan respons adalah objek JSON. Komposisi objek ini tergantung pada jenis permintaan atau kata kerja. Lihat bagian khusus API di bawah untuk detailnya.

Dalam kasus kesalahan, semua API akan mengembalikan objek JSON dalam tubuh respon dengan error sebagai kunci dan pesan kesalahan sebagai nilai:

{
  "error": <error message string>
}

API status model

API ini erat mengikuti ModelService.GetModelStatus API gRPC. Ini mengembalikan status model di ModelServer.

URL

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

Termasuk /versions/${VERSION} atau /labels/${LABEL} adalah opsional. Jika dihilangkan status untuk semua versi dikembalikan dalam respons.

Format tanggapan

Jika berhasil, mengembalikan representasi JSON dari GetModelStatusResponse protobuf.

Model Metadata API

API ini erat mengikuti PredictionService.GetModelMetadata API gRPC. Ini mengembalikan metadata model di ModelServer.

URL

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

Termasuk /versions/${VERSION} atau /labels/${LABEL} adalah opsional. Jika dihilangkan, metadata model untuk versi terbaru dikembalikan dalam respons.

Format tanggapan

Jika berhasil, mengembalikan representasi JSON dari GetModelMetadataResponse protobuf.

Classify dan Regress API

API ini erat mengikuti Classify dan Regress metode PredictionService gRPC API.

URL

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

Termasuk /versions/${VERSION} atau /labels/${LABEL} adalah opsional. Jika dihilangkan digunakan versi terbaru.

Format permintaan

Permintaan tubuh untuk classify dan regress API harus menjadi objek JSON diformat sebagai berikut:

{
  // 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> adalah nomor JSON (keseluruhan atau desimal), string JSON, atau objek JSON yang mewakili data biner (lihat Pengkodean biner nilai di bawah untuk rincian). <list> adalah daftar nilai-nilai tersebut. Format ini mirip dengan gRPC ini ClassificationRequest dan RegressionRequest protos. Kedua versi menerima daftar Example benda.

Format tanggapan

Sebuah classify permintaan mengembalikan sebuah objek JSON dalam tubuh respon, diformat sebagai berikut:

{
  "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> adalah string (yang dapat menjadi string kosong "" jika model tidak memiliki label yang berhubungan dengan skor). <score> adalah desimal (floating point) nomor.

The regress permintaan mengembalikan sebuah objek JSON dalam tubuh respon, diformat sebagai berikut:

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

<value> adalah angka desimal.

Pengguna gRPC API akan melihat kesamaan format ini dengan ClassificationResponse dan RegressionResponse protos.

Prediksi API

API ini erat mengikuti PredictionService.Predict API gRPC.

URL

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

Termasuk /versions/${VERSION} atau /labels/${LABEL} adalah opsional. Jika dihilangkan digunakan versi terbaru.

Format permintaan

Permintaan tubuh untuk predict API harus JSON objek diformat sebagai berikut:

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

Menentukan tensor input dalam format baris.

Format ini mirip dengan PredictRequest proto dari gRPC API dan CMLE memprediksi API . Gunakan format ini jika semua tensor masukan bernama memiliki yang sama 0-th dimensi. Jika tidak, gunakan format kolom yang dijelaskan nanti di bawah.

Dalam format baris, input dikunci untuk kunci contoh dalam permintaan JSON.

Ketika hanya ada satu nama input, menentukan nilai contoh kunci untuk menjadi nilai input:

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

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

Tensor diekspresikan secara alami dalam notasi bersarang karena tidak perlu meratakan daftar secara manual.

Untuk beberapa input bernama, setiap item diharapkan menjadi objek yang berisi pasangan nama input/nilai tensor, satu untuk setiap input bernama. Sebagai contoh, berikut ini adalah permintaan dengan dua instance, masing-masing dengan satu set tiga tensor input bernama:

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

Catatan, masing-masing bernama input ( "tag", "sinyal", "sensor") secara implisit diasumsikan memiliki yang sama 0-th dimensi (dua di contoh di atas, karena ada dua benda dalam daftar kasus). Jika Anda telah menamai input yang memiliki dimensi ke-0 yang berbeda, gunakan format kolom yang dijelaskan di bawah ini.

Menentukan tensor input dalam format kolom.

Gunakan format ini untuk menentukan tensor input Anda, jika input bernama individual tidak memiliki dimensi ke-0 yang sama atau Anda menginginkan representasi yang lebih ringkas. Format ini mirip dengan inputs bidang gRPC Predict permintaan.

Dalam format columnar, input dikunci untuk kunci masukan dalam permintaan JSON.

Nilai untuk kunci input bisa baik tensor masukan tunggal atau peta nama masukan untuk tensor (terdaftar dalam bentuk bersarang alami mereka). Setiap input dapat memiliki bentuk arbitrer dan tidak perlu berbagi/dimensi ke-0 yang sama (alias ukuran batch) seperti yang dipersyaratkan oleh format baris yang dijelaskan di atas.

Representasi kolom dari contoh sebelumnya adalah sebagai berikut:

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

Catatan, masukan adalah objek JSON dan bukan daftar seperti contoh (yang digunakan dalam representasi baris). Juga, semua input bernama ditentukan bersama-sama, bukan membuka gulungannya ke dalam baris individual yang dilakukan dalam format baris yang dijelaskan sebelumnya. Ini membuat representasi menjadi ringkas (tetapi mungkin kurang mudah dibaca).

Format tanggapan

The predict permintaan pengembalian objek JSON dalam tubuh respon.

Permintaan di format baris telah respon diformat sebagai berikut:

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

Jika output dari model yang hanya berisi satu bernama tensor, kita menghilangkan nama dan predictions kunci peta ke daftar skalar atau daftar nilai-nilai. Jika model mengeluarkan beberapa tensor bernama, kami menampilkan daftar objek sebagai gantinya, mirip dengan permintaan dalam format baris yang disebutkan di atas.

Permintaan di Format columnar telah respon diformat sebagai berikut:

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

Jika output dari model yang hanya berisi satu bernama tensor, kita menghilangkan nama dan outputs kunci peta ke daftar skalar atau daftar nilai-nilai. Jika model mengeluarkan beberapa tensor bernama, kami mengeluarkan objek sebagai gantinya. Setiap kunci dari objek ini sesuai dengan tensor keluaran bernama. Formatnya mirip dengan permintaan dalam format kolom yang disebutkan di atas.

Keluaran nilai biner

TensorFlow tidak membedakan antara string non-biner dan biner. Semua yang DT_STRING jenis. Dinamakan tensor yang memiliki _bytes sebagai akhiran di nama mereka dianggap memiliki nilai-nilai biner. Nilai-nilai tersebut dikodekan berbeda seperti yang dijelaskan dalam pengkodean nilai biner bagian bawah.

pemetaan JSON

RESTful API mendukung pengkodean kanonik di JSON, membuatnya lebih mudah untuk berbagi data antar sistem. Untuk jenis yang didukung, pengkodean dijelaskan berdasarkan jenis per jenis dalam tabel di bawah ini. Jenis yang tidak tercantum di bawah dianggap tidak didukung.

Tipe Data TF Nilai JSON contoh JSON Catatan
DT_BOOL benar salah benar salah
DT_STRING rangkaian "Halo Dunia!" Jika DT_STRING mewakili byte biner (misalnya byte gambar serial atau protobuf), encode ini dalam Base64. Lihat Encoding nilai biner untuk info lebih lanjut.
DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64 nomor 1, -10, 0 Nilai JSON akan menjadi angka desimal.
DT_FLOAT, DT_DOUBLE nomor 1.1, -10,0, 0, NaN , Infinity Nilai JSON akan menjadi nomor atau salah satu dari nilai tanda khusus - NaN , Infinity , dan -Infinity . Lihat JSON kesesuaian untuk info lebih lanjut. Notasi eksponen juga diterima.

Presisi Titik Mengambang

JSON memiliki tipe data angka tunggal. Dengan demikian dimungkinkan untuk memberikan nilai input yang mengakibatkan hilangnya presisi. Misalnya, jika input x adalah float tipe data, dan input {"x": 1435774380} dikirim ke model yang berjalan pada hardware didasarkan pada IEEE 754 floating point standar (misalnya Intel atau AMD), maka nilai akan akan diam-diam dikonversi oleh hardware underyling ke 1435774336 sejak 1435774380 tidak dapat tepat diwakili dalam 32-bit angka floating point. Biasanya, input ke penayangan harus sama dengan distribusi pelatihan, jadi ini umumnya tidak akan bermasalah karena konversi yang sama terjadi pada waktu pelatihan. Namun, jika presisi penuh diperlukan, pastikan untuk menggunakan tipe data dasar dalam model Anda yang dapat menangani presisi yang diinginkan dan/atau mempertimbangkan pemeriksaan sisi klien.

Mengkodekan nilai biner

JSON menggunakan pengkodean UTF-8. Jika Anda memiliki fitur atau tensor masukan nilai-nilai yang perlu menjadi biner (seperti gambar byte), Anda harus Base64 menyandikan data dan merangkum dalam sebuah objek JSON memiliki b64 sebagai kunci sebagai berikut:

{ "b64": <base64 encoded string> }

Anda dapat menentukan objek ini sebagai nilai untuk fitur input atau tensor. Format yang sama juga digunakan untuk mengkodekan respons keluaran.

Permintaan klasifikasi dengan image (data biner) dan caption fitur ditunjukkan di bawah ini:

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

Kesesuaian JSON

Banyak fitur atau nilai tensor adalah bilangan floating point. Terlepas dari nilai-nilai yang terbatas (misalnya 3,14, 1,0 dll) ini dapat memiliki NaN dan non-terbatas ( Infinity dan -Infinity ) nilai-nilai. Sayangnya JSON spesifikasi ( RFC 7159 ) TIDAK mengenali nilai-nilai ini (meskipun spesifikasi JavaScript tidak).

REST API yang dijelaskan pada halaman ini memungkinkan objek JSON permintaan/tanggapan memiliki nilai seperti itu. Ini menyiratkan bahwa permintaan seperti berikut ini valid:

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

A (ketat) sesuai standar JSON parser akan menolak ini dengan kesalahan parse (karena NaN dan Infinity token dicampur dengan angka yang sebenarnya). Untuk menangani permintaan/respons dalam kode Anda dengan benar, gunakan parser JSON yang mendukung token ini.

NaN , Infinity , -Infinity token diakui oleh proto3 , Python JSON modul dan bahasa JavaScript.

Contoh

Kita dapat menggunakan mainan half_plus_three Model untuk melihat SISA API dalam tindakan.

Mulai ModelServer dengan titik akhir REST API

Download half_plus_three Model dari repositori git :

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

Kami akan menggunakan Docker untuk menjalankan ModelServer. Jika Anda ingin menginstal ModelServer native pada sistem Anda, ikuti instruksi pengaturan untuk menginstal sebaliknya, dan memulai ModelServer dengan --rest_api_port pilihan untuk ekspor SISA API endpoint (ini tidak diperlukan bila menggunakan 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 ...

Lakukan panggilan REST API ke ModelServer

Dalam terminal yang berbeda, gunakan curl alat untuk membuat panggilan API REST.

Dapatkan status model sebagai berikut:

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

Sebuah predict panggilan akan terlihat sebagai berikut:

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

Dan regress panggilan terlihat sebagai berikut:

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

Catatan, regress tersedia pada nama tanda tangan non-default dan harus ditentukan secara eksplisit. URL atau isi permintaan yang salah mengembalikan status kesalahan 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)" }
$