Майнинг бизнес-процессов и визуализация данных с помощью Neo4j, Plotly и GPT

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

Контекст:

Компания Фикус, один из лидеров Российского рынка по озеленению корпоративных и общественных пространств. Уже год мы с ними внедряем ИИ-решения по всему контуру бизнеса: от саппорт-службы для потенциальных заказчиков до разработки персональных ассистентов сотрудникам.

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

Решение:

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

Извлечение и связывание данных

Честно говоря, мы оказались в выгодном положении по нескольким причинам:

а) Компания последовательно применяет сквозные методологии управления проектами и канбан. Сквозное управление вовлекает участников практически всех отделов на разных этапах и позволяет системно накапливать информацию. До 2022 года «Фикус» работал в Trello, а затем перешел на Kaiten.

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

Первым шагом мы извлекли два JSON-файла:

— JSON со всей информацией по проектам за 2023 год;
— JSON со всеми комментариями за тот же период.

def get_kaiten_cards(token, **params):
    url = 'URL'
    headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {token}'
    }

    response = requests.get(url, headers=headers, params=params)

    if response.status_code == 200:
        return response.json()
    else:
        response.raise_for_status()


def get_all_kaiten_cards_for_period(token, start_date, end_date):
    offset = 0
    limit = 100
    all_cards = []

    while True:
        response_cards = get_kaiten_cards(token, limit=limit, offset=offset, created_after=start_date,
                                          created_before=end_date)
        if not response_cards:
            break

        all_cards.extend(response_cards)
        if len(response_cards) < limit:
            break

        offset += limit

    return all_cards


def save_to_json(data, filename):
    with open(filename, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=4)


def load_from_json(filename):
    with open(filename, 'r', encoding='utf-8') as f:
        return json.load(f)


def get_card_comments(token, card_id):
    url = f'.../api/latest/cards/{card_id}/comments'
    headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {token}'
    }

    response = requests.get(url, headers=headers)

    try:
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as e:
        print(f"Ошибка при получении комментариев для карточки {card_id}: {e}")
        return []


if __name__ == "__main__":
    token = 'TOKEN'
    start_date = "2023-01-01T00:00:00Z"
    end_date = datetime.now().isoformat() + "Z"
    cards_filename = "kaiten_cards.json"
    comments_filename = "kaiten_comments.json"

    all_comments = []

    if os.path.exists(cards_filename):
        cards = load_from_json(cards_filename)
        for card in cards:
            card_id = card.get("id")
            if card_id:
                comments = get_card_comments(token, card_id)
                all_comments.extend(comments)

        save_to_json(all_comments, comments_filename)
    else:
        print(f"Файл {cards_filename} не найден.")

Далее мы связали все комментарии, которые были оставлены в ИС, с проектами и сотрудниками, которые их оставляли.

Связывание информации: комментарии + проекты. По такой же логике позже создали CSV файл с комментариями каждого из сотрудников.

Связывание информации: комментарии + проекты. По такой же логике позже создали CSV файл с комментариями каждого из сотрудников.

Визуализация данных

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

809b5cfb51c563121b9b79c65dd3e72f.png

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

588222570af23a45c63d1073a4d7ab76.jpeg

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

В этом случае мы использовали данные об авторах сообщений и упоминаниях сотрудников в комментариях, чтобы создать новый граф. Чем больше упоминаний, тем больше размер вершины в графе. Для балансировки графа мы использовали формулу центральности по степени. Параметр «центральность» помогает оценить важность каждой вершины графа (сотрудника), основываясь на ее позиции в структуре. В результате мы получили следующую визуализацию:

f61c4548edd113413a178a410a45e3bf.png

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

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

Майнинг бизнес-процессов с помощью LLM

Теперь давайте перейдем к следующему этапу. Нам необходимо определить, какие бизнес-процессы действительно функционируют в компании. Важно также узнать, какие ожидания у коллег при взаимодействии, какие проблемы решаются в процессе, и какие компоненты включает каждый процесс. Для этого мы использовали модель генеративного ИИ из семейства GPT (gpt-3.5-turbo), которая проанализировала сообщения в информационной системе. Получилась такая таблица:

8348564d3bb58c3c7129e438b8dd2635.png

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

50e2e76b5505eaae02fd6c0623679ae1.png

В результате, как и требовалось, мы получили социальный граф бизнес-процессов «Как есть». Далее вместо упоминания процессов, мы можем ожидания от выполненной работы, решаемые проблемы, компоненты процесса и другие намайненные с помощью LLM данные. Например так:

c7102e44b273b9c0f0110da65923bdb4.png

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

Заключение

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

Спасибо, что дочитали до конца.

© Habrahabr.ru