Applications intelligentes

Maîtriser l'intelligence sur l'appareil avec ML Kit et LiteRT dans les services Google Play

Haut-parleurs

  • Chintan Parikh

    Responsable produit principal

  • Fergus Henderson

    Staff Software Engineer

À propos

À propos de l'intervention

Plus besoin de choisir entre la commodité de l'IA plug-and-play et la flexibilité des modèles personnalisés : vous pouvez déployer les deux dans une seule application ultra-légère sans ajouter de mégaoctets de code binaire inutile.

Dans cette session, nous allons vous montrer comment créer cette architecture double pile dans une seule application Android. Vous découvrirez comment exploiter ML Kit pour des tâches de ML classiques prêtes à l'emploi (comme la numérisation de documents) ainsi que LiteRT autonome dans les services Play pour vos charges de travail de vision par ordinateur ou audio personnalisées. Nous verrons en détail comment les deux chemins d'implémentation s'unissent en arrière-plan pour utiliser l'environnement d'exécution LiteRT moderne, offrant ainsi à votre application des performances fluides avec accélération matérielle sur les processeurs et les GPU, avec une empreinte de téléchargement de pratiquement zéro octet.

Points essentiels à retenir pour les développeurs :

- Performances sans compromis : les modèles clés en main et personnalisés sont automatiquement accélérés au niveau matériel à l'aide de l'API CompiledModel unifiée.

- Micro-APK : réduisez considérablement la taille de téléchargement de votre application en déchargeant les environnements d'exécution ML Kit et LiteRT vers les services Play.

- Intégration hybride : apprenez à exécuter plusieurs workflows de ML en parallèle en production sans conflits de ressources.

Résumé

  • LiteRT dans les services Google Play partage un environnement d'exécution géré entre les applications afin de réduire la taille des APK d'environ 8 Mo.
  • Les fonctionnalités ML Kit clés en main et les modèles LiteRT personnalisés peuvent s'exécuter ensemble dans une même application sur le même environnement d'exécution.
  • L'API CompiledModel simplifie l'accélération GPU et offre des performances jusqu'à 1,4 fois plus rapides que l'inférence GPU TFLite ancienne.
  • La disponibilité de la plate-forme s'étend au-delà des téléphones, à Wear OS 4 ou version ultérieure et à Android Automotive OS sur Android 11 ou version ultérieure.
  • Pour adopter LiteRT dans les services Google Play, vous devez mettre à jour les dépendances Maven vers play-services-litert, appeler LiteRt.initialize pour obtenir un environnement et le transmettre à CompiledModel.create.
  • Nous vous recommandons de migrer vers l'API CompiledModel 2.x, car la version 1.x est en mode de maintenance et l'API NN va disparaître.

Compétences

Ressources

Gemini Notebook

Thèmes

  • on-device-ai
  • ml-kit
  • litert
  • google-play-services
  • accélération-gpu
  • machine-learning

Transcription

