Этот материал будет полезен для 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} не найден.")
Далее мы связали все комментарии, которые были оставлены в ИС, с проектами и сотрудниками, которые их оставляли.

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

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

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

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

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

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

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