智能应用

通过 Google Play 服务中的机器学习套件和 LiteRT 掌握设备端智能

扬声器

  • Chintan Parikh

    Lead Product Manager

  • Fergus Henderson

    资深软件工程师

关于

演讲简介

不必再在即插即用 AI 的便利性和自定义模型的灵活性之间做出选择,您可以在一个超精简应用中同时部署这两者,而不会增加数兆字节的二进制文件膨胀。

在本讲座中,我们将演示如何在单个 Android 应用中构建这种双栈架构。您将了解如何利用机器学习套件执行即用型经典机器学习任务(例如文档扫描),同时在 Play 服务中利用 LiteRT 独立版处理自定义计算机视觉或音频工作负载。我们将深入探讨这两种实现路径如何在底层统一,以利用现代 LiteRT 运行时,从而让您的应用在 CPU 和 GPU 上实现无缝的硬件加速性能,且下载占用空间几乎为零字节。

开发者需要注意的主要事项:

- 性能不打折扣:一站式模型和自定义模型均可使用统一的 CompiledModel API 自动进行硬件加速。

-微型 APK:将机器学习套件和 LiteRT 运行时都卸载到 Play 服务,从而大幅缩减应用的下载大小。

- 混合集成:掌握在生产环境中并行运行多个机器学习工作流的方法,避免资源冲突。

摘要

  • Google Play 服务中的 LiteRT 在应用之间共享一个维护的运行时,从而将 APK 大小缩减约 8 MB。
  • 开箱即用的机器学习套件功能和自定义 LiteRT 模型可以在同一运行时中的单个应用中一起运行。
  • CompiledModel API 简化了 GPU 加速,性能比旧版 TFLite GPU 推理提升高达 1.4 倍。
  • 除了手机之外,该平台还支持 Wear OS 4 或更高版本,以及搭载 Android 11 或更高版本的 Android Automotive OS。
  • 在 Google Play 服务中采用 LiteRT 涉及将 Maven 依赖项更新为 play-services-litert、调用 LiteRt.initialize 以获取环境,并将其传递给 CompiledModel.create。
  • 建议迁移到 2.x CompiledModel API,因为 1.x 处于维护模式,且 NNAPI 即将停用。

技能

资源

Gemini Notebook

主题

  • on-device-ai
  • ml-kit
  • litert
  • google-play-services
  • gpu-acceleration
  • machine-learning

转写文稿

