এই নির্দেশিকায় ব্যাখ্যা করা হয়েছে কীভাবে আপনার অ্যান্ড্রয়েড অ্যাপে AppFunctions API একীভূত করবেন, একটি ফাংশনের লজিক প্রয়োগ করবেন এবং একীকরণটি সঠিকভাবে কাজ করছে কিনা তা যাচাই করবেন।
সংস্করণ সামঞ্জস্যতা
এই বাস্তবায়নের জন্য আপনার প্রজেক্টের compileSdk অবশ্যই এপিআই লেভেল ৩৬ বা তার বেশিতে সেট করতে হবে।
আপনার অ্যাপে AppFunctions সমর্থিত কিনা তা যাচাই করার প্রয়োজন নেই; এটি AppFunctions Jetpack লাইব্রেরির মধ্যে স্বয়ংক্রিয়ভাবে পরিচালিত হয়। ফিচারটি সমর্থিত হলে AppFunctionManager একটি ইনস্ট্যান্স রিটার্ন করে, এবং সমর্থিত না হলে null রিটার্ন করে।
নির্ভরশীলতা
আপনার মডিউলের build.gradle.kts (বা build.gradle) ফাইলে প্রয়োজনীয় লাইব্রেরি নির্ভরতাগুলো যোগ করুন, এবং দেখানো অনুযায়ী আপনার শীর্ষ-স্তরের অ্যাপ মডিউলে KSP প্লাগইনটি কনফিগার করুন:
# Add this to your app module at the top level. For multi module applications,
# you only need to specify this once.
ksp {
arg("appfunctions:aggregateAppFunctions", "true")
}
dependencies {
implementation("androidx.appfunctions:appfunctions:1.0.0-alpha09")
implementation("androidx.appfunctions:appfunctions-service:1.0.0-alpha09")
// If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
// See Add the KSP plugin to your project
ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha09")
}
AppFunctions লজিক বাস্তবায়ন করুন
আপনার অ্যান্ড্রয়েড অ্যাপের জন্য একটি AppFunction প্রয়োগ করতে, এমন একটি ক্লাস তৈরি করুন যা নির্দিষ্ট AppFunction-এর লজিক বাস্তবায়ন করে। এর জন্য প্যারামিটার এবং রেসপন্সের জন্য সিরিয়ালাইজেবল ডেটা ক্লাস তৈরি করতে হয় এবং তারপর ফাংশন মেথডের মধ্যে মূল লজিকটি প্রদান করতে হয়।
নিম্নলিখিত কোডটিতে TODO অ্যাপে একটি টাস্ক তৈরির উদাহরণমূলক বাস্তবায়ন দেখানো হয়েছে, যেখানে একটি রিপোজিটরি ব্যবহার করে কাস্টম প্যারামিটার ও রেসপন্স টাইপ নির্ধারণ এবং মেইন ফাংশনের লজিক অন্তর্ভুক্ত রয়েছে।
package com.example.android.appfunctions
import androidx.appfunctions.AppFunctionSerializable
import androidx.appfunctions.AppFunctionContext
import androidx.appfunctions.AppFunctionElementNotFoundException
import androidx.appfunctions.AppFunctionInvalidArgumentException
import androidx.appfunctions.service.AppFunction
import javax.inject.Inject
...
// Developers can provide additional parameters in the constructor if needed.
// This requires a custom factory setup in the next step.
class TaskFunctions @Inject constructor(
private val taskRepository: TaskRepository
) {
/** The parameter to create the task. */
@AppFunctionSerializable(isDescribedByKDoc = true)
data class CreateTaskParams(
/** The title of the task. */
val title: String,
/** The content of the task. */
val content: String
)
/** The user-created task. */
@AppFunctionSerializable(isDescribedByKDoc = true)
data class Task(
/** The ID of the task. */
val id: String,
/** The title of the task. */
val title: String,
/** The content of the task. */
val content: String
)
/**
* Creates a task based on [createTaskParams].
*
* @param createTaskParams The parameter to describe how to create the task.
*/
@AppFunction(isDescribedByKDoc = true)
suspend fun createTask(
appFunctionContext: AppFunctionContext,
createTaskParams: CreateTaskParams,
): Task = withContext(Dispatchers.IO) {
// Developers can use predefined exceptions to let the agent know
// why it failed.
if (createTaskParams.title == null && createTaskParams.content == null) {
throw AppFunctionInvalidArgumentException("Title or content should be non-null")
}
val id = taskRepository.createTask(
createTaskParams.title,
createTaskParams.content)
return taskRepository
.getTask(id)
?.toTask()
?: throw AppFunctionElementNotFoundException("Task not found for ID = $id")
}
// Maps internal TaskEntity
private fun TaskEntity.toTask() = Task(id = id, title = title, content = description)
}
কোড সম্পর্কে মূল বিষয়গুলো
- ডিফল্টরূপে, একটি AppFunction ইমপ্লিমেন্টেশন অ্যান্ড্রয়েড UI থ্রেডে চলে। তাই, একটি দীর্ঘ সময় ধরে চলা অপারেশনের নিম্নলিখিত কাজগুলো করা উচিত:
- AppFunction-টিকে একটি সাসপেন্ড ফাংশন হিসেবে ঘোষণা করুন।
- যখন অপারেশনটি থ্রেডকে ব্লক করতে পারে, তখন একটি উপযুক্ত কো-রুটিন ডিসপ্যাচারে স্যুইচ করুন।
- যখন
isDescribedByKDocমানtrueসেট করা থাকে, তখন ফাংশনের বিবরণ বা সিরিয়ালাইজেবল বিবরণটিAppFunctionMetadataএর অংশ হিসেবে এনকোড করা হয়, যাতে এজেন্ট বুঝতে পারে অ্যাপের AppFunction-টি কীভাবে ব্যবহার করতে হবে।
ঐচ্ছিক: একটি কাস্টম AppFunction ফ্যাক্টরি প্রদান করতে Hilt ব্যবহার করুন।
যদি আপনার AppFunction ইমপ্লিমেন্টেশন ক্লাসের কনস্ট্রাক্টরে ডিপেন্ডেন্সির প্রয়োজন হয় (যেমন আগের উদাহরণে TaskRepository ক্ষেত্রে), তাহলে আপনাকে একটি কাস্টম ফ্যাক্টরি সরবরাহ করতে হবে যাতে সিস্টেম জানতে পারে কীভাবে এটিকে ইনস্ট্যানশিয়েট করতে হয়। এটি একটি ঐচ্ছিক ধাপ এবং শুধুমাত্র তখনই প্রয়োজনীয় যখন আপনার ফাংশন ক্লাসে কনস্ট্রাক্টর প্যারামিটার থাকে। এই উদাহরণটি দেখায় কীভাবে একটি কাস্টম AppFunctionFactory তৈরি করতে হয় এবং ডিপেন্ডেন্সি ইনজেকশনের জন্য Hilt ব্যবহার করে আপনার Application ক্লাসের মধ্যে এটি কনফিগার করতে হয়।
import android.app.Application
import androidx.appfunctions.service.AppFunctionConfiguration
import com.example.android.appfunctions.TaskFunctions
import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject
@HiltAndroidApp
class TodoApplication : Application(), AppFunctionConfiguration.Provider {
@Inject lateinit var taskFunctions: TaskFunctions
override fun onCreate() {
super.onCreate()
}
// This shows how AppFunctions works with Hilt.
override val appFunctionConfiguration: AppFunctionConfiguration
get() =
AppFunctionConfiguration.Builder()
.addEnclosingClassFactory(TaskFunctions::class.java) { taskFunctions }
.build()
}
ঐচ্ছিক: রানটাইমে অ্যাপফাংশনের প্রাপ্যতা টগল করুন
আপনার AppFunction-গুলোকে গেটিং করার সময় ফাংশনগুলোকে সুস্পষ্টভাবে সক্রিয় বা নিষ্ক্রিয় করতে AppFunctionManager API ব্যবহার করুন। যখন আপনার অ্যাপের নির্দিষ্ট কিছু ফিচার সকল ব্যবহারকারীর জন্য উপলব্ধ থাকে না, তখন গেটিং কার্যকর হতে পারে। AppFunction-গুলোকে ডায়নামিকভাবে সক্রিয় বা নিষ্ক্রিয় করার মাধ্যমে, ইন্টেলিজেন্স সিস্টেমটি যেকোনো নির্দিষ্ট সময়ে আপনার ব্যবহারকারীর জন্য ঠিক কোন ফিচারগুলো উপলব্ধ আছে তা জানতে পারে।
যেসব অ্যাপফাংশনের জন্য একটি নির্দিষ্ট অ্যাকাউন্ট স্টেট প্রয়োজন, সেগুলোকে নিরাপদে গেট করার জন্য দুটি ধাপের একটি প্রক্রিয়া অনুসরণ করুন:
ধাপ ১. ফাংশনটি ডিফল্টরূপে নিষ্ক্রিয় করুন।
আপনার ফিচার ফ্ল্যাগ যাচাই হওয়ার আগে ফাংশনটি যাতে অ্যাক্সেসযোগ্য না হয়, সেজন্য আপনার @AppFunction অ্যানোটেশনের isEnabled প্যারামিটারটি false এ সেট করুন।
@AppFunction(isEnabled = false, isDescribedByKDoc = true)
suspend fun createTask(...) { ... }
ধাপ ২. রানটাইমে ফাংশনটি ডায়নামিকভাবে সক্রিয় করুন।
প্রতিটি AppFunction ক্লাসের জন্য, কম্পাইলার একটি সংশ্লিষ্ট ক্লাস তৈরি করে যাতে ফাংশন আইডি কনস্ট্যান্ট ( Ids সাফিক্স ব্যবহার করে) থাকে। রানটাইমে কোনো ফাংশনের এনাবলড অবস্থা পরিবর্তন করার জন্য আপনি AppFunctionManagerCompat এর setAppFunctionEnabled মেথডের পাশাপাশি এই তৈরি হওয়া আইডি কনস্ট্যান্টগুলো ব্যবহার করতে পারেন।
import androidx.appfunctions.AppFunctionManager
// Assuming there is a hook API to observe user state or feature flags
suspend fun onFeatureEnabled() {
try {
AppFunctionManager.getInstance(context)
.setAppFunctionEnabled(
// Function ID is generated for developer to get
TaskFunctionsIds.CREATE_TASK_ID,
AppFunctionManagerCompat.APP_FUNCTION_STATE_ENABLED,
)
} catch (e: Exception) {
// Handle exception: AppFunctions indexation may not be fully completed
// upon initial app startup.
}
}
suspend fun onFeatureDisabled() {
AppFunctionManagerCompat.getInstance(context)
.setAppFunctionEnabled(
TaskFunctionsIds.CREATE_TASK_ID,
AppFunctionManagerCompat.APP_FUNCTION_STATE_DISABLED,
)
}
উপলব্ধ করার জন্য কার্যকারিতার প্রকারভেদ বিবেচনা
নিরাপত্তাই সর্বাগ্রে। আপনার অ্যাপের কোন সক্ষমতাগুলোকে AppFunction হিসেবে উপলব্ধ করবেন তা নির্বাচন করার সময়, এটা মনে রাখা গুরুত্বপূর্ণ যে সিস্টেম এজেন্টরা উন্নত LLM সক্ষমতা কাজে লাগানোর জন্য সার্ভারে ব্যবহারকারীর কোয়েরিগুলো প্রসেস করতে পারে।
সংবেদনশীল তথ্য প্রকাশ এড়ানোর পাশাপাশি একটি চমৎকার ব্যবহারকারী অভিজ্ঞতা প্রদানের জন্য, আমরা নিম্নলিখিত নির্দেশিকাগুলো অনুসরণ করার পরামর্শ দিই:
- স্বাভাবিক ভাষা ব্যবহার করে সুবিধা নেওয়া যায় এমন কার্যকারিতা : এমন সব কাজ উপলব্ধ করুন যা ব্যবহারকারী ম্যানুয়াল UI নেভিগেশনের চেয়ে কথোপকথনের মাধ্যমে সহজে প্রকাশ করতে পারে।
- অ্যাক্সেস সীমিত করুন : এমন অ্যাপফাংশন তৈরি করুন যা এজেন্টকে শুধুমাত্র ব্যবহারকারীর নির্দিষ্ট অনুরোধ পূরণের জন্য প্রয়োজনীয় ডেটা এবং অ্যাকশনগুলিতে অ্যাক্সেস দেবে।
- অসংবেদনশীল তথ্য : শুধুমাত্র সেই ডেটা শেয়ার করুন যা অত্যন্ত ব্যক্তিগত বা গোপনীয় নয়, অথবা এমন ডেটা যা ব্যবহারকারী নির্দিষ্ট কাজের প্রেক্ষাপটে শেয়ার করার জন্য স্পষ্টভাবে সম্মতি দেন।
- যেকোনো ধ্বংসাত্মক কাজের জন্য সুস্পষ্ট নিশ্চিতকরণ : যেসব ফাংশন ধ্বংসাত্মক কাজ করে (যেমন ডেটা মুছে ফেলা), সেগুলোর ব্যাপারে অত্যন্ত সতর্ক থাকুন। যদিও এজেন্ট সেগুলোকে কল করতে পারে, আপনার অ্যাপে নিজস্ব একটি নিশ্চিতকরণ ধাপ থাকা উচিত এবং এর উদ্দেশ্য সম্পর্কে স্পষ্ট ও দ্ব্যর্থহীন ভাষা ব্যবহার করা উচিত। ব্যবহারকারীকে কী করতে বলা হচ্ছে সে সম্পর্কে তিনি পুরোপুরি সচেতন কি না, তা নিশ্চিত করার জন্য একাধিক নিশ্চিতকরণ ধাপ যোগ করাও সহায়ক।
অ্যাপফাংশন ইন্টিগ্রেশন যাচাই করুন
আপনি AppFunctions সঠিকভাবে সংহত করেছেন কিনা তা যাচাই করতে, আপনি adb shell cmd app_function ব্যবহার করতে পারেন।
আপনার অ্যাপের দেওয়া AppFunction-গুলোর বিস্তারিত দেখতে adb shell cmd app_function list-app-functions | grep --after-context 10 $myPackageName ব্যবহার করুন।
অ্যান্ড্রয়েড স্টুডিও-এর জেমিনিতে, অথবা আপনার পছন্দের অন্য কোনো এজেন্টে, নিম্নলিখিতের মতো একটি প্রম্পট প্রদান করুন।
Execute `adb shell cmd app_function` to learn how the tool works, then act as a
chat agent aiming to invoke AppFunctions to fulfil user prompts for this app.
Rely on the AppFunction description as instructions.