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, inteligentneoparte na agentach środowisko. W poprzednim poście pokazaliśmy, jak tworzyć inteligentne funkcje na urządzeniu za pomocą Gemini Nano w interfejsie Prompt API z pakietu 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 chmurowych. 

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 w razie potrzeby przełączać się na chmurę, aby zapewnić zgodność ze wszystkimi urządzeniami.

features.png
Funkcje chmurowe i hybrydowe w Jetpackerze: asystent muzealny z wyszukiwaniem w internecie, hybrydowe tworzenie recenzji restauracji i czat pomocy z tłumaczeniem na żywo kierowanym do odpowiednich osób.

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

  • asystent muzealny z groundingiem w internecie,
  • hybrydowe tworzenie opinii o restauracji;
  • czat pomocy hotelowej z tłumaczeniem na żywo kierowanym do odpowiednich osób.

Korzystanie z uzasadnienia LLM w celu uzyskiwania aktualnych informacjiCzatbot asystenta w muzeum z uzasadnieniem 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 godzin otwarcia w danym dniu.

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

Aby wypełnić tę lukę, możemy użyć technik ugruntowania, aby dodać dodatkowy kontekst do okna kontekstu modelu. 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 Firebase AI SDK:

// 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 dodajemy bezpośrednio adresy URL konkretnych zasobów muzeum:

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 połączone z internetem. 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 restauracjach 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 wykorzystuje wnioskowanie hybrydowe do tworzenia opinii 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 wykonywaniu w chmurze i przełącza się na urządzenie, jeśli to ostatnie przejdzie w tryb offline.
  • ONLY_ON_DEVICE: ogranicza wykonywanie wyłącznie do urządzenia.
  • ONLY_IN_CLOUD:ogranicza wykonywanie wyłącznie 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 użytkownikowi 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 pomocy dotyczącego hoteli z symulowanymi postaciami

Czat z obsługą hotelu umożliwia użytkownikom dopracowanie szczegółów logistycznych i sprawdzenie informacji o hotelu. 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 języku lokalnym hotelu (np. w przypadku Hotelu Le Meurice w Paryżu jest to francuski), dlatego musimy przetłumaczyć wiadomości na preferowany język użytkownika.

translation_upscaled.png
Wiadomości na czacie pomocy dotyczącego 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 wdrażamy niestandardowy stos kierowania, który uwzględnia:

  • Identyfikacja języka: za pomocą interfejsu ML Kit Language Identification API działającego na urządzeniu możemy wykryć język wiadomości przychodzącej.
  • Tłumaczenie na urządzeniu (Gemini Nano): interfejs Prompt API pakietu ML Kit umożliwia tłumaczenie popularnych par językowych bezpośrednio na urządzeniu, co pozwala zaoszczędzić przepustowość i obniżyć 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 API (wersja produkcyjna), jak i lokalnego dostawcy debugowania (na potrzeby lokalnego programowania lub emulatorów).

W pliku JetPackerApplication.kt instalujemy dostawcę debugowania podczas uruchamiania 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 kompilowania 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 lokalne testowanie aplikacji.

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 GenAI API 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ć logiki AI Firebase, aby opierać odpowiedzi LLM na rzeczywistych danych, takich jak Google Maps i kontekst internetowy.
Część 4: integracja z systemem. Integracja z systemem inteligencji Androida za pomocą funkcji aplikacji.
Część 5 (wkrótce): przepływy pracy agenta w aplikacji. 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