Сервисы
Алексей Оразов

Бот «Умный планировщик» — понимает с полуслова

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

Демонстрация работы "Умного планировщика"

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

Забегая вперёд, скажу, что этого удалось добиться, как и также парочки других приятных особенностей:

  1. Бот понимает слова с ошибками.
  2. Бот понимает голосовые сообщения.
  3. Бот умеет прикреплять файлы к напоминаниям.
  4. Бот может быть интегрирован в вашу Trello доску.

Если вам не терпится опробовать бота прямо сейчас, то вот ссылка на него.

Для всех остальных, кому интересно как 16-ти летний школьник смог написать его, я расскажу небольшую историю разработки и о том, как устроена система парсинга напоминаний внутри «Умного планировщика».

Краткая история создания

Бот был написан на Node.js. Почему? Просто потому что javascript в данный момент является одним из самых популярных языков программирования. Я также думал попробовать написать бота на Python или php, но я остановился на js, так как он обладает схожим синтаксисом с знакомым мне C++.

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

Я не буду рассказывать вам как работала эта «кривая» и топорная версия, которая была создана почти год назад. Лучше перейдём сразу к текущей стабильной версии.

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

Алгоритм работы бота следующий:

Проверка напоминаний сделана при помощи минутного таймера. На диаграмме эта часть обозначена «Планировщик задач». Он загружает все напоминания из базы данных, проверяет их время и если оно вышло, то уведомляет о них. Истёкшие напоминания удаляются

Изначально планировалось, что бот будет понимать русский и английский языки, поэтому я написал каждый ответ на двух языках. Для определения языка пользователя бот считает количество кириллических и латинских букв в тексте сообщения. Если кириллических больше чем латинских, тогда язык русский, иначе английский.

Для повышения безопасности я добавил шифровку текста напоминаний при помощи встроенной в Node.js библиотеки crypto.

База данных PostgreSQL

Выбор СУБД PostgreSQL обусловлен тем, что она бесплатна и изначально интегрирована в платформу Heroku, на которой хостится бот. В базе данных всего 3 таблицы: Пользователи, Чаты и Напоминания.

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

Извлечение даты

Процесс обработки сообщений пользователя разделён на два этапа: работу с числами и распознавание введённого напоминания.

Парсинг чисел

Прежде чем приступать к распознаванию времени, нам сначала нужно заменить все слова в строке, записанные в виде слов, реальными числами. Для этого я написал npm библиотеку parse-word-to-number. Она берёт строку и возвращает строку, в которой все возможные слова были заменены числами.
Для соотнесения фильтруемых слов из исходной строки с подходящими словами из словаря я использовал расстояние Дамерау-Левенштайна. Это позволяет библиотеке понимать слова, написанные с ошибками.

Особенности parse-word-to-number

Библиотека работает по такому алгоритму:

  1. Выбрать следующее слово в строке и найти его в словаре.
  2. Если оно найдено, то:
    ⠀⠀Если предыдущее слово это число:
    ⠀⠀⠀⠀Если разряд предыдущего числа больше текущего, то сложить текущее с предыдущим и соединить их.
    ⠀⠀⠀⠀Иначе если текущее число может быть умножено на предыдущее, то умножить текущее на предыдущее и соединить их.
  3. Во всех остальных случаях записать это слово в конец новой строки.

Она также поддерживает английский язык.

Распознавание текста и времени

Теперь, когда все числа в сообщении были заменены реальными числами, мы можем наконец извлечь описание времени из него. Для этого я написал ещё одну npm библиотеку date-parser. Она принимает строку и возвращает массив объектов класса ParsedDate (подробная информация в readme библиотеки). Каждый из этих объектов представляет собой одно событие и содержит в себе его дату и описание. Таким образом библиотека способна извлекать сразу несколько напоминаний из строки за раз.

Использование date-parser

Библиотека также поддерживает повторяющиеся напоминания и ограничения времени для них, как например: «Разминка каждые 30 минут до 8 вечера».

Процесс парсинга разделён на три стадии: упрощение, поиск и формирование.

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

(Слову "завтра" соответствует символ A, предлогу "в" – p, "6" – n, "вечера" – O. "Сходить" и "магазин" не были найдены в словаре – они помечены точками)

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

Поиск ключевых слов с помощью регулярных выражений

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

Описание формируется из оставшихся слов

Эта самая важная и основная часть парсинга. Настоящая библиотека date-parser устроена в разы сложней. Я не стал углубляться в технические нюансы, потому что этого алгоритма будет уже достаточно для мощного, но в то же время простого парсера даты.

Настройка часового пояса

Последняя, но не менее важная часть создания напоминаний это использование часового пояса. Для настройки часового пояса я сделал две опции.

