Проекты

Slack бот, который пишет стендапы сам!

Image for post
Image for post

Все началось с того, что в начале этого года, по интернету, пролетела волна тренда, по которому самой востребованной профессией, на 2019, год будет — Data Scientist (Специалист по работе с данными). Курсы стали как грибы расти в интернете, но большая часть из этих курсов стоит дорого, а толку мало. И я решил начать с курса от Яндекс и МФТИ. Пройдя первые две специализации, решил дальше не продолжать, так как понял, что знаний не хватает. Нужно их подтягивать. Сразу же определился для себя, куда я хочу двигаться. Так как меня совсем не заинтересовала работа с изображениями, ввиду необходимости в мощном железе и сложности внедрения в повседневную жизнь, я принялся за изучение более приближенного к реальности и более интересного для меня направления Обработка Естественного Языка, далее как NLP.

Про результаты применения полученных знаний в NLP, на примере бота для Slack и пойдет речь в этой статье.

Описание задачи

  • Вчера
  • Сегодня
  • Проблемы

В качестве основы для текстового корпуса использовать базу данных comedian. Боту необходимо генерировать авто-стендап, в определенное время. Уметь пропускать дни, по которым не нужно генерировать стендапы.

Немного о стендапах, что это такое и для чего нужно

Сферы применения NLP

  1. Анализ текста
  2. Генерирование текста
  3. Синтез речи

Анализ текста при этом включает следующие направления:

Задачи анализа и синтеза в комплексе:

О цикле поддержки приложения использующее NLP в своей работе

  1. Очистка и подготовка текстового корпуса для преобразования в структуру, которая будет удобна для анализа. Здесь используются подход WORM — расшифровывается как (Write-Once Read-Many или Записал один раз, прочитал много раз). Он берет свое начало с CD дисков, на которые запись происходила один раз, а читать можно было много раз, пока диск не будет испорчен или CD привод не накроется. Так как данных бывает очень и очень много, такой принцип хранения данных очень подходит. Обычно документы делятся по тематикам или по определенным признакам.
  2. Предобработка данных:
  • Токенизация — разбиение документа на предложения и отдельные слова.
  • Нормализация текста — приведение слова в нормальную форму, для того чтобы исключить повторное использование одного и того же слова, но в разных временах и формах множественного или единственного числа. Сюда можно отнести Стемминг или Лемматизацию.

4. Выбор модели

5. Подготовка данных для выбранной модели

  • Векторизация, Bag of Words (Мешок слов), Частотный словарь, Биграммы, Триграммы и так далее.

5. Обучение модели

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

Немного отступления и поправок

Для задач генерации текста, не нужен этап нормализации текста, так как при этом удаляются стоп слова, слова приводятся к нормальной форме, а для генерации текста нужны все части речи в предложений и стилистика написания, для того чтобы можно было подставлять следующие слова, в контексте предложения и последовательности слов. В этом случае можно генерировать очень даже неплохие и осмысленные предложения. Конечно, для того, чтобы генерировать более наполненные смыслом предложения, нужно увеличивать размерность n-грамм.

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

Image for post
Image for post
Помощник в генерации текста стендапа.
Image for post
Image for post
Еще один пример генерации стендапа, как видно выбранная моделька неплохо сохраняет контекст и выдает имена людей, у которых часто просят помощи.

Ну а далее, поговорим про шаги, предшествующие запуску бота в нашем #general канале Slack.

Подготовка данных для Бота Валеры

Получение данных из БД

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

Запрос на получение данных по стендапам

Дам некоторые пояснения:

  • channel_name — можно считать названием проекта
  • comment — текст стендапа
  • user_name — ник пользователя
  • user_id — идентификатор пользователя

Запрос можно составить и протестировать, хоть в консоле MySQL клиента или в MySQLWorkbench или Sequel Pro или DBeaver (Лучший визуальный инструмент для работы с БД).

Получение текстового корпуса из БД

Image for post
Image for post
И так, нажатием одной кнопки, можно экспортировать данные на диск в папки с названием проекта.

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

Сериализация текстового корпуса

Image for post
Image for post
Вот так выглядят результаты сериализации

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

Создание модели на основе n-грамм

Image for post
Image for post

Из рисунка выше, следует логичный вывод, чем выше N, тем больше контекста, в котором может использоваться последнее слово, сохраняется. Соответственно выбранные мной библиотеки и алгоритмы вполне нормально работают при N=3, а значит будут использоваться триграммы.

В интерфейсе, присутствует кнопка для создания модели триграмм. В ходе ее создания производится:

  • Загрузка скомпилированного корпуса в формате pickle.
  • Получение слов и предложений корпуса.
  • Создание частотного словаря на основе BOW (Bag of Words).
  • Создание модели триграмм на основе частотного словаря и предложений по всему корпусу.
  • Сериализация модели триграмм
  • Создание модели Кнесера-Нея на основе модели триграмм
  • Сериализация модели Кнесера-Нея

Эти все процессы хорошо видны в интерфейсе

Image for post
Image for post
Обучение и сериализация моделей триграмм и Кнесера-Нея

И как вы можете заметить, в нижней таблице, отображается список обученых и сериализованных моделей.

knm — модель Кнесера-Нея основана на сглаживание Кнесера — Нея (Kneser — Ney) использует частоту униграммы не саму по себе, а в отношении к n-­граммам, которые она завершает. Одни слова появляются в самых разных контекстах, но другие появляются часто и только в определенных контекстах их нужно интерпретировать по­-разному.

trigram_counts — модель на основе триграмм.

Генерация стендапа на основе модели триграмм и сглаживания Кнесера-Нея

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

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

Генерация стендапа осуществляется в отдельном приложении бота, которое использует сериализованные файлы моделей, загружая их в память при помощи все той же библиотеки pickle и метода pickle.load.

