Как мы разрабатывали бота в мессенджере eXpress для 1-й линии поддержки

Привет, уважаемые читатели Хабра!

На связи Лаборатория инноваций Московской биржи.

Хотим поделиться с вами нашим опытом разработки чат-бота для 1-й линии поддержки на базе корпоративного мессенджера eXpress.

Расскажем о нашем опыте, ошибках, сделанных выводах и поделимся полезными ссылками для желающих заняться разработкой ботов для eXpress.

Примечание: учтите, что доступ к ботам в eXpress предоставляется только корпоративным клиентам.

Итак, приступим.

В компаниях с 0 толерантностью к риску, таких как Московская биржа, даже самые простые инициативы требуют специального подхода, внимательного рассмотрения и согласования со Службой информационной безопасности (далее по тексту — СИБ) каждого этапа.

Нашей команде поступила задача купить/придумать/разработать простой инструмент, который позволил бы бизнес-пользователям, у которых нет прямого доступа к корпоративному тасктрекеру (далее по тексту ТТ), получать статус по своим заявкам без необходимости дополнительного обращения к первой линии поддержки. Изначально мы рассматривали возможность использования телеграм-бота, но выяснилось, что такое решение не подходит по ряду технических причин:

  1. Оно должно быть доступно из контура, откуда нет свободного выхода в интернет.

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

Вместо этого мы приняли решение разработать бота в eXpress. Их бот-платформа схожа по архитектуре с Телеграмом. Учитывая популярность языка Python и его обширное использование в различных областях, для написания бота мы выбрали именно его. Мы также рассчитывали на активное сообщество специалистов и доступный бюджетный фонд, ведь нашей целью была реализация MVP и передача бота заказчику в течение нескольких недель.

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

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

Схема бота

Схема бота

Т.к. мы хотели напрямую из бота ходить по API к нашему ТТ и забирать данные о заявках, это стало серьёзным ограничением как с точки зрения СИБ, так и с точки зрения самой реализации. В ходе переговоров и чтения документации выяснилось, что API ТТ не готов отдавать нам всё, что было нужно для данного кейса, и требовалось потратить несколько недель на выполнение доработок. Нас это не устроило и поэтому, на смену работы с ТТ по API, пришло решение работать через представления в БД (оказалось, это куда проще и безопаснее сделать) и работу с представлениями было принято вести не напрямую из бота, а через специальный сервер внутри контура, который будет выполнять роль фильтра.

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

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

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

Первая версия интеграционной схемы выглядела так:

c972bbb6c527c00f8c7fcfa89b5b8f0a.jpg

Но СИБ такую схему не утвердили, т.к. в ней недоставало деталей. На последнюю версию схемы мы нанесли названия сетей, подсетей, систем, IP-адреса и порты и сетевую схему взаимодействия. К тому же, доступ к нашему Application REST API реализован не через Gravitee, а внутри VPN тоннеля посредством прямого подключения по HTTPS, что тоже нашло отражение на новой схеме.

После всех этапов согласований и утверждения плана реализации мы приступили к написанию кода для самого бота. При написании использовали библиотеку для создания чат-ботов и SmartApps для мессенджера eXpress pybotx (т.к. она  простая в использовании  и легко интегрируется с асинхронными фреймворками).  Также у ребят из eXpress есть шаблон, в котором основной код для работы с библиотекой pybotx уже написан. В шаблоне используется fastapi, sqlalchemy, redis для конечных автоматов, psycopg для интеграции с PostgreSQL и библиотека  для работы конечных автоматов. Шаблон разворачивается с помощью библиотеки copier, чем мы и воспользовались. В результате первая часть — сам бот, который развернут на бот-сервере в Express, готова. Осталась вторая часть сервиса — бэкенд бота, который развернут на внутреннем сервере Биржи. В нем будет происходить вся бизнес-логика: обработка команд, проверка прав, соединения с другими сервисами.

