ML Kit の直接モデルアクセスでは、関数呼び出しを使用して、Gemini Nano モデルが書式なしテキストのレスポンスではなく、構造化された関数実行リクエスト(ツール呼び出し)を出力できるようにします。関数呼び出しを使用すると、オンデバイスの生成 AI モデルを外部ツール、API、ローカルアプリの機能に接続できます。
主な機能
関数呼び出しには、次の主な機能があります。
- シングルターン関数呼び出し: Gemini Nano が 1 つ以上のツール呼び出し(
FunctionCall)を予測し、アプリが関数をローカルで実行します。フローは、フォローアップ モデル レスポンスを必要とせずに完了します。 - マルチターン関数呼び出し: Gemini Nano が 1 つ以上のツール呼び出し(
FunctionCall)を予測し、アプリが関数をローカルで実行して、結果を返します(FunctionResponsePart)。これにより、さらにツール呼び出しを取得するか、最終的な合成テキスト レスポンスを取得します。
関数呼び出しを実装する際は、次の機能を利用できます。
- プログラムによるツール定義: ML Kit GenAI Schema API(
com.google.mlkit:genai-schema)を使用して、実行時に動的なFunctionDeclarationツール定義とFunctionSchemaツール定義を構築します。 - 構造化された引数の解析: モデル レスポンス候補から直接、厳密に型指定された引数値を受け取り、ローカルアプリ ロジックを実行します。
検索結果の例
関数呼び出しは、シングルターン フローとマルチターン フローの両方をサポートしています。どちらの場合も、モデルは関数名と引数で構成される 1 つ以上のツール呼び出しを予測します。マルチターンのフローでは、アプリの実行結果を受け取った後、アプリは会話履歴全体を含む別のリクエストをモデルに送信して、ユーザー向けのツール呼び出しや最終的なテキスト レスポンスを取得できます。
| 実行フロー | ユーザーによるプロンプト | モデル出力 |
|---|---|---|
| シングルターン | 「リビングの照明を明るさ 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 を使用して、ModelReleaseStage.PREVIEW と ModelPreference.FAST をターゲットとするように GenerativeModel インスタンスを構成します。
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 に 1 つ以上の 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 アプリでの関数呼び出しの完全な動作例については、こちらの 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)を使用する場合、ツール呼び出しはトークンごとにストリーミングされません。代わりに、モデルがツール呼び出しの生成を完了すると、完全なFunctionCallオブジェクトが(StreamingCallback.onNewFunctionCall経由または最後のストリーミングGenerateContentResponse.candidates[0].functionCallsで)出力されます。