不必再在即插即用 AI 的便利性和自定义模型的灵活性之间做出选择,您可以在一个超精简应用中同时部署这两者,而不会增加数兆字节的二进制文件膨胀。
在本讲座中,我们将演示如何在单个 Android 应用中构建这种双栈架构。您将了解如何利用机器学习套件执行即用型经典机器学习任务(例如文档扫描),同时在 Play 服务中利用 LiteRT 独立版处理自定义计算机视觉或音频工作负载。我们将深入探讨这两种实现路径如何在底层统一,以利用现代 LiteRT 运行时,从而让您的应用在 CPU 和 GPU 上实现无缝的硬件加速性能,且下载占用空间几乎为零字节。
开发者需要注意的主要事项:
- 性能不打折扣:一站式模型和自定义模型均可使用统一的 CompiledModel API 自动进行硬件加速。
-微型 APK:将机器学习套件和 LiteRT 运行时都卸载到 Play 服务,从而大幅缩减应用的下载大小。
- 混合集成:掌握在生产环境中并行运行多个机器学习工作流的方法,避免资源冲突。
play-services-litert、调用 LiteRt.initialize 以获取环境,并将其传递给 CompiledModel.create。转写文稿
大家晚上好。
讲座即将开始。
因此,现在人们提到“设备端 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。
延迟时间、隐私、离线工作或低成本,如果这些对您很重要,请离线运行,对吧?
可能还有更多原因,但这些是我们听到的在设备端运行的最明显原因。
在设备端运行也并非总是免费的。
它确实有一些细微差别和一些挑战。
因此,我们也会讨论其中一些挑战,并为您提供一条前进的道路,对吧?
接下来是性能:正如您所见,在前面提到的应用示例中,延迟时间和内存预算总是很紧张,对吧?
实时视频和音频需要极高的效率。
即使是简单的互动功能,也需要快速响应。
否则,您会失去用户互动度。
硬件多样性:市面上有数百种 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 是 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 都使用应用级类型,而不是原始张量,因此您实际上是在非常高的级别进行编程,这非常简单。
对于第二部分,即自定义模型,我们将使用 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 确实是亮点。
正如 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 后备。
好的。
因此,我们使用捆绑式 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 推动设备端 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 文档网站中,网址就在这里。
所以,是的。
感谢大家加入我们,我们迫不及待想看到大家的成果。
// 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 -> … }
}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")# 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")// 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()
}// 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// 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.// 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// 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)