الإجابة على الأسئلة مع الروبوت

سؤال وجواب مثال التطبيق في Android

يوضح لك هذا البرنامج التعليمي كيفية إنشاء تطبيق Android باستخدام TensorFlow Lite لتقديم إجابات للأسئلة المبنية في نص باللغة الطبيعية. يستخدم تطبيق المثال واجهة برمجة تطبيقات BERT Question Answerer ( BertQuestionAnswerer ) ضمن مكتبة المهام للغة الطبيعية (NL) لتمكين نماذج التعلم الآلي للإجابة على الأسئلة. تم تصميم التطبيق لجهاز Android فعليًا ولكن يمكن تشغيله أيضًا على محاكي الجهاز.

إذا كنت تقوم بتحديث مشروع موجود، فيمكنك استخدام التطبيق النموذجي كمرجع أو قالب. للحصول على إرشادات حول كيفية إضافة إجابة سؤال إلى تطبيق موجود، راجع تحديث التطبيق الخاص بك وتعديله .

نظرة عامة على إجابة الأسئلة

الإجابة على الأسئلة هي مهمة التعلم الآلي للإجابة على الأسئلة المطروحة باللغة الطبيعية. يتلقى نموذج الإجابة على الأسئلة المدرب مقطعًا نصيًا وسؤالًا كمدخلات، ويحاول الإجابة على السؤال بناءً على تفسيره للمعلومات الموجودة داخل المقطع.

يتم تدريب نموذج الإجابة على الأسئلة على مجموعة بيانات الإجابة على الأسئلة، والتي تتكون من مجموعة بيانات فهم القراءة إلى جانب أزواج الأسئلة والإجابات بناءً على أجزاء مختلفة من النص.

لمزيد من المعلومات حول كيفية إنشاء النماذج في هذا البرنامج التعليمي، ارجع إلى إجابة سؤال BERT مع البرنامج التعليمي TensorFlow Lite Model Maker .

النماذج ومجموعة البيانات

يستخدم التطبيق النموذجي نموذج Mobile BERT Q&A ( mobilebert ) وهو إصدار أخف وأسرع من BERT (تمثيلات التشفير ثنائية الاتجاه من المحولات). لمزيد من المعلومات حول mobilebert ، راجع MobileBERT: ورقة بحثية مضغوطة لا تحدد المهام للأجهزة محدودة الموارد .

تم تدريب نموذج mobilebert باستخدام مجموعة بيانات ستانفورد للإجابة على الأسئلة ( SQuAD )، وهي مجموعة بيانات لفهم القراءة تتكون من مقالات من ويكيبيديا ومجموعة من أزواج الأسئلة والأجوبة لكل مقالة.

قم بإعداد وتشغيل التطبيق المثال

لإعداد تطبيق الإجابة على الأسئلة، قم بتنزيل التطبيق النموذجي من GitHub وقم بتشغيله باستخدام Android Studio .

متطلبات النظام

  • إصدار Android Studio 2021.1.1 (Bumblebee) أو أعلى.
  • Android SDK الإصدار 31 أو أعلى
  • جهاز Android مزود بإصدار نظام تشغيل أدنى SDK 21 (Android 7.0 - Nougat) مع تمكين وضع المطور ، أو محاكي Android.

احصل على رمز المثال

قم بإنشاء نسخة محلية من رمز المثال. ستستخدم هذا الرمز لإنشاء مشروع في Android Studio وتشغيل تطبيق المثال.

لاستنساخ رمز المثال وإعداده:

  1. استنساخ مستودع git
    git clone https://github.com/tensorflow/examples.git
    
  2. بشكل اختياري، قم بتكوين مثيل git الخاص بك لاستخدام الدفع المتناثر، بحيث يكون لديك فقط الملفات الخاصة بمثال تطبيق الإجابة على السؤال:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/bert_qa/android
    

استيراد وتشغيل المشروع

قم بإنشاء مشروع من رمز المثال الذي تم تنزيله، وقم ببناء المشروع، ثم قم بتشغيله.

