Membuat modul yang menemukan jalur baru yang dapat diservis

Dokumen ini menjelaskan cara memperluas Penyajian TensorFlow untuk memantau berbagai sistem penyimpanan guna menemukan (versi) model atau data baru untuk disajikan. Secara khusus, ini mencakup cara membuat dan menggunakan modul yang memantau jalur sistem penyimpanan untuk kemunculan sub-jalur baru, di mana setiap sub-jalur mewakili versi baru yang dapat diservis untuk dimuat. Modul semacam itu disebut Source<StoragePath> , karena modul tersebut memancarkan objek bertipe StoragePath (diketik menjadi string ). Itu dapat disusun dengan SourceAdapter yang membuat Loader yang dapat diservis dari jalur tertentu yang ditemukan oleh sumber.

Pertama, catatan tentang umum

Tidak diperlukan jalur sebagai pegangan untuk data yang dapat diservis; ini hanya mengilustrasikan satu cara untuk memasukkan server yang dapat diservis ke dalam sistem. Meskipun lingkungan Anda tidak merangkum data yang dapat diservis dalam jalur, dokumen ini akan membiasakan Anda dengan abstraksi utama. Anda mempunyai opsi untuk membuat modul Source<T> dan SourceAdapter<T1, T2> untuk tipe yang sesuai dengan lingkungan Anda (misalnya pesan RPC atau pub/sub, catatan database), atau sekadar membuat Source<std::unique_ptr<Loader>> yang monolitik Source<std::unique_ptr<Loader>> yang memancarkan loader yang dapat diservis secara langsung.

Tentu saja, apa pun jenis data yang dikeluarkan sumber Anda (apakah itu jalur POSIX, jalur Google Cloud Storage, atau pegangan RPC), harus ada modul pendamping yang dapat memuat server berdasarkan data tersebut. Modul seperti ini disebut SourceAdapters . Membuat yang kustom dijelaskan dalam dokumen Custom Servable . TensorFlow Serving hadir dengan satu untuk membuat instance sesi TensorFlow berdasarkan jalur dalam sistem file yang didukung TensorFlow. Seseorang dapat menambahkan dukungan untuk sistem file tambahan ke TensorFlow dengan memperluas abstraksi RandomAccessFile ( tensorflow/core/public/env.h ).

Dokumen ini berfokus pada pembuatan sumber yang memancarkan jalur dalam sistem file yang didukung TensorFlow. Bagian ini diakhiri dengan panduan tentang cara menggunakan sumber Anda bersama dengan modul yang sudah ada sebelumnya untuk menyajikan model TensorFlow.

Membuat Sumber Anda

Kami memiliki implementasi referensi Source<StoragePath> , yang disebut FileSystemStoragePathSource (di sources/storage_path/file_system_storage_path_source* ). FileSystemStoragePathSource memantau jalur sistem file tertentu, mengawasi subdirektori numerik, dan melaporkan subdirektori terbaru sebagai versi yang ingin dimuat. Dokumen ini menjelaskan aspek-aspek penting dari FileSystemStoragePathSource . Anda mungkin merasa nyaman untuk membuat salinan FileSystemStoragePathSource dan kemudian memodifikasinya sesuai kebutuhan Anda.

Pertama, FileSystemStoragePathSource mengimplementasikan Source<StoragePath> API, yang merupakan spesialisasi dari Source<T> API dengan T terikat ke StoragePath . API terdiri dari satu metode SetAspiredVersionsCallback() , yang menyediakan penutupan yang dapat dipanggil oleh sumber untuk mengomunikasikan bahwa ia ingin serangkaian versi tertentu yang dapat diservis dimuat.

FileSystemStoragePathSource menggunakan panggilan balik versi yang dicita-citakan dengan cara yang sangat sederhana: ia secara berkala memeriksa sistem file (pada dasarnya melakukan ls ), dan jika ia menemukan satu atau lebih jalur yang terlihat seperti versi yang dapat diservis, ia menentukan mana yang merupakan versi terbaru dan memanggil panggilan balik dengan daftar ukuran satu yang hanya berisi versi tersebut (di bawah konfigurasi default). Jadi, pada waktu tertentu FileSystemStoragePathSource meminta paling banyak satu servable untuk dimuat, dan implementasinya memanfaatkan idempotensi callback agar tetap stateless (tidak ada salahnya memanggil callback berulang kali dengan argumen yang sama).

FileSystemStoragePathSource memiliki pabrik inisialisasi statis (metode Create() ), yang mengambil pesan protokol konfigurasi. Pesan konfigurasi mencakup detail seperti jalur dasar untuk memantau dan interval pemantauan. Ini juga mencakup nama aliran yang dapat diservis untuk dipancarkan. (Pendekatan alternatif mungkin mengekstrak nama aliran yang dapat diservis dari jalur dasar, untuk memancarkan beberapa aliran yang dapat diservis berdasarkan pengamatan hierarki direktori yang lebih dalam; varian tersebut berada di luar cakupan implementasi referensi.)

Sebagian besar implementasi terdiri dari thread yang secara berkala memeriksa sistem file, bersama dengan beberapa logika untuk mengidentifikasi dan mengurutkan setiap sub-jalur numerik yang ditemukan. Utas diluncurkan di dalam SetAspiredVersionsCallback() (bukan di Create() ) karena pada titik itulah sumber harus "memulai" dan mengetahui ke mana harus mengirim permintaan versi yang dicita-citakan.

Menggunakan Sumber Anda untuk memuat sesi TensorFlow

Anda mungkin ingin menggunakan modul sumber baru bersama dengan SavedModelBundleSourceAdapter ( servables/tensorflow/saved_model_bundle_source_adapter* ), yang akan menafsirkan setiap jalur yang dikeluarkan sumber Anda sebagai ekspor TensorFlow, dan mengonversi setiap jalur menjadi loader untuk servis TensorFlow SavedModelBundle . Anda mungkin akan menyambungkan adaptor SavedModelBundle ke AspiredVersionsManager , yang menangani pemuatan dan penyajian server. Ilustrasi bagus tentang merangkai ketiga jenis modul ini untuk mendapatkan pustaka server yang berfungsi dapat ditemukan di servables/tensorflow/simple_servers.cc . Berikut adalah panduan alur kode utama (dengan penanganan kesalahan yang buruk; kode sebenarnya harus lebih berhati-hati):

Pertama, buat manajer:

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

Kemudian, buat adaptor sumber SavedModelBundle dan sambungkan ke pengelola:

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());

Terakhir, buat sumber jalur Anda dan sambungkan ke adaptor SavedModelBundle :

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

Fungsi ConnectSourceToTarget() (didefinisikan dalam core/target.h ) hanya memanggil SetAspiredVersionsCallback() untuk menghubungkan Source<T> ke Target<T> ( Target adalah modul yang menangkap permintaan versi yang dicita-citakan, yaitu adaptor atau manajer ).