Создаем чат-бот с элементами Natural Language Understanding

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привет! Меня зовут Анастасия Селезень, я Data Scientist в NIX. Я уже успела поработать с направлениями Computer Vision (Object Detection и Segmentation), а также с Natural Language Preprocessing and Understanding.

В этой статье я расскажу, как создать чат-бот с использованием NLU. Материал будет полезен опытным специалистам, которые интересуются направлениями NLU и NLP.

Тема NLU сейчас очень востребована. Данная технология обеспечивает взаимодействие человека с компьютером путем интерпретации естественного языка: она извлекает смысл текста и определяет контекст. Это позволяет компьютерам понимать команды без формализованного синтаксиса языков программирования. А это уже существенно упрощает и улучшает качество коммуникации человека с той или иной системой.

Опираясь на опыт из реального проекта, я расскажу об особенностях работы, тренировки и тюнинга моделей Question Answering и Passage Retrieval для обработки и понимания естественного языка. Также я покажу примеры использования фреймворков Haystack и Rasa и проведенные нами эксперименты. Вы увидите, с какими вызовами столкнулась наша команда в процессе написания бота и как мы их решали.

Почему мы выбрали Question Answering алгоритм

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

Сложность заключалась в следующих факторах:

  • было очень много файлов;
  • очень большой объем информации;
  • разные части документов ссылаются на другие части документов;
  • существуют похожие документы.

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

  • элементы интерфейса зависят от определенных значений в полях;
  • поиск ответов должен осуществляться с учетом контекста;
  • бот должен быть интегрирован в приложение и доступен вместе с документацией.

Поэтому сначала надо было выяснить, что позволит решить задачу, если на входе у нас файлы в HTML-формате с текстом. Идеальный вариант: если бы был человек, который прочитал все файлы и запомнил их, а потом был доступен 24 часа 7 дней в неделю для ответов на любые вопросы пользователей. Сами понимаете, такой сценарий невозможен. Но все это реально с помощью с машинного обучения.

Мы решили реализовать Question Answering алгоритм. С ним все происходит, как и с человеком: задаем вопрос в естественной форме и получаем от системы ответ в такой же естественной форме. После чего остается обернуть алгоритм чат-ботом, который и внедрить в приложение заказчика.

Важный нюанс: клиент просил позже добавить поддержку мультиязычности. Поэтому в статье рассмотрим украинскую версию чат-бота. В нашем случае это этап Proof of concept. Мы хотели убедиться, что возможно реализовать алгоритм для другого языка, не английского, и что сложности с отсутствием претрейнов удастся решить. Чтобы не раскрывать всех подробностей проекта, бот в этой статье будет основан на романе Льва Толстого «Война и мир». По сути это будет помощник в подсказках по книге. В оригинальном проекте у нас используется английский и поддержка других языков.

Способы реализации Question Answering алгоритма

Существует два подхода к созданию этого алгоритма: Knowledge Based и Information Retrieval Based. Здесь все, как у людей. Если вы зададите вопрос человеку, первым делом он ищет ответ в своей голове. Если он не найдет там ответа, то погуглит или посмотрит в книге. Точно так с алгоритмами машинного обучения. Мы в проекте решили опираться на принцип Information Retrieval. Причина: Knowledge Based требует специального формата датасета, а на его преобразование нужно время. С Information Retrieval все достаточно просто. На данной схеме показано, что алгоритм состоит из двух частей: Question Processing и Passage Retrieval. Сначала обратим внимание на первый, а о втором я расскажу позже.

Существует уже достаточное количество реализаций Question Answering алгоритма. Благодаря этому у нас нет необходимости писать его с нуля. Одна из популярных реализаций — от Facebook 2017 года. Однако у нее есть минус — она поддерживает только английский язык. Поэтому в нашем случае следовало искать альтернативы. Другой вариант — Bert 2019 года. Точность здесь немного лучше и, что важнее, поддерживаются другие языки. Потому мы выбрали именно эту версию.

Также для удобства мы использовали Haystack. Он предлагает удобную реализацию всех требуемых элементов для question-алгоритмов. Плюс он лицензионный, и у него есть совместимость с Transformers и подобными моделями.

Давайте разберем на примере, как работает эта модель «из коробки». Сначала проверим мультиязычную модель на английском. Зададим вопрос «What is the largest city in Germany?» с контекстом «Berlin is the capital and largest city of Germany by both area and population». С достаточно высоким скором мы получаем ответ «Berlin».

Языковая локализация моделей

А теперь посмотрим, как эта модель отработает на украинском языке. Зададим вопрос «Хто є видатним українським поетом?» с контекстом «Тарас Шевченко — це видатний український поет і художник». И ответ с наивысшим скором — «художник». То есть на украинском модель работает не лучшим образом.

