Я всегда скептически относился к чат-ботам. Когда-то они были на хайпе. Говорили, что это новый UI – он же No UI. Но я всегда утверждал, что пользователю проще и быстрее все действия сделать через сайт, а не играть с ботом в вопрос-ответ. Каково же было моё удивление, когда через несколько лет я сам буду пропагандировать чат-ботов всем моим друзьям - backend-разработчикам? В данной статье расскажу, как я до этого дошел.
Каждый раз, когда я задумываю pet-project, в полный рост встаёт вопрос, как реализовывать пользовательский интерфейс. Честно признаюсь, я умею во фронтенд. Умею вот в эти ваши JavaScript. Знаком даже с React.js. Но так уж вышло, что специализируюсь на серверной разработке, и UI по-взрослому касаюсь очень редко, наскоками. Поэтому реализация UI у меня всегда как в первый раз. Вероятно из-за этого многие задуманные мною pet-project’ты так и остаются на уровне идеи… С этим нужно было что-то делать.
Как чат-боты уже упрощают работу целой социальной платформе
Осенью 2021 года, я присоединился к платформе Strike, которая помогает с самоорганизацией и профсоюзной деятельностью. Вся платформа крутится вокруг чат-бота в Telegram. Никаких сайтов - только чат-бот. И, черт возьми, какое же это было простое и, по своему, элегантное решение. Ничего космического и технически передового в этом боте не было. Но он эффективно решал поставленную задачу - учить людей самоорганизации и борьбе за свои трудовые права.
И тут меня осенило… Это ведь можно, совершенно не влезая во всякие фронтенды, сделать полноценный сервис! Изучив вопрос лучше, я с удивлением обнаружил богатые возможности в Telegram для реализации ботов (в сравнении с другими мессенджерами). Тут тебе и просто кнопки, и inline-кнопки. И текст можно вводить. И файлы посылать. А с недавних пор можно и JavaScript засунуть! В общем, всё что нужно для эффективной коммуникации.
Конечно, Telegram это жесткий vendor lock. Все мы знаем, что привязываться к какой-то определённой платформе не очень здорово. Но, как говорится, колхоз - дело добровольное. Это компромисс, на который я сознательно пошел.
Мне захотелось самому реализовать какого-нибудь бота, который был бы полезен платформе Strike. Я поинтересовался, какие у платформы есть проблемы. Как оказалось, у Strike’a есть внутри целый юридический отдел, который помогает с трудовыми спорами. Там работают волонтеры и, как и в любом волонтерском деле, людей порой не хватает. Посему, любая автоматизация рутинной работы тут была бы очень кстати. Мы обсудили несколько идей с Андреем Чируком, руководителем юр отдела платформы Strike, и остановились на идее бота, который умел бы составлять исковые заявления. Для меня был неожиданностью тот факт, что составление искового заявления отнимает у юриста несколько дней! Если упростить этот процесс с помощью бота - это бы значительно сократило трудозатраты юр отдела Strike.
Первый этап: декомпозиция задачи
Как известно, прежде чем начинать любую реализацию программного обеспечения нужно подумать. Необходимо пообщаться с экспертом в той области, для которой это ПО и разрабатывается. Привет Domain Driven Design! По прошествии нескольких итераций вопросов-ответов, я стал лучше понимать доменную область. Изначально мы хотели реализовывать функционал только для узкого числа исковых заявлений - исключительно по трудовым спорам. Потому как такова специфика платформы Strike. Но чем больше мы разбирались с доменной зоной, тем больше понимали, что можно сделать лучше и не прибивать всё жестко гвоздями. В итоге нам с Андреем удалось декомпозировать любое исковое заявление на шесть частей, которые и должен заполнить пользователь. А именно:
Шапку заявления, где указываются реквизиты истца и ответчика.
Фабулу, где описывается ситуация в хронологическом порядке.
Суть нарушения, где истец указывает, почему он считает, что его права нарушены.
Доказательства, подтверждающие нарушение прав истца.
Требования истца к ответчику.
Приложение.
![декомпозиция искового заявления декомпозиция искового заявления](https://habrastorage.org/getpro/habr/upload_files/37d/dcd/35b/37ddcd35b5486483229ffd1cd7dfaf55.png)
После заполнения всех разделов, пользователь сможет получить сгенерированное исковое заявление в виде *.docx документа.
Приятный side-effect от грамотной декомпозиции задачи
Одним из результатов декомпозиции искового заявления на составные части стала возможность создания шаблонов для различных типов исковых заявлений. А не только по трудовым спорам, как планировалось изначально.
// Фрагмент шаблона для искового заявления
{
"theme" : "восстановление на работе",
"story" : {
"examples" : [
"инженер",
"{end_work_date} приказом №2 от {end_work_date} я был уволен на основании пп. 'а' п. ст.81 Трудового кодекса Российской Федерации за прогул."
],
"actions" : [
"enter_end_date",
"enter_avr_salary"
]
},
…
}
Эти шаблоны описываются в JSON файлике с определённой схемой. Бот, опираясь на данные из шаблона, спрашивает те или иные вопросы в зависимости от типа искового заявления. Сейчас командой юристов платформы Strike составлено два шаблона исков для наиболее часто встречающихся трудовых споров. Это исковое заявление о “восстановлении на работе” и о “взыскании заработной платы”. В планах добавить другие шаблоны. Каждый может попробовать составить свой шаблон и прислать его нам, создав Pull Request. А мы уже попробуем интегрировать его в бота. Документация, как описывать шаблон, доступна на github в репозитории проекта.
Этап второй: реализация
Сама реализация бота заняла не так много времени - около двух месяцев работы по 1-2 часа в свободное время. И даже не каждый день. По техническому стеку использовал то, что умею готовить. В качестве основы: Python + aiogram (фреймворк для Telegram ботов), в качестве БД - mongoDB. Всё это дело погружено на docker контейнеры, и поднимается с помощью docker-compose. Минималистичный джентльменский набор. При этом я ни разу не прикасался к JavaScript (брр…). Но это не значит, что пользовательский интерфейс бота - это чисто текстовый ввод и вывод. В процессе разработки я придумал\прикрутил несколько интересных велосипедов. После всех этих, казалось бы косметических улучшений, интерфейс бота стал более дружелюбным к пользователю.
Первое, что я придумал, это использовать эмодзи на кнопках. Это, по моему мнению, пошло на пользу UX. Ведь одного взгляда на кнопку с эмодзи хватает, чтобы понять, какое действие за ней стоит. Ну и как приятный бонус - так проще в коде писать регулярки для распознавания команд.
![навигация стала гораздо нагляднее навигация стала гораздо нагляднее](https://habrastorage.org/getpro/habr/upload_files/b9b/f85/7f2/b9bf857f23d3226a73954eb51285a19f.png)
Второе улучшение, которое я подсмотрел в github репозитории aiogram_calendar, это отрисовка виджета календаря с помощью inline-кнопок. Пришлось немного адаптировать исходный код под свою задачу, но результат меня очень порадовал. Я снял с себя кучу головной боли по парсингу дат из текста! Вместо этого пользователь просто жмакает на кнопку, и ему даже нотификация о действии приходит!
![пример работы виджета календаря пример работы виджета календаря](https://habrastorage.org/getpro/habr/upload_files/0a9/0c1/93b/0a90c193bc8b9e5bd96f61c5db9dc495.gif)
Отдельно стоит упомянуть про подсказки-примеры. В процессе общения с ботом, пользователь вводит какие-то данные. Например, размер своей заработной платы. Или должность. А потом бот просит пользователя описать, почему он считает, что его права нарушены. И если жмакнуть по кнопке примера, то бот покажет пример ответа с уже подставленными пользовательскими данными. Этот пример можно в большинстве случаев использовать в качестве ответа, так как ситуации достаточно стандартные в рамках одного типа искового.
Ну и конечно во многих случаях бот предоставляет список вариантов ответа (например, список доказательств). Пользователю остается только выбрать необходимые. Или ввести свои - по ситуации.
![пример выбора опциональных значений (список доказательств пример выбора опциональных значений (список доказательств](https://habrastorage.org/getpro/habr/upload_files/996/13c/cf8/99613ccf828ae93236f1d2244e14b9a6.png)
Этап третий: 3 полезные фичи
Одной из киллер-фич бота является поиск суда, в который пользователь должен направить исковое заявление после заполнения. Суд подбирается в данном случае на основе адреса истца (т.е. пользователя). Под капотом идет обращение к API ГАС “Правосудие”. Но есть нюанс - работает оно хорошо только для крупных городов. В лучшем случае районных центров. Как говорится, дареному коню в зубы не смотрят.
Для некоторых исковых заявлений нужно прилагать дополнительные расчеты. Например, расчет компенсации за задержку выплат по заработной плате. Бот генерирует такой расчет автоматически, основываясь на данных, введенных пользователем. Это очень нетривиальная задача, если производить расчеты самому. За это я получил отдельный респект от юридического отдела Strike.
Еще одной малозаметной, но исключительно важной фичей, является подстановка введенной пользователем информации в нужном падеже с необходимым окончанием. Реализовано это под капотом с помощью библиотеки pymorphy2.
Этап четвертый: работа с персональными данными
Когда ты делаешь подобный сервис, в полный рост встаёт вопрос о работе с персональными данными. Исковое заявление содержит их в полной мере. При заполнении заявления бот спрашивает у пользователя его ФИО, адрес и ИНН. Пользователь может ввести любые данные, даже абракадабру, и потом поправить их на валидные в уже сгенерированном документе. Это такой хак для параноиков. Исключение тут составляет адрес. Как я уже упоминал ранее, по нему происходит поиск суда для подачи заявления. Но и тут предоставляется возможность ввести всё что угодно, а затем указать суд самостоятельно.
Для подачи заявления в суд, исковое заявления должно содержать дату и место рождения истца, а также паспортные данные. Мы с Андреем решили, что эта информация очень чувствительная и просто отметили место (жирненько и красненько) в сгенерированном файле, куда их нужно ввести уже после общения с ботом.
Все персональные данные так или иначе хранятся в зашифрованном виде. И лишь в течении двух часов. Потом специальный демон чистит базу.
Заключение: Telegram бот отличный выбор для pet-project
Работа над этим проектом принесла мне массу позитивных эмоций. Я открыл для себя мир telegram ботов, где для реализации приложения не нужно знать кучу фреймворков, которые устаревают быстрее, чем ты их изучаешь. Мир, где для апробации идеи нужно всего несколько вечеров.
Конечно, все мои аргументы в пользу “взрослых” приложений в начале статьи никуда не делись. Я по прежнему считаю, что полноценный сайт лучше бота. Но если ты backend разработчик и тебе хочется реализовать что-то посимпатичнее CLI тулзы - присмотрись к telegram боту. Возможно тебе его будет достаточно. А если идея взлетит - всегда можно найти специально обученного человека для UI.
P.S. Данная статья написана по горячим следам моего выступления на форуме, который был посвящен самоорганизации. Там, помимо моего выступления, можно найти много другой, не ИТ-шной, но актуальной годноты.
P.P.S. Ссылка на бота-истца (не дай бог кому пригодится).