استفاده از فراخوانی تابع

با دسترسی مستقیم به مدل ML Kit، می‌توانید از فراخوانی تابع استفاده کنید تا مدل‌های Gemini Nano بتوانند درخواست‌های اجرای تابع ساختاریافته (فراخوانی ابزار) را به‌جای پاسخ‌های نوشتار ساده برونداد کنند. فراخوانی تابع به شما امکان می‌دهد مدل‌های هوش مصنوعی زایای درون‌دستگاهی را به ابزارهای خارجی، میاناهای برنامه‌سازی کاربردی، و ویژگی‌های برنامه محلی متصل کنید.

قابلیت‌های کلیدی

«فراخوانی تابع» قابلیت‌های کلیدی زیر را ارائه می‌دهد:

  • فراخوانی تابع تک‌نوبتی: Gemini Nano یک یا چند فراخوانی ابزار را پیش‌بینی می‌کند (FunctionCall)، برنامه شما توابع را به‌صورت محلی اجرا می‌کند، و جریان بدون نیاز به پاسخ مدل پیگیری تکمیل می‌شود.
  • فراخوانی تابع چنددوره‌ای: Gemini Nano یک یا چند فراخوانی ابزار را پیش‌بینی می‌کند (FunctionCall)، برنامه شما توابع را به‌صورت محلی اجرا می‌کند و نتایج را برمی‌گرداند (FunctionResponsePart) تا فراخوانی‌های ابزار بیشتری یا پاسخ نوشتاری ترکیبی نهایی را بازیابی کند.

هنگام پیاده‌سازی فراخوانی تابع، می‌توانید از موارد زیر بهره ببرید:

  • تعاریف ابزار برنامه‌ای: تعاریف ابزار FunctionDeclaration و FunctionSchema پویا را در زمان اجرا بااستفاده از ML Kit GenAI Schema API (com.google.mlkit:genai-schema) بسازید.
  • تجزیه استدلال ساختاریافته: مقادیر استدلال با نوع قوی را مستقیماً از نامزد پاسخ مدل دریافت کنید تا منطق برنامه محلی‌تان را اجرا کنید.

نتایج نمونه

فراخوانی تابع از جریان‌های تک‌نوبتی و چندنوبتی پشتیبانی می‌کند. در هر دو مورد، مدل یک یا چند فراخوانی ابزار را که شامل نام تابع و آرگومان‌ها است پیش‌بینی می‌کند. برای جریان‌های چندنوبتی، پس‌از دریافت نتایج اجرای برنامه، برنامه می‌تواند درخواست دیگری را با سابقه کامل مکالمه به مدل ارسال کند تا فراخوانی‌های ابزار بیشتر یا پاسخ نوشتاری نهایی را برای کاربر دریافت کند.

جریان اجرا پیام‌واره کاربر خروجی مدل
تک‌نوبتی «چراغ‌های اتاق نشیمن را با روشنایی ۸۰٪ روشن کن.» فراخوانی ابزار:
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.

پیش‌نیازها

برای استفاده از فراخوانی تابع، باید شرایط لازم دستگاه و حساب زیر را داشته باشید:

برای بررسی اینکه این الزامات را برآورده کرده‌اید، بررسی کنید که مدل Gemini Nano 4 Fast در برنامه AICore دردسترس باشد: برنامه AICore را باز کنید، روی منو کرکره‌ای انتخاب مدل کلیک کنید، و بررسی کنید که Gemini Nano 4 Fast در فهرست وجود داشته باشد. اگر مدل در آنجا نیست، مشکلی در پشتیبانی دستگاه یا ثبت‌نام حساب وجود دارد و فراخوانی تابع کار نخواهد کرد.

علاوه‌براین، پروژه شما باید شرایط زیر را داشته باشد:

  • Kotlin نسخه ۲.۳.۰ یا بالاتر
  • حداقل نسخه کیت توسعه نرم‌افزار (minSdk) ۲۶ یا بالاتر

شروع کنید

مراحل شروع استفاده از فراخوانی تابع در اینجا آمده است.

  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
            // ...
        }
    }
    

نحوه استفاده از Function Calling API

برای پیاده‌سازی فراخوانی تابع، مراحل زیر را دنبال کنید:

  1. ابزارهایتان را تعریف کنید.
  2. مدل را انتخاب کنید.
  3. ابزارها را به درخواستتان پیوست کنید.
  4. مدیریت فراخوانی‌های ابزار (تک‌نوبتی یا چندنوبتی).

بخش‌های بعدی مثالی را نشان می‌دهند که این مراحل را توضیح می‌دهد.

تعریف کردن ابزارها

طرح‌واره‌های ابزار را به‌صورت برنامه‌نویسی‌شده بااستفاده از FunctionDeclaration، FunctionSchema، و FunctionType از بسته com.google.mlkit.genai.schema.tools بسازید. (برای تعریف ابزارها به‌صورت اعلانی در زمان ترجمه بااستفاده از حاشیه‌نویسی @AppFunction Android با اجرای خودکار، به تعریف ابزارها مراجعه کنید.)

برای مثال، می‌توانید ابزاری کنش‌گرا (مثل روشن کردن چراغ هوشمند برای اجرای تک‌نوبتی) تعریف کنید:

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، از میانای برنامه‌سازی کاربردی انتخاب مدل برای پیکربندی نمونه 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 تصمیم می‌گیرد ابزاری را فراخوانی کند، پاسخ نامزد مدل حاوی یک یا چند شیء FunctionCall در candidate.functionCalls است. برای مدیریت فراخوانی‌های ابزار، برنامه شما باید ابتدا نامزد پاسخ را بررسی کند تا تأیید کند آیا فراخوانی‌های ابزاری پیش‌بینی شده‌اند یا نه:

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 را ببینید.

مشکلات شناخته‌شده

  • AndroidX AppFunctions (@AppFunction) در دسترسی مستقیم به مدل (genai-prompt): کشف و اجرای ابزارهای @AppFunction زمان ترجمه مستقیماً ازطریق Prompt API (com.google.mlkit:genai-prompt:1.0.0-beta5) هنوز دردسترس نیست؛ ابزارهای موجود در کتابخانه genai-prompt باید به‌صورت برنامه‌نویسی‌شده بااستفاده از کلاس FunctionDeclaration تعریف شوند. برای استفاده از ابزارهای @AppFunction درحال‌حاضر، از گردش‌های کاری عامل‌گرا (com.google.mlkit:genai-agent) استفاده کنید.
  • هنگام استفاده از درخواست‌های جاری‌سازی (generateContentStream)، فراخوانی‌های ابزار به‌صورت توکن به توکن جاری‌سازی نمی‌شوند. درعوض، وقتی مدل تولید فراخوانی ابزار را به‌پایان می‌رساند، اشیای کامل FunctionCall (ازطریق StreamingCallback.onNewFunctionCall یا در GenerateContentResponse.candidates[0].functionCalls جاری‌شده نهایی) منتشر می‌شوند.