Rejoignez TensorFlow à Google I/O, du 11 au 12 mai. Inscrivez-vous maintenant

Création d'un module qui découvre de nouveaux chemins utilisables

Ce document explique comment étendre TensorFlow Serving pour surveiller différents systèmes de stockage afin de découvrir de nouveaux (versions de) modèles ou données à servir. En particulier, il explique comment créer et utiliser un module qui surveille un chemin de système de stockage pour l'apparition de nouveaux sous-chemins, où chaque sous-chemin représente une nouvelle version utilisable à charger. Ce genre de module est appelé Source<StoragePath> , car il émet des objets de type StoragePath (typedefed à string ). Il peut être composé d'une SourceAdapter qui crée un diffusable Loader à partir d' un chemin donné que les sources découvre.

Tout d'abord, une note sur la généralité

L'utilisation de chemins comme descripteurs de données pouvant être servies n'est pas requise ; il illustre simplement une façon d'ingérer des servables dans le système. Même si votre environnement n'encapsule pas de données utilisables dans des chemins, ce document vous familiarisera avec les abstractions clés. Vous avez la possibilité de créer Source<T> et SourceAdapter<T1, T2> modules pour les types qui conviennent à votre environnement (RPC ou pub / messages sous, enregistrements de base de données), ou simplement créer un monolithique Source<std::unique_ptr<Loader>> qui émet des chargeurs diffusables directement.

Bien sûr, quel que soit le type de données émises par votre source (qu'il s'agisse de chemins POSIX, de chemins de stockage Google Cloud ou de descripteurs RPC), il doit y avoir un ou plusieurs modules d'accompagnement capables de charger des serveurs sur cette base. Ces modules sont appelés SourceAdapters . Création d' un personnalisé est décrit dans le diffusables personnalisé document. TensorFlow Serving est fourni avec un pour instancier les sessions TensorFlow en fonction des chemins dans les systèmes de fichiers pris en charge par TensorFlow. On peut ajouter le support pour les systèmes de fichiers supplémentaires à tensorflow par l' extension de la RandomAccessFile abstraction ( tensorflow/core/public/env.h ).

Ce document se concentre sur la création d'une source qui émet des chemins dans un système de fichiers pris en charge par TensorFlow. Il se termine par une présentation de l'utilisation de votre source en conjonction avec des modules préexistants pour servir les modèles TensorFlow.

Création de votre source

Nous avons une implémentation de référence d'une Source<StoragePath> , appelé FileSystemStoragePathSource (à des sources/storage_path/file_system_storage_path_source* ). FileSystemStoragePathSource surveille un chemin du système de fichiers particulier, montres pour les sous-répertoires numériques, et signale le dernier en date que la version qu'il aspire à la charge. Ce document guide à travers les aspects saillants de FileSystemStoragePathSource . Vous trouverez peut - être commode de faire une copie de FileSystemStoragePathSource puis le modifier en fonction de vos besoins.

Tout d' abord, FileSystemStoragePathSource met en œuvre la Source<StoragePath> API, ce qui est une spécialisation de la Source<T> API avec T liés à StoragePath . L'API est constitué d'une seule méthode SetAspiredVersionsCallback() , qui fournit une fermeture de la source peut invoquer pour communiquer qu'il veut un ensemble de versions diffusables à charger.

FileSystemStoragePathSource utilise les-versions aspiraient callback d'une manière très simple: il inspecte périodiquement le système de fichiers (faire un ls , essentiellement), et si elle trouve un ou plusieurs chemins qui ressemblent à des versions diffusables il détermine lequel est la dernière version et invoque le rappel avec une liste de taille un contenant uniquement cette version (sous la configuration par défaut). Donc, à un moment donné FileSystemStoragePathSource demandes au plus un diffusable à charger, et sa mise en œuvre profite de l'idempotence de la fonction de rappel pour se maintenir sans état (il n'y a pas de mal à invoquer le rappel à plusieurs reprises avec les mêmes arguments).

FileSystemStoragePathSource a une usine d'initialisation statique (le Create() de la méthode), qui prend un message de protocole de configuration. Le message de configuration comprend des détails tels que le chemin de base à surveiller et l'intervalle de surveillance. Il inclut également le nom du flux pouvant être diffusé à émettre. (D'autres approches pourraient extraire le nom du flux utilisable du chemin de base, pour émettre plusieurs flux utilisables en fonction de l'observation d'une hiérarchie de répertoires plus profonde ; ces variantes dépassent le cadre de l'implémentation de référence.)

La majeure partie de l'implémentation consiste en un thread qui examine périodiquement le système de fichiers, ainsi qu'une logique pour identifier et trier tous les sous-chemins numériques qu'il découvre. Le fil est lancé à l' intérieur SetAspiredVersionsCallback() (pas Create() ) parce que c'est le point auquel la source doit « commencer » et sait où envoyer des demandes de version aspiraient.

Utiliser votre source pour charger des sessions TensorFlow

Vous voudrez probablement utiliser votre nouveau module source conjointement avec SavedModelBundleSourceAdapter ( servables/tensorflow/saved_model_bundle_source_adapter* ), qui interprétera chaque ACHEMINEMENT émet source comme une exportation de tensorflow, et convertir chaque chemin d'un chargeur pour une tensorflow SavedModelBundle diffusable. Vous branchez probablement le SavedModelBundle adaptateur dans un AspiredVersionsManager , qui prend en charge le chargement et en fait au service des servables. Une bonne illustration de ces enchaînant trois types de modules ensemble pour obtenir une bibliothèque de serveur de travail se trouve dans servables/tensorflow/simple_servers.cc . Voici un aperçu du flux de code principal (avec une mauvaise gestion des erreurs ; le vrai code devrait être plus prudent) :

Tout d'abord, créez un gestionnaire :

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

Ensuite, créez un SavedModelBundle adaptateur source et branchez - le dans le gestionnaire:

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

Enfin, créez votre source de chemin et branchez - le dans le SavedModelBundle adaptateur:

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

Le ConnectSourceToTarget() fonction (définie dans le core/target.h ) invoque simplement SetAspiredVersionsCallback() pour connecter une Source<T> à une Target<T> (une Target est un module qui aspirent les captures demandes de version, à savoir un adaptateur ou un gestionnaire ).