LiteRT 简介和概览

  • 大家晚上好。

  • 讲座即将开始。

  • 因此,现在人们提到“设备端 AI”时,通常是指 LLM。

  • 今天早些时候,您已经听过几场关于 Gemini Nano 的演讲,其中涉及机器学习套件、Firebase 和 Google 的许多其他产品。

  • 本课程将介绍另一半:传统机器学习和您自带的模型。

  • 您今天可能已经用过几次,只是自己不知道而已。

  • 想想您使用的任何应用,其中您模糊了背景、使用了条形码扫描器或使用了某种图片编辑功能。

  • 其中许多功能都基于传统机器学习,通常甚至在设备端运行。

  • 如果您曾向自己的应用或 APK 添加过这些功能,您可能经常会面临这样的权衡:是使用现成的 API,还是自带模型?

  • 这会对我的应用大小产生什么影响?

  • 今天,您会发现,您无需在即用型模型和自带模型之间做出选择。

  • 实际上,您可以使用一个精简运行时同时实现这两点。

  • 我叫 Chintan Parikh。

  • 我是 LiteRT 的产品经理,与我一起的是 Android 机器学习服务工程主管 Fergus。

  • 尊敬的用户:

  • 最后,您将了解如何构建一个应用,让其在每个相机帧上运行两个模型,帧速率约为每秒 30 帧。

  • 本次演讲分为四个部分。

  • 第一部分,我们将讨论 Google 专注于传统机器学习的设备端 AI 解决方案,即机器学习套件和 LiteRT。

  • 其次,我们还将介绍 LiteRT 和 Play 服务的新变化。

  • 此外,我们还将介绍 LiteRT 的新 CompiledModel API 以及我们支持的设备。

  • 第三,我们将向您展示如何构建新应用。

  • Fergus 将介绍如何使用机器学习套件和自定义模型构建应用,并将其打包到一个 APK 中。

  • 最后,我们将向您展示如何使用智能体模式升级现有应用。

  • 此外,您甚至可以在此智能体的支持下搭建新应用。

  • 好了

  • 首先,我们来了解一下什么是 LiteRT。

  • LiteRT 是 Google 的设备端推理运行时,可用于运行您自己的模型。

  • 它使用的 .tflite 文件格式与您之前在 TensorFlow Lite 中使用的格式相同。

  • 它经过重新设计,性能更出色,并且支持多框架。

  • 这意味着,您可以引入 PyTorch、TensorFlow 甚至 JAX 中的模型,并将其转换为 LiteRT 的 FlatBuffer 格式。

  • 自 2022 年起,Google Play 服务中的 TensorFlow Lite 已成为 Android 官方的自定义模型设备端运行时。

  • 今天,它迎来了重大升级,这也是本次演讲的主要内容。

  • 此次升级将带来最新的 LiteRT CompiledModel API,包括经过改进、速度提升 1.4 倍的全新 GPU 推理,还能让您构建体积更小、APK 尺寸更精简的应用。

  • 那么,为什么要通过 Play 服务提供该 SDK 呢?

  • 这有几个优势,而且这绝对是一个很大的痛点,我听过很多讨论,其中应用大小和 APK 膨胀正在成为一个真正的挑战,对吧?

  • 因此,您可以获得一个小型运行时。

  • 运行时不在 APK 中,因此您需要依赖瘦客户端,这会使 APK 缩小约 8 MB。

  • 第二个优势是高效。

  • 您只有一个运行时副本,因此 LiteRT 运行时会在所有应用之间共享。

  • 因此,您可以想象,如果您有众多应用,每个应用都可以为您节省 8 MB。

  • 如果您想节省磁盘可用空间并打造更精简的应用,这些资源会很快累积起来。

  • 第二,它会得到维护。

  • Google 会发布 bug 修复,解决您无需处理的 GPU 驱动程序问题,并且所有其他安全更新也会通过自动更新提供。

  • 正如我所提到的,GPU 的速度更快,因此 GPU 速度提升至 1.4 倍,我们也会对此进行更详细的介绍。

  • 从覆盖范围的角度来看,我们可以向旧版 Android 设备提供该功能。

  • Play 服务中的 LiteRT 最早可支持 2016 年发布的 Android 7。

  • 正如 Fergus 稍后将向您展示的那样,我们还将在接下来的幻灯片中介绍我们正在扩展到的其他新设备。

  • 以上就是交付载体,接下来我们来谈谈运行时。

  • 因此,LiteRT 并非新产品,也不是实验性产品。

  • 目前,TensorFlow Lite 和 LiteRT 已在超过 25 万个应用中运行。

  • 目前,Android 还在超过 38 亿台设备上运行。

  • 因此,您可能正在使用的许多应用,您甚至可能不知道,它们都在运行这个。

  • 这也相当于每天超过一万亿次推理,对吧?

  • 在如此庞大的规模下,我们肯定遇到过各种奇怪的芯片组问题,我们已经能够解决 ROM 问题或 GPU 驱动程序问题,并且我们有专门为您提供的解决方法。

  • Google 也在其旗舰应用中运行 LiteRT,涵盖各种应用、平台,甚至多种设备。

  • YouTube 短视频特效、Meet 背景分割、修复模糊等功能,都是在 LiteRT 上运行实时视频和大型图像模型的例子。

  • 这一点也非常重要,因为让用例变得快捷且吸引用户变得至关重要,对吧?

  • 因此,我们针对这些旗舰功能强化了这一运行时,而您通过 Play 服务即可获得这一运行时。