Собственно, это и была первая проблема. Готовый алгоритм справляется с украинским языком плохо. На Hugging Face мы нашли натренированную модель Ukr Roberta Base, но не на Question Answering алгоритме, а на украинском датасете из «Википедии».

Исследования просторов интернета продолжились. Мы задались вопросом, можно ли натренировать эту модель на украинском Question Answering алгоритме. Оказалось, похожая работа уже есть. Ребята со Львовского католического университета перевели машинным переводом на украинский язык SQuAD Dataset — специальный датасет для тренировки Question Answering моделей. В их работе точность получилась около 60% Exact Match и около 80% F1 Score. Это послужило окончательным решением взять их переведенный машинным способом SQuAD и натренировать нашу «роберту». При этом тренировали мы ее не с нуля, а файнтюнили уже натренированную на «Википедии» модель. Правда, точность у нас получилась чуть ниже, чем у авторов. Однако это все равно достаточно быстро и приемлемо по результату.

Проверяем заново систему с тем же самым вопросом «Хто є видатним українським поетом?» с абсолютно тем же контекстом. Ответ с наивысшим скором — «Тарас Шевченко». Это уже более логично и правильно.

Работа с контекстами при Passage Retrieval

Passage Retrieval — это специальный алгоритм, который сужает область поиска контекстов. По сути он выбирает наиболее вероятные контексты, где может содержаться ответ на вопрос. Это упрощает работу Question Answering алгоритма. Существует много таких алгоритмов с разными подходами в основе. Их выбор зависит от типа решаемой задачи. Большинство из них также поддерживается в Haystack.

Мы выбрали Dense Passage Retrieval, поскольку он учитывает контексты в вопросах и ответах. Также на момент создания проекта это был state-of-the-art алгоритм. И еще он превзошел предыдущий алгоритм на 9–19%.

Однако и тут еще не все гладко: обнаружилась новая проблема. Dense Passage Retrieval основан на Query и Embedding моделях, заточенных под английский язык. Поэтому нам снова приходится тренировать модель. В процессе мы опять-таки брали за основу открытый ноутбук (файлы с кодом), который помогал нам. Важно отметить, что оригинальный датасет для DPR достаточно велик. Мы понимали, что датасет SQuAD не сильно подходит под тренировку, но все же взяли его. Ведь у нас он уже переведен на украинский. Хотя учтите, что в документации Haystack указано: лучше использовать оригинальный датасет и перевести его.

Оцениваем результат: с позитивными контекстами алгоритм справляется чуть хуже, чем с негативными. Это объясняется тем, что негативных контекстов больше, чем позитивных. Тем не менее, полученная точность нас на этом этапе устроила. Теперь мы имеем натренированные алгоритмы: QA question answering и Dense Passage Retrieval.

Построение архитектуры бота

В этой статье мы используем как пример роман «Война и мир» Льва Толстого. Главная причина: объем. Нам же нужно обработать очень много данных. При этом мы взяли перевод произведения на украинский язык. Для обработки информации мы шли по определенному сценарию. Сначала создали модуль с препроцессингом, где мы читали файлы.

Подробнее код можно посмотреть по ссылке.

Мы разбивали файлы на тома, на части и на главы и записывали эти файлы в Elastic Search хранилище. Ниже можете увидеть, как мы все записывали в наше хранилище. Потом мы из него и будем использовать их:

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

Теперь у нас есть данные, Question Answering алгоритм и DPR-алгоритм. Осталось все это объединить. Для этого мы применили фреймворк RASA, который имеет все необходимое для быстрой сборки всего воедино. Мы будем использовать одну историю с запросом, и у нас будет один action. Посмотрим, как это выглядит в коде.

Обращаемся к хранилищу с данными и загружаем DPR Retrieval. Далее устанавливаем параметры, которые будут необходимы, чтобы задать, сколько выдавать правильных ответов и в каком количестве текстов искать их:

Отмечу еще карусель, которая нам нужна для UI:

И еще есть класс QA, собственно, метод QA Request. В нем мы получаем топ-5 предикшенов с наивысшим скором и сортируем от лучшего к худшему. Затем в методе Run все это помещаем в карусель, чтобы было красиво для пользователя:

Соберем все получившееся в виде готовой архитектуры. Обработанные данные из «Войны и мира» хранятся в Elastic Search. Также есть натренированные QA-модель и DPR-модель, которые обращаются к данным и вытаскивают кусочки текста, где с наивысшей вероятностью хранится ответ. Также есть один action и UI.

Итоговая проверка: как улучшить результаты

