开发者关系工程师
在 Android 应用中构建可用于生产用途的生成式 AI,不仅需要连接到 LLM,还需要企业级安全性和成本控制。在本讲座中,您将了解 Firebase AI Logic 如何助力开发者大规模部署安全、经济实惠的 AI 体验。
我们将涵盖从安全基础和 Firebase App Check、费用管理、动态模型路由到利用多模态功能等各个方面。
转写文稿
欢迎参加 Android 开发者峰会。
我是 Ankita Saxena,Firebase 产品经理。
我是 Arthur Thompson,Firebase 团队的开发者关系工程师。
今天,我们将向您展示如何为 Android 应用添加生成式功能。
好了
Firebase 是什么?
听说过 Firebase 的人请举手。
哦,我看到了很多。
太好了。
Firebase 是 Google 的应用开发平台。
Firebase 提供了一个统一的平台,其中集成了 20 多款产品,因此您不会像使用其他软件那样获得碎片化的体验。
我们来谈谈在移动应用中部署生成式 AI 的挑战。
我们发现了三大挑战。
首先,API 密钥泄露:只需几分钟即可提取。
其次,更新模型名称:我们始终建议开发者不要在应用中对模型名称进行硬编码,否则,每次有新模型时,您都必须推送另一个版本。
第三是文件隐私:对于任何开发者或应用用户来说,保护其数据并为应用设置适当的防护措施都非常重要。
介绍 Firebase AI Logic,它是应对我们讨论的挑战的关键解决方案。
Firebase AI Logic 为您提供的价值主张是什么?
我们基本上会处理所有复杂的自定义后端,因此您无需在自己的端进行开发。
其次,通过使用我们的客户端 SDK,您可以直接从移动应用安全地调用 Gemini API。
我们来深入了解一下,看看架构是如何运作的。
左侧是 Firebase 客户端 SDK。
我们目前支持各种客户端 SDK。
我想指出的是,我们也支持 Kotlin。
当开发者想要执行 AI 操作时,SDK 会将请求发送到 Firebase AI Logic,后者随后会将请求安全地路由到 Gemini Developer API 或 Agent Platform Gemini API。
基本上,我们负责处理您今天创建的所有自定义后端。
我们从中获得的价值是,您在零成本的情况下加快了上市期。
现在进入最有趣的环节。
这是一个演示 FriendlyMeals 应用的演示。
顺便提一下,在本课程的后续演示中,我们将使用同一应用,因此您可以随时下载。
您可以使用此处的二维码进行扫描。
我们来演示一下。
FriendlyMeals 应用基本上可以帮助您根据输入的食材识别食谱。
因此,在此工作流中,您可以看到基本上有两种方法来捕获这些要素。
第一种,输入您现有的食材。
第二步,拍摄食材的照片。
我将使用第一个工作流,即输入食材。
这些就是我在冰箱里找到的所有食材。
在生成食谱的过程中,我想提醒大家注意几点。
因此,在后台,我们在这里调用 Gemini 模型。
对于这个特定应用场景,我们将调用三个 Gemini 3.8 Flash。
如果您看到顶部,该图片实际上使用的是 Gemini Nano Banana 模型,即 2.1 Nano Banana,这是最新版本。
在深入探讨代码之前,我想先强调一下 Firebase AI Logic 为您带来的价值主张。
第一种是无服务器 SDK。
您想添加 AI 功能,但不想设置后端。
这正是我们的客户端 SDK 发挥作用的地方。
您直接从 Android 应用调用 Gemini。
第二个是强大的内置安全功能。
因此,在调用 Gemini 时,您可以利用 Firebase App Check 以及服务器提示模板等功能,我们稍后会详细介绍这些安全功能。
第三,支持多模态输入和流式传输等高级功能。
假设您想构建一款应用,添加一个简单的 AI 功能,用于生成关于神奇背包的故事。
import com.google.firebase.Firebase
import com.google.firebase.ai.ai
@Composable
fun MagicBackpackGenerator() {
var output by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
val model=Firebase.ai.generativeModel("gemini-4-argon")
val response = model.generateContent("Write a story about a magic backpack")
output = response.text.toString()
}
MagicBackpackUI(output)
}只需以下三个简单步骤,即可添加该 AI 功能并将其投入生产。
Firebase AI Logic 让您能够轻松地向应用添加 AI 功能,因此您应该首先考虑如何确保此功能的安全。
接下来,我们深入了解安全细节,首先从 Firebase App Check 开始。
Firebase App Check 通过验证请求是否来自您的应用,帮助您保护数据、保护用户,并控制谁有权访问您的 API 资源。
这会为您的应用增添一道安全屏障,有助于防止应用被滥用。
在开始编写代码之前,您需要在 Firebase 控制台中执行几个步骤。
因此,在 Firebase 控制台的 App Check 下,您需要注册 Android 应用,并添加相应的认证提供方。
例如 Play Integrity 或 reCAPTCHA Enterprise。
请注意,在设置 App Check 后,您需要先从非强制执行模式开始。
这样,您就可以让应用提供遥测数据,以确保在强制执行之前,所有应用都能成功向后端发出 API 调用。
当您看到遥测数据正常传输后,就可以强制执行 App Check,届时任何没有有效、经过硬件证明的令牌的请求都将被拒绝。
以下是实现 App Check 的代码。
class FireTravelApp : Application() {
lateinit var appContainer: AppContainer
private set
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Firebase.appCheck.installAppCheckProviderFactory(
DebugAppCheckProviderFactory.getInstance()
)
} else {
Firebase.appCheck.installAppCheckProviderFactory(
PlayIntegrityAppCheckProviderFactory.getInstance()
)
}
appContainer = AppContainer(this)
}
}在应用类中,安装 App Check 提供程序。
在开发阶段,您可能需要使用调试提供程序,然后在准备好进入生产阶段时,切换到 Play Integrity 或 reCAPTCHA Enterprise。
不过,请务必记住,您需要先配置 App Check,然后再进行任何其他 Firebase 调用。
在构建 AI 功能时,开发者通常会将提示直接硬编码到应用代码中,但这会带来两大挑战。
第一,如果需要对提示进行任何改进,您必须推送完整更新。
其次,任何解压您应用的人都可以访问您的专有提示词工程。
为了解决此问题,Firebase AI Logic 使用了服务器提示模板。
此设置会将您的提示存储在云端,而不是设备上。
这是 Firebase 控制台中服务器提示模板的视图。
您可以使用 .prompt 格式编写模板。
---
model: 'gemini-3-flash'
input:
schema:...
tools:...
---
{{role "system"}}
You're a storyteller that tells nice and joyful stories with happy endings.
{{role "user"}}
Create a story about {{topic}} with the length of {{length}} words in the {{language}} language.您可以在此处设置模型名称。
您可以随时更新。
您无需推送完整的应用更新。
您还可以更新系统指令,并且它还接受严格的 JSON 架构作为输入和输出。
同样,您无需发布应用。
由于它位于云端,您可以立即调整提示或更换模型。
这是 Kotlin 中的代码。
val generativeModel = Firebase.ai.templateGenerativeModel()
val response = generativeModel.generateContent("storyteller-v1",
mapOf(
"topic" to topic,
"length" to length,
"language" to language
)
)
output.value = response.text这里需要特别说明的是,服务器提示模板目前处于公开试用功能阶段。
您还可以实现“仅限身份验证”模式。
此方法使用 Firebase Auth 用户令牌来授权请求。
为了完善安全功能并完全锁定您的应用,您还可以直接在 Firebase 控制台中使用“仅限模板”模式。
应用发布后,您可能希望了解其运行情况。
在“AI 监控”标签页中,只需点击一下,即可启用 AI 监控并配置采样率。
Firebase 会自动捕获指标、延迟时间和 token 数量,您无需为此编写自定义分析代码。
这里提到了我们刚才看到的两种模式,它们都可以在同一个窗口中使用。
在 Firebase 控制台中启用 AI 监控后,这些数据会直接馈送到 AI 监控信息中心。
您可以观察第 95 百分位的延迟时间、发现突发的错误峰值,并跟踪不同模态(例如文本、图片和音频)的 token 消耗情况。
您还可以检查 Trace 查看器,查看某些跟踪记录。
因此,在本例中,由于它展示了我们所用模型的差异,您可以看到延迟时间和成功率。
在 Firebase 控制台中,您可以获取所有遥测数据,并了解 AI 功能的运行情况。
因此,在这种情况下,假设您发现 token 使用量突然激增,或者延迟时间突然激增,那么混合搜索就是降低这些费用或延迟时间的一种方法。
随着生成式 AI 功能成为应用的核心部分,完全依赖云端可能并非最佳选择。
因此,通过利用 Nano 4(Android 上的设备端模型),可以解锁三大主要优势,您可能对这些优势都很熟悉。
第一种是离线模式。
因此,无论您是在大型会议中,还是在飞机或地铁上,AI 功能都能正常运行。
费用。
因此,由于推理是在设备上运行的,您可以添加这些功能,而无需担心 AI 功能的成本不断上升。
第三个是数据隐私权。
因此,如果是敏感数据,您可以向用户保证,所有推理都不会离开设备。
因此,借助 Firebase AI Logic,您可以设置这些推理模式,并制定清晰的路由策略,例如 PREFER_ON_DEVICE、PREFER_IN_CLOUD 或 ONLY_ON_DEVICE。
选择 ONLY_ON_DEVICE 后,SDK 会直接利用设备端模型,完全绕过云端。
我们切换到手机上看看。
同样,我们先打开 FriendlyMeals,看看一些设备端功能。
首先,我们要尝试根据冰箱里可能有的食材来创建一份食谱。
之前,您看到 Ankita 使用了手动方法,即输入食材,然后生成食谱。
所以,我们试试另一种方法。
我们来看一下这台非常真实的冰箱,它绝对不是生成的。
冰箱里有很多橄榄,我们来看看会生成什么样的食谱。
因此,我想指出几点。
一种是图片从未离开过设备。
图片由 Nano by Gemma 在本地分析…
Nano 4。
其次,是响应速度。
素材已生成。
因此,您将获得两大好处。
数据不会离开设备,而且延迟时间也显著缩短。
好,我们来看看冰箱里只有橄榄时,会得到什么食谱。
因此,这次我们使用的是云端。
因此,我们现在使用 Firebase AI Logic 将冰箱中识别出的食材发送到云端,以生成食谱。
我没在冰箱里看到三文鱼,但食谱里有三文鱼。
但我们还是先回到幻灯片吧。
正如我们在演示中看到的,在本地模型和云端模型之间切换非常简单。
目前,Firebase AI Logic 可根据网络可用性,使用基本路由进行推理。
为了管理这种推理,您可以将其视为防护措施。
因此,该架构内置了对多模态和输入/输出架构等功能的支持,并与 Gemma(抱歉,是 Gemini Nano 4)完全集成。
接下来,我们来看看这些护栏在实践中是如何实现的。
因此,混合路由不需要您构建复杂的中间件或自行构建大量回退逻辑。
从代码角度来看,它只是一个额外的参数。
您需要向 onDeviceConfig 传递一个参数,以设置您偏好的模式。
import com.google.firebase.Firebase
import com.google.firebase.ai.ai
@Composable
fun MagicBackpackGenerator() {
var output by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
val model = Firebase.ai.generativeModel(modelName = "gemini-3.8-flash",
onDeviceConfig = OnDeviceConfig(mode = InferenceMode.PREFER_ON_DEVICE))
val response = model.generateContent("Write a story about a magic backpack")
output = response.text.toString()
}
MagicBackpackUI(output)
}在这种情况下,SDK 会先尝试使用本地模型,如果本地模型不可用,则会自动回退到云端。
我们已经介绍了如何构建安全的应用以及如何利用设备端模型,接下来我们来谈谈成本优化。
生成式功能可以快速扩缩,您的 Cloud Billing 账单也是如此。
因此,我们需要设置适当的防护措施,确保我们拥有正确的主动式基础架构控制措施和自动化功能,从而帮助您预测预算并提高应用的财务效率。
虽然 Arthur 刚才强调了设备端推理是完全免费的,但仍然会有一些场景需要复杂的推理任务,并且需要回退和路由到云端。
当这些云调用发生时,您需要设置防护机制,以确保预算可预测。
这正是 Firebase 支出上限功能的用武之地。
借助支出上限,您可以更精细地控制应用费用。
因此,您无需使用通用的项目级预算设置,也不必依赖仅发送电子邮件的预算提醒,而是可以为 Firebase AI Logic 等单个服务设置具体的预算限额。
当支出达到 100% 时,Firebase 会自动暂停 AI 服务,以防止账单金额失控。
除了简单的支出上限之外,还有几种高级费用优化策略。
今天,我们想重点介绍的是 Firebase AI Logic 触发器。
如果您需要在中间使用自定义逻辑,该怎么办?
这就是 Firebase AI Logic 触发器。
您可以在生成内容之前或之后运行函数。
您可以使用它来检查用户、过滤输入、添加上下文,以及调整返回的回答。
现在,我们已经介绍了成本优化和安全性,接下来让我们转向模型功能,看看 Firebase AI Logic 提供了哪些功能。
为了支持这些多模态体验,Firebase AI Logic 提供了全面的可用于生产用途的模型和工具目录。
如需进行高速推理、处理文本、代码和媒体,您可以使用 Gemini 4 Argon、Gemini 3.1 Pro、Gemini 3.8 Flash 等模型。
您还可以使用搜索和地图接地功能,将这些模型与真实数据相关联。
最后,在语音方面,我们提供自然的文字转语音和 Gemini Live 音频生成工具。
我们再切换到手机。
所以,这里有甜味和咸味。
噢,抱歉,不是那个。
这里有我们制作这道菜所需的芝士番茄酱吐司。
听起来很美味。
首先,我们来看看 Live API。
因此,在这种情况下,我们可以使用返回的视频,然后说:“Gemini,你能告诉我桌上有什么食材吗?”
根据笔记本电脑屏幕上的图片,您现有的食材是面包、切达干酪和番茄酱。
好了
那么,我可以开始执行食谱的第一步了吗?
是。
第一步是将烤箱或烤架预热至中高火。
谢谢。
好了
在这种情况下,使用的是 Live API,对话会一直保持打开状态,直到我主动关闭它。
另一个我想展示的是语音转文字,或者文字转语音,抱歉。
在这个示例中,我们有食谱说明,并且带有文字转语音功能。
这样,我就不用自己阅读了,只需点击“生成”或“朗读”,系统就会将说明文本发送到 TTS 模型。
它会生成音频,并将音频发送回设备。
我可以播放它,将其缓存以供日后使用,它会像我们在这里看到的那样播放。
1.
将烤箱或烤架预热至中高火。
2.
将两片面包放在烤盘或烤面包机托盘上。
不错。
很酷吧?
因此,Firebase AI Logic 让我们只需几行代码即可实现这些炫酷的功能。
我们切换回幻灯片。
在演示中,我们已经了解了 Gemini Live API 的工作原理。如果您想自己打造免触摸的对话式体验,该怎么做呢?
这时,Gemini Live API 就派上用场了,它能让您创建双向语音对话。
您的 Android 应用可以向上游流式传输实时麦克风音频和摄像头画面,并实时接收自然、低延迟的语音。
在 Kotlin 中,设置过程看起来非常熟悉。
val model = Firebase.ai.liveModel(
modelName = "gemini-3.1-flash-live-preview",
generationConfig = liveGenerationConfig {
responseModality = ResponseModality.AUDIO
},
systemInstruction = "Your main job is to change the color...",
tools = listOf(Tool.functionDeclarations(listOf(changeColorFunction)))
)
val session = model.connect(::handler)
session.startAudioConversation(::handler)
session.stopAudioConversation()您需要实例化一个配置为音频回答的实时模型,并使用流处理程序连接到会话。
我们在此要强调的第一点是,该 SDK 会在后台处理完整的 WebSocket 内容和流式传输协议。
所以,您不必编写代码,对吧?
继续写。
import com.google.firebase.Firebase
import com.google.firebase.ai.ai
@Composable
fun MagicBackpackGenerator() {
var output by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
val model=Firebase.ai.generativeModel("gemini-4-argon")
val response = model.generateContent("Write a story about a magic backpack")
output = response.text.toString()
}
MagicBackpackUI(output)
}class FireTravelApp : Application() {
lateinit var appContainer: AppContainer
private set
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Firebase.appCheck.installAppCheckProviderFactory(
DebugAppCheckProviderFactory.getInstance()
)
} else {
Firebase.appCheck.installAppCheckProviderFactory(
PlayIntegrityAppCheckProviderFactory.getInstance()
)
}
appContainer = AppContainer(this)
}
}---
model: 'gemini-3-flash'
input:
schema:...
tools:...
---
{{role "system"}}
You're a storyteller that tells nice and joyful stories with happy endings.
{{role "user"}}
Create a story about {{topic}} with the length of {{length}} words in the {{language}} language.val generativeModel = Firebase.ai.templateGenerativeModel()
val response = generativeModel.generateContent("storyteller-v1",
mapOf(
"topic" to topic,
"length" to length,
"language" to language
)
)
output.value = response.textimport com.google.firebase.Firebase
import com.google.firebase.ai.ai
@Composable
fun MagicBackpackGenerator() {
var output by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
val model = Firebase.ai.generativeModel(modelName = "gemini-3.8-flash",
onDeviceConfig = OnDeviceConfig(mode = InferenceMode.PREFER_ON_DEVICE))
val response = model.generateContent("Write a story about a magic backpack")
output = response.text.toString()
}
MagicBackpackUI(output)
}val model = Firebase.ai.liveModel(
modelName = "gemini-3.1-flash-live-preview",
generationConfig = liveGenerationConfig {
responseModality = ResponseModality.AUDIO
},
systemInstruction = "Your main job is to change the color...",
tools = listOf(Tool.functionDeclarations(listOf(changeColorFunction)))
)
val session = model.connect(::handler)
session.startAudioConversation(::handler)
session.stopAudioConversation()# Execute to add agent capabilities to your workspace
npx skills add firebase/agent-skills