Instructivos

Crea apps inteligentes para Android: inferencia híbrida y en la nube

Lectura de 8 min

Te damos la bienvenida a la serie de publicaciones de blog "Crea apps inteligentes para Android", en la que tomamos una app básica para Android y la transformamos en una experiencia personalizada, inteligente y con agentes. En nuestra publicación anterior, exploramos cómo crear funciones inteligentes integradas en el dispositivo con Gemini Nano a través de la API de Prompt de ML Kit.

En esta publicación, veremos cómo puedes aprovechar Firebase AI Logic para crear funciones híbridas y alojadas en la nube potenciadas por IA: 

  • Fundamentar las respuestas en el contexto del mundo real
  • Cómo enrutar solicitudes de forma dinámica entre la ejecución local y la de la nube con la inferencia híbrida
  • Cómo traducir contenido con sistemas de enrutamiento personalizados

A veces, un caso de uso requiere modelos de IA con mayor conocimiento mundial, una ventana de contexto mucho más grande o la capacidad de controlar consultas complejas. En esos casos, podemos aprovechar los modelos basados en la nube. 

En otras ocasiones, querrás lo mejor de ambos mundos: usar la inferencia híbrida para ejecutarla integrado en el dispositivo cuando esté disponible y reducir los costos, y recurrir a la nube para garantizar la compatibilidad con todos los dispositivos.

features.png
Funciones híbridas y en la nube en Jetpacker: asistente de museo con fundamentación web, redacción híbrida de reseñas de restaurantes y chat de asistencia con traducción en vivo personalizada.

Veamos cómo implementamos tres funciones híbridas y de nube en Jetpacker:

  • un asistente de museo con fundamentación web
  • Redacción híbrida de opiniones sobre restaurantes
  • Chat de asistencia para hoteles con traducción en vivo personalizada.

Usa la fundamentación de LLM para obtener información actualizada. Chatbot de asistente de museo con fundamentación de LLM

El Asistente de museo es un chatbot interactivo diseñado para ayudar a los usuarios a planificar sus visitas a museos. Proporciona a los visitantes detalles actualizados sobre exposiciones específicas, horarios de atención actuales, precios de las entradas y mucho más.

museum_assistant_upscaled.png
El asistente del museo es un chatbot que responde preguntas, como “¿Cómo puedo obtener un descuento en la entrada al Louvre?”.

Cuando se crean funciones basadas en IA, un desafío común es lograr que el modelo responda con información actualizada, precisa y específica del mundo real. Si bien los modelos basados en la nube poseen grandes cantidades de conocimiento del mundo, es posible que no conozcan las exposiciones de temporada o el horario de atención del día.

grounding.png
Se agregan datos de fundamentación a la ventana de contexto para permitir que el modelo responda preguntas de forma correcta y precisa.

Para superar esta brecha, podemos usar técnicas de fundamentación para agregar contexto adicional a la ventana de contexto del modelo. El SDK de Firebase AI Logic admite tres tipos de fundamentación:

En Jetpacker, construimos de forma dinámica las herramientas disponibles según las marcas de funciones habilitadas y, luego, inicializamos el modelo generativo con el SDK de Firebase AI:

// 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
    )

Cuando el usuario le hace una pregunta al asistente, si la fundamentación de URL está habilitada, agregamos las URLs de recursos específicos del museo directamente en la instrucción:

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)

No todas las tareas de IA requieren un modelo basado en la nube, y no todos los dispositivos están en línea. Para ayudar a los desarrolladores a equilibrar la latencia, el costo y la disponibilidad sin conexión, hace poco presentamos la API de Firebase para la inferencia híbrida.

En Jetpacker, la función de opiniones sobre restaurantes permite que los usuarios revisen temas seleccionados y redacten automáticamente una opinión. Para habilitar esta función para todos los usuarios, priorizamos la ejecución local con Gemini Nano y recurrimos a los modelos en la nube en los dispositivos que no admiten Gemini Nano. 

review_upscaled.png
La función de opiniones sobre restaurantes usa la inferencia híbrida para redactar una opinión basada en temas
// 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
    )
)

La API de Hybrid Inference admite cuatro modos de enrutamiento distintos:

  • PREFER_ON_DEVICE: Prioriza la ejecución local y recurre a la nube si Gemini Nano no está disponible.
  • PREFER_IN_CLOUD: Prioriza la ejecución en la nube y recurre a la ejecución integrada en el dispositivo si este se desconecta.
  • ONLY_ON_DEVICE: Restringe la ejecución estrictamente al dispositivo.
  • ONLY_IN_CLOUD: Restringe la ejecución estrictamente a la nube.

