מדריכים

פיתוח אפליקציות חכמות ל-Android: הסקת מסקנות בענן ובסביבה היברידית

משך הקריאה: 8 דקות

ברוכים השבים לסדרת הפוסטים בבלוג בנושא פיתוח אפליקציות חכמות ל-Android. בסדרה הזו אנחנו לוקחים אפליקציית Android בסיסית והופכים אותה לחוויה מותאמת אישית, חכמה ומבוססת-סוכנים. בפוסט הקודם הסברנו איך ליצור תכונות חכמות במכשיר באמצעות Gemini Nano דרך Prompt API של ML Kit.

בפוסט הזה נראה איך אפשר להשתמש ב-Firebase AI Logic כדי ליצור תכונות AI היברידיות שמתארחות בענן: 

  • התשובות מבוססות על הקשר מהעולם האמיתי
  • ניתוב בקשות באופן דינמי בין ענן לבין ביצוע מקומי באמצעות הסקה היברידית
  • תרגום תוכן באמצעות מערכות ניתוב בהתאמה אישית

לפעמים, תרחיש שימוש מסוים דורש מודלים של AI עם ידע רחב יותר על העולם, חלון הקשר גדול יותר או יכולת לטפל בשאילתות מורכבות. בתרחישים כאלה, אפשר להשתמש במודלים של Cloud. 

במקרים אחרים, רוצים את הטוב משני העולמות: להשתמש בהסקת מסקנות היברידית כדי להפעיל את המודל במכשיר כשהאפשרות זמינה, כדי להפחית את העלויות, ובמקביל להשתמש בענן כדי להבטיח תאימות לכל המכשירים.

features.png
תכונות ענן והיברידיות ב-Jetpacker: עזרה במוזיאון עם חיפוש באינטרנט, טיוטה של ביקורת על מסעדה עם חיפוש באינטרנט וצ'אט תמיכה עם תרגום בזמן אמת שמועבר במסלול מותאם אישית.

נבחן איך הטמענו שלוש תכונות של ענן והיברידיות ב-Jetpacker:

  • עוזר מוזיאון עם עיגון בנתונים מהאינטרנט
  • טיוטה משולבת של ביקורת על מסעדה
  • צ'אט תמיכה למלונות עם תרגום בזמן אמת שמועבר באופן מותאם אישית.

שימוש בהארקה של LLM לקבלת מידע עדכניצ'אט בוט של עוזר מוזיאון עם הארקה של LLM

העוזר הווירטואלי במוזיאון הוא צ'אטבוט אינטראקקטיבי שנועד לעזור למשתמשים לתכנן את הביקור שלהם במוזיאון. הוא מספק למבקרים פרטים עדכניים לגבי תערוכות ספציפיות, שעות הפתיחה הנוכחיות, מחירי הכרטיסים ועוד.

museum_assistant_upscaled.png
עוזר מוזיאון הוא צ'אטבוט שעונה על שאלות, כמו 'איך אפשר לקבל הנחה על כרטיס למוזיאון הלובר?'

כשמפתחים תכונות מבוססות-AI, אתגר נפוץ הוא לגרום למודל לענות עם מידע עדכני, מדויק וספציפי מהעולם האמיתי. למודלים בענן יש כמויות עצומות של ידע על העולם, אבל יכול להיות שהם לא יודעים על תערוכות עונתיות או על שעות הפתיחה של היום.

grounding.png
נתוני Grounding מתווספים לחלון ההקשר כדי לאפשר למודל לענות על שאלות בצורה נכונה ומדויקת.

כדי לגשר על הפער הזה, אפשר להשתמש בטכניקות של ביסוס כדי להוסיף הקשר נוסף לחלון ההקשר של המודל. ‫Firebase AI Logic SDK תומך בשלושה סוגים של ביסוס:

  • הארקה של כתובת URL: הארקת התשובות באמצעות תוכן מדף אינטרנט ספציפי (למשל, מחירי כרטיסים עדכניים או כללי מוזיאון).
  • Google Search grounding: מאפשר למודל לשלוח שאילתות לאינדקס של חיפוש Google בזמן אמת כדי לקבל פרטים עדכניים.
  • הארקה של מפות: שימוש בנתוני מיקום ממפות Google.