لاستيراد وإنشاء مشروع التعليمات البرمجية النموذجي:

  1. ابدأ تشغيل أندرويد ستوديو .
  2. من Android Studio، حدد File > New > Import Project .
  3. انتقل إلى دليل التعليمات البرمجية النموذجي الذي يحتوي على ملف build.gradle ( .../examples/lite/examples/bert_qa/android/build.gradle ) وحدد هذا الدليل.
  4. إذا طلب Android Studio إجراء Gradle Sync، فاختر "موافق".
  5. تأكد من أن جهاز Android الخاص بك متصل بجهاز الكمبيوتر الخاص بك وأن وضع المطور ممكّن. انقر فوق سهم Run الأخضر.

إذا قمت بتحديد الدليل الصحيح، فسيقوم Android Studio بإنشاء مشروع جديد وإنشائه. يمكن أن تستغرق هذه العملية بضع دقائق، اعتمادًا على سرعة جهاز الكمبيوتر الخاص بك وما إذا كنت قد استخدمت Android Studio لمشاريع أخرى. عند اكتمال البناء، يعرض Android Studio رسالة BUILD SUCCESSFUL في لوحة حالة إخراج البناء .

لتشغيل المشروع:

  1. من Android Studio، قم بتشغيل المشروع عن طريق تحديد Run > Run… .
  2. حدد جهاز Android متصلًا (أو محاكيًا) لاختبار التطبيق.

باستخدام التطبيق

بعد تشغيل المشروع في Android Studio، يتم فتح التطبيق تلقائيًا على الجهاز المتصل أو محاكي الجهاز.

لاستخدام التطبيق النموذجي للإجابة على الأسئلة:

  1. اختر موضوعًا من قائمة المواضيع.
  2. اختر سؤالاً مقترحًا أو أدخل سؤالك في مربع النص.
  3. قم بتبديل السهم البرتقالي لتشغيل النموذج.

يحاول التطبيق التعرف على إجابة السؤال من نص المقطع. إذا اكتشف النموذج إجابة داخل المقطع، فسيقوم التطبيق بتمييز نطاق النص ذي الصلة للمستخدم.

لديك الآن تطبيق فعال للإجابة على الأسئلة. استخدم الأقسام التالية لفهم كيفية عمل تطبيق المثال بشكل أفضل، وكيفية تنفيذ ميزات الإجابة على الأسئلة في تطبيقات الإنتاج الخاصة بك:

كيف يعمل التطبيق المثال

يستخدم التطبيق BertQuestionAnswerer API ضمن مكتبة المهام لحزمة اللغة الطبيعية (NL) . تم تدريب نموذج MobileBERT باستخدام TensorFlow Lite Model Maker . يعمل التطبيق على وحدة المعالجة المركزية بشكل افتراضي، مع خيار تسريع الأجهزة باستخدام مندوب GPU أو NNAPI.

تحتوي الملفات والأدلة التالية على التعليمات البرمجية الهامة لهذا التطبيق:

  • BertQaHelper.kt - يقوم بتهيئة المجيب على الأسئلة ويتعامل مع اختيار النموذج والمفوض.
  • QaFragment.kt - يعالج النتائج وينسقها.
  • MainActivity.kt - يوفر المنطق التنظيمي للتطبيق.

تعديل التطبيق الخاص بك

تشرح الأقسام التالية الخطوات الأساسية لتعديل تطبيق Android الخاص بك لتشغيل النموذج الموضح في نموذج التطبيق. تستخدم هذه التعليمات التطبيق النموذجي كنقطة مرجعية. قد تختلف التغييرات المحددة المطلوبة لتطبيقك عن التطبيق النموذجي.

افتح أو أنشئ مشروع Android

أنت بحاجة إلى مشروع تطوير Android في Android Studio لمتابعة بقية هذه التعليمات. اتبع الإرشادات أدناه لفتح مشروع موجود أو إنشاء مشروع جديد.