为何要在设备端运行 AI

  • 接下来,我们来探讨一下为什么要采用设备端 AI。

  • 延迟时间、隐私、离线工作或低成本,如果这些对您很重要,请离线运行,对吧?

  • 可能还有更多原因,但这些是我们听到的在设备端运行的最明显原因。

  • 在设备端运行也并非总是免费的。

  • 它确实有一些细微差别和一些挑战。

  • 因此,我们也会讨论其中一些挑战,并为您提供一条前进的道路,对吧?

  • 接下来是性能:正如您所见,在前面提到的应用示例中,延迟时间和内存预算总是很紧张,对吧?

  • 实时视频和音频需要极高的效率。

  • 即使是简单的互动功能,也需要快速响应。

  • 否则,您会失去用户互动度。

  • 硬件多样性:市面上有数百种 SoC,它们具有不同的 CPU 配置和 GPU 配置。

  • 您无法为所有这些设备编写代码,对吧?

  • 如何解决这些问题?

  • APK 大小:捆绑原生运行时还会增加每次下载的大小,这可能会影响转化率。

  • 自定义:模型训练、质量、模型大小,这些在部署之前都至关重要。

  • 因此,打造一款出色的设备端应用确实不易。

  • 但无论哪种情况,我们都希望平台能为您分担工作,而不是让您为平台所累,对吧?

  • Google 的设备端产品组合正是为了应对这些挑战而生,我们接下来将对此进行详细介绍。

  • 所以,我们今天将重点介绍两种简单的解决方案,对吧?

  • 您可以通过 Play 服务轻松添加设备端 AI,有两种方法。

  • 路径 1 是使用机器学习套件的开箱即用路径,对吧?

  • 这些是即用型视觉和语言 API,只需具备有限的机器学习专业知识,提供多种模型,并且全部通过 Play 服务提供。

  • 我们还将在接下来的幻灯片中介绍一些相关示例。

  • 自定义路径,通过 LiteRT 实现。

  • LiteRT 允许您自带模型,并在 CPU、GPU 上运行。

  • 运行时也来自 Play 服务。

  • 因此,它位于您的…因此,您无需将其打包到 APK 中。

  • 这些并非二选一。

  • 它们也可以始终搭配使用,效果更佳。

  • 这正是我们今天要在接下来的几分钟内构建的内容。

  • 首先,我们来了解一下机器学习套件涵盖的内容。

  • 以下是机器学习套件开箱即用的功能。

  • 因此,如果您已经认为其中一些功能可以满足您的需求,那么这是一个很好的起点,您已经抢占了先机。

  • 我们涵盖了视觉、条形码、文档、文本、姿势等众多功能,以及翻译、智能回复甚至实体提取等语言 API,对吧?

  • 关键在于,许多此类视觉和语言 API 都在底层使用 LiteRT 运行。

  • 因此,如果 ML Kit 能够满足您的需求,您可以从这里开始。

  • 如果无法满足,您也可以自带模型。

  • 关键在于:正如我之前提到的,机器学习套件和自定义模型不会是两个运行时。

  • 您可以将它们视为通往同一个底层 LiteRT 的两扇前门。

  • 因此,LiteRT 将作为 Play 运行时,负责协调这两项功能。

  • 因此,如果您的应用已使用 Play 商店中的模型,那么对于机器学习套件,请继续使用。

  • 否则,我们也会介绍 LiteRT 路径。

