Guide pratiche

Creare app Android intelligenti: inferenza cloud e ibrida

8 minuti di lettura

Bentornato alla serie di post del blog "Creare app per Android intelligenti", in cui prendiamo un'app per Android di base e la trasformiamo in un'esperienza personalizzata, intelligente e agentica. Nel post precedente abbiamo esplorato come creare funzionalità intelligenti on-device utilizzando Gemini Nano tramite l'API Prompt di ML Kit.

In questo post, vedremo come sfruttare Firebase AI Logic per creare funzionalità di AI ibride e ospitate sul cloud: 

  • Basare le risposte sul contesto del mondo reale
  • Eseguire il routing dinamico delle richieste tra l'esecuzione cloud e quella locale utilizzando l'inferenza ibrida
  • Tradurre i contenuti con sistemi di routing personalizzati

A volte un caso d'uso richiede modelli di AI con una maggiore conoscenza del mondo, una finestra contestuale molto più grande o la capacità di gestire query complesse. In questi scenari, possiamo sfruttare i modelli cloud. 

Altre volte, vuoi il meglio di entrambi i mondi: utilizzare l'inferenza ibrida per l'esecuzione on-device quando disponibile per ridurre i costi, mentre il cloud garantisce la compatibilità per tutti i dispositivi.

features.png
Funzionalità cloud e ibride in Jetpacker: assistente museale con grounding web, stesura di recensioni di ristoranti ibride e chat di assistenza con traduzione live con routing personalizzato.

Vediamo come abbiamo implementato tre funzionalità cloud e ibride in Jetpacker:

  • Un assistente museale con grounding web
  • Stesura di recensioni di ristoranti ibride
  • Chat di assistenza per hotel con traduzione live con routing personalizzato.

Utilizzare il grounding LLM per informazioni aggiornateChatbot dell'assistente museale con grounding LLM

L'assistente museale è un chatbot interattivo progettato per aiutare gli utenti a pianificare le visite ai musei. Fornisce ai visitatori dettagli aggiornati su mostre specifiche, orari di apertura attuali, prezzi dei biglietti e altro ancora.

museum_assistant_upscaled.png
L'assistente museale è un chatbot che risponde a domande come "Come posso ottenere uno sconto sui biglietti per il Louvre?"

Quando si creano funzionalità di AI, una sfida comune è fare in modo che il modello risponda con informazioni sul mondo reale aggiornate, accurate e specifiche. Sebbene i modelli cloud possiedano enormi quantità di conoscenza del mondo, potrebbero non essere a conoscenza delle mostre stagionali o degli orari di apertura del giorno corrente.

grounding.png
I dati di grounding vengono aggiunti alla finestra contestuale per consentire al modello di rispondere alle domande in modo corretto e accurato.

Per colmare questo divario, possiamo utilizzare tecniche di grounding per aggiungere un contesto aggiuntivo alla finestra contestuale del modello. L'SDK Firebase AI Logic supporta tre tipi di grounding:

  • Grounding URL: risposte di grounding utilizzando i contenuti di una pagina web specifica (ad es. prezzi dei biglietti attuali o regole del museo).
  • Grounding della Ricerca Google: consente al modello di eseguire query sull'indice della Ricerca Google in tempo reale per ottenere dettagli aggiornati.
  • Grounding di Maps: utilizzo dei dati sulla posizione di Google Maps.

In Jetpacker, costruiamo dinamicamente gli strumenti disponibili in base ai flag delle funzionalità abilitate e inizializziamo il modello generativo utilizzando l'SDK AI di Firebase:

// implementation("com.google.firebase:firebase-ai-logic")

private var toolList = mutableListOf<Tool>()

init {
    if (ENABLE_SEARCH_GROUNDING) {
        toolList.add(Tool.googleSearch())
    }
    if (ENABLE_URL_GROUNDING) {
        toolList.add(Tool.urlContext())
    }
}

private val generativeModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash",
        systemInstruction = content {
            text("You are a helpful museum assistant answering questions about a museum. Use plain text.")
        },
        tools = toolList
    )

Quando l'utente esegue una query sull'assistente, se il grounding URL è abilitato, aggiungiamo gli URL delle risorse del museo specifiche direttamente nel prompt:

val groundingText = if (FeatureFlags.ENABLE_URL_GROUNDING) {
    "\n If the following message above is about the rules and terms to visit Le Louvre, " +
    "if needed answer this urls ${urlList.joinToString()}"
} else {
    ""
}

val prompt = "$text $groundingText"

var response = chat.sendMessage(prompt)