Introduction et présentation de LiteRT

  • Bonsoir à toutes et à tous.

  • Nous allons commencer la présentation.

  • Ainsi, lorsque les gens parlent d'IA sur l'appareil aujourd'hui, ils font souvent référence aux LLM.

  • Plus tôt dans la journée, vous avez assisté à plusieurs présentations sur Gemini Nano, qui ont abordé ML Kit, Firebase et de nombreux autres produits Google.

  • Cette session porte sur l'autre moitié : le ML classique et le modèle que vous apportez vous-même.

  • Vous l'avez probablement déjà utilisé plusieurs fois aujourd'hui sans même le savoir.

  • Pensez à l'utilisation de l'une de vos applications dans laquelle vous avez flouté l'arrière-plan, utilisé un lecteur de code-barres ou utilisé un type de retouche d'image.

  • Une grande partie de ces fonctionnalités repose sur le ML classique et s'exécute généralement sur l'appareil.

  • Si vous avez déjà ajouté l'une de ces fonctionnalités à votre propre application ou APK, vous avez souvent dû faire un choix : utiliser une API clé en main ou importer votre propre modèle ?

  • Quel sera l'impact sur la taille de mon application ?

  • Aujourd'hui, vous verrez que vous n'avez pas à choisir entre une solution clé en main ou l'utilisation de votre propre modèle.

  • En fait, vous pouvez faire les deux avec un seul environnement d'exécution léger.

  • Je m'appelle Chintan Parikh.

  • Je suis responsable produit pour LiteRT, et je suis accompagné de Fergus, responsable de l'ingénierie pour les services de ML Android.

  • Bonjour.

  • À la fin, vous verrez comment créer une application exécutant deux modèles sur chaque image de la caméra à environ 30 images par seconde.

  • Cette présentation est divisée en quatre parties.

  • Dans la première partie, nous allons parler des solutions d'IA sur l'appareil de Google axées sur le ML classique, à savoir ML Kit et LiteRT.

  • Ensuite, nous verrons les nouveautés de LiteRT et des services Play.

  • Nous allons également aborder la nouvelle API CompiledModel de LiteRT et les appareils que nous prenons en charge.

  • Troisièmement, nous vous montrerons comment créer une application.

  • Fergus va vous expliquer comment créer une application avec ML Kit et un modèle personnalisé, le tout dans un seul APK.

  • Enfin, nous allons vous montrer comment mettre à niveau une application existante à l'aide du mode Agent.

  • Vous pouvez même créer une application à l'aide de cet agent.

  • Très bien.

  • Commençons par définir ce qu'est LiteRT.

  • LiteRT est l'environnement d'exécution d'inférence sur l'appareil de Google pour vos propres modèles.

  • Il utilise le même format de fichier .tflite que celui que vous avez utilisé précédemment avec TensorFlow Lite.

  • Il a été repensé pour améliorer les performances et est également compatible avec plusieurs frameworks.

  • Cela signifie que vous pouvez importer des modèles depuis PyTorch, TensorFlow et même JAX pour les convertir au format FlatBuffer pour LiteRT.

  • Depuis 2022, TensorFlow Lite dans les services Google Play est l'environnement d'exécution officiel sur l'appareil d'Android pour les modèles personnalisés.

  • Aujourd'hui, nous lui apportons une mise à niveau majeure, et c'est ce dont nous allons parler en grande partie.

  • La mise à niveau apportera la dernière API LiteRT CompiledModel, y compris une nouvelle inférence GPU améliorée qui sera 1,4 fois plus rapide, et vous permettra également de créer des applications plus petites avec des APK beaucoup plus légers.

  • Alors, pourquoi la proposer via les services Google Play ?

  • Il y a plusieurs avantages, et c'est un problème majeur que je constate dans de nombreuses discussions, où la taille de l'application et l'encombrement de l'APK deviennent un véritable défi, n'est-ce pas ?

  • Vous obtenez ainsi un petit environnement d'exécution.

  • Le moteur d'exécution n'est pas dans votre APK. Vous dépendez donc d'un client léger, ce qui réduit la taille de votre APK d'environ 8 Mo.

  • Le deuxième avantage est l'efficacité.

  • Vous disposez d'une copie de l'environnement d'exécution. L'environnement d'exécution LiteRT est donc partagé entre toutes les applications.

  • Imaginez que vous ayez de nombreuses applications, chacune d'entre elles pourrait vous faire économiser 8 Mo.

  • Cela s'accumule très rapidement lorsque vous essayez d'économiser de l'espace disque et d'avoir une application plus légère.

  • Deuxièmement, il est géré.

  • Google fournit les corrections de bugs, résout les problèmes de pilote GPU que vous n'aurez pas à gérer, et toutes les autres mises à jour de sécurité sont également fournies via des mises à jour automatiques.

  • Comme je l'ai mentionné, le GPU est plus rapide (1, 4 fois plus rapide, pour être précis). Nous y reviendrons plus en détail.

  • En termes de couverture, nous pouvons livrer sur des appareils Android plus anciens.

  • LiteRT dans les services Play est compatible avec Android 7 (sorti en 2016) et les versions ultérieures.

  • Comme Fergus vous le montrera également, nous étendons notre compatibilité à d'autres nouveaux appareils dans les diapositives à venir.

  • Il s'agit donc du véhicule de livraison. Passons maintenant à l'étape suivante : l'environnement d'exécution.

  • LiteRT n'est donc pas nouveau et n'est pas expérimental.

  • TensorFlow Lite et LiteRT sont déjà exécutés dans plus de 250 000 applications.

  • Il est également exécuté sur plus de 3,8 milliards d'appareils aujourd'hui.

  • Vous ne le savez peut-être pas, mais de nombreuses applications que vous utilisez fonctionnent grâce à cela.

  • Cela équivaut également à plus de mille milliards d'inférences par jour.

  • À cette échelle, nous avons certainement rencontré tous les problèmes de chipset, nous avons pu résoudre les problèmes de ROM ou de pilote GPU, et nous avons une solution de contournement pour vous.

  • LiteRT est également utilisé par Google pour ses applications phares, sur différentes applications, plates-formes et même plusieurs appareils.

  • Les effets des Shorts YouTube, la segmentation de l'arrière-plan dans Meet et la fonctionnalité Anti-flou sont quelques exemples de modèles d'images lourds et de vidéos en temps réel qui s'exécutent tous sur LiteRT.

  • C'est également très important, car il est essentiel de proposer des cas d'utilisation rapides et attrayants aux utilisateurs, n'est-ce pas ?

  • Il s'agit donc du même environnement d'exécution que celui que nous avons renforcé pour ces fonctionnalités phares, et c'est ce que vous obtenez via les services Play.