LiteRT 的新变化

  • 接下来,我们再来了解一下 LiteRT 的新变化。

  • 正如我所说,LiteRT 是 TensorFlow Lite 的演进版本,对吧?

  • 因此,最大的改进是 GPU 速度更快。

  • 更快的 GPU 支持 OpenCL、OpenGL,甚至还支持 Metal 后端等跨平台支持。

  • 因此,您当然可以根据需要将其用于多个平台。

  • 也更简单。

  • 我们提供统一的工作流,支持 CPU、GPU 和 NPU 加速。

  • CPU 和 GPU 目前位于 Play 服务中,而 NPU 目前通过 LiteRT 捆绑,这项工作正在进行中。

  • 所以,以前每个加速器都意味着不同的委托设置,对吧?

  • 现在,您只需执行一次此操作。

  • 因此,只需一个 API 即可自动回退到 CPU,您无需进行专门的委托设置。

  • 您只需进行加速器调用,即可更简单地管理这些内容,且代码更少。

  • 它还非常强大,正如我所提到的,同一个模型可以在多个平台上运行。

  • 灵活性至关重要。

  • 因此,.tflite 格式保持不变。

  • 如果您已有应用,则仍可使用此格式。

  • 如果您要构建新应用,可以再次沿用此文件格式。

  • 同样有趣的是,我们还支持 Interpreter API,该 API 以前位于 TensorFlow Lite 中。

  • 因此,如果您希望分阶段迁移,Interpreter API 也包含在新的 LiteRT 中,这有助于您轻松迁移。

  • 这就是运行时。

  • 我们来谈谈您可以用它构建什么。

  • 以下是 Android 应用目前正在构建的功能。

  • 从相机特效、照片编辑、智能输入,到游戏和虚拟形象,无所不包,对吧?

  • 其中许多应用都需要实时功能。

  • GPU 直接从相机发送帧,因此确保快速和实时性非常重要。

  • 其中一些照片编辑模型也变得越来越大。

  • AR/VR 功能也是如此,正如你在一些眼镜演示中看到的那样,许多功能在底层都运行着 LiteRT。

  • 现在,Google 的旗舰功能和 Play 服务都采用了相同的运行时,因此您无需在 APK 中捆绑任何内容,即可获得所有这些功能。

  • 现在,我们来构建一个应用,Fergus 将向我们展示如何构建。

  • 那就开始吧。

  • 谢谢 Chintan。

  • 接下来,我将简要介绍 Google Play 服务中的 LiteRT 有哪些新变化。

  • 在构建之前,还有一个好消息:您刚才看到的所有内容现在不仅可以在手机上运行,Play 服务中的 LiteRT 还可以在 Wear OS 和 Android Automotive OS 上运行。

  • 因此,您可以在手表或其他穿戴式设备或汽车本身中运行设备端模型。

  • 以前,您可以在手机上使用一款应用作为 Wear 的配套应用,但现在您可以让该应用在穿戴式设备本身上运行,Android Automotive 也是如此。

  • 这样,您就可以使用相同的 API、相同的 .tflite 模型,但支持更多平台。

  • 您无需针对每种设备规格单独实现,只需在所有这些不同的设备上使用相同的实现即可。

  • Play 服务分发范式的优势在于,我们实际上可以将其向后移植,以便在旧款设备上运行。

  • 因此,对于 Android Automotive OS,我们支持 2020 年发布的 Android 11 及更高版本;对于 Wear OS,我们支持 Wear OS 4 及更高版本。

  • 好的。

  • 接下来,我将介绍两种不同的路径:构建新应用和升级现有应用。

  • 这就是本次讲座的全部内容。

  • 因此,我将从一个示例应用开始,该应用结合使用了机器学习套件和在 LiteRT 上运行的自定义 GPU 模型。

  • 然后,对于升级现有应用,需要进行三项小改动:更改 Gradle 以更新依赖项、更改初始化代码以在 Play 服务中启用 LiteRT,以及从 Interpreter API 切换到 CompiledModel API。

  • 不过,我们会先介绍新应用,因为在您了解升级后的应用后,升级就更有意义了。

示例应用概览

  • 所以,构建新应用。

  • 这是我们要构建的应用。

  • 它将提供实时相机画面,让您保持清晰,而背景则会呈现艺术风格。

  • 因此,我们将获取相机帧。

  • 我们将通过机器学习套件自拍照分割功能,对相机帧中的图像进行流式传输。

  • 这是现有的机器学习套件开箱即用 API 之一。

  • 这将生成一个前景遮罩,基本上可以指出图片中的哪些像素对应于图片中的人物。

  • 然后,我们将使用自定义模型(类似于风格迁移模型),将风格应用于图片。

  • 我们将把该样式应用到整个相机画面,但实际上我们只关心背景部分,因为最终我们会将原始相机画面、遮罩和样式化背景结合起来,通过一些简单的逻辑进行组合,从而得到一个合成画面,其中主体保持不变,而背景则应用了样式。

  • 因此,我们希望在有现成 API 的情况下使用现成 API,在需要让应用脱颖而出时使用自定义 API。

  • 这是第一部分,我们调用了 ML Kit 自拍分割 API。

    // 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 -> … }
    }
  • 所以,这就像一个常规 API,对吧?

  • 这就像是 Android 开发者的基本功。

  • 你可以查看 API 文档,也可以直接让 Gemini 帮你构建。

  • 不过,您知道,这相当简单。

  • 您在构建客户端时,会传入一些选项。

  • 在本例中,我们指定了流式传输模式,以便处理视频帧流。

  • 然后,您可以在其中调用此 process 方法,该方法的回调将获取由自拍照分割计算得出的返回遮罩。

  • 输入则是来自摄像头的图片。

  • 所有这些 API 都使用应用级类型,而不是原始张量,因此您实际上是在非常高的级别进行编程,这非常简单。

