रेस्टफुल एपीआई

जीआरपीसी एपीआई के अलावा टेन्सरफ्लो मॉडलसर्वर रेस्टफुल एपीआई का भी समर्थन करता है। यह पृष्ठ इन एपीआई एंडपॉइंट्स और उपयोग पर एक एंड-टू-एंड उदाहरण का वर्णन करता है।

अनुरोध और प्रतिक्रिया एक JSON ऑब्जेक्ट है। इस ऑब्जेक्ट की संरचना अनुरोध प्रकार या क्रिया पर निर्भर करती है। विवरण के लिए नीचे एपीआई विशिष्ट अनुभाग देखें।

त्रुटि के मामले में, सभी एपीआई प्रतिक्रिया निकाय में कुंजी के रूप में error और मान के रूप में त्रुटि संदेश के साथ एक JSON ऑब्जेक्ट लौटाएंगे:

{
  "error": <error message string>
}

मॉडल स्थिति एपीआई

यह एपीआई ModelService.GetModelStatus जीआरपीसी एपीआई का बारीकी से अनुसरण करता है। यह मॉडलसर्वर में एक मॉडल की स्थिति लौटाता है।

यूआरएल

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

/versions/${VERSION} या /labels/${LABEL} शामिल करना वैकल्पिक है। यदि सभी संस्करणों के लिए छोड़ी गई स्थिति प्रतिक्रिया में लौटा दी जाती है।

प्रतिक्रिया स्वरूप

सफल होने पर, GetModelStatusResponse protobuf का JSON प्रतिनिधित्व लौटाता है।

मॉडल मेटाडेटा एपीआई

यह एपीआई PredictionService.GetModelMetadata gRPC API का बारीकी से अनुसरण करता है। यह मॉडलसर्वर में किसी मॉडल का मेटाडेटा लौटाता है।

यूआरएल

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

/versions/${VERSION} या /labels/${LABEL} शामिल करना वैकल्पिक है। यदि छोड़ दिया जाए तो नवीनतम संस्करण के लिए मॉडल मेटाडेटा प्रतिक्रिया में लौटा दिया जाता है।

प्रतिक्रिया स्वरूप

सफल होने पर, GetModelMetadataResponse protobuf का JSON प्रतिनिधित्व लौटाता है।

एपीआई को वर्गीकृत और पुनः प्राप्त करें

यह एपीआई PredictionService gRPC API के Classify और Regress तरीकों का बारीकी से पालन करता है।

यूआरएल

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

/versions/${VERSION} या /labels/${LABEL} शामिल करना वैकल्पिक है। यदि छोड़ दिया जाए तो नवीनतम संस्करण का उपयोग किया जाता है।

अनुरोध प्रारूप

classify और regress एपीआई के लिए अनुरोध निकाय एक 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 प्रोटोस के समान है। दोनों संस्करण 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> एक दशमलव संख्या है.

जीआरपीसी एपीआई के उपयोगकर्ता इस प्रारूप की समानता ClassificationResponse और RegressionResponse प्रोटोज़ के साथ देखेंगे।

एपीआई की भविष्यवाणी करें

यह एपीआई PredictionService.Predict gRPC API का बारीकी से अनुसरण करता है।

यूआरएल

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

/versions/${VERSION} या /labels/${LABEL} शामिल करना वैकल्पिक है। यदि छोड़ दिया जाए तो नवीनतम संस्करण का उपयोग किया जाता है।

अनुरोध प्रारूप

predict एपीआई के लिए अनुरोध निकाय 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 के PredictRequest प्रोटो और 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-वें आयाम नहीं है या आप अधिक कॉम्पैक्ट प्रतिनिधित्व चाहते हैं। यह प्रारूप 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 में कैनोनिकल एन्कोडिंग का समर्थन करता है, जिससे सिस्टम के बीच डेटा साझा करना आसान हो जाता है। समर्थित प्रकारों के लिए, एन्कोडिंग का वर्णन नीचे दी गई तालिका में प्रकार-दर-प्रकार के आधार पर किया गया है। नीचे सूचीबद्ध नहीं किए गए प्रकारों को असमर्थित माना जाता है।

