Цель этой статьи - дать обзор типичной архитектуры для создания диалогового чат-бота с ИИ. Мы подробно рассмотрим архитектуру и соответствующие компоненты (Примечание - Архитектура и терминология, упомянутые в этой статье, в основном основаны на моем понимании программного обеспечения с открытым исходным кодом rasa-core).

Итак, приступим к делу ...

Как видно из названия этой статьи, основные аспекты:

  1. Это чат-бот. Для простоты в этой статье предполагается, что пользователь будет вводить текст, а бот ответит соответствующим сообщением в виде текста (Итак , нас не будут интересовать такие аспекты, как ASR, распознавание речи, преобразование речи в текст, преобразование текста в речь и т. д. Архитектура, приведенная ниже, в любом случае может быть улучшена с помощью этих компонентов при необходимости).

2. Это разговорный! - Что это значит? Бот должен каким-то образом поддерживать состояние разговора и отвечать на запрос пользователя в текущем контексте (иначе говоря, он должен учитывать контекст). Например, допустим, поток разговора выглядит примерно так:

  • Пользователь - какая погода будет завтра?
  • Бот - будет облачно, небольшой дождь.
  • Пользователь - как насчет послезавтра? (Таким образом, когда задается этот вопрос, бот должен помнить, что недавний контекст этого разговора касается сущности «погода» (а не чего-то еще, например, пробок на дорогах или доступности бронирования, если они присутствовали в предыдущие беседы).

3. Это архитектура, управляемая AI / ML: модель изучает действия на основе предоставленных обучающих данных (в отличие от традиционной архитектуры на основе конечного автомата, которая основана на кодировании всех возможных if-else условия для каждого возможного состояния разговора.)

Вот общий обзор такой архитектуры для чат-бота.

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

  1. Нам нужно знать намерения пользователя - мы назовем это намерениями. Несколько примеров намерений - «request_weather», «request_restaurant» и т. Д. Намерение в приведенном выше примере - «request_weather».
  2. Нам нужно знать конкретные намерения в запросе (мы будем называть их сущностями), например, ответы на такие вопросы, как когда ?, где ?, сколько ? и т. д., которые соответствуют извлечению информации из запроса пользователя о дате, времени, местоположении, номере соответственно. Здесь datetime, location, number - это объекты. Цитируя приведенный выше пример погоды, сущностями могут быть datetime (информация, предоставленная пользователем) и местоположение (примечание - местоположение не обязательно должно быть явным вводом, предоставленным пользователем, и будет определяться из местоположения пользователя по умолчанию, если ничего не указано) .

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

Теперь обратитесь к приведенному выше рисунку. Поле, представляющее компонент NLU ( Natural Language Understanding ), помогает в извлечении намерения и сущностей из запрос пользователя.

Компонент NLU состоит из -

  • Модель классификации намерений с учителем, которая обучается на различных предложениях в качестве входных данных и намерениях в качестве цели. Как правило, в качестве модели классификации намерений достаточно линейной SVM.
  • Модель извлечения сущностей - это может быть предварительно обученная модель, такая как Spacy или StanfordNLP library (OR), ее можно обучить с использованием некоторых вероятностных моделей, таких как CRF (условные случайные поля).

3. Теперь, поскольку наш бот является диалоговым ИИ-ботом, нам нужно отслеживать разговоры, которые произошли до сих пор, чтобы предсказать соответствующий ответ. Для этой цели нам нужен объект словаря, который может быть сохранен с информацией о текущем намерении, текущих сущностях, сохраняемой информации, которую пользователь предоставил бы на предыдущие вопросы бота, предыдущее действие бота, результаты вызова API (если таковые имеются). Эта информация будет составлять наш входной X, вектор признаков. Целевым y,, которому будет обучена модель диалога, будет 'next_action' ( next_action может быть просто вектором с горячим кодированием, соответствующим каждому действию, которое мы определяем в наших обучающих данных).

Тогда это подводит нас к следующему вопросу - как получить обучающие значения для нашего вектора признаков, введите X?

  • Получение информации о намерении и сущностях несложно, как мы видели из компонента NLU.
  • Получение оставшихся значений (информация, которую пользователь предоставил бы на предыдущие вопросы бота, предыдущее действие бота, результаты вызова API и т. Д.) немного сложно, и здесь компонент диспетчера диалогов берет на себя . Эти значения функций необходимо будет извлечь из обучающих данных, которые пользователь определит в форме примеров разговоров между пользователем и ботом. Эти образцы разговоров должны быть подготовлены таким образом, чтобы они охватывали большинство возможных разговоров, притворяясь одновременно пользователем и бот.

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

Я не буду вдаваться в подробности извлечения каждого значения функции здесь. На него можно сослаться из документации по ссылке rasa-core, которую я предоставил выше. Итак, предполагая, что мы извлекли все необходимые значения функций из примеров разговоров в требуемом формате, мы можем затем обучить модель ИИ, такую ​​как LSTM, а затем softmax, для прогнозирования next_action. На рисунке выше это то, что делает компонент управление диалогом. Почему LSTM более уместен? - Как упоминалось выше, мы хотим, чтобы наша модель учитывала контекст и просматривала историю разговоров, чтобы предсказать next_action. Это похоже на модель временных рядов (пожалуйста, см. мою другую статью LSTM-Time series) и, следовательно, лучше всего может быть зафиксировано в состоянии памяти модели LSTM. Объем истории разговоров, который мы хотим просмотреть, может быть настраиваемым гиперпараметром модели.

Теперь прогнозируемое значение next_action может быть примерно таким:

  • Ответьте пользователю соответствующим сообщением
  • Получить некоторые данные из базы данных (если она у нас есть)
  • Выполните вызов API и получите результаты, соответствующие намерению.

Если это вызов API / получение данных, то дескриптор потока управления останется в компоненте «управление диалогом», который в дальнейшем будет использовать / сохранять эту информацию для прогнозирования next_action, еще раз. Диспетчер диалогов обновит свое текущее состояние на основе этого действия и полученных результатов, чтобы сделать следующий прогноз. Как только next_action соответствует ответу пользователю, берет на себя компонент «генератор сообщений».

Компонент Генератор сообщений состоит из нескольких пользовательских шаблонов (шаблоны - это не что иное, как предложения с некоторыми заполнителями, в зависимости от ситуации), которые сопоставляются с именами действий. Таким образом, в зависимости от действия, предсказанного диспетчером диалога, вызывается соответствующее сообщение шаблона. Если шаблон требует заполнения некоторых значений-заполнителей, эти значения также передаются диспетчером диалогов в генератор. Затем пользователю отображается соответствующее сообщение, и бот переходит в режим ожидания, ожидая ввода пользователя.