הצטרף לקהילת SIG TFX-Addons ועזור להפוך את TFX לטוב עוד יותר! הצטרף לתוספות SIG TFX

ממשק API RESTful

בנוסף ל- API של gRPC תומך TensorFlow ModelServer גם ב- API של RESTful. דף זה מתאר נקודות קצה אלה של API ודוגמא מקצה לקצה לשימוש.

הבקשה והתגובה היא אובייקט JSON. הרכב אובייקט זה תלוי בסוג הבקשה או בפועל. לפרטים, עיין בסעיפים הספציפיים לממשק API.

במקרה של שגיאה, כל ממשקי ה- API יחזירו אובייקט JSON בגוף התגובה עם error כמפתח ואת הודעת השגיאה כערך:

{
  "error": <error message string>
}

ממשק API למצב דגם

ממשק API זה עוקב מקרוב אחר ה- API של ModelService.GetModelStatus gRPC. הוא מחזיר את הסטטוס של מודל ב- ModelServer.

כתובת אתר

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

כולל /versions/${VERSION} או /labels/${LABEL} הוא אופציונלי. אם הסטטוס של כל הגרסאות שהושמט מוחזר בתגובה.

פורמט תגובה

אם יצליח, מחזיר ייצוג JSON של GetModelStatusResponse protobuf.

ממשק API של מטא נתונים

ממשק API זה עוקב מקרוב אחר ה- PredictionService.GetModelMetadata gRPC API. הוא מחזיר את המטא-נתונים של מודל ב- ModelServer.

כתובת אתר

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

כולל /versions/${VERSION} או /labels/${LABEL} הוא אופציונלי. אם הושמט, מטא הנתונים של הגרסה האחרונה מוחזרים בתגובה.

פורמט תגובה

אם יצליח, מחזיר ייצוג JSON של GetModelMetadataResponse protobuf.

סיווג ו- Regress API

ממשק API זה עוקב מקרוב אחר השיטות Classify and Regress של PredictionService gRPC API.

כתובת אתר

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

כולל /versions/${VERSION} או /labels/${LABEL} הוא אופציונלי. אם הושמט משתמשים בגרסה האחרונה.

פורמט בקשה

גוף הבקשה לממשקי ה- API 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> היא רשימה של ערכים כאלה. פורמט זה דומה לפרוטוס ClassificationRequest ו- RegressionRequest של gRPC. שתי הגרסאות מקבלות רשימת אובייקטים 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> הוא מספר עשרוני.

משתמשים ב- gRPC API יבחינו בדמיון של פורמט זה עם ClassificationResponse ו- RegressionResponse protos.

חיזוי API

ממשק API זה עוקב מקרוב אחר ה- PredictionService.Predict API של gRPC.

כתובת אתר

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

כולל /versions/${VERSION} או /labels/${LABEL} הוא אופציונלי. אם הושמט נעשה שימוש בגרסה האחרונה.

פורמט בקשה

גוף הבקשה לממשק API 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>
}

ציון טנזורי קלט בפורמט שורה.

פורמט זה דומה PredictRequest פרוטו של API gRPC ואת 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 ( שניים בדוגמה לעיל, מכיוון שיש שני אובייקטים ברשימת המקרים ). אם ציינת תשומות בעלות ממד 0th שונה, השתמש בתבנית העמודה המתוארת להלן.

ציון טנזורי קלט בפורמט עמודות.

השתמש בתבנית זו כדי לציין את טנסורי הקלט שלך, אם תשומות בעלות שם אינן בעלות אותו ממד 0 או שאתה רוצה ייצוג קומפקטי יותר. תבנית זו דומה inputs בתחום gRPC Predict בקשה.

בפורמט העמודי, הקלטים מקודדים למפתח הקלט בבקשת JSON.