टीएफ डेटा प्रकार JSON मान JSON उदाहरण टिप्पणियाँ
DT_BOOL सही गलत सही गलत
DT_STRING डोरी "हैलो वर्ल्ड!" यदि DT_STRING बाइनरी बाइट्स (उदाहरण के लिए क्रमबद्ध छवि बाइट्स या प्रोटोबफ) का प्रतिनिधित्व करता है, तो इन्हें बेस 64 में एनकोड करें। अधिक जानकारी के लिए बाइनरी मान एन्कोडिंग देखें।
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 फ्लोटिंग पॉइंट मानक (जैसे इंटेल या एएमडी) के आधार पर हार्डवेयर पर चलने वाले मॉडल को भेजा जाता है, तो मान होगा अंडरइलिंग हार्डवेयर द्वारा चुपचाप 1435774336 में परिवर्तित किया जा सकता है क्योंकि 1435774380 32-बिट फ़्लोटिंग पॉइंट संख्या में सटीक रूप से प्रदर्शित नहीं किया जा सकता है। आमतौर पर, सेवा देने के इनपुट का वितरण प्रशिक्षण के समान ही होना चाहिए, इसलिए यह आम तौर पर समस्याग्रस्त नहीं होगा क्योंकि प्रशिक्षण के समय समान रूपांतरण हुए थे। हालाँकि, यदि पूर्ण परिशुद्धता की आवश्यकता है, तो अपने मॉडल में एक अंतर्निहित डेटा प्रकार का उपयोग करना सुनिश्चित करें जो वांछित परिशुद्धता को संभाल सकता है और/या क्लाइंट-साइड जाँच पर विचार कर सकता है।

बाइनरी मान एन्कोडिंग

JSON UTF-8 एन्कोडिंग का उपयोग करता है। यदि आपके पास इनपुट सुविधा या टेंसर मान हैं जिन्हें बाइनरी (छवि बाइट्स की तरह) होने की आवश्यकता है, तो आपको बेस 64 डेटा को एनकोड करना होगा और इसे जेएसओएन ऑब्जेक्ट में 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 ]
    }
  ]
}

एक (सख्त) मानकों का अनुपालन करने वाला JSON पार्सर इसे एक पार्स त्रुटि के साथ अस्वीकार कर देगा (वास्तविक संख्याओं के साथ NaN और Infinity टोकन मिश्रित होने के कारण)। अपने कोड में अनुरोधों/प्रतिक्रियाओं को सही ढंग से संभालने के लिए, एक JSON पार्सर का उपयोग करें जो इन टोकन का समर्थन करता है।

NaN , Infinity , -Infinity टोकन proto3 , Python JSON मॉड्यूल और जावास्क्रिप्ट भाषा द्वारा पहचाने जाते हैं।

उदाहरण

हम REST API को क्रियाशील देखने के लिए टॉय हाफ_प्लस_थ्री मॉडल का उपयोग कर सकते हैं।

REST API एंडपॉइंट के साथ मॉडलसर्वर प्रारंभ करें

गिट रिपॉजिटरी से half_plus_three मॉडल डाउनलोड करें:

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

हम मॉडलसर्वर को चलाने के लिए डॉकर का उपयोग करेंगे। यदि आप अपने सिस्टम पर मॉडलसर्वर को मूल रूप से इंस्टॉल करना चाहते हैं, तो इंस्टॉल करने के लिए सेटअप निर्देशों का पालन करें, और REST API एंडपॉइंट को निर्यात करने के लिए मॉडलसर्वर को --rest_api_port विकल्प के साथ शुरू करें (डॉकर का उपयोग करते समय इसकी आवश्यकता नहीं है)।

$ 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 कॉल करें

एक अलग टर्मिनल में, REST API कॉल करने के लिए curl टूल का उपयोग करें।

मॉडल की स्थिति इस प्रकार प्राप्त करें:

$ 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)" }
$