پاسخگویی به سوالات با اندروید

نمونه برنامه پاسخگویی به سوال در اندروید

این آموزش به شما نشان می دهد که چگونه با استفاده از TensorFlow Lite یک برنامه اندروید بسازید تا به سوالات ساختار یافته در متن زبان طبیعی پاسخ دهید. برنامه مثال از API پاسخ‌دهنده پرسش BERT ( BertQuestionAnswerer ) در کتابخانه وظیفه برای زبان طبیعی (NL) استفاده می‌کند تا مدل‌های یادگیری ماشین پاسخ‌گوی پرسش را فعال کند. این برنامه برای یک دستگاه اندروید فیزیکی طراحی شده است، اما می تواند بر روی یک شبیه ساز دستگاه نیز اجرا شود.

اگر یک پروژه موجود را به روز می کنید، می توانید از برنامه نمونه به عنوان مرجع یا الگو استفاده کنید. برای دستورالعمل‌هایی در مورد نحوه افزودن پاسخ سؤال به برنامه موجود، به به‌روزرسانی و اصلاح برنامه خود مراجعه کنید.

نمای کلی پاسخگویی به سوال

پاسخگویی به سؤال ، وظیفه یادگیری ماشینی است که به سؤالات مطرح شده به زبان طبیعی پاسخ می دهد. یک مدل پاسخ‌دهی به سؤال آموزش‌دیده، متن و سؤالی را به عنوان ورودی دریافت می‌کند و سعی می‌کند بر اساس تفسیری که از اطلاعات داخل متن دارد، به سؤال پاسخ دهد.

یک مدل پاسخ به سؤال بر روی یک مجموعه داده پاسخ به سؤال آموزش داده می شود که از مجموعه داده درک مطلب به همراه جفت سؤال-پاسخ بر اساس بخش های مختلف متن تشکیل شده است.

برای اطلاعات بیشتر در مورد نحوه تولید مدل های این آموزش، به آموزش پاسخ به پرسش BERT با TensorFlow Lite Model Maker مراجعه کنید.

مدل ها و مجموعه داده ها

برنامه مثال از مدل Mobile BERT Q&A ( mobilebert ) استفاده می‌کند، که نسخه سبک‌تر و سریع‌تر BERT (نمایش رمزگذار دوطرفه از Transformers) است. برای اطلاعات بیشتر در مورد mobilebert ، به مقاله تحقیقاتی MobileBERT: A Compact Task-Agnostic BERT for Resource-Limited Devices مراجعه کنید.

مدل mobilebert با استفاده از مجموعه داده پاسخ به پرسش استنفورد ( SQuAD )، یک مجموعه داده درک مطلب متشکل از مقالات ویکی‌پدیا و مجموعه‌ای از جفت‌های پرسش و پاسخ برای هر مقاله آموزش داده شد.

برنامه نمونه را راه اندازی و اجرا کنید

برای راه اندازی برنامه پاسخگویی به سؤال، برنامه نمونه را از GitHub دانلود کرده و با استفاده از Android Studio اجرا کنید.

سیستم مورد نیاز

  • Android Studio نسخه 2021.1.1 (Bumblebee) یا بالاتر.
  • Android SDK نسخه 31 یا بالاتر
  • دستگاه Android با حداقل نسخه سیستم عامل SDK 21 (Android 7.0 - Nougat) با حالت توسعه دهنده فعال یا شبیه ساز Android.

کد نمونه را دریافت کنید

یک کپی محلی از کد نمونه ایجاد کنید. شما از این کد برای ایجاد یک پروژه در اندروید استودیو و اجرای نمونه برنامه استفاده خواهید کرد.

برای شبیه سازی و تنظیم کد مثال:

  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. Android Studio را راه اندازی کنید.
  2. از Android Studio، File > New > Import Project را انتخاب کنید.
  3. به فهرست کد نمونه حاوی فایل build.gradle ( .../examples/lite/examples/bert_qa/android/build.gradle ) بروید و آن دایرکتوری را انتخاب کنید.
  4. اگر Android Studio درخواست Gradle Sync کرد، OK را انتخاب کنید.
  5. مطمئن شوید که دستگاه اندرویدی شما به رایانه شما متصل است و حالت توسعه دهنده فعال است. روی فلش سبز Run کلیک کنید.