Отправить геолокацию

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

Для определения часового пояса по долготе и широте бот использует сайт GeoNames.

Написать вручную

Или же, если вы используете Telegram с ПК, вы можете сами написать часовое смещение в формате ±ЧЧ:ММ.
Эта опция также доступна на мобильных устройствах.

Изменения в будущем

Даже имея столько полезных свойств, «Умному планировщику» ещё есть куда расти. В планах есть ещё множество улучшений, вот основные из них:

  1. Интеграция бота с Google календарём пользователя.
  2. Настройка индивидуального времени для неявных ключевых слов, как «утро», «день», «вечер» и «ночь».
  3. Улучшение интерфейса бот-человек при помощи замены большинства текстовых команд удобными встроенными клавиатурами.

Прочие мелкие доработки описаны в списке на Github’е проекта.

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

Спасибо за внимание, надеюсь у вас появится больше свободного времени с моим ботом!

З.Ы. Это перевод и адаптация моей статьи с английского языка. Оригинал вот.

{ "author_name": "Алексей Оразов", "author_type": "self", "tags": [], "comments": 66, "likes": 81, "favorites": 129, "is_advertisement": false, "subsite_label": "services", "id": 228652, "is_wide": false, "is_ugc": true, "date": "Mon, 05 Apr 2021 21:49:44 +0300", "is_special": false }
0
66 комментариев
Популярные
По порядку
Написать комментарий...
13

Алексей, жму руку, было очень интересно прочитать о Вашем проекте. И не слушайте критиков, которые говорят, что все уже придумано до нас. Даже если проект сам по себе и не выстрелит,  у Вас останется опыт и код в открытой репе, а это открытая дорога к успешной it-карьере, за Вас будут драться рекрутеры. А критики продолжат ныть в комментах :)

Ответить
6

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

Ответить
1

Большое спасибо!

Ответить
13

 Прикольно. Я пользуюсь стандартным IOS-овским.  Диктуешь ему и всё.  Никаких проблем. Единственное, надо выстраивать правильно предложение.

Ответить
0

Расскажите пожалуйста, вы имеете ввиду напоминания на иос? Или сири? Спасибо.

Ответить
2

У меня Iphone 8   Удерживая кнопку,  диктую Siri текст напоминания, время и дату.  он создает. Даже не нужно разблокировку делать. Очень удобно. По-крайней мере,  я очень  привык к этому. И не хочу менять айфон на выше, где этой кнопки нет.  

Ответить
1

Серьезно? Там где нет кнопки, можно просто вслух сказать "Hey, Siri" и спокойно диктовать напоминалку))

Ответить
0

 Да? )))). Спасибо, буду знать.  В настройках, наверное, надо включить это?

Ответить
0

Лучше загуглить, давно отказался от Айфона. Но вроде по умолчанию стоит

Ответить
–2

Просто убогая, не продуманная программа. К сожалению.

Ответить
0

Те кто минусит, вы че в танке? Вы реально используете родные напоминания iOS и типа счастливы и вас все устраивает?

Ответить
3

Зачем, если можно попросить напомнить Сири

Ответить
3

Никогда не видела людей без сири?

Ответить
3

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

Ответить
–3

Парень хотел влезть в тему, которая уже раскрыта - чего вы хотели? Если будет уровень выше, то его сделают Google

Ответить
4

Блин, чувак, только сегодня днём искал бота-напоминалку, но с поиске нашёл только который от клавиатуры. Потом сижу и думаю: Ну неужели нельзя сделать голосовой ввод задач? И тут - бац! И ты через пару часов публикуешь этот пост.
Ты реально посланник Вселенной!!!
Спасибо!

Ответить
3

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

Ответить
1

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

Ответить
0

Не совсем так на самом деле, если дата и время разделены в тексте - Todoist берет последнее для преобразования

Ответить
1

Ну пишите вместе
Это реально не проблема, учитывая удобство во всем остальном

У меня 20 проектов там, и в любом работают напоминания. С повторениями, автопереносами, и персональные данные не приходится отдавать абы кому

Представляю как перехожу с него на костыльного бота с одними напоминаниями и трепло доской :)

Ответить
1

Да, с этим я абсолютно согласен - в этом плане Todoist крутая штука, сам пользуюсь им и явно переходить на что-то другое пока не планирую.  Я просто отметил пример постановки задачи (напоминания) у бота и приложения, то что сам пакет date-parser не плохо реализован - добавил себе его в закладки. 

Думаю попробовать его применить к Алисе от Яндекс, чтобы там с помощью пакета реализовать распознавание даты и текста, и добавлять задачу в Todoist через их API :)