ב-Jetpacker, אנחנו בונים באופן דינמי את הכלים הזמינים על סמך דגלי התכונות המופעלים, ומפעילים את המודל הגנרטיבי באמצעות 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
    )

כשהמשתמש שואל שאלה את העוזר הדיגיטלי, אם ההצמדה לכתובת URL מופעלת, אנחנו מוסיפים את כתובות ה-URL הספציפיות של משאבי המוזיאון ישירות להנחיה:

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)

לא כל משימת AI דורשת מודל מבוסס-ענן, ולא כל מכשיר מחובר לאינטרנט. כדי לעזור למפתחים לאזן בין זמן האחזור, העלות והזמינות במצב אופליין, השקנו לאחרונה את Firebase API for Hybrid Inference.

ב-Jetpacker, התכונה restaurant review (ביקורת על מסעדה) מאפשרת למשתמשים לכתוב ביקורות על נושאים נבחרים, והמערכת יוצרת טיוטה של הביקורת באופן אוטומטי. כדי להפעיל את התכונה הזו לכל המשתמשים, אנחנו נותנים עדיפות להרצה מקומית באמצעות Gemini Nano, ועוברים למודלים בענן במכשירים שלא תומכים ב-Gemini Nano. 

review_upscaled.png
התכונה 'ביקורת על מסעדה' משתמשת בהסקת מסקנות היברידית כדי לנסח טיוטה של ביקורת על סמך נושאים
// 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
    )
)

ממשק ה-API של Hybrid Inference תומך בארבעה מצבי ניתוב שונים:

  • PREFER_ON_DEVICE: ניתנת עדיפות להפעלה מקומית, ואם Gemini Nano לא זמין, המערכת חוזרת לענן.
  • PREFER_IN_CLOUD: ניתנת עדיפות להפעלה בענן, ואם המכשיר עובר למצב אופליין, המערכת חוזרת להפעלה במכשיר.
  • ONLY_ON_DEVICE: מגביל את ההרצה למכשיר בלבד.
  • ONLY_IN_CLOUD: מגביל את הביצוע לענן בלבד.

אחרי שהביקורת נוצרת, אנחנו מעתיקים אותה ללוח העריכה ומשתמשים ב-Intent כדי לפתוח את דף הביקורת של המסעדה ישירות במפות Google, וכך מספקים חוויית משתמש חלקה:

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

ניתוב היברידי בהתאמה אישית: תרגום צ'אט לתמיכה במלונות עם פרסונות מדומה

הצ'אט לתמיכה במלונות נועד לאפשר למשתמשים לסיים את הלוגיסטיקה ולבדוק את פרטי המלון. התכונה הזו משתמשת בהוראות מערכת כדי להגדיר עוזרת מקומית לניתוב שיחות. אם נכלול בהוראות מידע ספציפי – כמו השפה המועדפת ופרטי המלון – נוכל להגדיר אישיות שיחה שמייצגת מלון ספציפי.

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

התשובות של פקידת הקבלה הן בשפה המקומית של המלון (לדוגמה, צרפתית במלון Le Meurice בפריז), ולכן אנחנו צריכים לתרגם את ההודעות לשפה המועדפת של המשתמש.

translation_upscaled.png
הודעות צ'אט לתמיכה במלונות מתורגמות אוטומטית לשפה המועדפת של המשתמש 

במודלים היברידיים אפשר להגדיר העדפות פשוטות לניתוב, אבל בתרחישים מורכבים נדרשת לוגיקה מותאמת אישית לניתוב. ב-Jetpacker, אנחנו מטמיעים מחסנית ניתוב מותאמת אישית שמתחשבת בנתונים הבאים:

  • זיהוי שפה: באמצעות ML Kit Language Identification API במכשיר, אפשר לזהות את השפה של ההודעה הנכנסת.
  • תרגום במכשיר (Gemini Nano): Prompt API של ML Kit מאפשר לנו לתרגם צמדי שפות נפוצים ישירות במכשיר, וכך לחסוך ברוחב פס ובעלויות של Cloud.
  • תרגום בענן (Gemini 3 Flash): בשפות מורכבות יותר, אנחנו משתמשים ב-Gemini Flash 3 כדי לקבל תרגום באיכות גבוהה יותר.
