?

Log in

No account? Create an account

Компьютерная лингвистика

Новостная лента www.solarix.ru

Previous Entry Share Next Entry
Большой рефакторинг чатбота: все правила в одном файле и модель определения intent'ов
kelijah
В репозиторий https://github.com/Koziev/chatbot залита текущая версия чатбота с множеством изменений и исправлений.

Правила для чатбота

Среди главного - все правила теперь в одном YAML-файле rules.yaml

Почему в качестве формата выбран yaml?
Я взвесил + и - трех альтернативных подходов.

1) Полностью свой формат, разбираемый каким набором инструментов для контекстно-свободной грамматики. Я так делал в предыдущих проектах на C# и C++. Достоинство подхода - можно делать красивую грамматику, не упираясь в ограничения XML/json/yaml форматов.

2) XML, JSON или YAML в качестве формата. XML по понятным причиным отпадает, хотя лет 10 назад я и видел сторонние "языки" на базе XML представления, и сам делал. Неудобно. JSON гораздо лучше. Но балансировать фигурные скобки без хорошего текстового редактора неудобно, а иногда даже подсветка не помогает. YAML гораздо читабельнее и проще в редактировании, на нем и остановился.

3) Зачем придумывать новый язык для записи правил, если уже есть Питон и его средства для динамического выполнения кода, например штатная либа parser? Самый большой минус по результатам экспериментов - слишком сильная завязка на контекст выполнения (надо знать имена переменных, через которые передается входная информация для питоновского кода), плюс некоторые неприятности с юникодными строками.

Порядок описания различных правил описан комментариями прямо в rules.yaml, там же сейчас есть рабочие простые примеры. Например, если в текущем релизе ввести вопрос "Какая сейчас погода", то увидим:

H:> какая сегодня будет погода
B:> Прогноз погоды сгенерирован в функции on_weather_forecast для демонстрации


Ответ бота просто сгенерирован функцией weather_forecast в модуле console_chatbot.py, вызываемый из правила в rules.yaml. Предполагается, что после введения модели определения entities это правило будет учитывать дату и место для прогноза.

Порядок применения правил

1) Если есть история диалога (>1 реплики), то реплика собеседника прогоняется через модель интерпретации для восстановления полной фразы, раскрытия анафоры, гэппинга и т.д.

2) Среди comprehension правил (секция comprehensions в rules.yaml) ищется достаточно близкий вариант фразы в if блоке. Если правило нашлось, то вместо исходной фразы дальше будет обрабатываться then-фраза из найденного правила. Таким образом
выполняется нормализация. Например, императивная реплика "Доложи погоду на завтра!" может быть нормализована в вопросительную форму "Какая завтра будет погода?".

3) Определяется intent с помощью обученного на датасете data/intents.txt классификатора. Датасет сейчас крошечный, но его можно легко расширять своими правилами и переобучать модель - см. далее.

4) Определяется грамматическая модальность - является ли реплика вопросом, утверждением или приказом.

5) Для приказов: пытаемся найти правило для обработки (секция rules в rules.yaml) и выполняем его. При поиске используется либо
определенный intent (if-часть содержит ключевое слово intent), либо проверяется синонимичность с помощью модели синонимичности. Если правило не найдено, то вызывается дефолтный обработчик - пользовательская функция, зарегистрированная в on_process_order. Если и он не обработал приказ, то будет сказана фраза "unknown_order" в rules.yaml

6) Для утверждений: пытаемся найти правило обработки (секция rules в rules.yaml) и выполнить его. Далее, факт сохраняется в базе знаний. Наконец, пытаемся найти smalltalk-правило: это правило в группе rules (rules.yaml), в котором опорная часть (if) и результативная часть (then) заданы с ключевым словом text. Ищется правило, в котором опорная часть максимально синонимична
входной фразе, если найдено - чатбот скажет фразу, которая указана в then-ветке.

7) Для вопросов: сначала проверяется, нет ли похожего (модель синонимичности) вопроса среди FAQ-правил (файл faq2.txt). Если есть - выдается содержимое найденного FAQ-правила. Иначе начинается процедура генерации ответа. С помощью модели релевантности (см. отдельный раздел про ее дообучение и валидацию) ищутся максимальной релевантные предпосылки в файлах premises*.txt. Если не найдена достаточно релевантная предпосылка, то выдается фраза "no_relevant_information" из rules.yaml.

В ходе генерации ответа может потребоваться ответить "да" или "нет". Эти фразы находятся в rules.yaml в разделе "answers".

Верификация модели синонимичности

С помощью скрипта scripts/query2_lgb_synonymy.sh можно искать примеры неверной работы модели синонимичности. В консоли вводится фраза, для которой модель вычисляет похожесть к набору фраз из датасетов. Результаты, ранжированные по убыванию похожести, выводятся в консоль. Если среди найденных фраз с похожестью > 0.5 есть явно ошибочные, их можно внести как негативные примеры (в файл paraphrases.txt или в собранный датасет synonymy_dataset.csv), затем переобучить модель скриптом scripts/train_lgb_synonymy.sh

Модель определения intent'а

С помощью модели intent'а можно присвоить фразе собеседника одну метку из набора возможных и далее обрабатывать фразу
с учетом этой метки правилами (раздел rules в rules.yaml).

Данные для обучения находятся в текстовом файле data/intents.txt. Его формат прост и описан в комментарии в начале файла.

После модификации этого файла необходимо собрать датасет с помощью PyModels/preparation/prepare_intents_dataset.py, затем
запустить обучение классификатора с помощью scripts/train_intent_classifier.sh