Instrukcje

Tworzenie inteligentnych aplikacji na Androida: wnioskowanie w chmurze i hybrydowe

Czas czytania: 8 minut

Witamy z powrotem w serii postów na blogu „Tworzenie inteligentnych aplikacji na Androida”, w której przekształcamy podstawową aplikację na Androida w spersonalizowane, inteligentne i oparte na agentach środowisko. W poprzednim poście pokazaliśmy, jak tworzyć inteligentne funkcje na urządzeniu za pomocą Gemini Nano w interfejsie Prompt API ML Kit.

W tym poście pokażemy, jak korzystać z Firebase AI Logic do tworzenia funkcji AI hostowanych w chmurze i hybrydowych: 

  • Osadzanie odpowiedzi w kontekście rzeczywistym
  • Dynamiczne kierowanie żądań między chmurą a wykonywaniem lokalnym za pomocą wnioskowania hybrydowego
  • Tłumaczenie treści za pomocą niestandardowych systemów routingu

Czasami przypadek użycia wymaga modeli AI z większą wiedzą o świecie, znacznie większym oknie kontekstu lub możliwością obsługi złożonych zapytań. W takich przypadkach możemy korzystać z modeli w chmurze. 

Czasami chcesz mieć to, co najlepsze w obu przypadkach: korzystać z wnioskowania hybrydowego, aby w razie potrzeby uruchamiać je na urządzeniu i obniżać koszty, a jednocześnie wracać do chmury, aby zapewnić zgodność ze wszystkimi urządzeniami.

features.png
Funkcje chmury i hybrydowe w Jetpackerze: asystent muzealny z uzasadnieniem internetowym, hybrydowe tworzenie recenzji restauracji i czat pomocy z tłumaczeniem na żywo kierowanym niestandardowo.

Przyjrzyjmy się, jak wdrożyliśmy 3 funkcje chmury i hybrydowe w Jetpackerze:

  • asystent muzeum z dostępem do internetu,
  • hybrydowe tworzenie opinii o restauracjach;
  • czat pomocy dla hoteli z tłumaczeniem na żywo kierowanym do odpowiednich osób.

Korzystanie z uzasadniania LLM w celu uzyskiwania aktualnych informacjiCzatbot asystenta muzealnego z uzasadnianiem LLM

Asystent muzealny to interaktywny chatbot, który pomaga użytkownikom planować wizyty w muzeach. Zawiera aktualne informacje o konkretnych wystawach, aktualnych godzinach otwarcia, cenach biletów i innych kwestiach.

museum_assistant_upscaled.png
Asystent muzealny to czatbot, który odpowiada na pytania, np. „Jak mogę uzyskać zniżkę na bilet do Luwru?”.

Podczas tworzenia funkcji AI częstym problemem jest uzyskanie od modelu odpowiedzi zawierających aktualne, dokładne i szczegółowe informacje ze świata rzeczywistego. Modele w chmurze mają ogromną wiedzę o świecie, ale mogą nie znać sezonowych wystaw ani aktualnych godzin otwarcia.

grounding.png
Do okna kontekstu dodawane są dane podstawowe, aby model mógł prawidłowo i dokładnie odpowiadać na pytania.

Aby to zniwelować, możemy użyć technik ugruntowania, aby dodać do okna kontekstu modelu dodatkowy kontekst. Pakiet SDK Firebase AI Logic obsługuje 3 rodzaje ugruntowania:

W Jetpackerze dynamicznie tworzymy dostępne narzędzia na podstawie włączonych flag funkcji i inicjujemy model generatywny za pomocą pakietu SDK 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
    )

Gdy użytkownik zada pytanie asystentowi, a funkcja zakotwiczenia w adresie URL jest włączona, do promptu dołączamy bezpośrednio adresy URL konkretnych zasobów muzealnych:

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)

Nie każde zadanie realizowane z wykorzystaniem AI wymaga modelu działającego w chmurze i nie każde urządzenie jest online. Aby pomóc deweloperom w zachowaniu równowagi między opóźnieniem, kosztem i dostępnością offline, wprowadziliśmy niedawno interfejs Firebase API do wnioskowania hybrydowego.

W Jetpacker funkcja opinii o restauracji umożliwia użytkownikom ocenianie wybranych tematów i automatyczne tworzenie opinii. Aby udostępnić tę funkcję wszystkim użytkownikom, nadajemy priorytet lokalnemu wykonywaniu zadań za pomocą Gemini Nano, a w przypadku urządzeń, które nie obsługują Gemini Nano, korzystamy z modeli w chmurze. 

review_upscaled.png
Funkcja opinii o restauracjach korzysta z wnioskowania hybrydowego, aby tworzyć opinie na podstawie tematów
// 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
    )
)

Interfejs Hybrid Inference API obsługuje 4 różne tryby routingu:

  • PREFER_ON_DEVICE: nadaje priorytet lokalnemu wykonywaniu i przechodzi do chmury, jeśli Gemini Nano jest niedostępny.
  • PREFER_IN_CLOUD: nadaje priorytet wykonaniu w chmurze i przechodzi na urządzenie, jeśli urządzenie przejdzie w tryb offline.
  • ONLY_ON_DEVICE:ogranicza wykonywanie wyłącznie do urządzenia.
  • ONLY_IN_CLOUD:ogranicza wykonywanie tylko do chmury.

Po wygenerowaniu opinii kopiujemy ją do schowka i używamy intencji, aby otworzyć Mapy Google bezpośrednio na stronie opinii o restauracji, zapewniając płynne działanie:

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

