Sie müssen sich nicht mehr zwischen der Bequemlichkeit von Plug-and-Play-KI und der Flexibilität benutzerdefinierter Modelle entscheiden. Sie können beides in einer einzigen, extrem schlanken App bereitstellen, ohne Megabyte an Binärdaten hinzuzufügen.
In dieser Session zeigen wir, wie Sie genau diese Dual-Stack-Architektur in einer einzigen Android-App erstellen. Sie erfahren, wie Sie das ML Kit für sofort einsatzbereite klassische ML-Aufgaben (z. B. Dokumentenscan) zusammen mit LiteRT als eigenständige Lösung in den Google Play-Diensten für Ihre benutzerdefinierten Computer Vision- oder Audio-Arbeitslasten nutzen können. Wir gehen im Detail darauf ein, wie beide Implementierungspfade im Hintergrund zusammengeführt werden, um die moderne LiteRT-Laufzeit zu nutzen. So erhält Ihre App eine nahtlose, hardwarebeschleunigte Leistung auf CPU und GPUs mit einem Download-Footprint von praktisch null Byte.
Wichtige Erkenntnisse für Entwickler:
– Kompromisslose Leistung: Sowohl schlüsselfertige als auch benutzerdefinierte Modelle werden automatisch über die einheitliche CompiledModel API hardwarebeschleunigt.
– Micro-APKs: Sie können die Downloadgröße Ihrer App drastisch reduzieren, indem Sie sowohl die ML Kit- als auch die LiteRT-Laufzeit in die Play-Dienste auslagern.
– Hybride Integration: Sie lernen, wie Sie mehrere ML-Workflows gleichzeitig in der Produktion ausführen, ohne dass es zu Ressourcenkonflikten kommt.
play-services-litert aktualisieren, LiteRt.initialize aufrufen, um eine Umgebung zu erhalten, und diese an CompiledModel.create übergeben.Transkript
Guten Abend zusammen.
Der Vortrag beginnt gleich.
Wenn heute von „On-Device-KI“ die Rede ist, sind damit also oft LLMs gemeint.
Heute haben Sie bereits mehrere Vorträge über Gemini Nano gesehen, die mit ML Kit, Firebase und vielen anderen Google-Produkten abgedeckt wurden.
In dieser Session geht es um die andere Hälfte: klassisches ML und das Modell, das Sie selbst mitbringen.
Wahrscheinlich haben Sie sie heute schon ein paar Mal verwendet, ohne es zu merken.
Denken Sie an Apps, in denen Sie den Hintergrund weichgezeichnet, einen Barcode-Scanner verwendet oder Bilder bearbeitet haben.
Ein Großteil davon basiert auf klassischem ML und wird in der Regel sogar auf dem Gerät ausgeführt.
Wenn Sie jemals eine dieser Funktionen zu Ihrer eigenen App oder Ihrem APK hinzugefügt haben, mussten Sie sich oft entscheiden: Verwende ich eine schlüsselfertige API oder bringe ich mein eigenes Modell mit?
Wie wirkt sich das auf die Größe meiner App aus?
Heute werden Sie sehen, dass Sie sich nicht zwischen einer schlüsselfertigen Lösung und einem eigenen Modell entscheiden müssen.
Mit einer schlanken Laufzeit können Sie beides tun.
Mein Name ist Chintan Parikh.
Ich bin Produktmanager für LiteRT und bei mir ist Fergus, Engineering Lead für Android ML-Dienste.
Hallo,
Am Ende sehen Sie, wie Sie eine App erstellen können, die zwei Modelle auf jedem Kameraframe mit etwa 30 Bilder pro Sekunde ausführt.
Dieser Vortrag besteht aus vier Teilen.
Im ersten Teil geht es um die On-Device-KI-Lösungen von Google, die sich auf klassisches ML konzentrieren, also ML Kit und LiteRT.
Zweitens gehen wir auf die Neuerungen in LiteRT und den Google Play-Diensten ein.
Außerdem geht es um die neue CompiledModel API von LiteRT und die unterstützten Geräte.
Drittens zeigen wir Ihnen, wie Sie eine neue App erstellen.
Fergus zeigt, wie man eine App mit ML Kit und einem benutzerdefinierten Modell in einem einzigen APK erstellt.
Und schließlich zeigen wir Ihnen, wie Sie eine vorhandene App im Agentenmodus aktualisieren.
Sie können mit der Unterstützung des KI-Agenten sogar eine neue App erstellen.
Okay.
Beginnen wir mit der Frage: Was ist LiteRT?
LiteRT ist die On-Device-Inferenzlaufzeit von Google für Ihre eigenen Modelle.
Es wird dasselbe .tflite-Dateiformat verwendet, das Sie möglicherweise bereits mit TensorFlow Lite verwendet haben.
Sie wurde für eine bessere Leistung überarbeitet und unterstützt auch mehrere Frameworks.
Das bedeutet, dass Sie Modelle aus PyTorch, TensorFlow und sogar JAX einbinden und in das FlatBuffer-Format für LiteRT konvertieren können.
Seit 2022 ist TensorFlow Lite in den Google Play-Diensten die offizielle On-Device-Laufzeitumgebung von Android für benutzerdefinierte Modelle.
Heute erhält es ein großes Upgrade, und darum geht es in diesem Vortrag.
Das Upgrade bringt die neueste LiteRT-CompiledModel-API mit, einschließlich einer neuen, verbesserten GPU-Inferenz, die 1,4-mal schneller ist.Außerdem können Sie damit kleinere Apps mit viel schlankeren APK-Größen erstellen.
Warum also über die Google Play-Dienste?
Es gibt einige Vorteile. Die App-Größe und die APK-Größe sind definitiv ein großes Problem, das ich in vielen Gesprächen höre, oder?
So erhalten Sie eine kleine Laufzeit.
Die Laufzeit ist nicht in Ihrem APK enthalten, sodass Sie auf einen Thin Client angewiesen sind. Dadurch wird Ihr APK um etwa 8 MB kleiner.
Der zweite Vorteil ist die Effizienz.
Sie haben eine Kopie der Laufzeit, sodass die LiteRT-Laufzeit von allen Apps gemeinsam genutzt wird.
Wenn Sie also viele Apps haben, können Sie sich vorstellen, dass Sie mit jeder App 8 MB sparen können.
Das summiert sich schnell, wenn Sie Speicherplatz sparen und eine schlankere App haben möchten.
Zweitens wird es gepflegt.
Google stellt die Fehlerkorrekturen bereit und kümmert sich um die Probleme mit GPU-Treibern, sodass Sie das nicht tun müssen. Auch alle anderen Sicherheitsupdates werden über automatische Updates bereitgestellt.
Wie bereits erwähnt, ist die GPU schneller – 1, 4-mal schneller, um genau zu sein.Darauf gehen wir später noch genauer ein.
Und was die Abdeckung betrifft, können wir auch ältere Android-Geräte beliefern.
LiteRT in den Play-Diensten unterstützt alle Android-Versionen bis zurück zu Android 7 aus dem Jahr 2016.
Fergus wird euch auf den nächsten Folien auch die anderen neuen Geräte zeigen, auf die wir die Funktion ausweiten.
Das ist also das Lieferfahrzeug. Kommen wir nun zum nächsten Schritt, der Laufzeit.
LiteRT ist also nicht neu und auch nicht experimentell.
TensorFlow Lite und LiteRT werden bereits in über 250.000 Apps verwendet.
Außerdem läuft es heute auf über 3,8 Milliarden Geräten.
Viele der Apps, die Sie verwenden, laufen also möglicherweise über diese Technologie, ohne dass Sie es wissen.
Das entspricht auch über einer Billion Inferenzen pro Tag, richtig?
Bei dieser Größenordnung sind wir sicherlich auf jedes ungewöhnliche Chipsatzproblem gestoßen, konnten ROM- oder GPU-Treiberprobleme beheben und haben eine Problemumgehung für Sie.
LiteRT wird auch von Google in seinen wichtigsten Apps verwendet, und zwar in verschiedenen Apps, auf verschiedenen Plattformen und sogar auf mehreren Geräten.
YouTube Shorts-Effekte, die Hintergrundsegmentierung in Meet, die Funktion „Scharfzeichnen“ und andere Funktionen, die Echtzeitvideos und komplexe Bildmodelle nutzen, werden alle über LiteRT ausgeführt.
Das ist auch extrem wichtig, da es entscheidend ist, Anwendungsfälle für Nutzer schnell und ansprechend zu gestalten, oder?
Das ist also dieselbe Laufzeit, die wir für diese Flaggschiff-Funktionen optimiert haben, und das ist es, was Sie über die Play-Dienste erhalten.
Sehen wir uns also an, warum On-Device-KI überhaupt sinnvoll ist.
Latenz, Datenschutz, Offline-Arbeit oder niedrige Kosten – wenn Ihnen einer dieser Punkte wichtig ist, sollten Sie das Modell offline ausführen.
Es gibt möglicherweise noch weitere Gründe, aber das sind einige der offensichtlichsten, die wir für die Ausführung auf dem Gerät gehört haben.
Die Ausführung auf dem Gerät ist auch nicht immer kostenlos.
Es gibt einige Nuancen und Herausforderungen.
Wir gehen also auch auf einige dieser Herausforderungen ein und zeigen Ihnen, wie Sie sie bewältigen können.
Leistung: Wie Sie gesehen haben, sind die Latenz- und Speicherbudgets bei einigen der Beispiele aus den vorherigen Apps immer knapp, oder?
Video- und Audioinhalte in Echtzeit erfordern extreme Effizienz.
Selbst einfache interaktive Funktionen müssen schnell reagieren.
Andernfalls verlieren Sie die Nutzerinteraktion.
Hardwarevielfalt: Es gibt Hunderte von SoCs mit unterschiedlichen CPU- und GPU-Konfigurationen.
Sie können nicht für alle diese Geräte Code schreiben, oder?
Wie lösen Sie diese Probleme?
APK-Größe: Durch das Einbinden einer nativen Laufzeit wird auch jeder Download größer, was sich auf die Conversion-Raten auswirken kann.
Anpassung: Modelltraining, Qualität, Modellgröße – all das ist schon vor der Bereitstellung extrem wichtig.
Ja, die Entwicklung einer guten On-Device-App kann schwierig sein.
In all diesen Situationen möchten wir aber, dass die Plattform die Arbeit für Sie erledigt und nicht umgekehrt, oder?
Das On-Device-Portfolio von Google wurde entwickelt, um diese Herausforderungen zu bewältigen. Darauf gehen wir als Nächstes ein.
Wir konzentrieren uns heute also auf zwei einfache Lösungen, richtig?
Es gibt zwei einfache Möglichkeiten, On-Device-KI über die Google Play-Dienste hinzuzufügen.
Pfad 1 ist der schlüsselfertige Pfad mit ML Kit, richtig?
Diese APIs für Bildverarbeitung und Sprache sind sofort einsatzbereit, erfordern nur begrenzte ML-Kenntnisse, bieten viele Modelle und werden alle über die Play-Dienste bereitgestellt.
Auf den nächsten Folien werden wir uns einige Beispiele dazu ansehen.
Der benutzerdefinierte Pfad, der über LiteRT verläuft.
Mit LiteRT können Sie Ihr eigenes Modell einbinden und auf CPU oder GPU ausführen.
Die Laufzeit stammt ebenfalls aus den Play-Diensten.
Sie bündeln es also nicht in Ihrem APK.
Diese schließen sich nicht gegenseitig aus.
Und sie können auch immer besser zusammenarbeiten.
Und genau das werden wir heute in den nächsten Minuten erstellen.
Sehen wir uns zuerst an, was ML Kit abdeckt.
Hier ist eine Übersicht über die Funktionen, die ML Kit standardmäßig bietet.
Wenn Sie also bereits der Meinung sind, dass einige dieser Funktionen Ihren Anforderungen entsprechen, ist das ein guter Ausgangspunkt und Sie haben bereits einen Vorsprung.
Wir decken Vision, Barcodes, Dokumente, Text, Pose, viele dieser Funktionen, Sprach-APIs wie Übersetzung, intelligente Antworten und sogar Entitätsextraktion ab, richtig?
Der entscheidende Punkt ist, dass viele dieser Vision- und Sprach-APIs im Hintergrund mit LiteRT ausgeführt werden.
Wenn ML Kit also das bietet, was Sie benötigen, können Sie hier beginnen.
Und wenn nicht, können Sie Ihr eigenes Modell verwenden.
Und hier ist der entscheidende Punkt: ML Kit und Ihr benutzerdefiniertes Modell sind nicht zwei Laufzeiten, wie ich bereits erwähnt habe.
Sie können sich das wie zwei Eingangstüren vorstellen, die zum selben LiteRT führen, das im Hintergrund ausgeführt wird.
LiteRT ist also die Laufzeit, die beide Funktionen orchestriert.
Wenn Ihre App also bereits den Google Play Store verwendet, können Sie ihn auch für ML Kit nutzen.
Andernfalls gehen wir auch den LiteRT-Pfad durch.
Sehen wir uns also an, was es Neues bei LiteRT gibt.
Wie bereits erwähnt, ist LiteRT eine Weiterentwicklung von TensorFlow Lite.
Die größten Verbesserungen sind die schnellere GPU.
Die schnellere GPU unterstützt OpenCL und OpenGL und bietet plattformübergreifende Unterstützung, sogar für Metal-Backends.
Sie können sie also bei Bedarf für mehrere Plattformen verwenden.
Außerdem ist es einfacher.
Wir haben einen einheitlichen Workflow für die CPU-, GPU- und NPU-Beschleunigung.
CPU und GPU sind derzeit in den Google Play-Diensten enthalten, während die NPU derzeit über LiteRT gebündelt wird. Daran wird noch gearbeitet.
Bisher bedeutete jeder Beschleuniger eine andere Delegate-Einrichtung, richtig?
Sie müssen das nur einmal tun.
Es gibt also eine API mit automatischem Fallback auf die CPU und Sie müssen keine dedizierten Delegierungen einrichten.
Sie können einfach Beschleunigeraufrufe verwenden, die dies viel einfacher und mit weniger Code verwalten können.
Es ist auch leistungsstark, da dasselbe Modell auf mehreren Plattformen ausgeführt wird, wie ich bereits erwähnt habe.
Die Flexibilität wird entscheidend sein.
Das .tflite-Format bleibt also gleich.
Wenn Sie bereits eine App hatten, können Sie dieses Format weiterhin verwenden.
Wenn Sie eine neue App entwickeln, können Sie dieses Dateiformat wieder verwenden.
Interessant ist auch, dass wir die Interpreter API unterstützen, die früher in TensorFlow Lite enthalten war.
Wenn Sie also schrittweise migrieren möchten, ist die Interpreter API enthalten, die auch Teil des neuen LiteRT ist. Das erleichtert die Migration.
Das ist die Laufzeit.
Sehen wir uns an, was Sie damit erstellen können.
Das sind die Android-Apps, die heute entwickelt werden.
Kameraeffekte, Fotobearbeitung, intelligentes Tippen, Spiele und Avatare – alles ist dabei, oder?
Viele dieser Anwendungen benötigen Echtzeitfunktionen.
Die GPU sendet Frames direkt von der Kamera. Es ist wichtig, dass die Dinge schnell und in Echtzeit ablaufen.
Einige dieser Fotobearbeitungsmodelle werden auch immer größer.
Das Gleiche gilt für die AR/VR-Funktionen, die Sie in einigen der Demos mit den Brillen gesehen haben. Viele davon nutzen LiteRT im Hintergrund.
Es ist dieselbe Laufzeit, die jetzt hinter den Flaggschiff-Funktionen von Google und auch in den Google Play-Diensten steckt. Sie erhalten also all diese Vorteile, ohne etwas in Ihr APK einbinden zu müssen.
Jetzt erstellen wir eine App. Fergus zeigt uns, wie das geht.
Das wollen wir nun tun.
Viele Grüße Chintan
Ich möchte Ihnen nun ein wenig über die Neuerungen bei LiteRT in den Google Play-Diensten erzählen.
Bevor wir mit dem Erstellen beginnen, noch eine Neuigkeit: Alles, was Sie gerade gesehen haben, läuft nicht nur auf Smartphones. LiteRT in den Play-Diensten ist auch auf Wear OS und Android Automotive OS verfügbar.
So können On-Device-Modelle auf Ihrer Smartwatch oder einem anderen Wearable oder im Auto selbst ausgeführt werden.
Bisher war es möglich, eine App auf dem Smartphone zu verwenden, die als Companion-App für Wear OS diente. Jetzt können Sie die App direkt auf dem Wearable ausführen. Das Gleiche gilt für Android Automotive.
Sie haben also dieselbe API, dasselbe .tflite-Modell, aber mehr Oberflächen.
Eine separate Implementierung pro Formfaktor ist nicht erforderlich. Sie können einfach dieselbe Implementierung für alle diese verschiedenen Geräte verwenden.
Das Schöne am Verteilungsmodell der Play-Dienste ist, dass wir diese Funktion auch auf ältere Geräte zurückportieren können.
Für Android Automotive OS unterstützen wir Versionen bis Android 11, das 2020 veröffentlicht wurde, und für Wear OS unterstützen wir Versionen ab Wear OS 4.
Okay.
Ich werde jetzt über zwei verschiedene Wege sprechen: das Erstellen einer neuen App und das Aktualisieren einer vorhandenen App.
Das ist das Thema des restlichen Vortrags.
Ich beginne mit einer Beispiel-App, die ML Kit mit einem benutzerdefinierten GPU-Modell kombiniert, das auf LiteRT ausgeführt wird.
Wenn Sie eine vorhandene App aktualisieren möchten, sind drei kleine Änderungen erforderlich: eine Gradle-Änderung, um die Abhängigkeiten zu aktualisieren, eine Init-Änderung, um LiteRT in den Play-Diensten zu aktivieren, und dann der Wechsel von der Interpreter API zur CompiledModel API.
Wir machen das aber zuerst in der neuen App, weil das Upgrade viel mehr Sinn ergibt, wenn du gesehen hast, worauf du upgradest.
Sie erstellen also eine neue App.
Hier ist die App, die wir erstellen werden.
Es wird eine Live-Kameraansicht angezeigt, in der du scharf zu sehen bist und der Hintergrund einen künstlerischen Stil erhält.
Wir nehmen also den Kamera-Frame.
Die Bilder aus dem Kameraframe werden über die Selfie-Segmentierung von ML Kit gestreamt.
Das ist eine der vorhandenen schlüsselfertigen ML Kit-APIs.
Dadurch wird eine Vordergrundmaske erstellt, die im Wesentlichen angibt, welche Pixel im Bild der Person im Bild entsprechen.
Dann nehmen wir unser benutzerdefiniertes Modell, das wie ein Stilübertragungsmodell funktioniert und einen Stil auf ein Bild anwendet.
Wir wenden das auf den gesamten Kameraframe an, aber uns geht es eigentlich nur um den Hintergrund. Am Ende nehmen wir den ursprünglichen Kameraframe, die Maske und den stilisierten Hintergrund und kombinieren sie mit ein wenig einfacher Logik, sodass wir einen zusammengesetzten Frame erhalten, in dem das Motiv erhalten bleibt und der Hintergrund den Stil hat.
Wir möchten also schlüsselfertige APIs verwenden, wo sie vorhanden sind, und benutzerdefinierte APIs, wo sie unsere App von anderen unterscheiden.
Das ist der erste Teil, in dem wir die Selfie-Segmentierungs-API des ML Kit aufrufen.
// 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 -> … }
}Das ist also wie eine normale API, oder?
Das ist das A und O für Android-Entwickler.
Sie können sich die API-Dokumentation ansehen oder Gemini bitten, es für Sie zu erstellen.
Aber es ist ziemlich einfach.
Sie erstellen einen Client und übergeben beim Erstellen des Clients einige Optionen.
In diesem Fall geben wir den Streamingmodus an, damit wir einen Stream von Videoframes verarbeiten können.
Dann rufen Sie die Methode „process“ auf. Der Callback davon erhält die Maske, die von der Selfie-Segmentierung zurückgegeben und berechnet wird.
Die Eingabe ist das Bild von der Kamera.
Und alle diese APIs verwenden Typen auf Anwendungsebene, keine Roh-Tensoren. Sie programmieren also auf einer sehr hohen Ebene, was wirklich unkompliziert ist.
Für den zweiten Teil, das benutzerdefinierte Modell, verwenden wir ein PyTorch-Modell.
Ich glaube, Chintan hat dieses Modell von Kaggle oder Hugging Face…
Genau.
Ja, und du kannst auch deine eigenen konvertieren.
Sie können Ihr eigenes Modell erstellen.
Entschuldigung, ich gehe zurück.
Ja, so sieht dieser Stack aus.
Sie können ein PyTorch-Modell konvertieren und quantisieren, um ein LiteRT-Modell zu erhalten.
Diese können Sie dann nach Belieben mit Ihrer App bereitstellen.
Sie kann als Asset in die App eingebunden oder separat heruntergeladen werden.
Beide Methoden funktionieren.
Diese befindet sich dann über der LiteRT-Laufzeit in den Google Play-Diensten.
Außerdem gibt es CPU-Kernel für die Optimierung auf der CPU und ML Drift ist der Name des GPU-Beschleunigers.
Ja, wie gesagt, Sie erhalten das TFLite-Modell. Sie können das Modell entweder selbst trainieren oder ein vorhandenes Modell verwenden. Beides funktioniert.
Die Konvertierung von PyTorch erfordert nur wenige Zeilen Python-Code.
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")Sie installieren also LiteRT-Torch mit pip, rufen litert_torch.convert auf, übergeben einige sample_inputs, die zufällige Eingaben sein können, und exportieren eine TFLite-Datei.
Übrigens: LiteRT-Torch ist der neue Name für ai-edge-torch, falls Sie damit vertraut sind.
Die Quantisierung ist ebenfalls sehr einfach.
# 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")Sie importieren den Quantisierer und das Rezept aus dem LiteRT Quantizer.
Wenn Sie den Quantisierer erstellen, übergeben Sie das ursprüngliche Gleitkommamodell und ein Rezept. Das ist das Standardrezept, das wir für die GPU empfehlen. Es verwendet 8-Bit-Ganzzahlgewichtungen, behält aber die Aktivierungen als 32-Bit-Gleitkomma bei.
Anschließend rufen Sie einfach „quantize“ und dann export_model auf, um das Ausgabemodell zu speichern.
Das ist dann ein quantisiertes Modell, das Sie ausführen können. Es hat viel kleinere Gewichtungen und wird effizienter ausgeführt.
Okay, also ja, die CompiledModel API und die GPU sind hier wirklich die Stars.
Wie Chintan bereits erwähnt hat, ist das eine erhebliche Beschleunigung im Vergleich zur alten TFLite-GPU.
Die genauen Zahlen variieren je nach Modell, aber Sie können mit dem 1,4-Fachen rechnen.
Bis zu zehnmal schneller als die CPU-Inferenz. Das ist der große Vorteil, oder?
Die meisten von Ihnen, die heute Modelle verwenden, führen sie wahrscheinlich auf einer CPU aus und verpassen so eine etwa zehnfache Leistungssteigerung, die Sie mit einer GPU erzielen könnten.
Das ist also ein echter Anreiz.
Was macht es so schnell?
Wir unterstützen eine Reihe von Dingen, z. B. die asynchrone Ausführung. Sie können also einen AHardwareBuffer nehmen und ihn direkt übergeben oder einen OpenGL-Zwischenspeicher aus der Kamera-Rendering-Pipeline direkt an einen Tensor-Zwischenspeicher übergeben.
Wir unterstützen die Zero-Copy-Optimierung. Wenn Sie also Dinge mit einem niedrigen Latenzbudget verarbeiten möchten, z. B. wenn Sie jeden Frame innerhalb weniger zehn Millisekunden verarbeiten müssen, kann selbst das einfache Kopieren eines Speicherpuffers einen erheblichen Aufwand bedeuten.
Für Anwendungen mit sehr hohen Echtzeitanforderungen sollten Sie die Zero-Copy-Optimierung verwenden, die wir unterstützen.
Und wie Chintan bereits erwähnt hat, ist es plattformübergreifend und unterstützt OpenGL, OpenCL und Metal als GPU-Backends.
Zu guter Letzt ist der ML-Drift-Optimierer Open Source.
Es ist unter der Apache-Lizenz verfügbar.
Google hat es vor Kurzem als Open Source veröffentlicht.
Okay, und hier ist der App-Code.
// 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()
}Wie Sie sehen, ist es recht klein und unkompliziert.
Sie erstellen das Modell also einmal und verwenden es dann in jedem Frame wieder.
Hier wird also die .tflite-Datei an CompiledModel.create übergeben.
Sie geben einfach an, dass Sie die GPU verwenden möchten, und erstellen dann die Eingabe und outputBuffers.
In der Hauptschleife, in der Sie jeden Frame verarbeiten, rufen Sie dann model.run auf und übergeben die Eingabe und Ausgabe.
Nachdem Sie in die inputBuffers geschrieben haben, rufen Sie model.run auf und lesen dann aus der outputBuffers.
Okay.
Ach ja, und wenn Sie dort einfach „GPU“ angeben, wird es auf der GPU ausgeführt.
Wenn Sie dort auch CPU und GPU angeben, wird versucht, die GPU auszuführen.
Wenn die GPU aus irgendeinem Grund nicht verfügbar ist, wird auf die CPU zurückgegriffen.
In einigen Fällen ist der CPU-Fallback möglicherweise nicht effizient genug für Ihre Anwendung. Dann sollten Sie die GPU wie oben gezeigt angeben.
Häufiger ist ein CPU-Fallback erforderlich.
Okay.
Wir haben sie also mit gebündeltem LiteRT erstellt, das noch nicht die Play-Dienste verwendet.
Ich zeige Ihnen, wie Sie LiteRT in den Google Play-Diensten verwenden.
Es gibt also drei Änderungen: Die erste ist die Änderung der Abhängigkeit.
// 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-apiSie müssen nur die Maven-Paketabhängigkeiten in Ihrer Gradle-Datei oder in einem anderen Build-System, das Sie verwenden, ändern.
Entfernen Sie die Abhängigkeit litert oder eine der älteren TensorFlow Lite-Maven-Paketabhängigkeiten und ersetzen Sie sie durch play-services-litert.
Dadurch wird auch das Paket litert-api abgerufen.
Wenn Sie eine mittlere Ebene schreiben, die nur von LiteRT abhängen soll, aber nicht wirklich darauf angewiesen ist, ob die Laufzeit von der App oder von den Play-Diensten stammt, können Sie einfach von der LiteRT API abhängen und eine Umgebung als Eingabeparameter verwenden.
Der zweite Schritt ist der Umgebungsparameter.
Dort geben Sie im Wesentlichen die Abhängigkeitsinjektion an, um festzulegen, dass Sie Play-Dienste LiteRT verwenden möchten.
Sie importieren also gms.litert.LiteRt und rufen die Initialisierungsfunktion auf. Dabei übergeben Sie den Kontext, also Ihre Android-Aktivität.
// 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.Das ist ein asynchroner Vorgang. Sie müssen also „.await“ aufrufen oder den Rest auf einem Callback basieren lassen.
Und schließlich übergeben Sie diese Umgebung einfach, wenn Sie CompiledModel.create aufrufen.
Dadurch wird die LiteRT-Laufzeit der Google Play-Dienste verwendet.
Das wars auch schon.
Der Rest Ihrer App verwendet genau dieselben LiteRT-CompiledModel-APIs aus der LiteRT API.
Der Rest des Inferenzcodes ändert sich nicht, wenn Sie die Play-Dienste verwenden.
Und Sie können diese Migration schrittweise durchführen.
Sie müssen nicht alles auf einmal tun, sondern können eine Komponente nach der anderen migrieren.
Wenn Sie eine große App haben, ist es sinnvoll, jede Komponente, die LiteRT verwendet, einzeln zu migrieren und zu testen.
Der einzige Nachteil ist, dass Sie nur die Größe reduzieren. Die Platzersparnis wird erst wirksam, wenn Sie die letzte Abhängigkeit von der gebündelten Laufzeit entfernen.
Wenn Sie das tun, sollten Sie Objekte zwischen LiteRT in den Google Play-Diensten und gebündeltem LiteRT nicht mischen.
Wenn Sie also Tensoren, kompilierte Modelle oder Interpreter von LiteRT in den Google Play-Diensten erhalten, sollten Sie diese nicht an das gebündelte LiteRT übergeben und umgekehrt.
Ansonsten funktioniert das Mischen dieser Dinge aber einwandfrei.
Okay.
Das war also die Erstellung einer neuen App.
Jetzt möchte ich darüber sprechen, wie Sie eine vorhandene App aktualisieren.
Möglicherweise haben Sie eine vorhandene App, die die Interpreter API verwendet.
Dies ist die ältere TFLite API, die den Interpreter als Hauptklasse verwendet.
Links sehen Sie den Code mit der Interpreter API und rechts den neuen CompiledModel API-Code.
// 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, outputBuffersSie ändern also einfach TfLite.initialize in LiteRt.initialize, und das gibt jetzt eine Umgebung zurück.
Anschließend übergeben Sie die Umgebung an CompiledModel.create.
Das ist also eine kleine Änderung, die APK wird nicht größer.
Auf der nächsten Folie zeigen wir Ihnen, wie Sie das mit einer GPU machen können. Das ist nur eine weitere Option.
Das ist also der zusätzliche Code, den Sie für die GPU-Aktivierung benötigen.
// 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)Wie Sie sehen, ist der Code in der neuen API zum Aktivieren der GPU etwas einfacher als der vorherige Code.
Der erste Aufruf eines setEnableGpu in den LiteRT-Initialisierungsoptionen, die Sie dann an LiteRt.initialize übergeben, führt dazu, dass der Code für den GPU-Beschleuniger in Ihre App geladen wird.
Wenn Sie dann die modelOptions erstellen und an CompiledModel.create übergeben, geben Sie an, welcher Beschleuniger für ein bestimmtes Modell verwendet werden soll, ob ein anderes Modell nur auf der GPU, auf der GPU mit CPU-Fallback oder nur auf der CPU ausgeführt werden soll.
Okay.
Ja, wie Sie sehen, ist das Aktivieren der GPU mit der neuen API viel einfacher.
Was genau sind die Vorteile?
Chintan wird es dir sagen.
Okay.
Ok, danke, Fergus.
Was bringt uns das alles?
Wir wollten ja eine App erstellen. Sehen wir uns also an, was wir tatsächlich erstellt haben.
Das bin also ich. Wir haben ML Kit verwendet, um mich zu finden. Die Segmentierung erfolgt also über eine schlüsselfertige API wie ML Kit.
Ich muss also nur meinen Kopf finden.
Anschließend verwendet LiteRT ein anderes Modell, das der Stilübertragung ähnelt, um den Hintergrund zu zeichnen.
Weitere Vorteile sind die Platzersparnis von etwa 8 MB, die Verwendung einer einzigen Laufzeit für alle Ihre Apps (oder zumindest für die hier freigegebenen), automatische Updates und eine schnellere GPU, die bei Echtzeitanwendungen für eine bessere Nutzererfahrung etwa 30 Bilder pro Sekunde liefert.
Das Gute ist, dass Sie das nicht alles manuell machen müssen.
Wir haben auch eine neue Fähigkeit in Android eingeführt: die Android LiteRT-Fähigkeit, mit der Sie das On-Device-ML in wenigen Minuten verbessern können.
Sie haben also mehrere Möglichkeiten: Sie können eine vorhandene App aktualisieren, eine neue App erstellen oder Ihre App so aktualisieren, dass sie diese neue Integration der Play-Dienste verwendet.
All das ist also verfügbar.
Der Link befindet sich auf der Folie, ist auch auf GitHub verfügbar und wird in unserer Dokumentation und unserem Blog angezeigt.
Das sollte also auch für alle nützlich sein, die bald umsteigen möchten.
Fergus wird uns dann sagen, wie es weitergeht.
Deshalb setzen wir mit LiteRT auf On-Device-KI.
Wir investieren weiterhin erheblich in die Verbesserung der GPU-Beschleunigung und der Modellabdeckung und stellen regelmäßig Updates für LiteRT 2.x bereit, sowohl für das Open-Source-Bundle von LiteRT als auch für das LiteRT Maven-Paket für die Play-Dienste, das LiteRT in den Play-Diensten ist.
Außerdem werden wir weiterhin die Abwärtskompatibilität gewährleisten.
Die Play-Dienste-Laufzeit unterstützt weiterhin Apps, die mit älteren SDKs erstellt wurden.
Ja.
Das ist für unsere Nutzer und für uns sehr wichtig.
Die LiteRT 1.x-SDKs befinden sich jetzt im Wartungsmodus, d. h., es werden nur kritische Sicherheitskorrekturen vorgenommen.
Die NNAPI, die wir 2024 eingestellt haben, wird voraussichtlich ab 2027 entfernt.
Wenn Sie also NNAPI verwenden, sollten Sie auf GPU- oder NPU-Beschleunigung mit gebündeltem LiteRT umstellen.
Okay.
Ja.
Je früher Sie also zu 2.x und CompiledModel wechseln, desto weniger müssen Sie später tun.
Drei Dinge sollten Sie sich merken.
Also, los gehts.
Beginnen Sie mit ML Kit. Wenn das bereits Ihren Anforderungen entspricht, ist das großartig.
Wenn das nicht der Fall ist, verwenden Sie LiteRT für Ihre benutzerdefinierten Modelle.
Führen Sie ein Upgrade auf LiteRT in den Google Play-Diensten durch, um von der APK-Einsparung und der gemeinsam genutzten Laufzeit zu profitieren.
Außerdem sollten Sie die CompiledModel API für eine schnellere und einfachere GPU-Inferenz verwenden.
Ja.
Alles ist auf unserer LiteRT-Dokumentationswebsite zu AI Edge unter der angegebenen URL dokumentiert.
Also.
Vielen Dank, dass Sie dabei waren. Wir sind schon gespannt, was Sie entwickeln werden.
// 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)