AI Edge Function Calling SDK (FC SDK) هي مكتبة تتيح للمطوّرين استخدام ميزة "استدعاء الدوال" مع النماذج اللغوية الكبيرة (LLM) على الأجهزة. تتيح لك ميزة "استدعاء الدوال" ربط النماذج بأدوات وواجهات برمجة تطبيقات خارجية، ما يمكّن النماذج من استدعاء دوال معيّنة مع المَعلمات اللازمة لتنفيذ إجراءات في العالم الحقيقي.
بدلاً من مجرد إنشاء نص، يمكن لنموذج لغوي كبير يستخدم حزمة تطوير البرامج (SDK) الخاصة بأداة "استدعاء الوظائف" إنشاء استدعاء منظَّم لوظيفة تنفّذ إجراءً، مثل البحث عن معلومات حديثة أو ضبط المنبّهات أو إجراء حجوزات.
يرشدك هذا الدليل إلى خطوات أساسية وسريعة لبدء استخدام LLM Inference API مع حزمة تطوير البرامج (SDK) الخاصة بـ FC في تطبيق Android. يركّز هذا الدليل على إضافة إمكانات استدعاء الدوال إلى نموذج لغوي كبير (LLM) على الجهاز. لمزيد من المعلومات حول استخدام واجهة برمجة التطبيقات LLM Inference API، يُرجى الاطّلاع على دليل LLM Inference لنظام Android.
البدء السريع
اتّبِع الخطوات التالية لاستخدام حزمة تطوير البرامج (SDK) الخاصة بـ FC في تطبيق Android. يستخدم هذا الدليل السريع واجهة LLM Inference API مع Hammer 2.1 (1.5 مليار). تم تحسين واجهة برمجة التطبيقات LLM Inference API لتتوافق مع أجهزة Android المتطورة، مثل هواتف Pixel 8 وSamsung S23 أو الإصدارات الأحدث، ولا تتوافق بشكل موثوق مع محاكيات الأجهزة.
إضافة حِزم تابعة
تستخدم حزمة تطوير البرامج (SDK) الخاصة بـ FC مكتبة com.google.ai.edge.localagents:localagents-fc، بينما تستخدم واجهة برمجة التطبيقات LLM Inference مكتبة com.google.mediapipe:tasks-genai. أضِف كلتا التبعيتين إلى ملف build.gradle في تطبيق Android:
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.24'
implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}
بالنسبة إلى الأجهزة التي تعمل بالإصدار 12 من نظام التشغيل Android (المستوى 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 (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());
لمزيد من المعلومات، يُرجى الاطّلاع على خيارات إعداد استنتاج النماذج اللغوية الكبيرة.
إنشاء مثيل للنموذج
استخدِم عنصر 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());
}
نموذج التعليمات البرمجية هو عملية تنفيذ مبسطة للغاية. لمزيد من المعلومات حول كيفية فحص التطبيق لردود النموذج، اطّلِع على التنسيق والتحليل.
آلية العمل
يقدّم هذا القسم معلومات أكثر تفصيلاً حول المفاهيم الأساسية ومكوّنات حزمة تطوير البرامج (SDK) الخاصة بميزة "استدعاء الدوال" على Android.
النماذج
تتطلّب حزمة تطوير البرامج (SDK) الخاصة بميزة "استدعاء الدوال" نموذجًا يتضمّن أداة تنسيق ومحلّلاً. تحتوي حزمة تطوير البرامج (SDK) الخاصة بـ FC على أداة تنسيق وتحليل مدمجة للنماذج التالية:
لاستخدام نموذج مختلف مع حزمة تطوير البرامج (SDK) الخاصة بـ FC، عليك تطوير أداة تنسيق وتحليل خاصة بك تكون متوافقة مع واجهة LLM Inference API.
التنسيق والتحليل
يتمثّل أحد الجوانب الرئيسية في إتاحة استخدام الدوال في تنسيق الطلبات وتحليل ناتج النموذج. مع أنّ هاتين العمليتين منفصلتان، إلا أنّ حزمة تطوير البرامج (SDK) الخاصة بـ FC تتعامل مع كلتا العمليتين، أي التنسيق والتحليل، باستخدام واجهة ModelFormatter.
يكون المنسّق مسؤولاً عن تحويل تعريفات الدوال المنظَّمة إلى نص، وتنسيق ردود الدوال، وإدراج الرموز المميزة للإشارة إلى بداية ونهاية أدوار المحادثة، بالإضافة إلى أدوار هذه الأدوار (مثل "المستخدم" و"النموذج").
يكون المحلّل مسؤولاً عن رصد ما إذا كانت استجابة النموذج تتضمّن استدعاء دالة. إذا رصد المحلّل اللغوي استدعاء دالة، سيحلّله إلى نوع بيانات منظَّمة. بخلاف ذلك، يتم التعامل مع النص على أنّه ردّ بلغة طبيعية.
فك الترميز المقيّد
الترميز المقيّد هو أسلوب يوجّه عملية إنشاء الناتج في النماذج اللغوية الكبيرة (LLM) لضمان التزامها بتنسيق منظَّم محدّد مسبقًا، مثل عناصر JSON أو استدعاءات وظائف Python. ومن خلال فرض هذه القيود، ينسّق النموذج مخرجاته بطريقة تتوافق مع الدوال المحدّدة مسبقًا وأنواع المَعلمات المقابلة لها.
لتفعيل فك الترميز المقيد، حدِّد القيود في عنصر 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();