دليل الاتصال بدالة الذكاء الاصطناعي (AI) على الأجهزة الطرفية لنظام التشغيل Android

‫AI Edge Function Calling SDK (حزمة تطوير البرامج (SDK) لاستدعاء الدوالّ على الأجهزة الطرفية) هي مكتبة تتيح للمطوّرين استخدام استدعاء الدوالّ مع النماذج اللغوية الكبيرة (LLM) على الجهاز فقط. يتيح لك طلب البيانات من الدوالّ ربط نماذج بالأدوات وواجهات برمجة التطبيقات الخارجية، ما يتيح للنماذج طلب بيانات من دوالّ محدّدة باستخدام المَعلمات اللازمة لتنفيذ إجراءات في العالم الواقعي.

بدلاً من إنشاء نص فقط، يمكن لنموذج اللغة الضخمة الذي يستخدم حزمة تطوير البرامج (SDK) لـ FC إنشاء دعوة منظَّمة لدالة تنفِّذ إجراءً، مثل البحث عن معلومات محدّثة أو ضبط المنبّهات أو إجراء الحجوزات.

يرشدك هذا الدليل خلال عملية بدء سريعة أساسية لإضافة واجهة برمجة التطبيقات LLM Inference API مع حزمة تطوير البرامج (SDK) لـ Firebase إلى تطبيق Android. يركز هذا الدليل على إضافة إمكانات معالجة الوظائف إلى نموذج لغوي كبير على الجهاز. لمزيد من المعلومات حول استخدام واجهة برمجة التطبيقات LLM Inference API، يُرجى الاطّلاع على دليل LLM Inference for Android.

البدء السريع

اتّبِع الخطوات التالية لاستخدام حزمة تطوير البرامج (SDK) لنظام Firebase في تطبيق Android. يستخدم الدليل السريع واجهة برمجة التطبيقات LLM Inference API مع Hammer 2.1 (1.5B). تم تحسين واجهة برمجة التطبيقات LLM Inference API لأجهزة Android المتطوّرة، مثل Pixel 8 و Samsung S23 أو الإصدارات الأحدث، ولا تتوافق بشكل موثوق مع محاكيات الأجهزة.

إضافة التبعيات

تستخدم حزمة تطوير البرامج (SDK) لـ FC مكتبة com.google.ai.edge.localagents:localagents-fc، ويستخدم com.google.mediapipe:tasks-genai Inference API مكتبة 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 أو تستردّ المعلومات من قاعدة بيانات.

تحدِّد العبارة التالية دالتَي 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 وأرسِل إليها عنصر تنسيق لنموذجك. يعمل "مُنسق حزمة تطوير البرامج (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 لربط الخلفية لاستنتاج البيانات وprompt النظام والأدوات. لدينا حاليًا أدوات وخلفية الاستنتاج، لذا لن نحتاج سوى إلى إنشاء طلب النظام التالي:

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 على أداة تنسيق وتحليل مدمجة للنمذجَين التاليَين:

  • Gemma: استخدِم GemmaFormatter.
  • Llama: استخدِم LlamaFormatter.
  • المطرقة: استخدِم HammerFormatter.

لاستخدام نموذج مختلف مع حزمة تطوير البرامج (SDK) لميزة "الاستنتاج من النصوص الطويلة"، عليك تطوير أدوات تنسيق وتحليل متوافقة مع واجهة برمجة التطبيقات Inference API لنموذج "الاستنتاج من النصوص الطويلة".

التنسيق والتحليل

يتمثل أحد الأجزاء الرئيسية لدعم استدعاء الدوال في تنسيق الطلبات وتحليل مخرجات النماذج. على الرغم من أنّ هاتين العمليتين منفصلتان، تعالج حزمة تطوير البرامج (SDK) لنظام التشغيل Firebase كلاً من التنسيق والتحليل باستخدام واجهة ModelFormatter.

يتحمّل أداة التنسيق مسؤولية تحويل تعريفات الدوالّ منظَّمةً إلى نص وتنسيق ردود الدوالّ وإدراج الرموز المميّزة للإشارة إلى بداية ونهاية أدوار المحادثة، بالإضافة إلى أدوار هذه الأدوار (مثل "مستخدم" و"نموذج").

يتحمّل المُحلِّل مسؤولية رصد ما إذا كان ردّ النموذج يحتوي على طلب دالة. إذا رصد المُحلِّل طلب دالة، سيحلّله إلى نوع data منظَّم. بخلاف ذلك، يتعامل مع النص على أنّه ردّ بلغة طبيعية.

فك التشفير المحدود

فك التشفير المحدود هو أسلوب يوجّه عملية إنشاء الإخراج في النماذج اللغوية الكبيرة لأجل ضمان التزامها بتنسيق منظَّم محدّد مسبقًا، مثل عناصر 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();