LiteRT 上的自定义模型

  • 对于第二部分,即自定义模型,我们将使用 PyTorch 模型。

  • 我想 Chintan 是从 Kaggle 或 Hugging Face 等平台获取的…

  • 是的。

  • 是的,你也可以转换自己的视频。

  • 您可以构建自己的模型。

  • 抱歉,正在返回。

  • 是的,这就是这种堆栈的样子。

  • 您可以将 PyTorch 模型进行转换和量化,从而获得 LiteRT 模型。

  • 然后,您就可以按自己喜欢的方式将其与应用一起分发。

  • 它可以作为素材资源捆绑到应用中,也可以单独下载。

  • 两种方式均可。

  • 然后,该模型会位于 Play 服务中的 LiteRT 运行时之上。

  • 此外,还有用于在 CPU 上进行优化的 CPU 内核,而 ML Drift 是 GPU 加速器的名称。

  • 是的,正如我所说,您可以获得 TFLite 模型,您可以自己训练模型,也可以找到现有模型,无论哪种方式都可以。

  • 只需几行 Python 代码,即可完成 PyTorch 转换。

    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")
  • 因此,您需要通过 pip 安装 LiteRT-Torch,调用 litert_torch.convert,向其传递一些可以是随机输入的 sample_inputs,然后导出 TFLite 文件。

  • 顺便提一下,LiteRT-Torch 是 ai-edge-torch 的新名称,如果您熟悉后者的话。

  • 量化过程也非常简单。

    # 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")
  • 您需要从 LiteRT 量化器中导入量化器和配方。

  • 在构建量化器时,您需要传入原始浮点模型,并传入一个配方,这是我们推荐用于 GPU 的标准配方,它使用 8 位整数权重,但将激活值保持为 32 位浮点数。

  • 然后,只需调用 quantize,再调用 export_model 即可保存输出模型。

  • 这将是一个量化模型,您可以运行该模型,其权重会小得多,执行效率也会更高。

使用 CompiledModel API 进行 GPU 加速

  • 好的,CompiledModel API 和 GPU 确实是亮点。

  • 正如 Chintan 所说,与旧版 TFLite GPU 相比,速度有了显著提升。

  • 具体数字会因型号而略有不同,但 1.4 倍是您可以合理预期的。

  • 速度提升至 CPU 推理的 10 倍,这可是个巨大的优势,对吧?

  • 如果您是…目前大多数使用模型的人可能都是在 CPU 上运行模型,而错过了 GPU 可以带来的 10 倍性能提升。

  • 因此,这确实是一种激励。

  • 是什么让它如此快速?

  • 我们支持很多功能,例如异步执行,因此您可以直接传递 AHardwareBuffer 或相机渲染流水线中的 OpenGL 缓冲区,并将其直接传递给张量缓冲区。

  • 零拷贝优化我们支持零拷贝,因此基本上,当您尝试处理事务时,您知道,在低延迟预算下,例如当您必须在几毫秒内处理每一帧时,那么即使只是简单地复制内存缓冲区也可能是一笔不小的开销。

  • 因此,对于那些对实时性要求极高的应用,如果您想使用零拷贝优化,我们支持这种做法。

  • 然后,正如 Chintan 所提到的,它是跨平台的,支持 OpenGL、OpenCL 和 Metal 作为 GPU 后端。

  • 最后但同样重要的一点是,ML Drift 优化器是开源的。

  • 它根据 Apache 许可提供。

  • Google 最近将其开源。

  • 好的,然后是应用代码。

    // 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()
    }
  • 如您所见,它非常小巧且简单。

  • 因此,您只需创建一次模型,然后在每一帧中重复使用。

  • 因此,CompiledModel.create 会传入 .tflite 文件。

  • 您只需指定要在 GPU 上运行,然后构建输入和 outputBuffers。

  • 然后,在实际处理每一帧的主循环中,您调用此 model.run,并传递输入和输出。

  • 写入 inputBuffers 后,调用 model.run,然后从 outputBuffers 中读取。

  • 好的。

  • 哦,是的,然后,如果您只是在那里指定 GPU,它将在 GPU 上运行。

  • 如果您还在其中指定了 CPU 和 GPU,它会尝试运行 GPU。

  • 如果 GPU 因任何原因而不可用,则会回退到 CPU。

  • 因此,在某些情况下,CPU 后备方案可能无法为您的应用提供足够高的效率,此时您就需要像这样指定仅使用 GPU。

  • 更常见的情况是,您希望有一个 CPU 后备。

