借助机器学习套件的直接模型访问功能,您可以使用函数调用,让 Gemini Nano 模型输出结构化函数执行请求(工具调用),而不是纯文本回答。借助函数调用,您可以将设备端生成式 AI 模型连接到外部工具、API 和本地应用功能。
主要功能
函数调用提供以下关键功能:
- 单轮函数调用:Gemini Nano 预测一个或多个工具调用 (
FunctionCall),您的应用在本地执行这些函数,流程完成,无需后续模型响应。 - 多轮函数调用:Gemini Nano 预测一个或多个工具调用 (
FunctionCall),您的应用在本地执行函数,并将结果传回 (FunctionResponsePart) 以检索更多工具调用或最终合成的文本回答。
实现函数调用时,您可以利用以下功能:
- 程序化工具定义:使用机器学习套件 GenAI Schema API (
com.google.mlkit:genai-schema) 在运行时构建动态FunctionDeclaration和FunctionSchema工具定义。 - 结构化实参解析:直接从模型回答候选项中接收强类型实参值,以执行本地应用逻辑。
示例结果
函数调用支持单轮和多轮流程。在这两种情况下,模型都会预测一个或多个由函数名称和实参组成的工具调用。对于多轮对话流程,在收到应用的执行结果后,应用可以向模型发送另一个请求,其中包含完整的对话历史记录,以便获取更多工具调用或用户的最终文本回答。
| 执行流程 | 用户提示 | 模型输出 |
|---|---|---|
| 单轮 | “将客厅灯的亮度调到 80%。” |
工具调用:turn_on_light(room="living room", brightness=80)
|
| 单轮 | “打开‘相机’应用。” |
工具调用:open_app(appName="Camera")
|
| 多轮 | “旧金山的天气怎么样?请用摄氏度回答。” |
中间工具调用:get_current_weather(location="San Francisco, CA", unit="celsius")
向用户显示的最终模型输出: In SF it's currently 25 degrees Celsius.
|
前提条件
如需使用函数调用,您必须满足以下设备和账号要求:
- 您的设备支持 Prompt API。
- 您设备上的 Google 账号已加入 AICore 开发者预览版计划。
如需确认您是否满足这些要求,请检查 AICore 应用中是否提供了 Gemini Nano 4 Fast 模型:打开 AICore 应用,点击选择模型下拉菜单,然后检查是否列出了 Gemini Nano 4 Fast。如果模型不存在,则表示设备支持或账号注册存在问题,函数调用将无法正常运行。
此外,您的项目还必须满足以下要求:
- Kotlin 2.3.0 版或更高版本
- 最低 SDK (
minSdk) 版本 26 或更高版本
开始使用
以下是开始使用函数调用的步骤。
在项目级
settings.gradle.kts(或settings.gradle)文件中,将mavenCentral()添加到repositories {}代码块。dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }在模块级
build.gradle.kts(或build.gradle文件)中,添加 ML Kit Prompt API 和架构依赖项:Kotlin
plugins { id("com.android.application") id("org.jetbrains.kotlin.android") } dependencies { // ML Kit GenAI Prompt and Schema SDKs implementation("com.google.mlkit:genai-prompt:1.0.0-beta5") implementation("com.google.mlkit:genai-schema:1.0.0-alpha2") }Groovy
plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } dependencies { // ML Kit GenAI Prompt and Schema SDKs implementation 'com.google.mlkit:genai-prompt:1.0.0-beta5' implementation 'com.google.mlkit:genai-schema:1.0.0-alpha2' }在模块级
build.gradle(或build.gradle.kts文件)中,将minSdk版本设置为26或更高版本。Kotlin
android { defaultConfig { // ... minSdk = 26 // ... } }Groovy
android { defaultConfig { // ... minSdk 26 // ... } }
如何使用函数调用 API
如需实现函数调用,请执行以下步骤:
- 定义工具。
- 选择模型。
- 将工具附加到请求中。
- 处理工具调用(单轮或多轮)。
以下部分将通过一个示例来演示这些步骤。
定义工具
使用 com.google.mlkit.genai.schema.tools 软件包中的 FunctionDeclaration、FunctionSchema 和 FunctionType 以编程方式构建工具架构。(如需在编译时使用 Android 的 @AppFunction 注解以声明方式定义工具并自动执行,请参阅定义工具。)
例如,您可以定义一个面向操作的工具(例如打开智能灯,以便单轮执行):
import com.google.mlkit.genai.schema.tools.FunctionDeclaration
import com.google.mlkit.genai.schema.tools.FunctionSchema
import com.google.mlkit.genai.schema.tools.FunctionType
val turnOnLightTool = FunctionDeclaration(
name = "turn_on_light",
description = "Turn on the lights in a room and set the brightness",
parameters = FunctionSchema(
type = FunctionType.OBJECT,
properties = mapOf(
"room" to FunctionSchema(
type = FunctionType.STRING,
description = "The room name"
),
"brightness" to FunctionSchema(
type = FunctionType.INTEGER,
description = "Brightness level from 0 to 100"
)
),
required = listOf("room")
)
)
或者定义一个数据检索工具(例如,获取当前天气以进行多轮合成):
import com.google.mlkit.genai.schema.tools.FunctionDeclaration
import com.google.mlkit.genai.schema.tools.FunctionSchema
import com.google.mlkit.genai.schema.tools.FunctionType
val getWeatherTool = FunctionDeclaration(
name = "get_current_weather",
description = "Get the current weather for a location",
parameters = FunctionSchema(
type = FunctionType.OBJECT,
properties = mapOf(
"location" to FunctionSchema(
type = FunctionType.STRING,
description = "The city and state, e.g. San Francisco, CA"
),
"unit" to FunctionSchema(
type = FunctionType.STRING,
description = "The temperature unit, either 'celsius' or 'fahrenheit'"
)
),
required = listOf("location")
)
)
选择模型
函数调用需要 Gemini Nano 4。如需访问 Gemini Nano 4,请使用模型选择 API 将 GenerativeModel 实例配置为以 ModelReleaseStage.PREVIEW 和 ModelPreference.FAST 为目标。
import com.google.mlkit.genai.prompt.Generation
import com.google.mlkit.genai.prompt.ModelPreference
import com.google.mlkit.genai.prompt.ModelReleaseStage
import com.google.mlkit.genai.prompt.generationConfig
import com.google.mlkit.genai.prompt.modelConfig
// Target the preview fast model (Gemini Nano 4)
val config = generationConfig {
modelConfig = modelConfig {
releaseStage = ModelReleaseStage.PREVIEW
preference = ModelPreference.FAST
}
}
val generativeModel = Generation.getClient(config)
将工具附加到请求
创建 GenerateContentRequest 对象时,请在请求构建器中将 FunctionDeclaration 列表传递给 setTools()。
例如,如需为带有系统指令的单轮操作请求附加工具,请执行以下操作:
import com.google.mlkit.genai.prompt.SystemInstruction
import com.google.mlkit.genai.prompt.TextPart
import com.google.mlkit.genai.prompt.generateContentRequest
val requestText = "Turn on the living room lights and set brightness to 50"
val request = generateContentRequest(
SystemInstruction("You are a helpful home automation assistant."),
TextPart(requestText)
) {
// Attach the FunctionDeclaration tool schemas
setTools(listOf(turnOnLightTool))
temperature = 0.2f
}
// Run non-streaming inference
val response = generativeModel.generateContent(request)
或者,如需为多轮查询附加 FunctionDeclaration 列表,请执行以下操作:
import com.google.mlkit.genai.prompt.SystemInstruction
import com.google.mlkit.genai.prompt.TextPart
import com.google.mlkit.genai.prompt.generateContentRequest
val availableTools = listOf(getWeatherTool)
// Use the generateContentRequest DSL
val request = generateContentRequest(
TextPart("What is the weather in San Francisco, CA in celsius?")
) {
setTools(availableTools)
}
val response = generativeModel.generateContent(request)
处理工具调用
当 Gemini Nano 决定调用工具时,模型的回答候选对象会在 candidate.functionCalls 中包含一个或多个 FunctionCall 对象。如需处理工具调用,您的应用必须先检查响应候选内容,以验证是否预测了任何工具调用:
import com.google.mlkit.genai.common.FunctionArgValue
import com.google.mlkit.genai.prompt.Content
import com.google.mlkit.genai.prompt.FunctionCallPart
import com.google.mlkit.genai.prompt.FunctionResponsePart
import com.google.mlkit.genai.prompt.GenerateContentRequest
import com.google.mlkit.genai.prompt.TextPart
import com.google.mlkit.genai.prompt.content
val candidate = response.candidates.firstOrNull()
val functionCalls = candidate?.functionCalls ?: emptyList()
if (functionCalls.isNotEmpty()) {
// Process tool calls using either the single-turn or multi-turn flow
// described in the following sections
}
单轮函数调用
对于应用直接执行请求的操作导向型任务(例如“打开相机应用”或“打开客厅灯”),请使用单轮函数调用。应用在本地执行函数后,流程即告完成,无需后续模型响应。
for (functionCall in functionCalls) {
val name = functionCall.name
val args = functionCall.arguments // Map<String, FunctionArgValue>
when (name) {
"open_app" -> {
val appName = (args["appName"] as? FunctionArgValue.StringValue)?.value
launchApp(appName)
}
"turn_on_light" -> {
val room = (args["room"] as? FunctionArgValue.StringValue)?.value
val brightness = (args["brightness"] as? FunctionArgValue.IntValue)?.value ?: 100
setLightState(room, brightness)
}
else -> Log.w(TAG, "Unhandled tool call: $name")
}
}
多轮函数调用
当用户希望根据工具检索到的数据获得自然语言回答时(例如,“旧金山的天气如何?”),请使用多轮函数调用。
在多轮对话流程中,您的应用会执行以下操作:
- 在本地执行请求的函数。
- 将结果打包到
FunctionResponsePart对象中。 - 将模型的调用(
MODEL角色)和您的执行结果(USER角色)附加到对话历史记录中。 - 向 Gemini Nano 发送后续请求,以合成最终的自然语言回答。
// 1. Execute each predicted tool call and collect results
val responseParts = mutableListOf<FunctionResponsePart>()
for (functionCall in functionCalls) {
val responsePart: FunctionResponsePart = when {
functionCall.name == "get_current_weather" -> {
val location = (functionCall.arguments["location"] as? FunctionArgValue.StringValue)?.value ?: ""
val unit = (functionCall.arguments["unit"] as? FunctionArgValue.StringValue)?.value ?: "celsius"
val weatherData = fetchWeather(location, unit) // Local network/API call
// Package the tool execution result as a key-value map
FunctionResponsePart(
id = functionCall.id,
name = functionCall.name,
response = mapOf("result" to weatherData)
)
}
else -> throw IllegalArgumentException("Unknown tool: ${functionCall.name}")
}
responseParts.add(responsePart)
}
// 2. Append turns to conversation history to construct the multi-turn context
val history = request.contents.toMutableList().apply {
// Turn 1: Model's request containing the predicted FunctionCallPart object
add(
content(Content.Role.MODEL) {
for (call in functionCalls) {
addPart(FunctionCallPart(call))
}
}
)
// Turn 2: User's response containing the executed FunctionResponsePart object
add(
content(Content.Role.USER) {
for (responsePart in responseParts) {
addPart(responsePart)
}
}
)
}
// 3. Send the updated history back to Gemini Nano for final text synthesis
val followUpRequest = GenerateContentRequest.Builder(history)
.setTools(availableTools) // Include tools in case the model requires subsequent tool calls
.build()
val finalResponse = generativeModel.generateContent(followUpRequest)
val answer = finalResponse.candidates.firstOrNull()?.text
Log.d(TAG, "Final Model Response: $answer")
示例代码
如需查看 Android 应用中函数调用的完整工作示例,请参阅此机器学习套件示例应用。
已知问题
- 直接模型访问 (
genai-prompt) 中的 AndroidX AppFunctions (@AppFunction):尚不支持直接通过 Prompt API (com.google.mlkit:genai-prompt:1.0.0-beta5) 发现和执行编译时@AppFunction工具;genai-prompt库中的工具必须使用FunctionDeclaration类以编程方式定义。如需立即使用@AppFunction工具,请使用Agentic Workflows (com.google.mlkit:genai-agent)。 - 使用流式请求 (
generateContentStream) 时,工具调用不会逐个 token 进行流式传输。相反,一旦模型完成生成工具调用,就会发出完整的FunctionCall对象(通过StreamingCallback.onNewFunctionCall或在最终流式传输的GenerateContentResponse.candidates[0].functionCalls中)。