Dùng lệnh gọi hàm

Với quyền truy cập trực tiếp vào mô hình của Bộ công cụ học máy, bạn có thể sử dụng tính năng gọi hàm để cho phép các mô hình Gemini Nano đưa ra yêu cầu thực thi hàm có cấu trúc (lệnh gọi công cụ) thay vì phản hồi bằng văn bản thuần túy. Tính năng gọi hàm cho phép bạn kết nối các mô hình AI tạo sinh trên thiết bị với các công cụ bên ngoài, API và tính năng của ứng dụng cục bộ.

Các chức năng chính

Tính năng gọi hàm cung cấp các chức năng chính sau:

  • Gọi hàm một lượt: Gemini Nano dự đoán một hoặc nhiều lệnh gọi công cụ (FunctionCall), ứng dụng của bạn thực thi các hàm trên thiết bị và quy trình hoàn tất mà không cần phản hồi tiếp theo của mô hình.
  • Gọi hàm nhiều lượt: Gemini Nano dự đoán một hoặc nhiều lệnh gọi công cụ (FunctionCall), ứng dụng của bạn thực thi các hàm trên thiết bị và truyền kết quả trở lại (FunctionResponsePart) để truy xuất thêm lệnh gọi công cụ hoặc câu trả lời dạng văn bản tổng hợp cuối cùng.

Khi triển khai tính năng gọi hàm, bạn có thể tận dụng những điều sau:

  • Định nghĩa công cụ có lập trình: Tạo các định nghĩa công cụ FunctionDeclaration và FunctionSchema động trong thời gian chạy bằng API Lược đồ GenAI của Bộ công cụ học máy (com.google.mlkit:genai-schema).
  • Phân tích cú pháp đối số có cấu trúc: Nhận trực tiếp các giá trị đối số được nhập chính xác từ ứng viên phản hồi của mô hình để thực thi logic ứng dụng cục bộ.

Kết quả mẫu

Tính năng gọi hàm hỗ trợ cả quy trình một lượt và nhiều lượt. Trong cả hai trường hợp, mô hình đều dự đoán một hoặc nhiều lệnh gọi công cụ bao gồm tên hàm và đối số. Đối với các luồng nhiều lượt, sau khi nhận được kết quả thực thi của ứng dụng, ứng dụng có thể gửi một yêu cầu khác đến mô hình kèm theo toàn bộ nhật ký trò chuyện để nhận thêm lệnh gọi công cụ hoặc phản hồi văn bản cuối cùng cho người dùng.

Quy trình thực thi Câu lệnh của người dùng Đầu ra của mô hình
Một lượt "Bật đèn phòng khách ở độ sáng 80%." Gọi công cụ:
turn_on_light(room="living room", brightness=80)
Một lượt "Mở ứng dụng Máy ảnh". Gọi công cụ:
open_app(appName="Camera")
Nhiều lượt "Thời tiết ở San Francisco thế nào, tính theo độ C?" Lệnh gọi công cụ trung gian:
get_current_weather(location="San Francisco, CA", unit="celsius")

Kết quả cuối cùng của mô hình được hiển thị cho người dùng:
In SF it's currently 25 degrees Celsius.

Điều kiện tiên quyết

Để sử dụng tính năng gọi hàm, bạn phải đáp ứng các yêu cầu sau đây về thiết bị và tài khoản:

Để kiểm tra xem bạn đã đáp ứng các yêu cầu này hay chưa, hãy kiểm tra xem mô hình Gemini Nano 4 Fast có trong ứng dụng AICore hay không: mở ứng dụng AICore, nhấp vào trình đơn thả xuống Select a model (Chọn một mô hình) và kiểm tra xem Gemini Nano 4 Fast có trong danh sách hay không. Nếu mô hình không có ở đó, thì tức là có vấn đề về việc hỗ trợ thiết bị hoặc đăng ký tài khoản và tính năng gọi hàm sẽ không hoạt động.

Ngoài ra, dự án của bạn phải đáp ứng các yêu cầu sau:

  • Kotlin phiên bản 2.3.0 trở lên
  • SDK tối thiểu (minSdk) phiên bản 26 trở lên

Bắt đầu

Dưới đây là các bước để bắt đầu sử dụng tính năng gọi hàm.

  1. Trong tệp settings.gradle.kts (hoặc settings.gradle) cấp dự án, hãy thêm mavenCentral() vào khối repositories {}.

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
        }
    }
    
  2. Trong tệp build.gradle.kts (hoặc build.gradle) ở cấp mô-đun, hãy thêm các phần phụ thuộc giản đồ và Prompt API của Bộ công cụ học máy:

    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. Trong tệp build.gradle (hoặc build.gradle.kts) ở cấp mô-đun, hãy đặt phiên bản minSdk thành 26 trở lên.

    Kotlin

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

    Groovy

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

Cách sử dụng API Gọi hàm