Pourquoi exécuter l'IA sur l'appareil ?

  • Voyons également pourquoi il est intéressant d'utiliser l'IA sur l'appareil.

  • Si la latence, la confidentialité, le fonctionnement hors connexion ou les coûts réduits sont importants pour vous, exécutez-le hors connexion.

  • Il peut y avoir d'autres raisons, mais ce sont les plus évidentes que nous avons entendues pour l'exécution sur l'appareil.

  • L'exécution sur l'appareil n'est pas toujours sans frais.

  • Il comporte quelques nuances et défis.

  • Nous allons donc également passer en revue certains de ces défis et vous proposer une solution.

  • Parlons des performances. Comme vous l'avez vu dans certains exemples d'applications précédentes, les budgets de latence et de mémoire sont toujours serrés.

  • La vidéo et l'audio en temps réel nécessitent une efficacité extrême.

  • Même les fonctionnalités interactives simples doivent être rapides.

  • Sinon, vous perdez l'engagement des utilisateurs.

  • Diversité matérielle : il existe des centaines de SoC avec différentes configurations de CPU et de GPU.

  • Vous ne pouvez pas écrire de code pour chacun d'eux, n'est-ce pas ?

  • Comment résoudre ces problèmes ?

  • Taille de l'APK : l'intégration d'un environnement d'exécution natif augmente également la taille de chaque téléchargement, ce qui peut avoir un impact sur vos taux de conversion.

  • Personnalisation : l'entraînement, la qualité et la taille du modèle sont des facteurs extrêmement importants avant même le déploiement.

  • Oui, créer une application de qualité sur l'appareil peut être difficile.

  • Mais dans chacune de ces situations, nous voulons que la plate-forme fasse le travail à votre place, et non l'inverse, n'est-ce pas ?

  • Le portefeuille de solutions sur l'appareil de Google permet de relever ces défis, et nous allons l'examiner ensuite.

  • Nous allons donc nous concentrer sur deux solutions simples aujourd'hui.

  • Il existe deux façons simples d'ajouter l'IA sur l'appareil via les services Play.

  • Le parcours 1 est la solution clé en main utilisant ML Kit, n'est-ce pas ?

  • Il s'agit d'API de vision et de langage prêtes à l'emploi, qui nécessitent peu d'expertise en ML. De nombreux modèles sont fournis et tous sont diffusés via les services Play.

  • Nous verrons également quelques exemples dans les prochaines diapositives.

  • Le chemin personnalisé, qui passe par LiteRT.

  • LiteRT vous permet d'utiliser votre propre modèle et de l'exécuter sur un processeur ou un GPU.

  • L'environnement d'exécution provient également des services Play.

  • Il n'est donc pas intégré à votre APK.

  • Ces deux approches ne sont pas mutuellement exclusives.

  • Ils peuvent également être plus efficaces ensemble.

  • C'est exactement ce que nous allons créer aujourd'hui, en quelques minutes.

  • Mais d'abord, voyons ce que couvre ML Kit.

  • Voici ce que ML Kit couvre d'emblée.

  • Si vous pensez déjà que certaines de ces fonctionnalités répondent à vos besoins, c'est un excellent point de départ et vous avez déjà une longueur d'avance.

  • Nous proposons des fonctionnalités de vision, de lecture de codes-barres, de documents, de texte, de pose, et bien d'autres encore, ainsi que des API de langage telles que la traduction, les réponses suggérées et même l'extraction d'entités.

  • Le point essentiel est que bon nombre de ces API de vision et de langage s'exécutent toutes avec LiteRT en arrière-plan.

  • Si ML Kit répond à vos besoins, vous pouvez commencer par là.

  • Et si ce n'est pas le cas, vous pouvez utiliser votre propre modèle.

  • Et voici le point essentiel : ML Kit et votre modèle personnalisé ne seront pas deux environnements d'exécution, comme je l'ai mentionné.

  • Imaginez-les comme deux portes d'entrée menant au même LiteRT qui s'exécutera en arrière-plan.

  • LiteRT sera donc l'environnement d'exécution qui orchestrera ces deux fonctionnalités.

  • Si votre application utilise déjà le Play Store, vous pouvez l'utiliser pour ML Kit.

  • Sinon, nous allons également examiner le chemin d'accès LiteRT.

