Привет, Хабр! Мы продолжаем рассматривать конкретный практический вопрос — интеграцию Python для внедрения ML-моделей и расширенной аналитики в BI. В прошлом посте мы уже рассуждали о том, зачем это нужно, и как можно реализовать подобное расширение. Сегодня же мы остановимся на том, как реализована поддержка Python в популярных BI-системах. И сразу спойлер: в существующих системах (в том числе в Visiology) это было сделано неудобно, и чтобы решить эту проблему, мы придумали новую штуку, а именно — интеграцию через JupyterHub. Под катом — подробный рассказ о том, какие мы знаем подходы к работе с Python, и что меняется в этом процессе при подключении Jupyter Hub. Если вы еще не пробовали эту схему, то скорее давайте читать наш пост, а если уже работали таким образом — давайте  обсуждать новый подход в комментариях.  В прошлый раз мы рассказали о том, почему сделали выбор в пользу Python для углубления возможностей аналитики. Как показала практика, к такому же выводу пришли и другие разработчики решений BI. Так, с Python можно работать в PowerBI. В этой системе Python можно использовать для загрузки данных, трансформации данных внутри PowerQuery Editor, а также для создания Python-визуализаций, тем самым значительно расширяя возможности обработки данных. Однако PowerBI полагается на исполнение скриптов на машине пользователя. Поэтому для более глубокой аналитики у клиента должен быть установлен Power BI Desktop, и установка всех библиотек лежит на плечах пользователя. Потенциально это может стать проблемой, которая лечится выгрузкой в Power BI Service — то есть веб-версию решения. При этом исполнение скриптов происходит на сервере, но зато в ограниченной среде. Перечень установленных библиотек приведен в документации к решению, и при внедрении новых ML-моделей придется ограничиться этим списком.  Еще один плюс подхода, реализованного в PowerBI — это тесная интеграция с Pandas, который представляет вообще основной формат взаимодействия между PowerBI и Python-скриптом.  Что касается визуализации, здесь Python работает следующим образом: на входе скрипт получает pandas-таблицу с выбранными пользователем данными (возможно, отфильтрованными на дашборде). Далее, скрипт строит по ним matplotlib-визуализацию. Такой график легко автоматически перестраивается, когда пользователь меняет фильтры или другие параметры. Но график является статичным: кликнуть на него нельзя, и получить более подробные данные в интерактиве — тоже. Для каждого графика используется свой код на Python. Здесь действует правило: "один скрипт - один график". Интеграция с Python в Qlik реализована иначе. Для этого используется механизм Server-side Extensions. От администратора/разработчика требуется предварительно настроить (или написать) отдельный Python-сервер, работающий по протоколу gRPC. Внутри сервера пишутся специальные Python-функции, обрабатывающие данные в формате Qlik, они регистрируются в манифесте Python-расширения. После добавления Python-расширения в Qlik любая из этих функций становится доступна во встроенном движке запросов. С одной стороны, пользователю предоставляется удобный доступ к кастомной функциональности, с другой же, для добавления чего-то нового требуется непосредственное участие администратора для внесения правок в работу python-сервера. Прежде чем приступать к интеграции, мы изучили отраслевой опыт и решили сделать ставку на повышенную гибкость. В рамках глобальной интеграции Visiology и Python этот язык используется не только в ML, но и для расчетов произвольной сложности, работы с кастомными источниками данных и т.д. В целом это работает следующим образом: на входе мы передаем скрипту состояние управляющих элементов дашборда. Это могут быть фильтры, источники данных — все, что выбирается и определяется пользователем. Для выполнения скриптов должен быть запущен специальный сервер, взаимодействие с которым происходит через SSH. Результат работы каждого скрипта возвращается платформе и дальше визуализируется виджетами, это позволяет построить дашборд максимально гибко. Поскольку Visiology в основном используется в режиме on-premise, заказчик самостоятельно контролирует выполнение скриптов, обеспечивает нужную производительность и безопасность.  Данные, которые использует Python-скрипт, могут храниться непосредственно в ViQube (аналитическом движке нашей платформы), в любой сторонней БД с открытым для скрипта доступом... или вообще нигде, если мы хотим визуализировать что-то простое. Ниже приведен пример скрипта, выполнение которого зависит от значения переменной yearFilter. На дашборде она представляет собой выпадающий список. И в зависимости от выбранного пользователем параметра, скрипт выполняется по-разному. Однако, в процессе использования такой интеграции, мы столкнулись с двумя серьёзными проблемами. Первая проблема заключается в сложности отладки скриптов. Как мы уже обсуждали в предыдущем посте (ссылка), нам хотелось бы снизить порог вхождения для новых пользователей, которые часто не имеют большого опыта программирования. Однако, исполнение скрипта в отдельном от пользователя окружении может сделать результаты непредсказуемыми, а нам бы не хотелось принуждать пользователя разворачивать Python локально и отлаживать скрипт перед публикацией в платформу. Неопытный пользователь часто не может предсказать, как поведет себя отдельная строчка кода, а в текущем режиме перед исполнением кода нужно написать весь скрипт. Таким образом, имеется недостаток интерактивности в написании кода. Вторая проблема заключается во взаимодействии с данными на дашборде. Часто мы применяем Python-скрипты, чтобы как-то дополнительно обработать эти данные, но на текущий момент это приходится делать через составление JSON-запросов к нашей БД и парсинг результатов. Хотелось бы иметь простой способ получать данные с других виджетов в удобном формате. Для упрощения написания скриптов и снижения порога вхождения мы решили также интегрировать платформу с сервером JupyterHub. Jupyter — вообще полезная штука. На сегодня он представляет собой среду для интерактивного выполнения кода на различных языках: Python, R, Julia и других. На Jupyter доступны богатые возможности визуализации, потому что все выходящее из среды просто рендерится на веб-страницу. Вы можете дополнять код markdown и html-разметкой. Фактически, в Jupyter можно писать “исполняемые статьи”, в которых понятным языком расписано, что же на самом деле происходит, а рядом показан результат исполнения кода. Использование Jupyter позволяет вести исполнение кода по шагам (ячейкам). После выполнения клетки интерпретатор останавливается и ждет следующий фрагмент кода. В итоге на каждом шагу пользователь видит текущее состояние данных. Вы можете редактировать код, по мере его выполнения, править ошибки, не теряя накопленный результат и не перезапуская всю программу. Такой подход снижает цену ошибки, а значит делает не столь критичными навыки программирования. Для интеграции платформы с Jupyter мы используем JupyterHub — инструмент, позволяющий работать с Jupyter множеству пользователей. JupyterHub Server настраивается администратором, а аналитику остается только редактировать и отлаживать скрипты в более удобной форме. При этом не нужно настраивать среду, что-то перезапускать и конфигурировать.  В системе уже предусмотрено встроенное отображение таблиц в формате Pandas, построение графиков matplotlib и интерактивных графиков Plotly (за счет javaScript): Более того, мы сделали возможным получение данных уже существующих виджетов в формате pandas.DataFrame, тем самым минимизировав необходимость самостоятельно писать запросы в аналитическую БД. Мы также разработали API для конверсии объектов между форматами платформы и популярными форматами DS-стека. Благодаря всем проделанным интеграциям, сегодня работа пользователя Visiology с Jupyter выполняется следующим образом:   Открываем специальный виджет, который привязан к Python-скрипту (для которого источником данных служит Python-скрипт) и нажимаем кнопку “запустить отладку скрипта” скриншот В браузере автоматически открывается Jupyter-сервер, предназначенный для текущего пользователя Python-скрипт, к которому привязан виджет, преобразуется в нативный для Jupyter ipynb-формат и загружается в Jupyter-сервер. Пользователь редактирует скрипт в Jupyter. В это время он может интерактивно исполнять его части и просматривать промежуточные результаты. Это дает возможность отлаживать скрипт, не перезапуская его полностью. Когда пользователь считает скрипт готовым, он выполняет последнюю специальную клетку в ipynb-блокноте. После этого сессия прекращается, ipynb-файл конвертируется в чистый python-скрипт, который сохраняется в платформе. Новый скрипт тут же выполняется на дашборде и обновляет его. Данные, предоставленные Python-скриптом, мы можем визуализировать на свой вкус через конструктор дашбордов. Кстати, мы используем Jupyter и в других проектах. Например, наш ETL на языке Python называется ViXtract. Это сборка на основе Jupyter и открытых библиотек, и распространяется она тоже как бесплатное ПО. Если кому-то интересно, ViXtract можно скачать и протестировать для своих задач здесь. Новый подход, включающий в себя JupyterHub и Python, появился в Visiology недавно. Мы продолжаем тестировать его и развивать это направление. Однако уже сейчас понятно, что подобная схема имеет ряд преимуществ: Гибкость и широта возможностей. По сравнению с No-code и low-code подходами мы получаем намного больше возможностей и прямую интеграцию со стеком решений Data Science Удобство и интерактивность. В отличие от использования “просто Python”, добавление JupyterHub дает простоту отладки, освобождает пользователя от необходимости настраивать окружения и дает широкие возможности промежуточной визуализации. Кстати, именно такая интеграция позволила решить задачу, о которой мы говорили в одном из прошлых постов. Чтобы решить задачу анализа и прогнозирования рисков для крупного энергетического холдинга, нужно было собрать воедино всю информацию и показать Value At Risk, а также ее производные. Для этого Data Scientist’ом была подготовлена Python-модель на бэкенде.  Пользователи — рисковики и менеджеры — даже не видят этой модели. Они просто пользуются результатами сложных расчетов, которые учитывают большое количество денежных потоков, задолженности в разных валютах и на разных условиях, с различными процентными ставками, сроками, условиями рефинансирования. И при необходимости можно в любой момент дополнить эту модель, написать новый скрипт и расширить возможности аналитики. Кстати, нам хотелось бы узнать ваше мнение о том, насколько такая связка выглядит удобной со стороны. И, если у вас уже есть позитивный или негативный опыт внесения ML-моделей в BI, использования Python или JupyterHub для решения этой задачи, поделитесь, пожалуйста, своим мнением в комментариях.