Проблемы при генерации текста

Так же нужно было убирать ссылки на тикеты, так как в любом случае не для всех они доступны и в целом не будут полезны в тексте стендапа.

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

Генерация трех составляющих стендапа

  • *Вчера*
  • *Сегодня*
  • *Проблемы*
Image for post
Image for post

Часть текста стендапа генерируется при помощи частотной модели триграмм, а часть на основе сглаживания Кнесера-Нея.

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

Как работает бот?

Image for post
Image for post
Схема работы бота

Сам бот размещается на Heroku, вместе с бинарной частотной моделью и моделью на основе сглаживания Кнесера-Нея.

Бот соединяется со Slack, компании, при помощи RTM соединения, основанного на веб-сокетах. Что позволяет отсылать в реалтайме сообщения и получать все события в момент их возникновения, без особых затрат на запросы и ответы как с веб-хуками. И отмечу сразу, такой способ очень хорош в планет того, что не нужно регистрировать точку доступа, смотрящую в интернет. Все без проблем работает и с локального хоста. Так как инициатором соединения является моя сторона, то сервер Слака, после установления соединения, без проблем можете передавать данные посредством установленного веб-сокетного соединения.

Firebase тут нужен лишь для хранения даты последнего стендапа, чтобы при перезапусках серверов на Heroku, не терять временную метку отправленного стендапа, что уберегает от повторной отправки стендапа в слак. Так как на Heroku эфемерная файловая система, в которой любые изменения, сделанные пользователем, теряются после перезагрузке контейнера. Поведение очень похоже на папку /tmp.

Бот в 9:00 утра по UTC+6 отправляет стендап в #general канал Slack.

Если же хочется, чтобы бот, сгенерировал стендап, то на этот случай есть фразы, для триггера генерации стендапа:

Image for post
Image for post
Фразы настраиваются через переменную окружения.
  • Валера стендап
  • 🔫 стендап
  • 🔫стендап (без пробела между иконкой пистолета и словом)

Так же наряду с фразами настраивается и время авто-стендапа и дни когда не нужно слать авто-стендап и необходимые для работы приложения параметры.

Image for post
Image for post
Общий вид настроек

Ну и сама демонстрация генерации стендапа по запросу

Image for post
Image for post
Пример генерации стендапа по запросу
Image for post
Image for post
Ну или вот такой забавный стендап
Image for post
Image for post

Нюансы деплоя на хероку приложений использующих NLTK библиотеку

Чтобы установить необходимые данные для NLTK библиотеки, необходимо проделать следующие шаги:

  • Установить переменную окружения NLTK_DATA со значением пути /app/.heroku/python/nltk_data. Этот каталог подходит для хранения данных.
  • Создать папку bin, в корне проекта.
  • В папке bin файл post_compile с командой по установке необходимых библиотек.

Еще один упрощенный способ, если нет необходимости устанавливать корпусы данных из нестандартных источников, то достаточно создать файл nltk.txt и в нем перечислить названия нужных словарей и данных для работы библиотеки, к примеру:

  • punkt
  • averaged_perceptron_tagger
  • averaged_perceptron_tagger_ru
  • wordnet
  • stopwords

Но у меня есть необходимость устанавливать данные из github. А вообще я столкнулся с реальной проблемой поддержки русского языка. Очень мало библиотек и данных позволяющих полноценно работать с русским текстом. По этой причине для скачивания библиотек мне потребовалось написать специальный downloader.

Код кастомного скачивальщика данных для nltk библиотеки

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

Image for post
Image for post
Папка nltk_data/tokenizers/punkt

Все копируется в папку nltk_data/tokenizers/punkt и необходимые подпапки.

Таким образом при помощи содержимого файла post_compile

происходит запуска скрипта на python для скачивания всех необходимых данных, а переменная окружения рулит пунктом назначения для установки данных.

Этот файл также пригодится и локально, так как автоматизирует процесс скачивания данных локально.

Заключение

Код бота и системы генерации моделей не выкладываю, так как он не очень хорошо оформлен и в принципе, при желании, примеры реализации легко гуглятся в интернете, решений для генерации текста — множество. Можете попробовать использовать LSTM сети для генерации текста, но в этом случае получается точное воспроизведение текста, что не хорошо, ведь проще выводить куски текста как есть. Ну а для разнообразия генерации можно придумать разные способы.

Посмотрев фильм “Большой хак” (Great Hack) от Netflix, еще раз осознал, что полученные знания и умения, по машинному обучению и Искусственному Интеллекту, а также безграничный доступ к данным пользователей, может быть использован в не очень хороших целях. Так что используйте свои знания в ИИ (AI) и МО (ML) с умом, руководствуясь этическими нормами. Хотя порой деньги и выгода перевешивают этику и нормы морали.

Спасибо за прочтение!

Mad Devs Blog — Custom Software Development Company

Engineering your growth. Mad Devs is the team behind large scalable projects, globally.

Thanks to Oleg Puzanov

Alexander Vishnyakov

Written by

«Переписывание с нуля гарантирует лишь одно — ноль!» — Мартин Фаулер

Mad Devs Blog — Custom Software Development Company

Mad Devs is a Cambridge-headquartered IT company developing enterprise-level software solutions for finance, transportation & logistics, security, edtech, and advertising industries. For more information about us, please browse our website: https://maddevs.io/

Alexander Vishnyakov

Written by

«Переписывание с нуля гарантирует лишь одно — ноль!» — Мартин Фаулер

Mad Devs Blog — Custom Software Development Company

Mad Devs is a Cambridge-headquartered IT company developing enterprise-level software solutions for finance, transportation & logistics, security, edtech, and advertising industries. For more information about us, please browse our website: https://maddevs.io/

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store