Nouveautés de LiteRT

  • Voyons également les nouveautés de LiteRT.

  • Comme je l'ai mentionné, LiteRT est une évolution de TensorFlow Lite.

  • Les améliorations les plus importantes sont un GPU plus rapide.

  • Le GPU plus rapide est compatible avec OpenCL et OpenGL, et offre une compatibilité multiplateforme, même pour les backends Metal.

  • Vous pouvez donc l'utiliser pour plusieurs plates-formes, selon vos besoins.

  • C'est également plus simple.

  • Nous disposons d'un workflow unifié pour l'accélération du processeur, du GPU et du NPU.

  • Le CPU et le GPU sont actuellement dans les services Play, tandis que le NPU est intégré via LiteRT, et ce travail est en cours.

  • Auparavant, chaque accélérateur nécessitait une configuration de délégué différente, n'est-ce pas ?

  • Vous n'avez plus qu'à le faire une seule fois.

  • Il existe donc une API avec un remplacement automatique par le processeur, et vous n'avez pas besoin de configurer des délégués dédiés.

  • Vous pouvez simplement utiliser des appels d'accélérateur qui peuvent gérer cela beaucoup plus simplement et avec moins de code.

  • Il est également puissant, car le même modèle s'exécute sur plusieurs plates-formes, comme je l'ai mentionné.

  • La flexibilité est un aspect crucial.

  • Le format .tflite reste donc le même.

  • Si vous aviez déjà une application, vous pouvez toujours utiliser ce format.

  • Si vous créez une application, vous pouvez réutiliser ce format de fichier.

  • Il est également intéressant de noter que nous prenons en charge l'API Interpreter, qui se trouvait auparavant dans TensorFlow Lite.

  • Si vous souhaitez effectuer une migration par étapes, l'API Interpreter est incluse dans le nouveau LiteRT, ce qui facilite la migration.

  • Voilà pour l'environnement d'exécution.

  • Voyons ce que vous pouvez créer avec.

  • Voici ce que les applications Android développent aujourd'hui.

  • Tout, des effets de l'appareil photo à la retouche photo, en passant par la saisie intelligente, les jeux et les avatars, n'est-ce pas ?

  • Beaucoup de ces applications auront besoin de fonctionnalités en temps réel.

  • Le GPU envoie des images directement depuis la caméra. Il est donc important que les éléments soient réactifs et en temps réel.

  • Certains de ces modèles de retouche photo sont également de plus en plus lourds.

  • Il en va de même pour les fonctionnalités de RA/RV que vous avez également vues dans certaines des démonstrations avec les lunettes. Beaucoup d'entre elles exécutent LiteRT en arrière-plan.

  • Il s'agit du même environnement d'exécution que celui qui est désormais utilisé pour les fonctionnalités phares de Google, ainsi que dans les services Play. Vous bénéficiez donc de tout cela sans avoir à ajouter quoi que ce soit à votre APK.

  • Maintenant, pourquoi ne pas créer une application ? Fergus va nous montrer comment faire.

  • C'est ce que nous allons faire à présent.

  • Merci, Chintan.

  • Je vais donc vous parler un peu des nouveautés de LiteRT dans les services Google Play.

  • Avant de passer à la compilation, une dernière chose : tout ce que vous venez de voir ne fonctionne pas seulement sur les téléphones. LiteRT dans les services Play est également disponible sur Wear OS et Android Automotive OS.

  • Vous pouvez donc exécuter des modèles sur l'appareil, sur votre montre ou un autre accessoire connecté, ou dans la voiture elle-même.

  • Auparavant, il était possible d'utiliser une application sur votre téléphone qui servait d'application associée à Wear, mais vous pouvez désormais l'exécuter sur l'accessoire connecté lui-même, et il en va de même pour Android Automotive.

  • Vous disposez ainsi de la même API, du même modèle .tflite, mais de plus de surfaces.

  • Il n'est pas nécessaire d'implémenter une solution distincte pour chaque facteur de forme. Vous pouvez utiliser la même implémentation pour tous ces différents appareils.

  • L'avantage du paradigme de distribution des services Play est que nous pouvons rétro-porter cette fonctionnalité pour qu'elle s'exécute sur des appareils plus anciens.

  • Pour Android Automotive OS, nous prenons en charge les versions jusqu'à Android 11, sorti en 2020. Pour Wear OS, nous prenons en charge Wear OS 4 et les versions ultérieures.

  • OK.

  • Je vais maintenant parler de deux approches différentes : créer une application et mettre à niveau une application existante.

  • C'est ce que nous allons aborder dans la suite de cette présentation.

  • Je vais donc commencer par un exemple d'application qui combine l'utilisation de ML Kit avec un modèle de GPU personnalisé exécuté sur LiteRT.

  • Pour mettre à niveau une application existante, trois petites modifications sont nécessaires : une modification Gradle pour mettre à jour les dépendances, une modification d'initialisation pour activer LiteRT dans les services Play, puis le passage de l'API Interpreter à l'API CompiledModel.

  • Mais nous allons d'abord nous intéresser à la nouvelle application, car la mise à niveau est beaucoup plus logique une fois que vous avez vu ce vers quoi vous effectuez la mise à niveau.

Présentation de l'exemple d'application

  • Créer une application.

  • Voici l'application que nous allons créer.

  • Il propose une vue en direct de la caméra, où vous restez net et l'arrière-plan prend un style artistique.

  • Nous allons donc prendre le cadre de la caméra.

  • Nous allons diffuser les images de l'appareil photo via la segmentation de selfie de ML Kit.

  • Il s'agit de l'une des API ML Kit clés en main existantes.

  • Cela va produire un masque de premier plan qui indiquera en gros quels pixels de l'image correspondent à la personne sur l'image.

  • Nous allons ensuite prendre notre modèle personnalisé, qui est un modèle de transfert de style, et l'appliquer à une image.

  • Nous allons l'appliquer à l'ensemble de l'image de la caméra, mais seule la partie arrière-plan nous intéresse. En effet, nous allons prendre l'image d'origine de la caméra, le masque et l'arrière-plan stylisé, puis les combiner à l'aide d'une logique simple. Nous obtiendrons ainsi une image composite dans laquelle le sujet est conservé et l'arrière-plan est stylisé.

  • Nous voulons donc utiliser des API clés en main lorsqu'elles existent, et des API personnalisées lorsqu'elles permettent de différencier notre application.

  • Il s'agit de la première partie, où nous appelons l'API ML Kit Selfie Segmentation.

    // 1. Configure and create segmenter client
    val segmenter = Segmentation.getClient(
        SelfieSegmenterOptions.Builder()
            .setDetectorMode(
                SelfieSegmenterOptions.STREAM_MODE)
            .build())
    
    // 2. Prepare image & run inference
    fun processFrame(mediaImage: Image) {
      val image = InputImage.fromMediaImage(
          mediaImage, /* rotationDegrees= */ 0)
      segmenter.process(image)
          .addOnSuccessListener { mask -> … }
    }
  • Il s'agit donc d'une API standard, n'est-ce pas ?

  • C'est le pain quotidien des développeurs Android.

  • Il vous suffit de consulter la documentation de l'API ou de demander à Gemini de le créer pour vous.

  • Mais, vous savez, c'est assez simple.

  • Vous créez un client et vous transmettez certaines options lors de la création du client.

  • Dans ce cas, nous spécifions le mode de streaming afin de pouvoir traiter un flux d'images vidéo.

  • Ensuite, vous appelez la méthode "process" et le rappel de celle-ci récupère le masque renvoyé, calculé par la segmentation de selfie.

  • L'entrée est l'image de la caméra.

  • Toutes ces API utilisent des types au niveau de l'application, et non des tenseurs bruts. Vous programmez donc à un niveau très élevé, ce qui est très simple.