Để triển khai tính năng gọi hàm, hãy làm theo các bước sau:

  1. Xác định công cụ.
  2. Chọn mô hình.
  3. Đính kèm công cụ vào yêu cầu của bạn.
  4. Xử lý lệnh gọi công cụ (một lượt hoặc nhiều lượt).

Các phần tiếp theo sẽ trình bày một ví dụ minh hoạ các bước này.

Xác định công cụ

Tạo giản đồ công cụ theo phương thức lập trình bằng cách sử dụng FunctionDeclaration, FunctionSchema và FunctionType từ gói com.google.mlkit.genai.schema.tools. (Để khai báo công cụ một cách khai báo tại thời gian biên dịch bằng chú giải @AppFunction của Android có thực thi tự động, hãy xem phần Xác định công cụ.)

Ví dụ: bạn có thể xác định một công cụ hướng đến hành động (chẳng hạn như bật đèn thông minh để thực hiện một lượt):

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

Hoặc xác định một công cụ truy xuất dữ liệu (chẳng hạn như tìm nạp thông tin thời tiết hiện tại để tổng hợp nhiều lượt):

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

Chọn mô hình

Tính năng gọi hàm yêu cầu Gemini Nano 4. Để truy cập Gemini Nano 4, hãy sử dụng API lựa chọn mô hình để định cấu hình thực thể GenerativeModel của bạn nhằm nhắm đến ModelReleaseStage.PREVIEW VÀ 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)

Đính kèm công cụ vào yêu cầu của bạn

Khi tạo đối tượng GenerateContentRequest, hãy truyền danh sách FunctionDeclaration của bạn đến setTools() trong trình tạo yêu cầu.

Ví dụ: để đính kèm một công cụ cho yêu cầu hành động một lượt bằng chỉ dẫn hệ thống:

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)

Hoặc để đính kèm danh sách FunctionDeclaration cho một truy vấn nhiều lượt:

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)

Xử lý lệnh gọi công cụ

Khi Gemini Nano quyết định gọi một công cụ, ứng viên phản hồi của mô hình sẽ chứa một hoặc nhiều đối tượng FunctionCall trong candidate.functionCalls. Để xử lý lệnh gọi công cụ, trước tiên, ứng dụng của bạn phải kiểm tra ứng viên phản hồi để xác minh xem có lệnh gọi công cụ nào được dự đoán hay không:

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
}

Gọi hàm một lượt

Sử dụng lệnh gọi hàm một lượt cho các nhiệm vụ thiên về hành động, trong đó ứng dụng trực tiếp thực hiện yêu cầu (ví dụ: "Mở ứng dụng camera" hoặc "Bật đèn phòng khách"). Sau khi ứng dụng thực thi hàm trên thiết bị, quy trình sẽ hoàn tất và không cần phản hồi tiếp theo của mô hình.

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

Gọi hàm nhiều lượt

Sử dụng lệnh gọi hàm nhiều lượt khi người dùng muốn nhận được câu trả lời bằng ngôn ngữ tự nhiên dựa trên dữ liệu mà công cụ truy xuất (ví dụ: "Thời tiết ở San Francisco như thế nào?").

Trong quy trình nhiều lượt, ứng dụng của bạn sẽ làm những việc sau:

  1. Thực thi hàm được yêu cầu trên thiết bị.
  2. Đóng gói kết quả trong đối tượng FunctionResponsePart.
  3. Thêm cả lệnh gọi của mô hình (vai trò MODEL) và kết quả thực thi của bạn (vai trò USER) vào nhật ký trò chuyện.
  4. Gửi yêu cầu tiếp theo đến Gemini Nano để tổng hợp câu trả lời cuối cùng bằng ngôn ngữ tự nhiên.
// 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")

Mã mẫu

Để xem ví dụ hoàn chỉnh về cách hoạt động của tính năng gọi hàm trong một ứng dụng Android, hãy xem ứng dụng mẫu Bộ công cụ học máy này.

Vấn đề đã biết

  • AndroidX AppFunctions (@AppFunction) trong quyền truy cập trực tiếp vào mô hình (genai-prompt): Bạn chưa thể khám phá và thực thi các công cụ @AppFunction trong thời gian biên dịch trực tiếp thông qua Prompt API (com.google.mlkit:genai-prompt:1.0.0-beta5); các công cụ trong thư viện genai-prompt phải được xác định theo phương thức lập trình bằng lớp FunctionDeclaration. Để sử dụng các công cụ @AppFunction ngay hôm nay, hãy dùng quy trình làm việc dựa trên tác nhân (com.google.mlkit:genai-agent).
  • Khi sử dụng yêu cầu truyền trực tuyến (generateContentStream), các lệnh gọi công cụ sẽ không được truyền trực tuyến theo từng mã thông báo. Thay vào đó, các đối tượng FunctionCall hoàn chỉnh sẽ được phát ra (thông qua StreamingCallback.onNewFunctionCall hoặc trong GenerateContentResponse.candidates[0].functionCalls được truyền trực tuyến cuối cùng) sau khi mô hình hoàn tất việc tạo lệnh gọi công cụ.