Первой трудностью, с которой мы столкнулись при разработке бэкенд части, стала банальная версионная несовместимость. В разработке бэкенда мы хотели использовать последний python, но не получилось, т.к. все нужно брать из корпоративного Nexus, а некоторых библиотек там вообще не оказалось, например fastapi-users. Пришлось остановиться на python версии 3.8, менять все версии библиотек в pyproject.toml под него, пересобирать poetry.lock и писать самим аутентификацию пользователей с JWT и хешированием паролей (спасибо документации FastAPI за подробный гайд)

Следующим фактором, с которым боролись не один день, стала сложность свместимости одновременно синхронного и асинхронного подключения к двум разным БД. Для работы с данными по заявкам на поддержку нам необходимо иметь соединение с базой данной MSSQL, находящейся на другом сервере, а для хранения пользовательских данных нужно соединение с базой данных PostgreSQL, находящейся рядом с приложением на одном сервере. Так как эндпоинты в приложении асинхронные, мы использовали асинхронное соединение с PostgreSQL с помощью create_async_engine в SQLAlchemy и библиотеки asyncpg. А вот для соединения с БД MSSQL в Nexus не оказалось асинхронной библиотеки, была только синхронная — pymssql.

Мы попробовали использовать обычный create_engine для соединения с MSSQL и засунули его в Depends:

b8e7332d29601142d2ff2dade0f0b880.jpg

К сожалению, это не сработало, при использовании параметра mssql_db в коде возникала ошибка cannot unpack non iterable coroutine object. Как мы поняли, проблема может быть связана с тем, что FastAPI ожидает, что все обработчики зависимостей (dependencies) будут асинхронными в асихронном эндпоинте.

Потом мы решили использовать run_in_executor из библиотеки asyncio, чтобы запустить
синхронный код в асинхронной функции:

f2a4f5903d908b0fc7e2ad16560f3a70.jpg

И это сработало! Мы получили то, чего добивались.

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

cef175530ae1d256d40ef8def13a7317.png

На весь проект ушло 4 месяца, вместо пары недель, на которые мы рассчитывали xD.

В ближайшие пару месяцев планируем проверить работоспособность бота на тестовой группе сотрудников Московской биржи: посмотрим, кто и как будет его использовать, какие запросы чаще всего будут отправляться. Далее, если бот будет пользоваться спросом — будем думать, как его масштабировать на всех сотрудников Группы MOEX.

Результатами поделимся с вами в следующих статьях.

ЗАКЛЮЧЕНИЕ

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

В завершение несколько общих советов (которые, кстати, можно применить к любому ИТ-проекту):

  1. закладывайте время на возможные срывы сроков, форс-мажоры и уход ключевых разработчиков с проекта;

  2. в планировании сроков реализации важное место отводите этапу согласования с СИБ;

  3. продумывайте «план Б» на случай, если по основному плану всё пойдёт не так;

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

  5. описывайте предполагаемый бизнес-процесс;

  6. моделируйте взаимодействия прецедентов и бизнес-процессов;

  7. обращайте внимание на детали, фиксируйте всё письменно.

Благодарим за внимание и желаем удачи в ваших проектах!

P.S. А для тех, кто решит разрабатывать ботов в Express, список статей и материалов по их разработке ниже:

  1. Статьи:
    · https://docs.express.ms/chatbot-and-smartapp/developer-guide/getting-started/what-is-chatbot-and-smartapp/
    · https://hackmd.ccsteam.ru/s/4IHk-iFDR

  2. Библиотеки Бот-сервисов:
    · https://github.com/ExpressApp/pybotx
    · https://github.com/ExpressApp/async-box
    · https://github.com/ExpressApp/pybotx-fsm
    · https://github.com/ExpressApp/pybotx-smartapp-rpc
    · https://github.com/ExpressApp/pybotx-smart-logger
    · https://github.com/ExpressApp/pybotx-smartapp-smart-logger
    · https://github.com/ExpressApp/smartapp-bridge
    · https://github.com/ExpressApp/smartapp-sdk

© Habrahabr.ru