В последнее время я экспериментировал с машинным обучением, и меня интересовало, как далеко я могу зайти с Javascript и Vue.

Думаю, большинство из вас уже слышали Tensorflow.js. В этом примере мы создадим приложение Vue 3, используя модель Ответы на вопросы на естественном языке Tensorflow, основанную на BERT.

Вот требования:

  • Создание приложения VUE 3
  • Установите зависимости из Tensorflow.js
  • Импорт зависимостей из Tensorflow.js
  • Загрузка нашей модели QNA
  • Подготовка необходимых элементов пользовательского интерфейса для получения данных от пользователя.
  • Передача данных из элементов пользовательского интерфейса в необходимые методы QNA
  • Отображение ответов с наивысшими оценками в нашем интерфейсе

Начнем с первого шага.

Чтобы создать приложение VUE 3, мы получаем поддержку от vue-cli и используем эту команду в нашем терминале для завершения шага

vue create tensorflow-qna

После этого мы увидим несколько вариантов настройки нашего приложения vue перед его созданием.

У меня есть пресет из предыдущих проектов, поэтому я бы выбрал:

  • Vue 3
  • Node-sass
  • Вавилон
  • Маршрутизатор
  • Vuex
  • Эс-линт
  • Юнит-шутка

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

Теперь нам нужно установить наши зависимости, чтобы ...

yarn add @tensorflow/tfjs @tensorflow-models/qna

Как только эта задача будет завершена, нашим следующим шагом будет импорт наших зависимостей из Tensorflow.js.

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

Чтобы импортировать наши зависимости, мы переходим к компоненту Helloworld.vue и добавляем их после нашего тега скрипта.

import * as tf from '@tensorflow/tfjs'
import * as qna from '@tensorflow-models/qna'

Итак, мы установили и импортировали наши зависимости. Пришло время поработать над нашей моделью и нашими методами для передачи / извлечения данных из нее.

Нам нужно загрузить нашу модель один раз при создании экземпляра этого компонента, поэтому правильный метод жизненного цикла будет «установлен».

Сначала мы создаем наш метод в объекте методов. А это выглядит так.

async loadModel() {
  this.loadedModel = Object.freeze(await qna.load())
  const tensorflow = tf
  console.log('tensorflow : ', tensorflow);
  console.log('qna-model : ', this.loadedModel);},

Здесь мы собрали наш объект tensorflow, чтобы увидеть его свойства, и наиболее важным из них является загрузка нашей модели qna.

Здесь мы применяем один трюк - использовать Object.freeze. Если вы не используете это, поскольку Vue использует оболочку для нашего объекта, Tensorflow выдаст ошибку, и вы не сможете передать или получить данные в требуемую модель.

Пришло время добавить этот метод в наш смонтированный жизненный цикл.

mounted() {
  this.loadModel()
},

Если вы выполните этот шаг, когда ваш компонент Helloworld проснется, вы увидите две консоли - Модель Qna и Объект Tensorflow -

Итак, следующим шагом будет передача и получение данных с помощью метода findAnswers нашей модели QNA.

Для этого мы создаем другой метод как answerQuestion, и он выглядит так:

async answerQuestion() {
  if(this.loadedModel !== null) {
    console.log('this.loadedModel : ', this.loadedModel);
    console.log('this.question : ', this.question);
    console.log('this.passage : ', this.passage);
    this.answers = await this.loadedModel.findAnswers(this.question, this.passage)
  }
}

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

После установки этих методов теперь нам нужно рассказать, как получить этот вопрос и передать часть нашей функции.

Мы будем использовать data () {} из Vue и хранить внутри пару переменных.

data() {
  return {
    loadedModel: '',
    answers: [],
    question: '',
    passage: ''
  }
},

Наши данные в компоненте выглядят так.

Теперь нам нужны элементы HTML для соединения этих переменных, чтобы они могли хранить данные, вводимые пользователем.

<div class="home">
 <div class="home__block">
   <h2>PASSAGE</h2>
   <textarea name="" id="" cols="30" rows="10" ref="passage" v-model="passage">
   </textarea>
 </div>
  
  <div class="home__block">
    <h2>QUESTION</h2>
    <input type="text" ref="question" @keyup.enter="answerQuestion" v-model="question">
  </div>

  <div class="home__block">
    <h2>ANSWERS</h2>
    <div class="home__block-answer" v-for="(answer, id) in answers" :key="answer">
      <span > {{ id + 1 }} : {{ answer.text }} ----- {{ answer.score }}</span>
    </div>
  </div>
  
</div>

Наш HTML выглядит так. Чтобы быстро понять, что здесь происходит, нам нужно понять наши требования.

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

Затем нам нужен элемент ввода, чтобы пользователь мог задать вопрос.

И, наконец, нам нужен наш блок ответов, в котором мы зацикливаем результаты, в этом случае ответы и печатаем их внутри нашего блока с их индексами и оценками.

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

Наконец, чтобы он выглядел немного лучше, мы можем использовать пару таких кодов scss.

.home {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

  &__block {
    margin-top: 30px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  &__block-answer {
    margin-top: 8px;
    font-size: 18px;
  }
}

textarea {
  border-radius: 8px;
  width: 600px;
  height: 300px;
  outline: none;
  padding: 12px 16px;
  font-size: 16px;
}

input {
  border-radius: 4px;
  padding: 18px 16px;
  width: 600px;
  font-size: 16px;
  outline: none;
}

h2, span {
  color: whitesmoke;
}

span {
  margin-top: 8px;
}

Это не лучшая практика использования css, но это не главное в нашей статье, поэтому этого будет достаточно.

Теперь, если вы обслуживаете свой проект, вы увидите результат на своем экране.

Я брошу здесь свою ссылку на репозиторий github, чтобы вы могли проверить весь проект.

Вы также можете посмотреть демо здесь.

Надеюсь, вам понравилось !!