Давайте теперь оценим, как это работает. Обращаемся к боту с вопросом: «Коли відбулася війна?». Тут отмечу: Haystack рекомендует использование GPU даже при работе с inference, потому что иногда поиск может занимать какое-то время. Из-за этого нам приходится немного подождать ответ.

Итог: карусель из ответов. Но какие они? Первый — «Зі вступу ворога у Смоленськ». Второй — «В тисячу сажнів». Далее идут ответы — «О другій годині дня», «22 жовтня», «Після сутички» и т. д. В общем, «22 жовтня» наиболее приемлем как ответ, хотя я не уверена в этом. Значит, еще есть возможности для улучшения нашего алгоритма. Как это сделать? Вариантов много.

Прежде всего можно использовать GPU даже для inference. Так как у нас только один worker и один elastic на одном instance для демонстрационных целей, то при масштабировании лучше увеличивать их количество. К тому же, еще DPR все-таки ожидает модель Bert, а не Roberta. Плюс стоит перевести оригинальный DPR датасет, чтобы качество подбора контекстов было выше.

Наш пример доказал: несмотря на то, что с современными возможностями NLU можно достичь хороших цифр, до совершенства еще далеко. Поэтому стоит постоянно искать новые решения, изучать их и экспериментировать. Только так мы сможем создать чат-бот, который будет точным и приближенным к живому, естественному общению.

👍ПодобаєтьсяСподобалось5
До обраногоВ обраному6
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

У приведенной реализации есть несколько слабостей, для данного примера вполне терпимых :) :малая обучаемая выборка, потому персептрон иногда может ошибаться
веса выбираются случайно, каждый раз при запуске, в идеале их нужно было бы сохранять после обучения, отсутствует обратный проход, после которого сеть корректирует свои веса и лучше адаптируется к новым данным
Если я что то неправильно понял, в данной реалиизиции поставленной задачи подкорректируйте меня

Аффтор жжет, вы про эту библиотечку слышали? Просто юзаете такое и все!neuroph.sourceforge.net
Питоша он очень медленный для подобного класса задач... Как только модель (или две модели) будет обучена, мы можем начать использовать их для индексирования и поиска вопросов и ответов? Ваш ретривер определил наиболее релевантные контексты для вашего вопроса.
Затем эти релевантные контексты передаются вашей модели читателя (или генератора), которая создаст ответ на основе контекстов далее ваш процесс вопросов и ответов завершен!Я правильно понял?Можно поподробнее про open-domain question answering (ODQA)?

Пиши свой пост, расскажешь чего «наюзал и всё». Потому что за естественными языками стоит мелочь: их недостаточно связывать, их нужно ещё и ранжировать. А это, как говорят медики, non penis canina.

Ты хотя бы русский матерный его научи понимать, тогда и поговорим. Не с тобой, разумеется, с ним.

Я еще с универом не разобрался, меня больше инетересовало мнение людей, которые уже как следует из статьи имеют богатый практический опыт использования подобных технологий. Каждая библиотека для решения специфических задач в программировании имеет свои плюсы и минусы.Например, DL4J использует сверточные, полносвязные и пулинговые слои, что позволяет реализовать практически любую архитектуру нейронной сети для глубокого обучения. Скорее всего если программировать с 0 нейронку, то данная реализация хорошё ложится на объектную модель и позволяет учесть особенности конкретной сети, чтобы использовать только те элементы, которые необходимы. Neuroph представляет графический интерфейс и упрощает создание архитектуры сети, давая возможность реализовать большинство известных типов нейронных сетей. Deeplearning4j позволяет решать задачи глубокого обучения, а также оптимизирует вычисления за счет использования распределенных ресурсов. Основой для выбора подхода является задача, которую необходимо решить.
Разработка нейронки на С и плюсах, как компилируемых, в отличии от питоши,конечно, имеют вынужденные сложности с разработкой, но java и прочие интерпретируемые строго типизированные языки при определеном размере кода могут быть проще в написании (IDE, как правило, проще работать с языками «построже»), и в сопровождении (проверки на уровне компиляции это хорошо — в слишком гибких языках regression можно отслеживать только тестами. Неподумайте что я против разработки через тестирование, TDD это неплохо, но когда тест надо писать на любой случай, чтобы ничего не крешанулось, то это так себе свойство языка). Единственное чего я не понял, почему удалили мои комменты из топика, шё ниже, я там никог не оскорблял...

Круто!

Зачем вы написали шё бы удалили мой коммент, я же там ничего не такого не написал, просто задавал уточняющие вопросы?

я нікому не писав, адміни самі видалили

Сокращу до смысла: «отложенный успех»

Підписатись на коментарі