Modèles personnalisés sur LiteRT

  • Pour la deuxième partie, le modèle personnalisé, nous allons utiliser un modèle PyTorch.

  • Je pense que Chintan a trouvé celui-ci sur Kaggle ou Hugging Face…

  • C'est vrai.

  • Oui, et vous pouvez aussi convertir vos propres fichiers.

  • Vous pouvez créer votre propre modèle.

  • Désolé, je reviens en arrière.

  • Voici à quoi ressemble la pile.

  • Vous prenez un modèle PyTorch, vous pouvez le convertir et le quantifier, puis vous obtenez un modèle LiteRT.

  • Vous pouvez ensuite distribuer ce fichier avec votre application, comme vous le souhaitez.

  • Il peut être intégré à l'application en tant qu'élément ou téléchargé séparément.

  • Les deux méthodes fonctionnent.

  • qui repose sur l'environnement d'exécution LiteRT dans les services Play.

  • Ensuite, il y a les noyaux de CPU pour l'optimisation sur CPU, et ML Drift est le nom de l'accélérateur GPU.

  • Comme je l'ai dit, vous obtenez le modèle TFLite. Vous pouvez soit entraîner le modèle vous-même, soit trouver un modèle existant. Les deux méthodes fonctionnent.

  • La conversion depuis PyTorch ne nécessite que quelques lignes de code Python.

    import litert_torch
    
    model = my_models.Stylizer().eval()
    
    # Convert with torch.export under the hood
    edge_model = litert_torch.convert(
        model, sample_inputs)
    edge_model.export("stylizer_f32.tflite")
  • Vous installez LiteRT-Torch avec pip, vous appelez litert_torch.convert, vous lui transmettez des sample_inputs qui peuvent être des entrées aléatoires, et vous exportez un fichier TFLite.

  • Pour info, LiteRT-Torch est le nouveau nom d'ai-edge-torch, si vous connaissez ce nom.

  • La quantification est, elle aussi, très simple.

    # Python
    # previously ai_edge_quantizer
    from litert_quantizer import quantizer, recipe
    
    qt = quantizer.Quantizer("stylizer_f32.tflite")
    
    # int8 weights, float activations
    qt.load_quantization_recipe(
        recipe.dynamic_wi8_afp32())
    
    qt.quantize().export_model("stylizer_int8.tflite")
  • Vous importez le quantificateur et la recette depuis LiteRT Quantizer.

  • Lorsque vous construisez le quantificateur, vous transmettez le modèle à virgule flottante d'origine, ainsi qu'une recette. Il s'agit de la recette standard que nous recommandons pour les GPU, qui utilise des pondérations d'entiers 8 bits, mais conserve les activations sous forme de virgule flottante 32 bits.

  • Ensuite, il vous suffit d'appeler la quantification, puis export_model pour enregistrer le modèle de sortie.

  • Vous obtiendrez ainsi un modèle quantifié que vous pourrez ensuite exécuter, avec des pondérations beaucoup plus petites et une exécution plus efficace.

Accélération GPU avec l'API CompiledModel

  • Oui, l'API CompiledModel est vraiment idéale pour les GPU.

  • Comme Chintan l'a mentionné, l'accélération est significative par rapport à l'ancien GPU TFLite.

  • Les chiffres exacts varient légèrement d'un modèle à l'autre, mais vous pouvez raisonnablement vous attendre à une augmentation de 1,4 fois.

  • Jusqu'à 10 fois plus rapide que l'inférence CPU, ce qui est un avantage considérable.

  • Si vous utilisez des modèles aujourd'hui, vous les exécutez probablement sur un processeur, et vous passez à côté d'un facteur de performance de 10 que vous pourriez obtenir avec un GPU.

  • C'est donc une véritable incitation.

  • Qu'est-ce qui le rend rapide ?

  • Nous prenons en charge de nombreuses fonctionnalités, comme l'exécution asynchrone. Vous pouvez ainsi prendre un AHardwareBuffer et le transmettre directement, ou un tampon OpenGL du pipeline de rendu de la caméra, et le transmettre directement à un tampon de tenseur.

  • Nous prenons en charge l'optimisation sans copie. En gros, lorsque vous essayez de traiter des éléments avec un budget de faible latence, par exemple lorsque vous devez traiter chaque frame en quelques dizaines de millisecondes, même la simple copie d'un tampon de mémoire peut représenter une surcharge non négligeable.

  • Pour les applications qui exigent des performances en temps réel très élevées, vous pouvez utiliser l'optimisation sans copie, que nous prenons en charge.

  • Et comme Chintan l'a mentionné, il est multiplate-forme et compatible avec OpenGL, OpenCL et Metal en tant que backends GPU.

  • Enfin, l'optimiseur de dérive de ML est Open Source.

  • Il est disponible sous licence Apache.

  • Il a récemment été partagé en Open Source par Google.

  • Voici le code de l'application.

    // Kotlin
    // Build once, off the main thread.
    private val model: CompiledModel =
        CompiledModel.create(
            context.assets,
            "stylizer_int8.tflite",
            // Simple GPU setup!
            CompiledModel.Options(Accelerator.GPU),
            environment
        )
    
    // Reuse buffers across frames.
    private val inputBuffers  = model.createInputBuffers()
    private val outputBuffers = model.createOutputBuffers()
    
    fun stylize(input: FloatArray): FloatArray {
        inputBuffers[0].writeFloat(input)
        model.run(inputBuffers, outputBuffers) // sync
        return outputBuffers[0].readFloat()
    }
  • Comme vous pouvez le voir, il est assez petit et simple.

  • Vous créez donc le modèle une fois, puis vous le réutilisez dans chaque frame.

  • Ici, CompiledModel.create transmet le fichier .tflite.

  • Il vous suffit de spécifier que vous souhaitez exécuter le modèle sur un GPU, puis de construire l'entrée et outputBuffers.

  • Ensuite, dans la boucle principale, où vous traitez chaque image, vous appelez ce model.run en transmettant l'entrée et la sortie.

  • Après avoir écrit dans inputBuffers, appelez model.run, puis lisez à partir de outputBuffers.

  • OK.

  • Ah oui, et si vous spécifiez "GPU" ici, il s'exécutera sur le GPU.

  • Si vous y spécifiez également un processeur et un GPU, il essaiera d'exécuter le GPU.

  • Si le GPU n'est pas disponible pour une raison quelconque, il basculera vers le CPU.

  • Dans certains cas, la solution de secours du processeur peut ne pas être assez efficace pour votre application. C'est alors que vous devez spécifier le GPU de cette manière.

  • Plus généralement, vous souhaitez disposer d'un remplacement de processeur.

