יצירת מודול שמגלה נתיבים חדשים שניתנים להגשה

מסמך זה מסביר כיצד להרחיב את TensorFlow Serving לניטור מערכות אחסון שונות כדי לגלות (גרסאות של) דגמים או נתונים חדשים לשרת. בפרט, הוא מכסה כיצד ליצור ולהשתמש במודול המנטר נתיב מערכת אחסון להופעת נתיבים חדשים, כאשר כל תת נתיב מייצג גרסה חדשה שניתן להגשה לטעינה. סוג זה של מודול נקרא Source<StoragePath> , מכיוון שהוא פולט אובייקטים מסוג StoragePath (typedefed to string ). זה יכול להיות מורכב עם SourceAdapter שיוצר Loader שניתן להגשה מנתיב נתון שהמקור מגלה.

ראשית, הערה לגבי כלליות

אין צורך להשתמש בנתיבים כנקודות אחיזה לנתונים הניתנים להצגה; זה רק ממחיש דרך אחת להכניס חומרי הגשה למערכת. גם אם הסביבה שלך לא תכלול נתונים שניתנים להגשה בנתיבים, מסמך זה יכיר את ההפשטות העיקריות. יש לך אפשרות ליצור מודולי Source<T> ו- SourceAdapter<T1, T2> עבור סוגים המתאימים לסביבה שלך (למשל RPC או הודעות פאב/משנה, רשומות מסד נתונים), או פשוט ליצור Source<std::unique_ptr<Loader>> שפולט מעמיסים הניתנים להגשה ישירות.

כמובן, כל סוג של נתונים שהמקור שלך פולט (בין אם זה נתיבי POSIX, נתיבים של Google Cloud Storage או מטפלים ב-RPC), צריכים להיות מודולים נלווים שמסוגלים לטעון קבצי שרת על סמך זה. מודולים כאלה נקראים SourceAdapters . יצירת מותאם אישית מתוארת במסמך שניתן להגשה בהתאמה אישית . TensorFlow Serving מגיע עם אחד להפעלת הפעלות של TensorFlow המבוסס על נתיבים במערכות קבצים בהן TensorFlow תומך. אפשר להוסיף תמיכה במערכות קבצים נוספות ל-TensorFlow על ידי הרחבת ההפשטה RandomAccessFile ( tensorflow/core/public/env.h ).

מסמך זה מתמקד ביצירת מקור שפולט נתיבים במערכת קבצים הנתמכת ב-TensorFlow. זה מסתיים בהליכה כיצד להשתמש במקור שלך בשילוב עם מודולים קיימים כדי לשרת מודלים של TensorFlow.

יצירת המקור שלך

יש לנו יישום ייחוס של Source<StoragePath> , הנקרא FileSystemStoragePathSource (בכתובת sources/storage_path/file_system_storage_path_source* ). FileSystemStoragePathSource מנטרת נתיב מסוים של מערכת קבצים, עוקבת אחר ספריות משנה מספריות ומדווחת על העדכנית שבהן כגרסה שהיא שואפת לטעון. מסמך זה עובר על ההיבטים הבולטים של FileSystemStoragePathSource . ייתכן שיהיה לך נוח ליצור עותק של FileSystemStoragePathSource ולאחר מכן לשנות אותו כך שיתאים לצרכים שלך.

ראשית, FileSystemStoragePathSource מיישמת את ה-API Source<StoragePath> , שהוא התמחות של ה-API של Source<T> עם T קשור ל- StoragePath . ה-API מורכב משיטה יחידה SetAspiredVersionsCallback() , המספקת סגירה שהמקור יכול להפעיל כדי לתקשר שהוא רוצה שקבוצה מסוימת של גרסאות ניתנות להגשה תיטען.

