AI Edge Function Calling SDK (FC SDK) کتابخانه ای است که توسعه دهندگان را قادر می سازد از فراخوانی تابع با LLM های روی دستگاه استفاده کنند. فراخوانی تابع به شما امکان میدهد مدلها را به ابزارهای خارجی و APIها متصل کنید و مدلها را قادر میسازد تا توابع خاصی را با پارامترهای لازم برای اجرای اقدامات در دنیای واقعی فراخوانی کنند.
به جای تولید متن، یک LLM با استفاده از FC SDK میتواند یک فراخوانی ساختاریافته برای عملکردی ایجاد کند که عملکردی را اجرا میکند، مانند جستجوی اطلاعات بهروز، تنظیم آلارمها یا رزرو کردن.
این راهنما شما را از طریق یک شروع سریع اولیه برای افزودن API استنتاج LLM با FC SDK به یک برنامه اندروید راهنمایی می کند. این راهنما بر افزودن قابلیت های فراخوانی تابع به LLM روی دستگاه تمرکز دارد. برای اطلاعات بیشتر در مورد استفاده از LLM Inference API، به راهنمای LLM Inference for Android مراجعه کنید.
شروع سریع
از مراحل زیر برای استفاده از FC SDK در برنامه اندروید خود استفاده کنید. این شروع سریع از LLM Inference API با Hammer 2.1 (1.5B) استفاده می کند. LLM Inference API برای دستگاههای Android سطح بالا، مانند Pixel 8 و Samsung S23 یا جدیدتر، بهینهسازی شده است و از شبیهسازهای دستگاه پشتیبانی نمیکند.
وابستگی ها را اضافه کنید
FC SDK از کتابخانه com.google.ai.edge.localagents:localagents-fc و LLM Inference API از کتابخانه com.google.mediapipe:tasks-genai استفاده می کند. هر دو وابستگی را به فایل build.gradle برنامه اندروید خود اضافه کنید:
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.24'
implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}
برای دستگاههای دارای Android 12 (API 31) یا بالاتر، وابستگی کتابخانه OpenCL بومی را اضافه کنید. برای اطلاعات بیشتر، به مستندات مربوط به برچسب uses-native-library مراجعه کنید.
تگ های uses-native-library زیر را به فایل AndroidManifest.xml اضافه کنید:
<uses-native-library android:name="libOpenCL.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false"/>
دانلود یک مدل
Hammer 1B را با فرمت کوانتیزه 8 بیتی از Hugging Face دانلود کنید. برای اطلاعات بیشتر در مورد مدلهای موجود، به مستندات مدلها مراجعه کنید.
محتوای پوشه hammer2.1_1.5b_q8_ekv4096.task را به دستگاه Android فشار دهید.
$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push hammer2.1_1.5b_q8_ekv4096.task /data/local/tmp/llm/hammer2.1_1.5b_q8_ekv4096.task
تعاریف تابع را اعلام کنید
توابعی را که در دسترس مدل قرار خواهند گرفت را تعریف کنید. برای نشان دادن این فرآیند، این شروع سریع شامل دو تابع به عنوان روشهای ثابت است که پاسخهای رمزگذاری شده را برمیگرداند. یک پیاده سازی عملی تر، توابعی را تعریف می کند که یک REST API را فراخوانی می کند یا اطلاعات را از پایگاه داده بازیابی می کند.
زیر توابع getWeather و getTime را تعریف می کند:
class ToolsForLlm {
public static String getWeather(String location) {
return "Cloudy, 56°F";
}
public static String getTime(String timezone) {
return "7:00 PM " + timezone;
}
private ToolsForLlm() {}
}
از FunctionDeclaration برای توصیف هر تابع، دادن نام و توصیف به هر کدام و مشخص کردن انواع آن استفاده کنید. این مدل را از آنچه توابع انجام می دهند و زمان برقراری فراخوانی تابع مطلع می کند.
var getWeather = FunctionDeclaration.newBuilder()
.setName("getWeather")
.setDescription("Returns the weather conditions at a location.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"location",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The location for the weather report.")
.build())
.build())
.build();
var getTime = FunctionDeclaration.newBuilder()
.setName("getTime")
.setDescription("Returns the current time in the given timezone.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"timezone",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The timezone to get the time from.")
.build())
.build())
.build();
اعلان های تابع را به یک شی Tool اضافه کنید:
var tool = Tool.newBuilder()
.addFunctionDeclarations(getWeather)
.addFunctionDeclarations(getTime)
.build();
باطن استنتاج را ایجاد کنید
یک باطن استنتاج با استفاده از LLM Inference API ایجاد کنید و آن را به عنوان یک شی قالبکننده برای مدل خود ارسال کنید. FC SDK Formatter ( ModelFormatter ) هم به عنوان فرمت کننده و هم به عنوان تجزیه کننده عمل می کند. از آنجایی که این شروع سریع از Gemma-3 1B استفاده می کند، ما از GemmaFormatter استفاده خواهیم کرد:
var llmInferenceOptions = LlmInferenceOptions.builder()
.setModelPath(modelFile.getAbsolutePath())
.build();
var llmInference = LlmInference.createFromOptions(context, llmInferenceOptions);
var llmInferenceBackend = new llmInferenceBackend(llmInference, new GemmaFormatter());
برای اطلاعات بیشتر، به گزینه های پیکربندی LLM Inference مراجعه کنید.
مدل را نمونه سازی کنید
از شی GenerativeModel برای اتصال باطن استنتاج، اعلان سیستم و ابزارها استفاده کنید. ما قبلاً باطن و ابزارهای استنتاج را داریم، بنابراین فقط باید اعلان سیستم را ایجاد کنیم:
var systemInstruction = Content.newBuilder()
.setRole("system")
.addParts(Part.newBuilder().setText("You are a helpful assistant."))
.build();
نمونه سازی مدل با GenerativeModel :
var generativeModel = new GenerativeModel(
llmInferenceBackend,
systemInstruction,
List.of(tool),
)
یک جلسه چت را شروع کنید
برای سادگی، این شروع سریع یک جلسه چت را شروع می کند. همچنین می توانید چندین جلسه مستقل ایجاد کنید.
با استفاده از نمونه جدید GenerativeModel ، یک جلسه چت را شروع کنید:
var chat = generativeModel.startChat();
با استفاده از روش sendMessage ، درخواستها را از طریق جلسه چت به مدل ارسال کنید:
var response = chat.sendMessage("How's the weather in San Francisco?");
پاسخ مدل را تجزیه کنید
پس از ارسال یک اعلان به مدل، برنامه باید پاسخ را بررسی کند تا تعیین کند که آیا یک تابع فراخوانی کند یا متن زبان طبیعی را خروجی کند.
// Extract the model's message from the response.
var message = response.getCandidates(0).getContent().getParts(0);
// If the message contains a function call, execute the function.
if (message.hasFunctionCall()) {
var functionCall = message.getFunctionCall();
var args = functionCall.getArgs().getFieldsMap();
var result = null;
// Call the appropriate function.
switch (functionCall.getName()) {
case "getWeather":
result = ToolsForLlm.getWeather(args.get("location").getStringValue());
break;
case "getTime":
result = ToolsForLlm.getWeather(args.get("timezone").getStringValue());
break;
default:
throw new Exception("Function does not exist:" + functionCall.getName());
}
// Return the result of the function call to the model.
var functionResponse =
FunctionResponse.newBuilder()
.setName(functionCall.getName())
.setResponse(
Struct.newBuilder()
.putFields("result", Value.newBuilder().setStringValue(result).build()))
.build();
var functionResponseContent = Content.newBuilder()
.setRole("user")
.addParts(Part.newBuilder().setFunctionResponse(functionResponse))
.build();
var response = chat.sendMessage(functionResponseContent);
} else if (message.hasText()) {
Log.i(message.getText());
}
کد نمونه یک پیاده سازی بیش از حد ساده شده است. برای اطلاعات بیشتر در مورد اینکه چگونه یک برنامه کاربردی میتواند پاسخهای مدل را بررسی کند، به قالببندی و تجزیه مراجعه کنید.
چگونه کار می کند
این بخش اطلاعات عمیق تری در مورد مفاهیم و اجزای اصلی Function Calling SDK برای Android ارائه می دهد.
مدل ها
Function Calling SDK به مدلی با قالبکننده و تجزیهکننده نیاز دارد. FC SDK شامل یک قالبکننده و تجزیهکننده داخلی برای مدلهای زیر است:
- Gemma : از
GemmaFormatterاستفاده کنید. - Llama : از
LlamaFormatterاستفاده کنید. - Hammer : از
HammerFormatterاستفاده کنید.
برای استفاده از یک مدل متفاوت با FC SDK، باید قالبکننده و تجزیهکننده خود را توسعه دهید که با LLM Inference API سازگار باشد.
قالب بندی و تجزیه
بخش کلیدی پشتیبانی از فراخوانی تابع، قالب بندی دستورات و تجزیه خروجی مدل است. در حالی که این دو فرآیند مجزا هستند، FC SDK هم قالببندی و هم تجزیه را با رابط ModelFormatter انجام میدهد.
فرمتکننده مسئول تبدیل اعلانهای عملکرد ساختاریافته به متن، قالببندی پاسخهای تابع، و درج نشانههایی برای نشان دادن شروع و پایان نوبتهای مکالمه، و همچنین نقش آن نوبتها (به عنوان مثال "کاربر"، "مدل") است.
تجزیه کننده مسئول تشخیص اینکه آیا پاسخ مدل حاوی یک فراخوانی تابع است یا خیر. اگر تجزیه کننده یک فراخوانی تابع را تشخیص دهد، آن را به یک نوع داده ساختاریافته تجزیه می کند. در غیر این صورت، متن را به عنوان یک پاسخ زبان طبیعی در نظر می گیرد.
رمزگشایی محدود
رمزگشایی محدود تکنیکی است که تولید خروجی LLM ها را هدایت می کند تا اطمینان حاصل شود که به یک قالب ساختاریافته از پیش تعریف شده مانند اشیاء JSON یا فراخوانی تابع پایتون پایبند است. با اعمال این محدودیتها، مدل خروجیهای خود را بهگونهای قالببندی میکند که با توابع از پیش تعریفشده و انواع پارامترهای مربوط به آنها هماهنگ باشد.
برای فعال کردن رمزگشایی محدود، محدودیتها را در یک شی ConstraintOptions تعریف کنید و متد enableConstraint یک نمونه ChatSession را فراخوانی کنید. وقتی فعال باشد، این محدودیت پاسخ را محدود میکند که فقط شامل ابزارهای مرتبط با GenerativeModel باشد.
مثال زیر نحوه پیکربندی رمزگشایی محدود برای محدود کردن پاسخ به تماسهای ابزار را نشان میدهد. فراخوانی ابزار را محدود میکند که با پیشوند ```tool_code\n شروع شود و با پسوند \n``` پایان یابد.
ConstraintOptions constraintOptions = ConstraintOptions.newBuilder()
.setToolCallOnly( ConstraintOptions.ToolCallOnly.newBuilder()
.setConstraintPrefix("```tool_code\n")
.setConstraintSuffix("\n```"))
.build();
chatSession.enableConstraint(constraintOptions);
برای غیرفعال کردن محدودیت فعال در همان جلسه، از روش disableConstraint استفاده کنید:
chatSession.disableConstraint();