Utiliser LiteRT dans les services Google Play

  • OK.

  • Nous l'avons donc compilé avec LiteRT groupé, qui n'utilise pas encore les services Play.

  • Je vais donc vous montrer comment utiliser LiteRT dans les services Play.

  • Il y a donc trois modifications : la première est la modification de la dépendance.

    // Easier with CompiledModel API: 3 steps
    
    // 1. app/build.gradle: replace litert with play-services-litert
    - implementation 'com.google.ai.edge.litert:litert:...'
    + implementation 'com.google.android.gms:play-services-litert:17.0.0'  // also pulls in litert-api
  • Il vous suffit de remplacer les dépendances du package Maven dans votre fichier Gradle ou dans tout autre système de compilation que vous utilisez, partout où vous les spécifiez.

  • Vous supprimez la dépendance litert ou l'une des anciennes dépendances du package Maven TensorFlow Lite, et vous les remplacez par play-services-litert.

  • Cela extrait également le package litert-api.

  • Maintenant, si vous écrivez une couche intermédiaire qui ne dépend que de LiteRT, mais que vous ne vous souciez pas vraiment de savoir si l'environnement d'exécution provient de l'application ou des services Play, vous pouvez simplement dépendre de l'API LiteRT et utiliser un environnement comme paramètre d'entrée.

  • La deuxième étape est le paramètre d'environnement.

  • C'est là que vous fournissez l'injection de dépendances, essentiellement pour spécifier que vous utilisez, ou que vous souhaitez utiliser, LiteRT des services Play.

  • Vous importez donc gms.litert.LiteRt et appelez la fonction d'initialisation en transmettant le contexte, qui est votre activité Android.

    // 2. Initialize the LiteRT Environment from Play services (context = your Activity)
    - val environment = Environment.create(...)
    + import com.google.android.gms.litert.LiteRt
    + val environment = LiteRt.initialize(context).await()
    
    // 3. Pass environment whenever you call CompiledModel.create
    
    // That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.
  • Comme il s'agit d'une opération asynchrone, vous devez appeler .await ou baser le reste sur un rappel.

  • Enfin, une fois que vous avez cet environnement, il vous suffit de le transmettre chaque fois que vous appelez CompiledModel.create.

  • C'est ce qui lui permettra d'utiliser l'environnement d'exécution LiteRT des services Play.

  • Et voilà.

  • Le reste de votre application utilise exactement les mêmes API LiteRT CompiledModel de l'API LiteRT.

  • Le reste de votre code d'inférence ne change pas pour l'utilisation des services Play.

  • Vous pouvez effectuer cette migration de manière incrémentielle.

  • Vous n'êtes pas obligé de tout faire en une seule fois. Vous pouvez migrer un composant à la fois.

  • Si vous avez une application volumineuse, il est judicieux de migrer chaque composant qui utilise LiteRT, puis de les migrer un par un et de les tester un par un.

  • Le seul inconvénient est que vous ne bénéficiez du gain de taille et de l'économie d'espace que lorsque vous supprimez la dernière dépendance à l'environnement d'exécution groupé.

  • Si c'est le cas, l'autre mise en garde est que vous ne devez pas mélanger les objets entre LiteRT dans les services Play et LiteRT groupé.

  • Donc, si vous obtenez des tenseurs, des modèles compilés ou des interpréteurs à partir de LiteRT dans les services Play, vous ne devez pas les transmettre au LiteRT groupé, ni inversement.

  • Mais sinon, mélanger ces éléments fonctionne très bien.

  • OK.

  • Voilà pour la création d'une application.

  • Je vais maintenant vous expliquer comment mettre à niveau une application existante.

  • Vous avez peut-être une application existante qui utilise l'API Interpreter.

  • Il s'agit de l'ancienne API TFLite qui utilise l'interpréteur comme classe principale.

  • À gauche, vous voyez le code utilisant l'API Interpreter, et à droite, le nouveau code de l'API CompiledModel.

    // Dependencies (Gradle):
    // play-services-tflite-java and/or litert (bundled)
    
    // Init
    TfLite.initialize(context).await()
    
    // Load
    val interpreterOptions =
        InterpreterApi.Options().apply {
          runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
        }
    
    val interpreter =
        InterpreterApi.create(modelFile, interpreterOptions)
    
    // Prepare inputs/outputs
    val inputs = …
    val outputs = …
    
    // Execute
    interpreter.run(inputs, outputs)
    // Dependencies (Gradle):
    // play-services-litert
    
    // Init
    val environment =
      LiteRt.initialize(context).await()
    
    // Load
    val modelOptions = CompiledModel.Options(Accelerator.CPU)
    
    val model =
        CompiledModel.create(modelPath, modelOptions, environment)
    
    // Prepare inputs/outputs
    val inputBuffers = model.createInputBuffers()
    val outputBuffers = model.createOutputBuffers()
    
    // Execute
    model.run(inputBuffers, outputBuffers
  • Il vous suffit donc de remplacer TfLite.initialize par LiteRt.initialize, qui renvoie désormais un environnement.

  • Vous transmettez ensuite l'environnement à CompiledModel.create.

  • Il s'agit donc d'un petit changement, sans augmentation de la taille de l'APK.

  • Sur la diapositive suivante, nous vous montrerons comment procéder avec un GPU, qui n'est qu'une option parmi d'autres.

  • Voici donc le code supplémentaire dont vous aviez besoin pour activer le GPU.

    // Dependencies (Gradle):
    // play-services-tflite-java and/or litert (bundled)
    
    // Init
    val initOptions = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true).build()
    TfLite.initialize(context, initOptions).await()
    val useGpu =
        TfLiteGpu.isGpuDelegateAvailable(context).await()
    
    // Load
    val interpreterOptions =
        InterpreterApi.Options().apply {
          runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
        }
    if (useGpu) {
        interpreterOptions.addDelegateFactory(
            GpuDelegateFactory());
    }
    val interpreter =
        InterpreterApi.create(modelFile, interpreterOptions)
    
    // Prepare inputs/outputs
    val inputs = …
    val outputs = …
    
    // Execute
    interpreter.run(inputs, outputs)
    // Dependencies (Gradle):
    // play-services-litert
    
    // Init
    val initOptions = LiteRtInitializationOptions.builder()
        .setEnableGpu(true).build()
    val environment = LiteRt.initialize(context, initOptions).await()
    
    // Load
    val modelOptions =
        CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
    
    val model =
        CompiledModel.create(modelPath, modelOptions, environment)
    
    // Prepare inputs/outputs
    val inputBuffers = model.createInputBuffers()
    val outputBuffers = model.createOutputBuffers()
    
    // Execute
    model.run(inputBuffers, outputBuffers)
  • Comme vous pouvez le voir, le code de la nouvelle API pour activer le GPU est un peu plus simple que le code précédent.

  • Ainsi, le premier appel à un setEnableGpu dans les options d'initialisation LiteRT que vous transmettez ensuite à LiteRt.initialize entraîne le chargement du code de l'accélérateur GPU dans votre application.

  • Ensuite, lorsque vous construisez le modelOptions et que vous le transmettez à CompiledModel.create, vous spécifiez l'accélérateur qui sera utilisé pour un modèle particulier, que vous souhaitiez que l'autre modèle s'exécute uniquement sur GPU, sur GPU avec remplacement par CPU ou uniquement sur CPU.

  • Très bien.

  • Comme vous pouvez le voir, l'activation du GPU est beaucoup plus simple avec la nouvelle API.

  • Alors, qu'est-ce que vous y gagnez ?

  • Chintan va vous l'expliquer.

  • Très bien.

  • Merci, Fergus.

  • Voyons maintenant ce que tout cela nous apporte.

  • Nous avons dit que nous allions créer une application. Voyons ce que nous avons créé.

  • C'est moi, et ce que nous avons fait ici, c'est que nous avons utilisé ML Kit pour me trouver. La segmentation est donc effectuée par une API clé en main comme ML Kit.

  • Je vais donc chercher ma tête là-bas.

  • LiteRT utilise ensuite un autre modèle semblable au transfert de style pour peindre l'arrière-plan.

  • Comme nous l'avons mentionné, vous bénéficiez d'autres avantages : vous économisez environ 8 Mo d'espace, vous disposez d'un seul environnement d'exécution partagé entre toutes vos applications, vous bénéficiez de mises à jour automatiques et vous disposez d'un GPU plus rapide qui vous permet d'atteindre près de 30 images par seconde pour une expérience utilisateur riche en temps réel.

  • Autre avantage : vous n'avez pas besoin de tout faire manuellement.

  • Nous venons également de lancer une nouvelle compétence dans Android. En gros, nous avons publié une compétence Android LiteRT qui améliore le ML sur l'appareil en quelques minutes.

  • Vous pouvez donc faire plusieurs choses : mettre à niveau une application existante, créer une nouvelle application ou mettre à niveau votre application pour utiliser cette nouvelle intégration des services Play.

  • Tout cela est donc disponible.

  • Le lien est sur la diapositive, il est également sur GitHub, et il apparaîtra aussi dans notre documentation et notre blog.

  • Cela devrait également être utile pour tous ceux qui envisagent de passer à la nouvelle version prochainement.

  • Fergus nous expliquera ensuite où cela nous mène.