اگر دایرکتوری صحیح را انتخاب کنید، Android Studio یک پروژه جدید ایجاد می کند و آن را می سازد. این فرآیند بسته به سرعت کامپیوتر شما و اگر از اندروید استودیو برای پروژه های دیگر استفاده کرده اید، ممکن است چند دقیقه طول بکشد. پس از اتمام ساخت، Android Studio یک پیام BUILD SUCCESSFUL را در پانل وضعیت Build Output نمایش می دهد.

برای اجرای پروژه:

  1. از Android Studio، پروژه را با انتخاب Run > Run… اجرا کنید.
  2. یک دستگاه اندروید (یا شبیه ساز) متصل را برای آزمایش برنامه انتخاب کنید.

با استفاده از اپلیکیشن

پس از اجرای پروژه در اندروید استودیو، برنامه به طور خودکار در دستگاه متصل یا شبیه ساز دستگاه باز می شود.

برای استفاده از برنامه مثال Question answerer:

  1. موضوعی را از لیست موضوعات انتخاب کنید.
  2. یک سوال پیشنهادی را انتخاب کنید یا سوال خود را در کادر متن وارد کنید.
  3. برای اجرای مدل، پیکان نارنجی را تغییر دهید.

برنامه سعی می کند پاسخ سوال را از متن قسمت شناسایی کند. اگر مدل پاسخی را در متن متن تشخیص دهد، برنامه دامنه متن مربوطه را برای کاربر برجسته می‌کند.

شما اکنون یک برنامه کاربردی پاسخگویی به سوال دارید. از بخش‌های زیر برای درک بهتر نحوه عملکرد برنامه نمونه و نحوه پیاده‌سازی ویژگی‌های پاسخ به سؤال در برنامه‌های تولیدی خود استفاده کنید:

برنامه نمونه چگونه کار می کند

این برنامه از API BertQuestionAnswerer در بسته کتابخانه وظیفه برای زبان طبیعی (NL) استفاده می کند. مدل MobileBERT با استفاده از TensorFlow Lite Model Maker آموزش داده شد. برنامه به طور پیش فرض بر روی CPU اجرا می شود، با گزینه شتاب سخت افزاری با استفاده از نماینده GPU یا NNAPI.

فایل ها و دایرکتوری های زیر حاوی کد حیاتی برای این برنامه هستند:

  • BertQaHelper.kt - پاسخ دهنده سوال را راه اندازی می کند و مدل و انتخاب نماینده را مدیریت می کند.
  • QaFragment.kt - نتایج را کنترل و قالب بندی می کند.
  • MainActivity.kt - منطق سازماندهی برنامه را ارائه می دهد.

برنامه خود را اصلاح کنید

بخش‌های زیر مراحل کلیدی تغییر برنامه Android خود را برای اجرای مدل نشان داده شده در برنامه مثال توضیح می‌دهند. این دستورالعمل ها از برنامه مثال به عنوان یک نقطه مرجع استفاده می کنند. تغییرات خاص مورد نیاز برای برنامه شخصی شما ممکن است با برنامه نمونه متفاوت باشد.

یک پروژه اندرویدی را باز یا ایجاد کنید

شما به یک پروژه توسعه اندروید در اندروید استودیو نیاز دارید تا به همراه بقیه این دستورالعمل ها عمل کنید. دستورالعمل های زیر را برای باز کردن یک پروژه موجود یا ایجاد یک پروژه جدید دنبال کنید.

برای باز کردن یک پروژه توسعه اندروید موجود:

  • در Android Studio، File > Open را انتخاب کرده و پروژه موجود را انتخاب کنید.

برای ایجاد یک پروژه توسعه پایه اندروید:

برای اطلاعات بیشتر در مورد استفاده از 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 را راه اندازی کنید

در برنامه اندروید خود، باید قبل از اجرای پیش‌بینی‌ها با مدل، مدل یادگیری ماشینی 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 ماژول‌های نرم‌افزاری هستند که اجرای مدل‌های یادگیری ماشین را با استفاده از سخت‌افزار پردازش تخصصی روی یک دستگاه تلفن همراه، مانند واحد پردازش گرافیکی (GPU) یا واحدهای پردازش تانسور (TPU) سرعت می‌بخشند.

برای فعال کردن شتاب سخت افزاری در برنامه خود:

  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 Delegates مراجعه کنید.

داده ها را برای مدل آماده کنید

در برنامه 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
        )
    }
    

هنگامی که مدل مجموعه ای از نتایج را برگرداند، برنامه شما می تواند با ارائه نتیجه به کاربر یا اجرای منطق اضافی، بر اساس آن پیش بینی ها عمل کند.

مراحل بعدی