لفتح مشروع تطوير Android حالي:

  • في Android Studio، حدد ملف > فتح وحدد مشروعًا موجودًا.

لإنشاء مشروع تطوير Android أساسي:

لمزيد من المعلومات حول استخدام Android Studio، راجع وثائق Android Studio .

إضافة تبعيات المشروع

في التطبيق الخاص بك، أضف تبعيات مشروع محددة لتشغيل نماذج التعلم الآلي TensorFlow Lite والوصول إلى وظائف الأداة المساعدة. تقوم هذه الوظائف بتحويل البيانات مثل السلاسل إلى تنسيق بيانات موتر يمكن معالجته بواسطة النموذج. تشرح الإرشادات التالية كيفية إضافة المشروع المطلوب وتبعيات الوحدة النمطية إلى مشروع تطبيق Android الخاص بك.

لإضافة تبعيات الوحدة النمطية:

  1. في الوحدة التي تستخدم TensorFlow Lite، قم بتحديث ملف build.gradle الخاص بالوحدة ليشمل التبعيات التالية.

    في تطبيق المثال، توجد التبعيات في app/build.gradle :

    dependencies {
      ...
      // Import tensorflow library
      implementation 'org.tensorflow:tensorflow-lite-task-text:0.3.0'
    
      // Import the GPU delegate plugin Library for GPU inference
      implementation 'org.tensorflow:tensorflow-lite-gpu-delegate-plugin:0.4.0'
      implementation 'org.tensorflow:tensorflow-lite-gpu:2.9.0'
    }
    

    يجب أن يتضمن المشروع مكتبة المهام النصية ( tensorflow-lite-task-text ).

    إذا كنت تريد تعديل هذا التطبيق ليعمل على وحدة معالجة الرسومات (GPU)، فإن مكتبة GPU ( tensorflow-lite-gpu-delegate-plugin ) توفر البنية الأساسية لتشغيل التطبيق على وحدة معالجة الرسومات (GPU)، وDelegate ( tensorflow-lite-gpu ) يوفر قائمة التوافق.

  2. في Android Studio، قم بمزامنة تبعيات المشروع عن طريق تحديد: File > Sync Project with Gradle Files .

تهيئة نماذج ML

في تطبيق Android الخاص بك، يجب عليك تهيئة نموذج التعلم الآلي TensorFlow Lite باستخدام المعلمات قبل تشغيل التنبؤات مع النموذج.

يتم تخزين نموذج TensorFlow Lite كملف *.tflite . يحتوي ملف النموذج على منطق التنبؤ ويتضمن عادةً بيانات تعريف حول كيفية تفسير نتائج التنبؤ. عادة، يتم تخزين ملفات النموذج في دليل src/main/assets لمشروع التطوير الخاص بك، كما في مثال التعليمات البرمجية:

  • <project>/src/main/assets/mobilebert_qa.tflite

من أجل الراحة وسهولة قراءة التعليمات البرمجية، يعلن المثال عن كائن مصاحب يحدد إعدادات النموذج.

لتهيئة النموذج في تطبيقك:

  1. قم بإنشاء كائن مصاحب لتحديد إعدادات النموذج. في تطبيق المثال، يوجد هذا الكائن في BertQaHelper.kt :

    companion object {
        private const val BERT_QA_MODEL = "mobilebert.tflite"
        private const val TAG = "BertQaHelper"
        const val DELEGATE_CPU = 0
        const val DELEGATE_GPU = 1
        const val DELEGATE_NNAPI = 2
    }
    
  2. قم بإنشاء إعدادات النموذج عن طريق إنشاء كائن BertQaHelper ، وإنشاء كائن TensorFlow Lite باستخدام bertQuestionAnswerer .

    في تطبيق المثال، يوجد هذا في الدالة setupBertQuestionAnswerer() ضمن BertQaHelper.kt :

    class BertQaHelper(
        ...
    ) {
        ...
        init {
            setupBertQuestionAnswerer()
        }
    
        fun clearBertQuestionAnswerer() {
            bertQuestionAnswerer = null
        }
    
        private fun setupBertQuestionAnswerer() {
            val baseOptionsBuilder = BaseOptions.builder().setNumThreads(numThreads)
            ...
            val options = BertQuestionAnswererOptions.builder()
                .setBaseOptions(baseOptionsBuilder.build())
                .build()
    
            try {
                bertQuestionAnswerer =
                    BertQuestionAnswerer.createFromFileAndOptions(context, BERT_QA_MODEL, options)
            } catch (e: IllegalStateException) {
                answererListener
                    ?.onError("Bert Question Answerer failed to initialize. See error logs for details")
                Log.e(TAG, "TFLite failed to load model with error: " + e.message)
            }
        }
        ...
        }
    