Feuille de route et résumé de LiteRT

  • C'est pourquoi nous nous engageons à proposer une IA sur l'appareil avec LiteRT.

  • Nous continuons d'investir massivement dans l'amélioration de l'accélération GPU et de la couverture des modèles, et de fournir des mises à jour régulières pour LiteRT 2.x, à la fois pour le package LiteRT Open Source et pour le package Maven LiteRT des services Play, qui est LiteRT dans les services Play.

  • Nous continuerons également à assurer la rétrocompatibilité.

  • L'environnement d'exécution des services Play continuera de prendre en charge les applications créées avec d'anciens SDK.

  • Oui.

  • C'est très important pour nos utilisateurs et pour nous.

  • Les SDK LiteRT 1.x sont désormais en mode maintenance. Seuls les correctifs de sécurité critiques sont donc appliqués.

  • Et l'API NN, que nous avons abandonnée en 2024, va disparaître. Elle sera probablement supprimée à partir de 2027.

  • Par conséquent, si vous utilisez NNAPI, veuillez passer à l'accélération GPU ou NPU avec LiteRT groupé.

  • OK.

  • Oui.

  • Par conséquent, plus vous passerez rapidement à la version 2.x et à CompiledModel, moins vous aurez de travail par la suite.

  • Voici donc trois points à retenir.

  • Alors, créez.

  • Commencez par ML Kit. Si cela répond déjà à vos besoins, c'est parfait.

  • Si ce n'est pas le cas, utilisez LiteRT pour vos modèles personnalisés.

  • Passez à LiteRT dans les services Google Play pour bénéficier d'un APK plus léger et d'un environnement d'exécution partagé.

  • Envisagez également d'utiliser l'API CompiledModel pour une inférence GPU plus rapide et plus simple.

  • Oui.

  • Tout est documenté sur notre site de documentation LiteRT sur AI Edge, à l'URL indiquée ici.

  • Voilà.

  • Merci de nous avoir rejoints. Nous avons hâte de voir ce que vous allez créer.

