Вопросно-ответная диалоговая система (чатбот)
Краткое описание
Чатбот позволяет вести беседы примерно такого вида:
Запуск чатбота в Telegram
Для запуска бота в Телеграме нужно зарегистрировать его у @botfather и получить токен.
Затем загружаем докер-образ и запускаем сервис такой командой:
docker run -it inkoziev/chatbot_v4 bash -c "/chatbot/scripts/tg_bot.sh"
После старта появится приглашение ввода токена и выбора профиля бота.
Архитектура бота
В состав нейросимвольного пайплайна входят следующие модели и программные компоненты:
-
интерпретатор на базе ruT5 для восстановления полного текста реплики в контексте диалога, исправления ошибок, нормализации - см. карточку модели на huggingface.
-
textual knowledge retriever - модель с архитектурой sentence transformer для подбора релевантных фактов в базе знаний и переписывания истории диалога, см. карточку модели на huggingface.
-
chitchat & reasoner на базе ruGPT для формирования текста ответа по найденному в базе знаний факту и заданному вопросу - см. карточку модели на huggingface.
-
детектор перефразировок на базе rubert-tiny для определения синонимичности двух предложений - см карточку модели на huggingface.
-
scripting engine - правила и сценарии для изменения и дополнения работы вышеперечисленных моделей.
Кастомизация чатбота, константы профиля
Используемая база знаний (в текущей реализации - plain text файл с фактами) указывается в профиле, который загружается при старте экземпляра бота. В скрипте tg_bot.sh можно увидеть указание на тестовый профиль profile_1.json, позволяющий боту отвечать на простые вопросы. В нем в качестве базы знаний указан файл profile_facts_1.dat. Формат этого файла описан в шапке файла.
Среди разных фактов там можно увидеть запись:
меня зовут $name_nomn
Конструкция $name_nomn означает
, что в строку при загрузке чатбота будет подставлена
константа с именем name_nomn, определенная в файле profile_1.json в разделе constants:
"constants": {
"gender": "ЖЕН",
"name_nomn": "Вика"
}
Так как имя бота может встречаться в нескольких местах, то удобнее задать имя в одном файле профиля.
Когда чатбот обрабатывает вопрос "Как тебя зовут?"
, он определяет, что факт меня зовут Вика
релевантен для ответа на заданный вопрос, и далее запускает процедуру построения
ответа с помощью генеративной модели читчата. Само имя "Вика" нигде не "зашито" в языковых моделях. Поэтому для его смены не нужно переобучать
нейросетки, а достаточно отредактировать данную запись.
Вторая константа с именем "gender" определяет грамматический род для бота, в данном случае женский. В том же файле фактов можно найти такую запись:
Я $chooseAdjByGender(нужен, нужна), чтобы отвечать на вопросы посетителей чата
Конструкция $chooseAdjByGender(нужен, нужна)
позволяет выбрать одно из перечисленных слов, фильтруя
их по константе грамматического рода. Таким образом, реплики бота становятся более релевантными
"биологической" природе бота.
Правила для управления диалогом
С помощью правил можно изменять или дополнять реплики, генерируемые нейропайплайном.
На данный момент движок поддерживает 2 типа правил.
greedy - эти правила срабатывают до генеративных моделей и в случае успешного применения полностью их заменяют.
smalltalk - эти правила запускаются параллельно генеративным моделям, порождаемые ими варианты реплики взвешиваются на уместность в текущем контексте вместе с репликами, сгенерированными читчатом.
Примеры этих правил можно увидеть в файле profile_rules_1.yaml.
Самое простое правило выглядит примерно так:
- rule:
name: "тестовое stateful правило с реакцией на фразу ку-ку"
if:
h: "* (куку/ку-ку) *"
then:
say:
phrases:
- "[(ну/да,/ага,)] ку-ку!"
Строка после тега h:
описывает требование к реплике человека-собеседника.
Описание представляет из себя выражение регулярной грамматики, похожей
на обычные регулярные выражения, но работающей со словами. В данном примере
символ *
означает произвольно длинную цепочку любых слов. Выражение (куку/ку-ку)
описывает альтернативы, каждый допустимый вариант отделяется от других символом /
.
Вариантов может быть сколько угодно много, любой вариант может быть в свою очередь паттерном. Глубина
вложения паттернов не ограничивается.
Среди других полезных конструкций в этих паттернах:
[subpattern]
- опциональность патерна
начал*
- проверка начала слова, обратите внимание на отсутствие пробела перед *
*снуть
- проверка окончания слова.
Ответные реплики перечислены в секции phrases
. Каждая реплика описывается шаблоном, в котором можно задавать
вариативные фрагменты:
[подшаблон]
- подшаблон будет с равной вероятность раскрыт или выкинут
(вариант1/вариант2)
- с равной вероятностью будет выбран один из вариантов вариант1
, вариант2
и т.д.
Обратите внимание, что правила работают с раскрытыми репликами собеседника, в которых подставлены анафоры, заполнены эллипсисы и т.д.
Датасеты
Некоторые данные, которые я собирал для обучения моделей в этом чатботе, доступны публично:
inkoziev/arithmetic - арифметические школьные задачи.
inkoziev/paraphrases - перефразировки коротких предложений и диалоговых реплик.