使用函式呼叫

透過 ML Kit 的直接模型存取功能,您可以使用函式呼叫,讓 Gemini Nano 模型輸出結構化函式執行要求 (工具呼叫),而非純文字回覆。函式呼叫可讓您將裝置端生成式 AI 模型,連結至外部工具、API 和本機應用程式功能。

主要功能

呼叫函式提供下列主要功能:

  • 單輪函式呼叫:Gemini Nano 預測一或多個工具呼叫 (FunctionCall),應用程式在本機執行函式,流程完成,不需要後續模型回覆。
  • 多輪函式呼叫:Gemini Nano 會預測一或多個工具呼叫 (FunctionCall),應用程式會在本機執行函式,並將結果傳回 (FunctionResponsePart),以擷取更多工具呼叫或最終合成文字回應。

實作函式呼叫時,您可以善用下列功能:

  • 程式輔助工具定義:使用 ML Kit 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.

必要條件

如要使用呼叫函式功能,裝置和帳戶必須符合下列條件:

如要確認是否符合這些需求,請檢查 AICore 應用程式中是否有 Gemini Nano 4 Fast 模型:開啟 AICore 應用程式,按一下「Select a model」下拉式選單,然後確認清單中是否有「Gemini Nano 4 Fast」。如果沒有,表示裝置支援或帳戶註冊有問題,無法使用呼叫函式。

此外,專案必須符合下列規定:

  • Kotlin 2.3.0 以上版本
  • SDK (minSdk) 最低版本為 26

開始使用

以下是開始使用函式呼叫功能的步驟。

  1. 在專案層級的 settings.gradle.kts (或 settings.gradle) 檔案中,將 mavenCentral() 新增至 repositories {} 區塊。

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
        }
    }
    
  2. 在模組層級 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'
    }
    
  3. 在模組層級 build.gradle (或 build.gradle.kts 檔案) 中,將 minSdk 版本設為 26 以上。

    Kotlin

    android {
        defaultConfig {
            // ...
            minSdk = 26
            // ...
        }
    }
    

    Groovy

    android {
        defaultConfig {
            // ...
            minSdk 26
            // ...
        }
    }
    

如何使用呼叫函式 API

如要實作函式呼叫,請按照下列步驟操作:

  1. 定義工具。
  2. 選取模型。
  3. 在要求中附加工具。
  4. 處理工具呼叫 (單輪或多輪)。

接下來,我們將透過範例示範這些步驟。

定義工具

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

多輪呼叫函式

如果使用者預期根據工具擷取的資料,取得自然語言答案 (例如「舊金山天氣如何?」),請使用多輪呼叫函式。

在多輪對話流程中,應用程式會執行下列操作:

  1. 在本機執行要求的函式。
  2. 將結果封裝在 FunctionResponsePart 物件中。
  3. 將模型的呼叫 (MODEL 角色) 和執行結果 (USER 角色) 附加至對話記錄。
  4. 將後續要求傳回 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 應用程式中函式呼叫的完整範例,請參閱這個 ML Kit 範例應用程式。

已知問題

  • 直接存取模型 (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) 時,工具呼叫不會逐一串流詞元。模型產生工具呼叫後,會透過 StreamingCallback.onNewFunctionCall 或最終串流的 GenerateContentResponse.candidates[0].functionCalls 發出完整的 FunctionCall 物件。