Code

Extraits de code

Extrait Kotlin à 15:09 dans "Présentation de l'exemple d'application"
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
    SelfieSegmenterOptions.Builder()
        .setDetectorMode(
            SelfieSegmenterOptions.STREAM_MODE)
        .build())

// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
  val image = InputImage.fromMediaImage(
      mediaImage, /* rotationDegrees= */ 0)
  segmenter.process(image)
      .addOnSuccessListener { mask -> … }
}
Extrait de code Python à 17:34 dans "Modèles personnalisés sur LiteRT"
import litert_torch

model = my_models.Stylizer().eval()

# Convert with torch.export under the hood
edge_model = litert_torch.convert(
    model, sample_inputs)
edge_model.export("stylizer_f32.tflite")
Extrait de code Python à 18:04 dans "Modèles personnalisés sur LiteRT"
# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe

qt = quantizer.Quantizer("stylizer_f32.tflite")

# int8 weights, float activations
qt.load_quantization_recipe(
    recipe.dynamic_wi8_afp32())

qt.quantize().export_model("stylizer_int8.tflite")
Extrait de code Kotlin à 21:06 dans "Accélération GPU avec l'API CompiledModel"
// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
    CompiledModel.create(
        context.assets,
        "stylizer_int8.tflite",
        // Simple GPU setup!
        CompiledModel.Options(Accelerator.GPU),
        environment
    )

// Reuse buffers across frames.
private val inputBuffers  = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()

fun stylize(input: FloatArray): FloatArray {
    inputBuffers[0].writeFloat(input)
    model.run(inputBuffers, outputBuffers) // sync
    return outputBuffers[0].readFloat()
}
Extrait Groovy à 22:36 dans "Utiliser LiteRT dans les services Google Play"
// Easier with CompiledModel API: 3 steps

// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0'  // also pulls in litert-api
Extrait de code Kotlin à 23:43 dans "Utiliser LiteRT dans les services Google Play"
// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()

// 3. Pass environment whenever you call CompiledModel.create

// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.
Extrait de code Kotlin à 25:45 dans "Utiliser LiteRT dans les services Google Play"
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)

// Init
TfLite.initialize(context).await()

// Load
val interpreterOptions =
    InterpreterApi.Options().apply {
      runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
    }

val interpreter =
    InterpreterApi.create(modelFile, interpreterOptions)

// Prepare inputs/outputs
val inputs = …
val outputs = …

// Execute
interpreter.run(inputs, outputs)
Extrait de code Kotlin à 25:45 dans "Utiliser LiteRT dans les services Google Play"
// Dependencies (Gradle):
// play-services-litert

// Init
val environment =
  LiteRt.initialize(context).await()

// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)

val model =
    CompiledModel.create(modelPath, modelOptions, environment)

// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

// Execute
model.run(inputBuffers, outputBuffers
Extrait de code Kotlin à 26:25 dans "Utiliser LiteRT dans les services Google Play"
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)

// Init
val initOptions = TfLiteInitializationOptions.builder()
    .setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
    TfLiteGpu.isGpuDelegateAvailable(context).await()

// Load
val interpreterOptions =
    InterpreterApi.Options().apply {
      runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
    }
if (useGpu) {
    interpreterOptions.addDelegateFactory(
        GpuDelegateFactory());
}
val interpreter =
    InterpreterApi.create(modelFile, interpreterOptions)

// Prepare inputs/outputs
val inputs = …
val outputs = …

// Execute
interpreter.run(inputs, outputs)
Extrait de code Kotlin à 26:25 dans "Utiliser LiteRT dans les services Google Play"
// Dependencies (Gradle):
// play-services-litert

// Init
val initOptions = LiteRtInitializationOptions.builder()
    .setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()

// Load
val modelOptions =
    CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)

val model =
    CompiledModel.create(modelPath, modelOptions, environment)

// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

// Execute
model.run(inputBuffers, outputBuffers)