Ответить
2

Вот еще два бота для напоминаний:
@SkeddyBot Имеет веб админку
@remindmemegabot Можно добавлять в групповые чаты

Ответить
2

Да, я в курсе про них. Я уже сравнивал их функциональность с возможностями моего бота, результат приведен ниже:

Ответить
0

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

Ответить
1

Голосом не пробовал, а первый же тест текстом провалился. Написал "аптека в 9.00", а бот не понял чего хочу.

Ответить
0

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

Ответить
0

а у меня спросил время в которое напомнить. 

Ответить
0

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

А зачем было писать что-то свое? Неужели тысячи NLP либ на гитхабе не принесли результатов?)

Ответить
2

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

Ответить
0

такое мне всегда нравится. Спасибо за разъяснение)

Ответить
1

они вроде под python в большинстве своем или под js их так же активно штампуют?

Ответить
0

И правда, спасибо. Я увидел в начале Python, а про JavaScript традиционно не стал читать :))

На JS, из известных, есть библиотека Chrono как раз для этого, но в ней нет поддержки русского, если я правильно понял. Напрашивается PR вместо создания своего решения, кмк

Ответить
0

На айфоне проще сири пользоваться

Ответить
1

на Android - Google Assistant, но лично мне удобнее набить в телеге, например

Ответить
0

Указал время 19 00
Но бот почему-то зафиксировал в 18:59
Фича? Или баг?

Ответить
1

Склонен считать что не 18:59, а 06:59, ваше текущее время на скрине. Бот не распарсил 19 00 и указал текущее

Ответить
0

Хреновый бот значит)
Ничего зубодробительного в моей команде боту не было

Ответить
0

Просто кейс %число_число% не распознаётся ботом как определение времени. Я могу добавить поддержку для него, но боюсь, что его придётся отключить в групповых чатах, иначе бот может на не на те сообщения среагировать.

Ответить
0

Чисто моя боль, делюсь.

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

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

Как было бы удобно....
Пишет тебе кто то важный в телеге, ты читаешь сообщение, форвардишь это сообщение боту в телеге, бот быстро спрашивает когда напомнить. Интеграция с trello и всяким остальным уже вторична.

Ответить
1

Бот и это умеет.

Ответить
0

Форвардишь в saved messages + просишь Сири напомнить.

Ответить
1

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

Ответить
0

На андроиде нет возможности голосом назначить оповещение?

Ответить
0

не пользуюсь сири вообще, но идея хорошая, попробую.

Ответить
0

Я Сири как раз пользуюсь для напоминаний таких и установки таймера. Очень удобно.

Ответить
0

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

Ответить
0

Так почему в обед, а не после работы?

Ответить
0

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

Ответить
0

А чем отличается от @remindmemegabot ?
Им пользуюсь уже 2 года

Ответить
–1

Отличия Умного планировщика от бота RemindMe, а также Skeddy приведены тут:

Ответить
0

Вапщет у ремаинда есть часть этих функций

Ответить
1

Разве что поддержка английского языка, но разработчики зачем-то вместо одного бота сделали 2 отдельных для русского и английского языков.
Остальные функции не поддерживаются:

Ответить
0

Спасибо за труды!Буду следить за твоей работой😎

Ответить
0

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

Ответить
0

Почему часть вопросов на русском, часть на англ?

Ответить
0

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

Ответить
0

Моего личного телеграмм-канала нет, но есть телеграмм-канал, посвященный боту: https://t.me/SmartScheduler_Info

Ответить
0

Что нужно 👍

Ответить
0

Автор молодец в любом случае.
Ну и если позволяет время и ресурсы, я советую проект не бросать и нащупать свою нишу. Тем более как показывают комментарии в целом такие функции востребованы.
Единственное что отмечу, таки написание своих библиотек крайне нежелательно (случаи, когда цель обучение я не беру в расчёт), вы таким образом сами себе делаете медвежью услугу. Нужно отвлекаться на баги, костыли, фичи вместо разработки основного продукта. Лучше начать принимать участие в развитии уже какого-нибудь готового и хорошего опенсурс решения, если уж хочется. а свои велосипеды, почти всегда не имеют смысла.

Ответить
0

Спасибо за совет, учту, бота бросать не планирую.

Ответить
0

Отправил задачу утром, а получается из будущего в прошлое:)

Ответить
0

Машина времени исправлена, спасибо за баг-репорт.

Ответить
0

/2. 8 Апреля 17:05 (четверг) "0 9 0 0 анализ найти"

Говорю 8 апреля 0900 анализ найти. Почему 17:05

Ответить
0

бот просто супееер
ращраб, ты крутой :3

Ответить

Комментарии

null