Niestandardowy routing hybrydowy: tłumaczenie czatu z obsługą hotelu z symulowanymi postaciami

Czat pomocy dotyczący hoteli został stworzony, aby umożliwić użytkownikom dopracowanie szczegółów logistycznych i sprawdzenie informacji o hotelach. Ta funkcja korzysta z instrukcji systemowych, aby skonfigurować lokalnego asystenta recepcji. Przekazując w instrukcjach konkretne informacje, takie jak preferowany język i dane hotelu, możemy skonfigurować osobowość konwersacyjną reprezentującą konkretny hotel.

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

Odpowiedzi recepcjonisty są w lokalnym języku hotelu (np. w przypadku Hotelu Le Meurice w Paryżu jest to francuski), dlatego musimy przetłumaczyć wiadomości na język preferowany przez użytkownika.

translation_upscaled.png
Wiadomości na czacie pomocy dotyczącej hotelu są automatycznie tłumaczone na preferowany język użytkownika 

Modele hybrydowe mogą konfigurować proste preferencje routingu, ale w przypadku złożonych scenariuszy wymagana jest niestandardowa logika routingu. W Jetpackerze implementujemy niestandardowy stos routingu, który uwzględnia:

  • Identyfikacja języka: za pomocą interfejsu ML Kit Language Identification API na urządzeniu możemy wykryć język wiadomości przychodzącej.
  • Tłumaczenie na urządzeniu (Gemini Nano): interfejs Prompt API w ML Kit umożliwia tłumaczenie popularnych par językowych bezpośrednio na urządzeniu, co pozwala zaoszczędzić przepustowość i koszty chmury.
  • Tłumaczenie w chmurze (Gemini 3 Flash): w przypadku bardziej złożonych języków używamy Gemini 3 Flash, aby uzyskać tłumaczenie wyższej jakości.
// 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"
    )

Gdy wiadomość wymaga przetłumaczenia, rozpoznajemy język źródłowy i stosujemy niestandardową logikę routingu, wykonując tłumaczenie na urządzeniu lub w chmurze:

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

W tym przykładzie niestandardowa logika routingu uwzględnia tylko język źródłowy i docelowy tłumaczenia. W zależności od przypadku użycia aplikacji możesz jednak rozszerzyć logikę routingu, aby uwzględniała inne czynniki, takie jak wersja modelu na urządzeniu, łączność sieciowa, stan baterii i inne.

Zabezpieczanie potoków AI: Sprawdzanie aplikacji Firebase

Korzystanie z AI w chmurze otwiera też możliwości nadużywania kluczy interfejsu API lub nieautoryzowanych płatności. Aby zabezpieczyć wywołania interfejsu API, zintegrowaliśmy funkcję Sprawdzanie aplikacji Firebase, korzystając zarówno z interfejsu Play Integrity (wersja produkcyjna), jak i z lokalnego dostawcy debugowania (na potrzeby lokalnego programowania lub emulatorów).

W pliku JetPackerApplication.kt instalujemy dostawcę debugowania przy uruchamianiu i wywołujemy anonimowe uwierzytelnianie, aby utworzyć bezpieczną sesję użytkownika:

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

Podczas tworzenia aplikacji lokalnie na emulatorze funkcja Sprawdzanie aplikacji drukuje w Logcat lokalny klucz tajny tokena:

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

Po zarejestrowaniu w konsoli Firebase lokalne żądania są w pełni weryfikowane i uwierzytelniane przez Sprawdzanie aplikacji, co chroni nasz backend i umożliwia nam testowanie aplikacji lokalnie.

Podsumowanie

Łącząc możliwości modelu w chmurze (uzasadnianie, instrukcje systemowe) z możliwościami na urządzeniu (routing hybrydowy, tłumaczenie, sprawdzanie aplikacji pod kątem bezpieczeństwa), stworzyliśmy aplikację podróżniczą, która jest inteligentna, bezpieczna i dostępna offline.

Zapoznaj się z pełnym kodem źródłowym Jetpackera na GitHubie i przejrzyj dokumentację Firebase, aby rozpocząć:

Dokumentacja Firebase AI Logic
Firebase Hybrid Inference API

Więcej informacji

Zapoznaj się z pozostałymi częściami tej serii postów na blogu:

Część 1.: wprowadzenie do aplikacji i ogólny przegląd
Część 2.: inteligencja na urządzeniu. Poznaj szczegółowo interfejsy API generatywnej AI w ML Kit i Gemini Nano, aby tworzyć funkcje skoncentrowane na ochronie prywatności, takie jak podsumowywanie planów podróży, analizowanie paragonów i lokalne przetwarzanie dźwięku.
Część 3 (ten post): Wnioskowanie hybrydowe i w chmurze. Dowiedz się, jak używać Firebase AI Logic, aby opierać odpowiedzi LLM na danych z rzeczywistego świata, takich jak Mapy Google i kontekst internetowy.
Część 4: integracja systemu. Integracja z systemem inteligencji Androida za pomocą funkcji aplikacji. 
Część 5 (wkrótce): przepływy pracy agentów w aplikacjach. Rozszerz aplikację o kompleksowego asystenta rezerwacji opartego na A2UI i ADK.

Chcesz dowiedzieć się więcej o tworzeniu aplikacji na Androida? Obserwuj Android Developers w YouTube lub LinkedIn.

Wszystkie fragmenty kodu w tym poście na blogu są objęte tym powiadomieniem o prawach autorskich:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0
Autorzy:
Czytaj dalej