Отвечаем на вопросы с помощью Android

Пример приложения с ответами на вопросы в Android

В этом руководстве показано, как создать приложение Android с помощью TensorFlow Lite, чтобы предоставлять ответы на вопросы, структурированные в виде текста на естественном языке. В примере приложения используется API ответа на вопросы BERT ( BertQuestionAnswerer ) в библиотеке задач для естественного языка (NL), чтобы включить модели машинного обучения для ответов на вопросы. Приложение предназначено для физического устройства Android, но также может работать на эмуляторе устройства.

Если вы обновляете существующий проект, вы можете использовать пример приложения в качестве ссылки или шаблона. Инструкции о том, как добавить ответы на вопросы в существующее приложение, см. в разделе Обновление и изменение вашего приложения .

Обзор ответов на вопросы

Ответ на вопросы — это задача машинного обучения, позволяющая отвечать на вопросы, заданные на естественном языке. Обученная модель ответа на вопросы получает в качестве входных данных отрывок текста и вопрос и пытается ответить на вопрос на основе интерпретации информации, содержащейся в отрывке.

Модель ответов на вопросы обучается на наборе данных для ответов на вопросы, который состоит из набора данных для понимания прочитанного, а также пар вопрос-ответ, основанных на различных сегментах текста.

Для получения дополнительной информации о том, как генерируются модели в этом руководстве, обратитесь к руководству «Вопрос-ответ по BERT с помощью TensorFlow Lite Model Maker» .

Модели и набор данных

В примере приложения используется модель вопросов и ответов Mobile BERT ( mobilebert ), которая представляет собой более легкую и быструю версию BERT (представления двунаправленного кодировщика от Transformers). Дополнительные сведения о mobilebert см. в исследовательской статье MobileBERT: компактный BERT, независимый от задач, для устройств с ограниченными ресурсами .

Модель 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. Запустите Android-студию .
  2. В Android Studio выберите «Файл» > «Создать» > «Импортировать проект» .
  3. Перейдите в каталог примера кода, содержащий файл build.gradle ( .../examples/lite/examples/bert_qa/android/build.gradle ), и выберите этот каталог.
  4. Если Android Studio запрашивает синхронизацию Gradle, выберите «ОК».
  5. Убедитесь, что ваше устройство Android подключено к компьютеру и включен режим разработчика. Нажмите зеленую стрелку Run .

Если вы выберете правильный каталог, Android Studio создаст новый проект и соберет его. Этот процесс может занять несколько минут, в зависимости от скорости вашего компьютера и того, использовали ли вы Android Studio для других проектов. По завершении сборки Android Studio отображает сообщение BUILD SUCCESSFUL на панели состояния вывода сборки .

Чтобы запустить проект:

  1. В Android Studio запустите проект, выбрав «Выполнить» > «Выполнить…» .
  2. Выберите подключенное устройство Android (или эмулятор), чтобы протестировать приложение.

Использование приложения

После запуска проекта в Android Studio приложение автоматически откроется на подключенном устройстве или в эмуляторе устройства.

Чтобы использовать пример приложения «Вопрос-ответчик»:

  1. Выберите тему из списка предметов.
  2. Выберите предложенный вопрос или введите свой в текстовое поле.
  3. Переключите оранжевую стрелку, чтобы запустить модель.

Приложение пытается найти ответ на вопрос в тексте отрывка. Если модель обнаруживает ответ в отрывке, приложение выделяет для пользователя соответствующий фрагмент текста.

Теперь у вас есть работающее приложение для ответов на вопросы. Используйте следующие разделы, чтобы лучше понять, как работает пример приложения и как реализовать функции ответа на вопросы в ваших рабочих приложениях:

Как работает пример приложения

Приложение использует API BertQuestionAnswerer в библиотеке задач для пакета естественного языка (NL) . Модель MobileBERT была обучена с помощью TensorFlow Lite Model Maker . По умолчанию приложение работает на ЦП с возможностью аппаратного ускорения с использованием графического процессора или делегата 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 ) предоставляет инфраструктуру для запуска приложения на графическом процессоре, а Delegate ( tensorflow-lite-gpu ) предоставляет список совместимости.

  2. В Android Studio синхронизируйте зависимости проекта, выбрав « Файл» > «Синхронизировать проект с файлами Gradle» .

Инициализируйте модели машинного обучения

В своем приложении для 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 — это программные модули, которые ускоряют выполнение моделей машинного обучения с использованием специализированного оборудования обработки на мобильном устройстве, такого как графический процессор (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 .

Подготовьте данные для модели

В вашем приложении 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
        )
    }
    

Как только модель вернет набор результатов, ваше приложение может действовать на основе этих прогнозов, представляя результат вашему пользователю или выполняя дополнительную логику.

Следующие шаги