Una vez que se genera la opinión, la copiamos en el portapapeles y usamos un intent para abrir Google Maps directamente en la página de opiniones del restaurante, lo que proporciona una experiencia del usuario 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)
}

Enrutamiento híbrido personalizado: Traducción de chat de asistencia al cliente de hoteles con arquetipos simulados

El chat de asistencia para hoteles se creó para que los usuarios puedan finalizar la logística y consultar los detalles del hotel. Esta función usa instrucciones del sistema para configurar un asistente de recepción localizado. Si pasamos información específica en las instrucciones, como el idioma preferido y la información del hotel, podemos configurar un personaje conversacional que represente a un hotel específico.

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"
    )

Dado que las respuestas de la recepcionista están en el idioma local del hotel (por ejemplo, francés para el Hotel Le Meurice en París), debemos traducir los mensajes al idioma de preferencia del usuario.

translation_upscaled.png
Los mensajes de chat de asistencia para hoteles se traducen automáticamente al idioma preferido del usuario. 

Si bien los modelos híbridos pueden configurar preferencias de rutas simples, las situaciones complejas requieren una lógica de rutas personalizada. En Jetpacker, implementamos una pila de enrutamiento personalizada que tiene en cuenta lo siguiente:

  • Identificación de idioma: Con la API de ML Kit Language Identification integrada en el dispositivo, podemos detectar el idioma del mensaje entrante.
  • Traducción integrada en el dispositivo (Gemini Nano): La API de Prompt de ML Kit nos permite traducir pares de idiomas comunes directamente en el dispositivo, lo que ahorra ancho de banda y costos de la nube.
  • Traducción en la nube (Gemini 3 Flash): Para los idiomas más complejos, usamos Gemini Flash 3 para obtener una traducción de mayor calidad.
// 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"
    )

Cuando se necesita traducir un mensaje, identificamos el idioma de origen y aplicamos nuestra lógica de enrutamiento personalizada, que se ejecuta integrado en el dispositivo o en la nube:

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")
            }
        }
    }
}

En este ejemplo, la lógica de enrutamiento personalizada solo tiene en cuenta el idioma de origen y el idioma de destino de la traducción. Sin embargo, según el caso de uso de tu app, puedes expandir la lógica de enrutamiento para incluir otros factores, como la versión del modelo integrado en el dispositivo, la conectividad de red, el estado de la batería y mucho más.

Protección de las canalizaciones de IA: Verificación de aplicaciones de Firebase

Por último, el uso de la IA en la nube abre la posibilidad de abuso de claves de API o facturación no autorizada. Para proteger las llamadas a la API, integramos la Verificación de aplicaciones de Firebase con Play Integrity (producción) y el proveedor de depuración local (para el desarrollo local o los emuladores).

En el archivo JetPackerApplication.kt, instalamos el proveedor de depuración en el inicio y activamos la autenticación anónima para establecer una sesión de usuario segura:

//  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()
}

Cuando compilas de forma local en un emulador, App Check imprime un secreto del token local en logcat:

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

Una vez que se registran en Firebase console, la Verificación de aplicaciones verifica y autentica por completo las solicitudes locales, lo que protege nuestro backend y nos permite probar la app de forma local.

Conclusión

Combinamos las capacidades del modelo en la nube (fundamentación, instrucciones del sistema) con las capacidades integradas en el dispositivo (enrutamiento híbrido, traducción, verificaciones de seguridad de la app) para crear una app de viajes inteligente, segura y disponible sin conexión.

Consulta el código fuente completo de Jetpacker en GitHub y explora la documentación de Firebase para comenzar:

Documentación de Firebase AI Logic
API de Firebase Hybrid Inference

Más información

Consulta las otras partes de esta serie de entradas de blog:

Parte 1: Introducción a la app y descripción general.
Parte 2: Inteligencia integrada en el dispositivo Analiza en detalle las APIs de IA generativa de ML Kit y Gemini Nano para crear funciones que prioricen la privacidad, como el resumen de itinerarios, el análisis de recibos y el procesamiento de audio local.
Parte 3 (esta publicación): Razonamiento híbrido y en la nube Explora cómo usar Firebase AI Logic para fundamentar las respuestas de los LLM en datos del mundo real, como Google Maps y el contexto web.
Parte 4: Integración del sistema. Integración con el sistema de inteligencia de Android a través de AppFunctions 
Parte 5 (próximamente): Flujos de trabajo de agentes integrados en la app Extiende la app con un asistente de reservas integral potenciado por A2UI y el ADK.

¿Te interesa obtener más información sobre el desarrollo para Android? Sigue a Android Developers en YouTube o LinkedIn.

Todos los fragmentos de código de esta entrada de blog incluyen el siguiente aviso sobre derechos de autor:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0
Escrito por:
Continuar leyendo