使用 Google Play 服务中的 LiteRT

  • 好的。

  • 因此,我们使用捆绑式 LiteRT 构建了该应用,但尚未开始使用 Play 服务。

  • 下面我来演示一下如何在 Play 服务中使用 LiteRT。

  • 因此,有三项更改:第一项是依赖项更改。

    // 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
  • 您只需在 Gradle 文件或任何其他位置(无论您使用的是哪种构建系统,只要是您指定 Maven 软件包依赖项的位置)进行替换即可。

  • 并且您移除了 litert 依赖项或任何旧版 TensorFlow Lite Maven 软件包依赖项,并将其替换为此 play-services-litert。

  • 这也会拉取 litert-api 软件包。

  • 现在,如果您正在编写一个中间层,该中间层只想依赖 LiteRT,但并不真正关心运行时是来自应用还是来自 Play 服务,那么您只需依赖 LiteRT API,并将环境作为输入参数。

  • 因此,第二步是环境参数。

  • 您可以在此处提供依赖项注入,实质上就是指定您要使用 Play 服务 LiteRT。

  • 因此,您需要导入 gms.litert.LiteRt,并调用初始化函数,传入上下文(即您的 Android activity)。

    // 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.
  • 这是一个异步操作,因此您必须调用 .await,或者让其余部分基于回调。

  • 最后,在获得该环境后,您只需在每次调用 CompiledModel.create 时传递该环境。

  • 这样,它就会使用 Play 服务中的 LiteRT 运行时。

  • 就是这样。

  • 也就是说,应用的其余部分使用的是 LiteRT API 中完全相同的 LiteRT CompiledModel API。

  • 其余推理代码不会因使用 Play 服务而发生变化。

  • 实际上,您可以逐步完成迁移。

  • 您不必一次性完成所有迁移,可以一次迁移一个组件。

  • 如果您的应用规模较大,建议逐个迁移使用 LiteRT 的组件,然后逐个进行测试。

  • 唯一的注意事项是,只有在移除对捆绑式运行时的最后一个依赖项后,才能实现缩减大小、节省空间。

  • 如果您这样做,另一个需要注意的事项是,您不应将 Play 服务中的 LiteRT 与捆绑的 LiteRT 之间的对象混用。

  • 因此,如果您从 Google Play 服务中的 LiteRT 获取张量、编译的模型或解释器,则不应将这些内容传递给捆绑的 LiteRT,反之亦然。

  • 但除此之外,混合使用这些内容完全没有问题。

  • 好的。

  • 以上就是构建新应用的过程。

  • 现在,我将介绍如何升级现有应用。

  • 因此,您可能有一个正在使用 Interpreter API 的现有应用。

  • 这是我们所说的旧版 TFLite API,它使用解释器作为主类。

  • 左侧是使用 Interpreter API 的代码,右侧是新的 CompiledModel API 代码。

    // 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
  • 因此,您只需将 TfLite.initialize 更改为 LiteRt.initialize,现在它会返回一个环境。

  • 然后,您将环境传递给 CompiledModel.create。

  • 因此,这是一个小改动,不会导致 APK 变大。

  • 在下一张幻灯片中,我们将向您展示如何使用 GPU,这只是另一种选择。

  • 因此,您需要添加这些代码才能启用 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)
  • 如您所见,新 API 中用于启用 GPU 的代码比之前的代码稍微简单一些。

  • 因此,在 LiteRT 初始化选项中首次调用 setEnableGpu,然后将其传递给 LiteRt.initialize,就会导致 GPU 加速器的代码加载到您的应用中。

  • 然后,在构建 modelOptions 并将其传递给 CompiledModel.create 时,您可以指定特定模型将使用哪种加速器,以及是否希望其他模型仅在 GPU 上运行、在 GPU 上运行并以 CPU 作为后备,或仅在 CPU 上运行。

  • 好了

  • 是的,如您所见,使用新 API 启用 GPU 要简单得多。

  • 那么,您究竟能获得什么?

  • Chintan 会告诉您。

  • 好了

  • 好的,谢谢 Fergus。

  • 那么,我们来谈谈这一切能给我们带来什么,好吗?

  • 还记得我们说过要构建一个应用吗?现在就来看看我们实际构建了什么,好吗?

  • 这就是我,我们在这里所做的是,使用机器学习套件来找到我,因此分割是由机器学习套件等一站式 API 完成的。

  • 所以,这只是在寻找我的头部。

  • 然后,LiteRT 会使用类似于风格迁移的另一个模型来绘制背景。

  • 正如我们提到的,其他好处还包括:您可以节省大约 8 MB 的空间;现在,您可以在所有应用之间使用一个运行时,或者至少像这里共享的那样;您可以获得自动更新;您还可以拥有更快的 GPU,在需要实时运行的应用上,您可以获得接近每秒帧数 30 的速度,从而获得丰富的用户体验。

  • 好消息是,您不必手动完成所有这些操作。

  • 我们还在 Android 中推出了一项新技能,基本上,我们发布了一项 Android LiteRT 技能,可在几分钟内升级设备端机器学习,对吧?

  • 因此,您可以利用它做几件事:升级现有应用、搭建新应用,还可以升级应用以使用这项新的 Play 服务集成。

  • 这些都是可以实现的。

  • 该链接位于幻灯片上,也在 GitHub 上,并且也会显示在我们的文档和博客中。

  • 是的,对于希望尽快做出改变的人来说,这也应该很有用。

  • 接下来,Fergus 将向我们介绍后续发展。