تمكين تسريع الأجهزة (اختياري)

عند تهيئة نموذج TensorFlow Lite في تطبيقك، يجب أن تفكر في استخدام ميزات تسريع الأجهزة لتسريع حسابات التنبؤ للنموذج. مندوبو TensorFlow Lite عبارة عن وحدات برمجية تعمل على تسريع تنفيذ نماذج التعلم الآلي باستخدام أجهزة معالجة متخصصة على جهاز محمول، مثل وحدة معالجة الرسومات (GPUs) أو وحدات معالجة الموتر (TPUs).

لتمكين تسريع الأجهزة في تطبيقك:

  1. قم بإنشاء متغير لتعريف المفوض الذي سيستخدمه التطبيق. في تطبيق المثال، يوجد هذا المتغير مبكرًا في BertQaHelper.kt :

    var currentDelegate: Int = 0
    
  2. إنشاء محدد مندوب. في تطبيق المثال، يوجد محدد المفوض في وظيفة setupBertQuestionAnswerer داخل BertQaHelper.kt :

    when (currentDelegate) {
        DELEGATE_CPU -> {
            // Default
        }
        DELEGATE_GPU -> {
            if (CompatibilityList().isDelegateSupportedOnThisDevice) {
                baseOptionsBuilder.useGpu()
            } else {
                answererListener?.onError("GPU is not supported on this device")
            }
        }
        DELEGATE_NNAPI -> {
            baseOptionsBuilder.useNnapi()
        }
    }
    

يوصى باستخدام المفوضين لتشغيل نماذج TensorFlow Lite، ولكنه غير مطلوب. لمزيد من المعلومات حول استخدام المفوضين مع TensorFlow Lite، راجع مندوبو TensorFlow Lite .

تحضير البيانات للنموذج

في تطبيق Android الخاص بك، توفر التعليمات البرمجية الخاصة بك البيانات إلى النموذج لتفسيرها عن طريق تحويل البيانات الموجودة مثل النص الخام إلى تنسيق بيانات Tensor الذي يمكن معالجته بواسطة النموذج الخاص بك. يجب أن يكون للموتر الذي تمرره إلى النموذج أبعاد أو شكل محدد يطابق تنسيق البيانات المستخدمة لتدريب النموذج. يقبل تطبيق الإجابة على الأسئلة هذا السلاسل كمدخلات لكل من مقطع النص والسؤال. لا يتعرف النموذج على الأحرف الخاصة والكلمات غير الإنجليزية.

لتوفير بيانات نص المرور إلى النموذج:

  1. استخدم كائن LoadDataSetClient لتحميل بيانات نص المقطع إلى التطبيق. في تطبيق المثال، يقع هذا في LoadDataSetClient.kt

    fun loadJson(): DataSet? {
        var dataSet: DataSet? = null
        try {
            val inputStream: InputStream = context.assets.open(JSON_DIR)
            val bufferReader = inputStream.bufferedReader()
            val stringJson: String = bufferReader.use { it.readText() }
            val datasetType = object : TypeToken<DataSet>() {}.type
            dataSet = Gson().fromJson(stringJson, datasetType)
        } catch (e: IOException) {
            Log.e(TAG, e.message.toString())
        }
        return dataSet
    }
    
  2. استخدم كائن DatasetFragment لسرد العناوين لكل مقطع من النص وبدء شاشة الأسئلة والأجوبة في TFL . في التطبيق النموذجي، يوجد هذا في DatasetFragment.kt :

    class DatasetFragment : Fragment() {
        ...
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val client = LoadDataSetClient(requireActivity())
            client.loadJson()?.let {
                titles = it.getTitles()
            }
            ...
        }
       ...
    }
    
  3. استخدم وظيفة onCreateViewHolder داخل كائن DatasetAdapter لتقديم العناوين لكل مقطع من النص. في تطبيق المثال، يوجد هذا في DatasetAdapter.kt :

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemDatasetBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return ViewHolder(binding)
    }
    

