Smetti di scegliere tra la comodità dell'AI plug-and-play e la flessibilità dei modelli personalizzati: puoi eseguire il deployment di entrambi in un'unica app ultra-snella senza aggiungere megabyte di bloatware binario.
In questa sessione, mostreremo come creare esattamente questa architettura dual-stack in un'unica app per Android. Vedrai come sfruttare ML Kit per attività di ML classiche pronte all'uso (come la scansione di documenti) insieme a LiteRT autonomo in Google Play Services per i tuoi workload di visione artificiale o audio personalizzati. Approfondiremo il modo in cui entrambi i percorsi di implementazione si uniscono dietro le quinte per utilizzare il moderno runtime LiteRT, offrendo alla tua app prestazioni fluide e con accelerazione hardware su CPU e GPU con un'impronta di download di quasi zero byte.
Punti chiave per gli sviluppatori:
- Prestazioni senza compromessi: i modelli pronti all'uso e personalizzati vengono accelerati automaticamente dall'hardware utilizzando l'API CompiledModel unificata.
- Micro-APK: riduci drasticamente le dimensioni di download della tua app scaricando i runtime di ML Kit e LiteRT su Play Services.
- Integrazione ibrida: impara a eseguire più workflow di ML contemporaneamente in produzione senza conflitti di risorse.
play-services-litert, la chiamata a LiteRt.initialize per ottenere un ambiente e il passaggio a CompiledModel.create.Trascrizione
Buonasera a tutti.
Stiamo per iniziare l'intervento.
Quindi, quando oggi si parla di "AI on-device", spesso si intendono gli LLM.
Oggi avete assistito a diversi interventi su Gemini Nano, che sono stati trattati con ML Kit, Firebase e molti altri prodotti Google.
Questa sessione riguarda l'altra metà: il ML classico e il modello che porti tu.
Probabilmente l'hai usata un paio di volte oggi senza nemmeno saperlo.
Pensa a tutte le app in cui hai sfocato lo sfondo, utilizzato uno scanner di codici a barre o un qualche tipo di editing delle immagini.
Gran parte di questo lavoro si è basato sul ML classico e, in genere, viene eseguito anche on-device.
Se hai mai aggiunto una di queste funzionalità alla tua app o al tuo APK, spesso hai dovuto fare un compromesso: utilizzo un'API pronta all'uso o porto il mio modello?
Quale sarà l'impatto sulle dimensioni della mia app?"
Oggi vedrai che non devi scegliere tra una soluzione pronta all'uso o l'utilizzo del tuo modello.
In realtà, puoi fare entrambe le cose con un unico runtime snello.
Mi chiamo Chintan Parikh.
Sono product manager di LiteRT e con me c'è Fergus, responsabile tecnico dei servizi ML di Android.
Salve.
Al termine, vedrai come creare un'app che esegue due modelli su ogni frame della videocamera a circa 30 frame al secondo.
Questo intervento è diviso in quattro parti.
Nella prima parte parleremo delle soluzioni di AI on-device di Google incentrate sul ML classico, ovvero ML Kit e LiteRT.
In secondo luogo, esamineremo le novità di LiteRT e di Play Services.
Inoltre, parleremo della nuova API CompiledModel di LiteRT e dei dispositivi supportati.
Tre, ti mostreremo come creare una nuova app.
Fergus spiegherà come creare un'app con ML Kit e un modello personalizzato, tutto in un unico APK.
Infine, ti mostreremo come eseguire l'upgrade di un'app esistente utilizzando Agent Mode.
Inoltre, puoi anche creare lo scaffolding di una nuova app con il supporto di questo agente.
Okay.
Innanzitutto, cos'è LiteRT?
LiteRT è il runtime di inferenza on-device di Google per i tuoi modelli.
Utilizza lo stesso formato file .tflite che hai utilizzato in precedenza con TensorFlow Lite.
È stato riprogettato per migliorare le prestazioni e supporta anche più framework.
Ciò significa che puoi importare modelli da PyTorch, TensorFlow e persino JAX per convertirli nel formato flat buffer per LiteRT.
Dal 2022, TensorFlow Lite in Google Play Services è il runtime on-device ufficiale di Android per i modelli personalizzati.
Oggi riceve un importante upgrade, ed è di questo che parleremo in gran parte di questo intervento.
L'upgrade porterà l'ultima API LiteRT CompiledModel, inclusa una nuova inferenza GPU migliorata che sarà 1, 4 volte più veloce e ti consentirà anche di creare app più piccole con dimensioni degli APK molto più ridotte.
Perché distribuirlo tramite Play Services?
Ci sono un paio di vantaggi e questo è sicuramente un grande pain point che sto riscontrando in molti interventi che sto ascoltando, in cui le dimensioni delle app e il bloatware degli APK stanno diventando una vera sfida, giusto?
In questo modo, ottieni un runtime di piccole dimensioni.
Il runtime non è presente nell'APK, quindi ti affidi a un thin client, il che riduce le dimensioni dell'APK di circa 8 MB.
Il secondo vantaggio è l'efficienza.
Hai una copia del runtime, quindi il runtime LiteRT è condiviso tra tutte le app.
Quindi, puoi immaginare che se hai numerose app, ognuna potrebbe farti risparmiare 8 MB.
Questo si somma molto rapidamente quando cerchi di risparmiare spazio su disco e avere un'app più snella.
In secondo luogo, è gestito.
Google fornisce le correzioni di bug, affronta le sfide dei driver GPU che non dovrai affrontare tu e tutti gli altri aggiornamenti della sicurezza vengono forniti tramite aggiornamenti automatici.
Come ho già detto, la GPU è più veloce, quindi ottieni una GPU 1,4 volte più veloce, e approfondiremo anche questo aspetto.
Inoltre, dal punto di vista della copertura, possiamo spedire ai dispositivi Android meno recenti.
LiteRT in Play Services supporta i dispositivi fino ad Android 7 del 2016.
Inoltre, come vi mostrerà Fergus, nelle prossime slide vedremo anche gli altri nuovi dispositivi a cui ci stiamo espandendo.
Quindi, questo è il veicolo di distribuzione. Parliamo ora del passaggio successivo, il runtime.
Quindi, LiteRT non è una novità e non è sperimentale.
TensorFlow Lite e LiteRT sono già in esecuzione in oltre 250.000 app.
Inoltre, oggi è presente su oltre 3,8 miliardi di dispositivi.
Quindi, molte delle app che utilizzi, anche se non lo sai, funzionano grazie a questo.
E questo equivale anche a oltre un trilione di inferenze ogni giorno, giusto?
A questa scala, abbiamo sicuramente riscontrato ogni strano problema di chipset, siamo stati in grado di risolvere i problemi di ROM o di driver della GPU e abbiamo una soluzione alternativa solo per te.
LiteRT è anche ciò che Google esegue sulle sue app di punta, su app, piattaforme e persino su diversi dispositivi.
Gli effetti di YouTube Shorts, la segmentazione dello sfondo di Meet, Foto Nitida sono alcuni esempi in cui i video in tempo reale e i modelli per le immagini pesanti vengono eseguiti su LiteRT.
Questo è anche estremamente importante, poiché rendere i casi d'uso rapidi e coinvolgenti per gli utenti diventa estremamente fondamentale, giusto?
Quindi, questo è lo stesso runtime che abbiamo rafforzato per queste funzionalità di punta, ed è quello che ottieni tramite Play Services.
Vediamo anche perché è importante utilizzare i dispositivi.
Latenza, privacy, lavoro offline o costi ridotti: se uno di questi aspetti è importante per te, esegui il modello offline, giusto?
Potrebbero essercene altri, ma questi sono alcuni dei motivi più ovvi che abbiamo sentito per l'esecuzione on-device.
Inoltre, l'esecuzione on-device non è sempre senza costi.
Presenta alcune sfumature e alcune sfide.
Quindi, esamineremo anche alcune di queste sfide e ti indicheremo un percorso da seguire, ok?
Quindi, prestazioni: come hai visto, giusto, alcuni degli esempi delle app precedenti, i budget di latenza e memoria sono sempre limitati, giusto?
I video e l'audio in tempo reale richiedono un'efficienza estrema.
Anche le funzionalità interattive semplici devono essere rapide.
In caso contrario, perdi il coinvolgimento degli utenti.
Diversità dell'hardware: esistono centinaia di SoC con diverse configurazioni di CPU e GPU.
Non puoi scrivere codice per tutti questi casi, giusto?
Come si risolvono questi problemi?
Dimensioni dell'APK: l'aggregazione di un runtime nativo aumenta anche le dimensioni di ogni download, il che può influire sui tassi di conversione.
Personalizzazione: l'addestramento, la qualità e le dimensioni del modello sono tutti aspetti estremamente critici prima ancora di eseguire il deployment.
Quindi sì, creare un'ottima app on-device può essere difficile.
Ma in ognuna di queste situazioni, vogliamo che sia la piattaforma a fare il lavoro per te e non il contrario, giusto?
Il portafoglio on-device di Google esiste per affrontare queste sfide, di cui parleremo di seguito.
Oggi ci concentreremo su due soluzioni semplici, giusto?
Esistono due modi semplici per aggiungere l'AI on-device tramite Play Services.
Il percorso 1 è quello chiavi in mano che utilizza ML Kit, giusto?
Si tratta di API di visione artificiale e linguaggio pronte all'uso, che richiedono competenze di ML limitate, con molti modelli forniti e distribuiti tramite Google Play Services.
Nelle prossime slide vedremo anche alcuni esempi di questi aspetti.
Il percorso personalizzato, ovvero tramite LiteRT.
LiteRT ti consente di utilizzare il tuo modello ed eseguirlo su CPU e GPU.
Anche il runtime proviene da Play Services.
Quindi, è nel tuo… quindi, non lo raggruppi nel tuo APK.
Queste non sono opzioni che si escludono a vicenda.
Inoltre, possono sempre essere migliori insieme.
Ed è esattamente ciò che creeremo oggi nei prossimi minuti.
Ma prima, vediamo cosa copre ML Kit.
Ecco cosa offre ML Kit fin da subito.
Quindi, se pensi già che alcune di queste funzionalità soddisfino le tue esigenze, è un ottimo punto di partenza e hai già un vantaggio.
Abbiamo una copertura per la visione, per i codici a barre, i documenti, il testo, la posa, molte di queste funzionalità, API per le lingue come la traduzione, le risposte rapide e persino l'estrazione di entità, giusto?
Il punto chiave è che molte di queste API di visione e linguaggio vengono eseguite con LiteRT in background.
Quindi, se ML Kit fa al caso tuo, puoi iniziare da qui.
E quando non è così, hai l'opportunità di portare il tuo modello.
Ed ecco il punto chiave: ML Kit e il tuo modello personalizzato non saranno due runtime, come ho già detto.
Immagina che siano come due porte d'ingresso che conducono allo stesso LiteRT che verrà eseguito in background.
LiteRT sarà il runtime di Google Play che orchestrerà entrambe queste funzionalità.
Quindi, se la tua app utilizza già il Play Store, per ML Kit, non esitare.
In caso contrario, esamineremo anche il percorso di LiteRT.
Vediamo anche le novità di LiteRT.
Come ho già detto, LiteRT è un'evoluzione di TensorFlow Lite, giusto?
Quindi, i miglioramenti più significativi sono una GPU più veloce.
La GPU più veloce supporta OpenCL, OpenGL e ha anche un supporto multipiattaforma anche per i backend Metal.
Quindi, puoi sicuramente utilizzarlo per più piattaforme, se necessario.
È anche più semplice.
Abbiamo un unico workflow unificato per l'accelerazione di CPU, GPU e NPU.
CPU e GPU sono attualmente in Play Services, mentre la NPU è integrata tramite LiteRT oggi, e questo è un lavoro in corso.
In precedenza, ogni acceleratore richiedeva una configurazione del delegato diversa, giusto?
Ora devi farlo una sola volta.
Quindi esiste un'API con fallback automatico alla CPU e non è necessario eseguire configurazioni dedicate-delegate.
Puoi semplicemente utilizzare le chiamate dell'acceleratore che possono gestire questo processo in modo molto più semplice e con meno codice.
È anche potente: lo stesso modello viene eseguito su più piattaforme, come ho già detto.
La flessibilità sarà fondamentale.
Quindi il formato .tflite rimane lo stesso.
Se avevi un'app esistente, puoi comunque utilizzare questo formato.
Se stai creando una nuova app, puoi utilizzare di nuovo questo formato file.
Un altro aspetto interessante è che supportiamo l'API Interpreter, che in precedenza era in TensorFlow Lite.
Quindi, se vuoi eseguire la migrazione in più fasi, l'API Interpreter è inclusa anche nel nuovo LiteRT, il che semplifica la migrazione.
Questo è il runtime.
Vediamo cosa puoi creare con questo.
Ecco cosa stanno creando oggi le app per Android.
Tutto, dagli effetti della fotocamera, all'editing fotografico, alla digitazione intelligente, ai giochi e agli avatar, giusto?
Molte di queste app avranno bisogno di funzionalità in tempo reale.
La GPU invia i frame direttamente dalla fotocamera, quindi è importante che le operazioni siano rapide e in tempo reale.
Anche alcuni di questi modelli di fotoritocco stanno diventando più pesanti.
Lo stesso vale per le funzionalità AR/VR che hai visto in alcune demo con gli occhiali, molte delle quali eseguono LiteRT dietro le quinte.
È lo stesso runtime che ora è alla base delle funzionalità di punta di Google e anche di Play Services, quindi ottieni tutto questo senza dover raggruppare nulla nel tuo APK.
Ora, perché non creiamo un'app? Fergus ci mostrerà come fare.
Procediamo.
Grazie, Chintan.
Quindi, parlerò un po' delle novità di LiteRT in Google Play Services.
Prima di iniziare a creare, un'altra notizia: tutto ciò che avete appena visto ora funziona non solo sugli smartphone, ma anche su Wear OS e Android Automotive OS, grazie a LiteRT in Play Services.
In questo modo, puoi avere modelli on-device in esecuzione sul tuo smartwatch o su un altro dispositivo indossabile, oppure nell'auto stessa.
In precedenza era possibile utilizzare un'app sullo smartphone che fungeva da app complementare per Wear, ma ora puoi eseguirla direttamente sul dispositivo indossabile, e lo stesso vale per Android Automotive.
In questo modo, hai la stessa API, lo stesso modello .tflite, ma più piattaforme.
Non è necessaria un'implementazione separata per fattore di forma, puoi semplicemente utilizzare la stessa implementazione per tutti questi diversi dispositivi.
Inoltre, la bellezza del paradigma di distribuzione di Play Services è che possiamo effettivamente eseguire il backporting per l'esecuzione su dispositivi meno recenti.
Per Android Automotive OS, supportiamo Android 11, rilasciato nel 2020, e versioni successive, mentre per Wear OS supportiamo Wear OS 4 e versioni successive.
Ok.
Ora parlerò di due percorsi diversi: la creazione di una nuova app e l'upgrade di un'app esistente.
Questo è l'argomento del resto del discorso.
Inizierò con un'app di esempio che combina l'uso di ML Kit con un modello GPU personalizzato in esecuzione su LiteRT.
Per eseguire l'upgrade di un'app esistente, saranno necessarie tre piccole modifiche: una modifica a Gradle per aggiornare le dipendenze, una modifica a init per attivare LiteRT in Play Services e il passaggio dall'API Interpreter all'API CompiledModel.
Ma prima lo faremo con la nuova app, perché l'upgrade ha molto più senso una volta che hai visto a cosa stai eseguendo l'upgrade.
Quindi, creiamo una nuova app.
Ecco l'app che creeremo.
Avrà una visione in diretta della videocamera, in cui tu rimani a fuoco e lo sfondo assume uno stile artistico.
Quindi, prenderemo il frame della videocamera.
Le immagini del frame della fotocamera verranno trasmesse in streaming tramite la segmentazione dei selfie di ML Kit.
Questa è una delle API chiavi in mano di ML Kit esistenti.
In questo modo verrà prodotta una maschera di primo piano che indicherà sostanzialmente quali pixel dell'immagine corrispondono alla persona nell'immagine.
Poi prenderemo il nostro modello personalizzato, che è un modello di tipo trasferimento di stile, e applicheremo uno stile a un'immagine.
Applicheremo questo stile all'intero fotogramma della videocamera, ma ci interessa solo la parte dello sfondo, perché alla fine prenderemo il fotogramma originale della videocamera, la maschera e lo sfondo con lo stile e, con una logica un po' semplice, li combineremo in modo da avere un fotogramma composito in cui abbiamo mantenuto il soggetto e lo sfondo ha lo stile.
Quindi, vogliamo avere un… Utilizziamo API pronte all'uso dove esistono e API personalizzate dove differenziano la nostra app.
Questa è la prima parte in cui richiamiamo l'API Selfie Segmentation di ML Kit.
// 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 -> … }
}Quindi, è proprio come una normale API, giusto?
Questo è il pane quotidiano degli sviluppatori Android.
Basta consultare la documentazione dell'API o chiedere a Gemini di creare l'app per te.
Ma, sai, è abbastanza semplice.
Quando crei un client, passi alcune opzioni.
In questo caso, specifichiamo la modalità di streaming in modo da poter elaborare uno stream di frame video.
Poi, chiami questo metodo di elaborazione e il callback riceverà la maschera restituita, calcolata dalla segmentazione dei selfie.
L'input è l'immagine della videocamera.
Inoltre, tutte queste API utilizzano tipi a livello di applicazione, non tensori non elaborati, quindi la programmazione avviene a un livello molto elevato ed è davvero semplice.
Per la seconda parte, il modello personalizzato, utilizzeremo un modello PyTorch.
Penso che Chintan abbia preso questo da una delle piattaforme come Kaggle o Hugging Face…
Infatti,
Sì, oppure puoi convertire i tuoi, sai.
Puoi creare il tuo modello.
Mi dispiace, torno indietro.
Sì, questo è l'aspetto dello stack.
Puoi prendere un modello PyTorch, convertirlo e quantizzarlo, quindi ottenere un modello LiteRT.
Dopodiché, puoi distribuire il file con la tua app come preferisci.
Può essere raggruppato come parte dell'app come asset o può essere scaricato separatamente.
Entrambi i modi funzionano.
che si trova sopra il runtime LiteRT in Play Services.
Inoltre, sono presenti kernel CPU per l'ottimizzazione su CPU e ML Drift è il nome dell'acceleratore GPU.
Sì, come ho detto, ottieni il modello TFLite, puoi addestrarlo tu o trovarne uno esistente, in entrambi i casi funziona.
La conversione da PyTorch richiede solo poche righe di 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")Quindi, installi LiteRT-Torch con pip, chiami litert_torch.convert, passi alcuni sample_inputs che possono essere input casuali ed esporti un file TFLite.
A proposito, LiteRT-Torch è il nuovo nome di ai-edge-torch, se lo conosci.
La quantizzazione è, ancora una volta, molto semplice.
# 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")Importi il quantizzatore e la formula da LiteRT Quantizer.
Quando crei il quantizzatore, passi il modello con rappresentazione in virgola mobile originale e una formula, che è quella standard che consigliamo per la GPU, che utilizza pesi interi a 8 bit, ma mantiene le attivazioni come rappresentazione in virgola mobile a 32 bit.
Poi, basta chiamare quantize e export_model per salvare il modello di output.
In questo modo, otterrai un modello quantizzato che potrai eseguire con pesi molto più piccoli e che verrà eseguito in modo più efficiente.
Ok, quindi sì, l'API CompiledModel è il punto di forza della GPU.
Quindi, come ha detto Chintan, si tratta di un'accelerazione significativa rispetto alla GPU TFLite precedente.
I numeri esatti variano leggermente da modello a modello, ma 1,4 volte è ciò che puoi ragionevolmente aspettarti.
Fino a 10 volte più veloce dell'inferenza della CPU, quindi è un grande vantaggio, giusto?
Se siete tra i molti che utilizzano i modelli oggi, probabilmente li eseguite su CPU e vi perdete un fattore di prestazioni pari a 10 che potreste ottenere dalla GPU.
Questo è un vero incentivo.
Cosa lo rende veloce?
Ok, quindi ci sono un sacco di cose che supportiamo, ad esempio l'esecuzione asincrona, in modo da poter prendere un AHardwareBuffer e passarlo direttamente o un buffer OpenGL dalla pipeline di rendering della fotocamera, passarlo direttamente a un buffer del tensore.
Supportiamo l'ottimizzazione zero-copy, quindi, in pratica, quando provi a elaborare elementi, ad esempio, con un budget a bassa latenza, come quando devi elaborare ogni frame in pochi, diciamo, decine di millisecondi, anche solo copiare un buffer di memoria può essere un overhead non banale.
Quindi, per le applicazioni con requisiti in tempo reale molto elevati, supportiamo l'ottimizzazione zero-copy.
Inoltre, come ha detto Chintan, è multipiattaforma con supporto per OpenGL, OpenCL e Metal come backend GPU.
Infine, l'ottimizzatore ML Drift è open source.
È disponibile con licenza Apache.
Di recente, Google ha reso open source questo modello.
Ok, ecco il codice dell'app.
// 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()
}Come puoi vedere, è piuttosto piccolo e semplice.
Quindi, crei il modello una volta e poi lo riutilizzi in ogni frame.
Quindi, qui, CompiledModel.create passa il file .tflite.
Devi solo specificare che vuoi eseguire l'operazione sulla GPU, quindi creare l'input e outputBuffers.
Poi, nel loop principale, dove elabori effettivamente ogni frame, chiami questo model.run passando l'input e l'output.
Dopo aver scritto in inputBuffers, chiama model.run e poi leggi da outputBuffers.
Ok.
Ah, sì, e poi, se specifichi GPU, verrà eseguito sulla GPU.
Se specifichi anche CPU e GPU, proverà a eseguire la GPU.
Se la GPU non è disponibile per qualsiasi motivo, verrà utilizzata la CPU.
In alcuni casi, quindi, il fallback della CPU potrebbe non essere abbastanza efficiente per la tua app ed è in questi casi che devi specificare la GPU in questo modo.
Più comunemente, è preferibile avere un fallback della CPU.
Ok.
Per questo motivo, l'abbiamo creata con LiteRT in bundle, che non utilizza ancora Play Services.
Quindi, lascia che ti mostri come utilizzare LiteRT in Play Services.
Quindi, ci sono tre modifiche: la prima è la modifica della dipendenza.
// 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-apiBasta sostituire, nel file Gradle o in qualsiasi altro sistema di build che utilizzi, ovunque specifichi le dipendenze del pacchetto Maven, ciò che vuoi modificare.
Rimuovi la dipendenza litert o una delle dipendenze dei pacchetti Maven TensorFlow Lite precedenti e sostituiscile con play-services-litert.
In questo modo viene importato anche il pacchetto litert-api.
Ora, se stai scrivendo un livello intermedio che vuole solo dipendere da LiteRT, ma non ti interessa se il runtime proviene dall'app o da Play Services, puoi semplicemente dipendere dall'API LiteRT e prendere un ambiente come parametro di input.
Il secondo passaggio è il parametro dell'ambiente.
È qui che fornisci l'inserimento delle dipendenze, essenzialmente, per specificare che stai utilizzando, vuoi utilizzare Play Services LiteRT.
Quindi, importa gms.litert.LiteRt e chiama la funzione di inizializzazione, passando il contesto, ovvero l'attività 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.Si tratta di un'operazione asincrona, quindi devi chiamare .await o basare il resto su un callback.
Infine, una volta ottenuto l'ambiente, devi solo passarlo ogni volta che chiami CompiledModel.create.
In questo modo, verrà utilizzato il runtime LiteRT di Play Services.
Questo è tutto.
Il resto dell'app utilizza esattamente le stesse API LiteRT CompiledModel dell'API LiteRT.
Il resto del codice di inferenza non cambia per l'utilizzo di Play Services.
Inoltre, puoi eseguire la migrazione in modo incrementale.
Non è necessario eseguire la migrazione di tutti i componenti contemporaneamente, ma puoi eseguirla un componente alla volta.
Se hai un'app di grandi dimensioni, è opportuno eseguire la migrazione di ogni componente che utilizza LiteRT, quindi puoi eseguire la migrazione uno alla volta e testare uno alla volta.
L'unico avvertimento è che ottieni solo la riduzione delle dimensioni, il risparmio di spazio si ottiene solo quando rimuovi l'ultima dipendenza dal runtime in bundle.
Inoltre, se lo fai, l'altro avvertimento è che non devi combinare oggetti tra LiteRT in Play Services e LiteRT in bundle.
Quindi, se ricevi tensori, modelli compilati o interpreti da LiteRT in Play Services, non devi passarli a LiteRT in bundle o viceversa.
In caso contrario, la combinazione di questi elementi funziona perfettamente.
Ok.
Questo era un esempio di creazione di una nuova app.
Ora parlerò di come eseguire l'upgrade di un'app esistente.
Potresti avere un'app esistente che utilizza l'API Interpreter.
Questa è l'API TFLite precedente che utilizza l'interprete come classe principale.
A sinistra, il codice che utilizza l'API Interpreter, mentre a destra, il nuovo codice dell'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, outputBuffersQuindi, basta cambiare TfLite.initialize in LiteRt.initialize per restituire un ambiente.
Poi passi l'ambiente a CompiledModel.create.
Si tratta di una piccola modifica, senza aumento delle dimensioni dell'APK.
Nella prossima slide vedremo come farlo con la GPU, che è solo un'altra opzione.
Questo è il codice aggiuntivo necessario per abilitare la 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)Come vedi, il codice nella nuova API per l'abilitazione della GPU è un po' più semplice rispetto al codice precedente.
Quindi, la prima chiamata a un setEnableGpu nelle opzioni di inizializzazione di LiteRT che passi poi a LiteRt.initialize, farà sì che il codice per l'acceleratore GPU venga caricato nella tua app.
Poi, quando crei l'oggetto modelOptions e lo passi a CompiledModel.create, specifichi quale acceleratore verrà utilizzato per un determinato modello, se vuoi che un altro modello venga eseguito solo su GPU, su GPU con fallback su CPU o solo su CPU.
Okay.
Sì, come puoi vedere, l'abilitazione della GPU è molto più semplice con la nuova API.
Quindi, cosa ottieni effettivamente?
Chintan te lo spiegherà.
Okay.
Ok, grazie Fergus.
Quindi, parliamo di cosa ci offre tutto questo, giusto?
Ricordi che abbiamo detto che avremmo creato un'app? Vediamo cosa abbiamo creato, ok?
Quindi, questo sono io, comunque, e quello che abbiamo fatto qui è che abbiamo usato ML Kit per trovarmi, quindi la segmentazione viene eseguita da un'API chiavi in mano come ML Kit.
Quindi, sto solo cercando la mia testa laggiù.
LiteRT utilizza quindi un altro modello simile al trasferimento di stile per dipingere lo sfondo.
E gli altri vantaggi, come abbiamo detto, sono un risparmio di spazio di circa 8 MB, un runtime ora utilizzato tra tutte le tue app, o almeno come quello condiviso qui, e aggiornamenti automatici, oltre a una GPU più veloce che ti offre quasi 30 frame al secondo su qualcosa che deve essere in tempo reale per un'esperienza utente completa.
Un altro aspetto positivo è che non devi fare tutto questo manualmente.
Abbiamo anche appena lanciato una nuova skill in Android, ovvero una skill Android LiteRT che esegue l'upgrade del ML on-device in pochi minuti.
Quindi, puoi fare un paio di cose: puoi eseguire l'upgrade di un'app esistente, puoi creare lo scaffold di una nuova app e puoi anche eseguire l'upgrade della tua app per utilizzare questa nuova integrazione di Play Services.
Quindi, tutto questo è disponibile.
Il link è nella slide, è anche su GitHub e verrà visualizzato anche nella nostra documentazione e nel nostro blog.
E sì, questo dovrebbe essere utile anche per chiunque voglia apportare la modifica a breve.
Quindi, Fergus ci dirà dove andrà a finire.
Per questo motivo, ci impegniamo a fornire l'AI on-device con LiteRT.
Continuiamo a investire in modo significativo nel miglioramento dell'accelerazione GPU e della copertura dei modelli, nonché nel fornire aggiornamenti regolari per LiteRT 2.x, sia per LiteRT open source in bundle sia per il pacchetto Maven LiteRT di Play Services, ovvero LiteRT in Play Services.
Inoltre, continueremo a fornire la compatibilità con le versioni precedenti.
Il runtime di Play Services continuerà a supportare le app create con SDK precedenti.
Sì.
Questo è un aspetto molto importante per i nostri utenti e per noi.
Gli SDK LiteRT 1.x sono ora in modalità di manutenzione, quindi vengono fornite solo correzioni di sicurezza critiche.
Inoltre, NNAPI, che abbiamo ritirato nel 2024, verrà rimosso, probabilmente a partire dal 2027.
Pertanto, se utilizzi NNAPI, passa all'accelerazione GPU o NPU con LiteRT integrato.
Ok.
Sì.
Pertanto, prima esegui il passaggio alla versione 2.x e a CompiledModel, meno dovrai fare in seguito.
In conclusione, tre cose da ricordare.
Quindi, crea.
Inizia con ML Kit e, se fa già ciò di cui hai bisogno, è fantastico.
In caso contrario, utilizza LiteRT per i tuoi modelli personalizzati.
Esegui l'upgrade a LiteRT in Google Play Services per risparmiare spazio nell'APK e utilizzare il runtime condiviso.
Inoltre, valuta la possibilità di utilizzare l'API CompiledModel per un'inferenza GPU più rapida e semplice.
Sì.
Tutto è documentato nel nostro sito di documentazione di LiteRT su AI Edge all'URL indicato.
Quindi, sì.
Grazie per averci seguito e non vediamo l'ora di vedere cosa creerete.
// 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)