Non tutte le attività AI richiedono un modello basato sul cloud e non tutti i dispositivi sono online. Per aiutare gli sviluppatori a bilanciare latenza, costi e disponibilità offline, di recente abbiamo introdotto l'API Firebase per l'inferenza ibrida.

In Jetpacker, la funzionalità Recensione del ristorante consente agli utenti di recensire argomenti selezionati e di scrivere automaticamente una recensione. Per abilitare questa funzionalità per tutti gli utenti, diamo la priorità all'esecuzione locale con Gemini Nano e torniamo ai modelli cloud sui dispositivi che non supportano Gemini Nano. 

review_upscaled.png
La funzionalità di recensione del ristorante utilizza l'inferenza ibrida per scrivere una recensione in base agli argomenti
// implementation("com.google.firebase:firebase-ai-logic")
// implementation("com.google.firebase:firebase-ai-ondevice:16.0.0-beta03")


// Initialize the model with hybrid routing configuration
val reviewModel = Firebase.ai.generativeModel(
    modelName = "gemini-3.1-flash-lite",
    onDeviceConfig = OnDeviceConfig(
        inferenceMode = InferenceMode.PREFER_ON_DEVICE
    )
)

L'API Inferenza ibrida supporta quattro modalità di routing distinte:

  • PREFER_ON_DEVICE: dà la priorità all'esecuzione locale e torna al cloud se Gemini Nano non è disponibile.
  • PREFER_IN_CLOUD: dà la priorità all'esecuzione cloud e torna al dispositivo se il dispositivo va offline.
  • ONLY_ON_DEVICE: limita l'esecuzione rigorosamente al dispositivo.
  • ONLY_IN_CLOUD: limita l'esecuzione rigorosamente al cloud.

Una volta generata la recensione, la copiamo negli appunti e utilizziamo un intent per aprire Google Maps direttamente nella pagina delle recensioni del ristorante, offrendo un'esperienza utente fluida:

private fun copyAndOpenMapsReview(context: Context, reviewText: String, placeId: String) {
    val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clip = ClipData.newPlainText("User Review", reviewText)
    clipboard.setPrimaryClip(clip)

    val uri = Uri.parse("https://search.google.com/local/writereview/mobile?placeid=$placeId")
    val intent = Intent(Intent.ACTION_VIEW, uri).apply {
        setPackage("com.google.android.apps.maps")
    }
    context.startActivity(intent)
}

Routing ibrido personalizzato: traduzione della chat di assistenza per hotel con personaggi simulati

La chat di assistenza per hotel è stata creata per consentire agli utenti di finalizzare la logistica e controllare i dettagli dell'hotel. Questa funzionalità utilizza le istruzioni di sistema per configurare un assistente di reception localizzato. Passando informazioni specifiche, come la lingua preferita e le informazioni sull'hotel, nelle istruzioni, possiamo configurare un personaggio conversazionale che rappresenta un hotel specifico.

private val generativeModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        systemInstruction = content {
            text("""
              You are a helpful hotel receptionist at $hotelName only speaking $language. 
              Answer politely in $language. The bar closes at 10pm and breakfast is from 7am to 10am.
              There's someone at the desk 24/7. You can retrieve your luggage from the storage room 
              at the back of the lobby at any time.
              """)
        },
        modelName = "gemini-3-flash-preview"
    )

Poiché le risposte della reception sono nella lingua locale dell'hotel (ad esempio, il francese per l'Hotel Le Meurice di Parigi), dobbiamo tradurre i messaggi nella lingua preferita dell'utente.

translation_upscaled.png
I messaggi della chat di assistenza per hotel vengono tradotti automaticamente nella lingua preferita dell'utente 

Sebbene i modelli ibridi possano configurare semplici preferenze di routing, gli scenari complessi richiedono una logica di routing personalizzata. In Jetpacker, implementiamo uno stack di routing personalizzato che tiene conto di:

  • Identificazione della lingua: utilizzando l'API di identificazione della lingua di ML Kit on-device, possiamo rilevare la lingua del messaggio in arrivo.
  • Traduzione on-device (Gemini Nano): l'API Prompt di ML Kit ci consente di tradurre le coppie di lingue comuni direttamente sul dispositivo, risparmiando larghezza di banda e costi cloud.
  • Traduzione cloud (Gemini 3 Flash): per le lingue più complesse, utilizziamo Gemini Flash 3 per ottenere una traduzione di qualità superiore.
// implementation("com.google.android.gms:play-services-mlkit-language-id:17.0.0") 

// ML Kit for Language Identification (powered by Google Play Services)
private val languageIdentifier = LanguageIdentification.getClient()

// On-device translator model (prefer Gemini Nano) for translating common language pairs
private val hybridTranslationModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.PREFER_ON_DEVICE)
    )