// 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"
    )

כשצריך לתרגם הודעה, אנחנו מזהים את שפת המקור ומפעילים את לוגיקת הניתוב המותאמת אישית שלנו, ומבצעים תרגום במכשיר או בענן:

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

בדוגמה הזו, לוגיקת הניתוב המותאמת אישית מתייחסת רק לשפת המקור ולשפת היעד של התרגום. עם זאת, בהתאם לתרחיש השימוש באפליקציה, אפשר להרחיב את לוגיקת הניתוב כך שתכלול גורמים נוספים כמו גרסת המודל במכשיר, קישוריות לרשת, מצב הסוללה ועוד.

אבטחת צינורות ה-AI: Firebase App Check

לבסוף, שימוש ב-AI בענן פותח אפשרויות לניצול לרעה של מפתחות API או לחיוב לא מורשה. כדי לאבטח קריאות ל-API, שילבנו את Firebase App Check באמצעות Play Integrity (בסביבת הייצור) וספק ניפוי הבאגים המקומי (לפיתוח מקומי או לאמולטורים).

בקובץ JetPackerApplication.kt, אנחנו מתקינים את ספק אימות לצורכי ניפוי באגים בהפעלה ומפעילים אימות אנונימי כדי ליצור סשן משתמש מאובטח:

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

כשמבצעים build באופן מקומי באמולטור, App Check מדפיס סוד של טוקן מקומי ב-logcat:

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

אחרי ההרשמה במסוף Firebase, בקשות מקומיות מאומתות ומאושרות באופן מלא על ידי App Check, וכך אנחנו יכולים לבדוק את האפליקציה באופן מקומי ועדיין להגן על ה-Backend שלנו.

סיכום

שילבנו בין יכולות של מודלים בענן (הארקה, הוראות מערכת) לבין יכולות במכשיר (ניתוב היברידי, תרגום, בדיקות אבטחה של אפליקציות) ויצרנו אפליקציית נסיעות חכמה ומאובטחת שזמינה גם במצב אופליין.

כדאי לעיין בקוד המקור המלא של Jetpacker ב-GitHub, ולעיין במסמכי התיעוד של Firebase כדי להתחיל:

Firebase AI Logic Documentation
Firebase Hybrid Inference API

מידע נוסף

כדאי לקרוא גם את החלקים האחרים בסדרת הפוסטים הזו בבלוג:

חלק 1: מבוא לאפליקציה וסקירה כללית.
חלק 2: בינה מובנית במכשיר. במאמר הזה נצלול לעומק אל ממשקי ה-API של AI גנרטיבי ב-ML Kit ואל Gemini Nano, כדי ליצור תכונות ששומרות על הפרטיות כמו סיכום מסלול נסיעה, ניתוח קבלות ועיבוד אודיו מקומי.
חלק 3 (המאמר הזה!): חשיבה רציונלית היברידית ובענן. בסרטון הזה נסביר איך להשתמש ב-Firebase AI Logic כדי להציג תשובות של מודלים גדולים של שפה (LLM) שמבוססות על נתונים מהעולם האמיתי, כמו נתונים מ-Google Maps והקשרים מהאינטרנט.
חלק 4: שילוב מערכות. שילוב עם מערכת ה-AI של Android באמצעות AppFunctions. 
חלק 5 (בקרוב): תהליכי עבודה מבוססי-סוכנים באפליקציה. הרחבת האפליקציה באמצעות עוזר הזמנות מקצה לקצה שמבוסס על A2UI ו-ADK.

רוצים לקבל מידע נוסף על פיתוח ל-Android? אפשר לעקוב אחרי Android Developers ב-YouTube או ב-LinkedIn.

כל קטעי הקוד בפוסט הזה בבלוג כפופים להודעה הבאה על זכויות יוצרים:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0
נכתב על ידי:
להמשך קריאה