FileSystemStoragePathSource משתמש ב-callback של הגירסאות הרצויות בצורה פשוטה מאוד: הוא בודק מעת לעת את מערכת הקבצים (עושה ls , בעצם), ואם הוא מוצא נתיב אחד או יותר שנראה כמו גירסה ניתנת להגשה, הוא קובע איזו מהן היא הגרסה האחרונה ומפעיל ההתקשרות חזרה עם רשימה בגודל 1 המכילה רק את הגרסה הזו (תחת תצורת ברירת המחדל). לכן, בכל זמן נתון FileSystemStoragePathSource מבקשת לטעון לכל היותר שרת אחד, והטמעתו מנצלת את האינטנסיביות של ה-callback כדי לשמור על עצמה חסרת מצב (אין שום נזק להפעיל את ה-callback שוב ושוב עם אותם טיעונים).

FileSystemStoragePathSource יש מפעל אתחול סטטי (שיטת Create() ), שמקבל הודעת פרוטוקול תצורה. הודעת התצורה כוללת פרטים כגון נתיב הבסיס לניטור ומרווח הניטור. זה כולל גם את שם הזרם שניתן להגשה לפלוט. (גישות אלטרנטיביות עשויות לחלץ את שם הזרם הניתן להגשה מנתיב הבסיס, כדי לפלוט זרמים מרובים שניתנים להגשה בהתבסס על התבוננות בהיררכיית ספריות עמוקה יותר; וריאציות אלו הן מעבר להיקף של יישום ההפניה).

עיקר היישום מורכב משרשור שבוחן מעת לעת את מערכת הקבצים, יחד עם היגיון כלשהו לזיהוי ומיון כל תת-נתיבים מספריים שהוא מגלה. השרשור מופעל בתוך SetAspiredVersionsCallback() (לא ב- Create() ) מכיוון שזו הנקודה שבה המקור צריך "להתחיל" ויודע לאן לשלוח בקשות לגרסה שאיפה.

שימוש במקור שלך לטעינת הפעלות של TensorFlow

סביר להניח שתרצה להשתמש במודול המקור החדש שלך בשילוב עם SavedModelBundleSourceAdapter ( servables/tensorflow/saved_model_bundle_source_adapter* ), אשר יפרש כל נתיב שהמקור שלך פולט כיצוא TensorFlow, וימיר כל נתיב לטעינה עבור TensorFlow SavedModelBundle שניתן להגשה. סביר להניח שתחבר את מתאם SavedModelBundle ל- AspiredVersionsManager , שדואג למעשה לטעון ולהגיש את הקבצים שניתן להגיש. המחשה טובה של שרשרת שלושת סוגי המודולים הללו יחד כדי להשיג ספריית שרת עובדת נמצאת ב- servables/tensorflow/simple_servers.cc . להלן סקירה של זרימת הקוד הראשית (עם טיפול שגיאות גרוע; קוד אמיתי צריך להיות זהיר יותר):

ראשית, צור מנהל:

std::unique_ptr<AspiredVersionsManager> manager = ...;

לאחר מכן, צור מתאם מקור SavedModelBundle וחבר אותו למנהל:

std::unique_ptr<SavedModelBundleSourceAdapter> bundle_adapter;
SavedModelBundleSourceAdapterConfig config;
// ... populate 'config' with TensorFlow options.
TF_CHECK_OK(SavedModelBundleSourceAdapter::Create(config, &bundle_adapter));
ConnectSourceToTarget(bundle_adapter.get(), manager.get());

לבסוף, צור את מקור הנתיב שלך וחבר אותו למתאם SavedModelBundle :

auto your_source = new YourPathSource(...);
ConnectSourceToTarget(your_source, bundle_adapter.get());

הפונקציה ConnectSourceToTarget() (מוגדרת ב- core/target.h ) רק מפעילה את SetAspiredVersionsCallback() כדי לחבר Source<T> ל- Target<T> ( Target הוא מודול שתופס בקשות לגרסה שאיפה, כלומר מתאם או מנהל ).