הערך עבור מקש הקלט יכול להיות טנסור קלט יחיד או מפה של שם קלט לטנסורים (המופיעים בצורתם המקוננת הטבעית). כל קלט יכול להיות בעל צורה שרירותית ואינו צריך לחלוק את אותו ממד 0 / (aka גודל אצווה) כנדרש בפורמט השורה המתואר לעיל.

הייצוג העמודי של הדוגמה הקודמת הוא כדלקמן:

{
 "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 שיש להם סיומת בשם נחשבים _bytes ערכים בינאריים. ערכים כאלה מקודדים בצורה שונה כמתואר בסעיף קידוד הערכים הבינאריים להלן.

מיפוי JSON

ממשקי ה- API של RESTful תומכים בקידוד קנוני ב- 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 יהיה מספר עשרוני.
DT_FLOAT, DT_DOUBLE מספר 1.1, -10.0, 0, NaN , Infinity ערך JSON יהיה מספר או אחד מערכי האסימונים המיוחדים - NaN , Infinity ו- -Infinity . ראה התאמה של JSON למידע נוסף. מקבלים גם סימון מעריכי.

דיוק נקודה צפה

ל- JSON יש סוג נתונים של מספר יחיד. לפיכך ניתן לספק ערך עבור קלט המביא לאובדן דיוק. לדוגמא, אם הקלט x הוא סוג נתונים float , והקלט {"x": 1435774380} נשלח לדגם הפועל על חומרה המבוססת על תקן הנקודה הצפה IEEE 754 (למשל אינטל או AMD), אז הערך יהיה יומרו בשקט על ידי החומרה של תת-הרישום ל- 1435774336 מכיוון 1435774336 1435774380 לא יכול להיות מיוצג בדיוק במספר נקודה צפה של 32 סיביות. בדרך כלל, התשומות להגשה צריכות להיות זהה להפצה כמו אימון, כך שבדרך כלל זה לא יהיה בעייתי מכיוון שאותן המרות אירעו בזמן האימון. עם זאת, במקרה שנדרש דיוק מלא, הקפד להשתמש בסוג נתונים בסיסי במודל שלך שיכול להתמודד עם הדיוק הרצוי ו / או לשקול בדיקת צד הלקוח.

קידוד ערכים בינאריים

JSON משתמש בקידוד UTF-8. אם יש לך תכונת קלט או ערכי טנסור שצריכים להיות בינאריים (כמו בתים של תמונה), עליך Base64 לקודד את הנתונים b64 באובייקט JSON עם 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 עושה).

ממשק ה- API של REST המתואר בעמוד זה מאפשר לאובייקטים של JSON לבקשה / תגובה לקבל ערכים כאלה. מכאן משתמע שבקשות כמו הבאות תקפות:

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

A (קפדנים) בהתאם לתקנים הנדרש מנתח JSON ידחה זה עם שגיאה בניתוח (עקב NaN ו Infinity אסימונים מעורב עם מספרים אמיתיים). כדי לטפל נכון בבקשות / תגובות בקוד שלך, השתמש בניתוח JSON התומך באסימונים אלה.

NaN , Infinity , -Infinity אסימונים מוכרים על ידי proto3 , Python JSON מודול ושפה JavaScript.

דוגמא

אנו יכולים להשתמש במודל הצעצוע half_plus_three כדי לראות ממשקי API של REST בפעולה.

הפעל את ModelServer עם נקודת הקצה של REST API

הורד את המודל half_plus_three ממאגר git :

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

נשתמש ב- Docker להפעלת ModelServer. אם ברצונך להתקין את ModelServer באופן מקורי במערכת שלך, עקוב אחר הוראות ההתקנה להתקנה במקום זאת, והפעל את ModelServer באמצעות אפשרות --rest_api_port כדי לייצא את נקודת הקצה של 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 ...

בצע שיחות REST API ל- ModelServer

במסוף אחר, השתמש בכלי 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 זמינה בשם חתימה שאינו ברירת מחדל ויש לציין אותה במפורש. כתובת אתר או גוף שגוי של בקשה מחזירים סטטוס שגיאת 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)" }
$