/chatbot

Русскоязычный генеративный чатбот с профилем и фактами

Primary LanguagePython

Вопросно-ответная диалоговая система (чатбот)

Краткое описание

Чатбот позволяет вести беседы примерно такого вида:

диалог с чатботом в телеграмме

Запуск чатбота в Telegram

Для запуска бота в Телеграме нужно зарегистрировать его у @botfather и получить токен.

Затем загружаем докер-образ и запускаем сервис такой командой:

docker run -it inkoziev/chatbot_v4 bash -c "/chatbot/scripts/tg_bot.sh"

После старта появится приглашение ввода токена и выбора профиля бота.

Архитектура бота

В состав нейросимвольного пайплайна входят следующие модели и программные компоненты:

  1. интерпретатор на базе ruT5 для восстановления полного текста реплики в контексте диалога, исправления ошибок, нормализации - см. карточку модели на huggingface.

  2. textual knowledge retriever - модель с архитектурой sentence transformer для подбора релевантных фактов в базе знаний и переписывания истории диалога, см. карточку модели на huggingface.

  3. chitchat & reasoner на базе ruGPT для формирования текста ответа по найденному в базе знаний факту и заданному вопросу - см. карточку модели на huggingface.

  4. детектор перефразировок на базе rubert-tiny для определения синонимичности двух предложений - см карточку модели на huggingface.

  5. 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 - перефразировки коротких предложений и диалоговых реплик.