LiteRT 路线图和摘要

  • 因此,我们致力于通过 LiteRT 推动设备端 AI 的发展。

  • 我们将继续投入大量资源来改进 GPU 加速和模型覆盖范围,并继续为 LiteRT 2.x 提供定期更新,包括开源捆绑的 LiteRT 以及 Play 服务中的 LiteRT Maven 软件包(即 Play 服务中的 LiteRT)。

  • 我们还将继续提供向后兼容性。

  • Play 服务运行时将继续支持使用旧版 SDK 构建的应用。

  • 没错

  • 这对我们的用户来说非常重要,对我们来说也同样重要。

  • LiteRT 1.x SDK 目前处于维护模式,因此仅提供关键安全修复。

  • 我们早在 2024 年就已弃用 NNAPI,该 API 即将停用,并可能从 2027 年开始移除。

  • 因此,如果您有任何使用 NNAPI 的情况,请切换到使用 GPU 加速或 NPU 加速,并搭配使用捆绑式 LiteRT。

  • 好的。

  • 没错

  • 因此,您越早迁移到 2.x 和 CompiledModel,以后需要做的工作就越少。

  • 因此,有三个要点需要注意。

  • 所以,请积极构建。

  • 先从机器学习套件开始,如果它已经能满足您的需求,那就太好了。

  • 但如果不支持,请为自定义模型使用 LiteRT。

  • 升级到 Google Play 服务中的 LiteRT,以节省 APK 空间并使用共享运行时。

  • 此外,您还可以考虑使用 CompiledModel API,以更快、更简单地进行 GPU 推理。

  • 没错

  • 所有内容都记录在 AI Edge 上的 LiteRT 文档网站中,网址就在这里。

  • 所以,是的。

  • 感谢大家加入我们,我们迫不及待想看到大家的成果。

代码

代码段

“示例应用概览”中 15:09 处的 Kotlin 代码段
// 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 -> … }
}
“LiteRT 上的自定义模型”中 17:34 处的 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")
“LiteRT 上的自定义模型”中 18:04 处的 Python 代码段
# 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")
“使用 CompiledModel API 实现 GPU 加速”视频中 21:06 处的 Kotlin 代码段
// 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()
}
“在 Google Play 服务中使用 LiteRT”视频中 22:36 处的 Groovy 代码段
// 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
“在 Google Play 服务中使用 LiteRT”中 23:43 处的 Kotlin 代码段
// 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.
“在 Google Play 服务中使用 LiteRT”视频中 25:45 处的 Kotlin 代码段
// 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)
“在 Google Play 服务中使用 LiteRT”中 25:45 处的 Kotlin 代码段
// 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
“在 Google Play 服务中使用 LiteRT”中 26:25 处的 Kotlin 代码段
// 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)
“在 Google Play 服务中使用 LiteRT”视频中 26:25 处的 Kotlin 代码段
// 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)