لتقديم أسئلة المستخدم إلى النموذج:

  1. استخدم كائن QaAdapter لتقديم السؤال إلى النموذج. في التطبيق النموذجي، يوجد هذا في QaAdapter.kt :

    class QaAdapter(private val question: List<String>, private val select: (Int) -> Unit) :
      RecyclerView.Adapter<QaAdapter.ViewHolder>() {
    
      inner class ViewHolder(private val binding: ItemQuestionBinding) :
          RecyclerView.ViewHolder(binding.root) {
          init {
              binding.tvQuestionSuggestion.setOnClickListener {
                  select.invoke(adapterPosition)
              }
          }
    
          fun bind(question: String) {
              binding.tvQuestionSuggestion.text = question
          }
      }
      ...
    }
    

تشغيل التوقعات

في تطبيق Android الخاص بك، بمجرد تهيئة كائن BertQuestionAnswerer ، يمكنك البدء في إدخال الأسئلة في شكل نص باللغة الطبيعية إلى النموذج. يحاول النموذج تحديد الإجابة داخل مقطع النص.

لتشغيل التوقعات:

  1. قم بإنشاء وظيفة answer ، والتي تقوم بتشغيل النموذج وقياس الوقت المستغرق لتحديد الإجابة ( inferenceTime ). في تطبيق المثال، توجد وظيفة answer في BertQaHelper.kt :

    fun answer(contextOfQuestion: String, question: String) {
        if (bertQuestionAnswerer == null) {
            setupBertQuestionAnswerer()
        }
    
        var inferenceTime = SystemClock.uptimeMillis()
    
        val answers = bertQuestionAnswerer?.answer(contextOfQuestion, question)
        inferenceTime = SystemClock.uptimeMillis() - inferenceTime
        answererListener?.onResults(answers, inferenceTime)
    }
    
  2. تمرير النتائج من answer إلى كائن المستمع.

    interface AnswererListener {
        fun onError(error: String)
        fun onResults(
            results: List<QaAnswer>?,
            inferenceTime: Long
        )
    }
    

التعامل مع إخراج النموذج

بعد إدخال سؤال، يوفر النموذج خمس إجابات محتملة كحد أقصى داخل المقطع.

للحصول على النتائج من النموذج:

  1. قم بإنشاء دالة onResult لكائن المستمع للتعامل مع الإخراج. في تطبيق المثال، يوجد كائن المستمع في BertQaHelper.kt

    interface AnswererListener {
        fun onError(error: String)
        fun onResults(
            results: List<QaAnswer>?,
            inferenceTime: Long
        )
    }
    
  2. قم بتمييز أقسام المقطع بناءً على النتائج. في التطبيق النموذجي، يوجد هذا في QaFragment.kt :

    override fun onResults(results: List<QaAnswer>?, inferenceTime: Long) {
        results?.first()?.let {
            highlightAnswer(it.text)
        }
    
        fragmentQaBinding.tvInferenceTime.text = String.format(
            requireActivity().getString(R.string.bottom_view_inference_time),
            inferenceTime
        )
    }
    

بمجرد أن يقوم النموذج بإرجاع مجموعة من النتائج، يمكن لتطبيقك التصرف بناءً على تلك التنبؤات من خلال تقديم النتيجة إلى المستخدم الخاص بك أو تنفيذ منطق إضافي.

الخطوات التالية