// Cloud translator model for more complex language pairs
private val cloudTranslationModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash"
    )

Quando è necessario tradurre un messaggio, identifichiamo la lingua di origine e applichiamo la nostra logica di routing personalizzata, eseguendo la traduzione on-device o cloud:

fun translateMessage(message: SupportChatMessage) {
    viewModelScope.launch {
        // 1. Detect language using ML Kit Language Identification
        val sourceLang = try {
            Tasks.await(languageIdentifier.identifyLanguage(message.text))
        } catch (e: Exception) {
            "Undefined"
        }

        // 2. Custom routing: we've verified the translation quality for English and Korean with Gemini Nano, and will translate message on-device for those two languages
        val routeToCloud = sourceLang != "en" && sourceLang != "kr"

        val prompt = "Translate the following text to $selectedLanguage. Just return the translated sentence: ${message.text}."

        val (translatedText, routePrefix) = if (routeToCloud) {
            val result = cloudTranslationModel.generateContent(prompt)
            result.text to "[Cloud]"
        } else {
            val result = hybridTranslationModel.generateContent(prompt)
            result.text to "[On-Device]"
        }

        if (translatedText != null) {
            _translations.update { current ->
                current + (message.id to "$routePrefix: $translatedText")
            }
        }
    }
}

In questo esempio, la logica di routing personalizzata prende in considerazione solo la lingua di origine e di destinazione della traduzione. Tuttavia, in base al caso d'uso della tua app, puoi espandere la logica di routing per includere altri fattori come la versione del modello on-device, la connettività di rete, lo stato della batteria e altro ancora.

Proteggere le pipeline di AI: Firebase App Check

Infine, l'utilizzo dell'AI nel cloud apre la possibilità di abusi delle chiavi API o di fatturazione non autorizzata. Per proteggere le chiamate API, abbiamo integrato Firebase App Check utilizzando sia Play Integrity (produzione) sia il provider di debug locale (per lo sviluppo locale o gli emulatori).

Nel file JetPackerApplication.kt, installiamo il provider di debug all'avvio e attiviamo l'autenticazione anonima per stabilire una sessione utente sicura:

//  implementation("com.google.firebase:firebase-appcheck-playintegrity") 
//  implementation("com.google.firebase:firebase-appcheck-debug")  
//  implementation("com.google.firebase:firebase-auth") 

override fun onCreate() {
    super.onCreate()
    Firebase.initialize(context = this)
    Firebase.appCheck.installAppCheckProviderFactory(
        DebugAppCheckProviderFactory.getInstance()
    )
    Firebase.auth.signInAnonymously()
}

Quando crei localmente su un emulatore, App Check stampa un segreto del token locale in logcat:

Enter this debug secret into the allow list in the Firebase Console: a8c2dd4c-xxxx-xxxx-xxxx-ef6c114ba27e

Una volta registrate nella console Firebase, le richieste locali vengono completamente verificate e autenticate da App Check, proteggendo il nostro backend e consentendoci di testare l'app localmente.

Conclusione

Combinando le funzionalità del modello cloud (grounding, istruzioni di sistema) con le funzionalità on-device (routing ibrido, traduzione, controlli di sicurezza delle app), abbiamo creato un'app di viaggio intelligente, sicura e disponibile offline.

Consulta il codice sorgente completo di Jetpacker su GitHub ed esplora la documentazione di Firebase per iniziare:

Documentazione di Firebase AI Logic
API Firebase Inferenza ibrida

Scopri di più

Dai un'occhiata alle altre parti di questa serie di post del blog:

Parte 1: introduzione dell'app e panoramica di alto livello.
Parte 2: intelligenza on-device. Approfondimento delle API AI generativa di ML Kit e di Gemini Nano per creare funzionalità incentrate sulla privacy, come il riepilogo degli itinerari, l'analisi delle ricevute e l'elaborazione audio locale.
Parte 3 (questo post!): Ragionamento ibrido e cloud. Scopri come utilizzare Firebase AI Logic per basare le risposte LLM su dati del mondo reale come Google Maps e il contesto web.
Parte 4: integrazione del sistema. Integrazione con il sistema di intelligenza di Android utilizzando AppFunctions.
Parte 5 (in arrivo): workflow basati su agenti in-app. Estendi l'app con un assistente di prenotazione end-to-end basato su A2UI e ADK.

Ti interessa saperne di più sullo sviluppo di Android? Segui Android for Developers su YouTube o LinkedIn.

Tutti gli snippet di codice in questo post del blog seguono la seguente nota sul copyright:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0
Scritto da:
Continua a leggere