О проекте
Команда: Ghost in the Shell
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Рабочий MVP
Задача кейса: «Граф денег»: восстановить структуру организованной группы по сети транзакций (AML)
Суть
Детерминированный пайплайн, который по графу транзакций присваивает узлам роли (coordinator, transit, consolidator, distributor, terminal), кластеризует сеть и выдаёт топ-лист для AML-проверки со Streamlit-просмотрщиком.
Как устроено
pipeline.py читает parquet (2248 узлов, 3119 рёбер), считает betweenness centrality, соотношение out/in, задержки переводов и число независимых seed-цепочек. Роли назначаются правилами сверху вниз, кластеры строятся Louvain, priority_score взвешивает роль, уверенность, seed-цепочки и степень. На выходе nodes_roles.csv, clusters.csv, top_nodes.csv с текстовыми обоснованиями; Streamlit + pyvis показывают поиск по gid, топ-лист и схему сети.
Ключевые решения
- betweenness centrality
- Louvain
- NetworkX
- pyvis
- правила ролей по порогам
- upstream_seeds
Особенности
Хорошо описаны ограничения данных (обрыв на 4-м колене понижает уверенность роли terminal, занижение входящих у seed, порог 5000 KZT) и план масштабирования до 1 млн узлов через приближённый betweenness и графовую БД.
Стек
Python · pandas · NetworkX · Streamlit · pyvis · parquet
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-3bb6f822-ghost-in-the-shell.
README
README.mdhack-3bb6f822-ghost-in-the-shell
Hackathon team repository for Ghost in the Shell
Ghost in the Shell Hackathon Solution
Граф денег: роли, кластеры, приоритеты
Пайплайн восстанавливает финансовую структуру сети по графу транзакций: определяет роль каждого узла, кластеризует сеть на сообщества и ранжирует узлы по приоритету для ручной проверки AML-аналитиком.
Все правила детерминированные (без ML/LLM) — результат воспроизводим.
Быстрый запуск (одна команда для пайплайна)
pip install -r requirements.txt
python pipeline.py
На выходе в текущей папке появятся: nodes_roles.csv, clusters.csv, top_nodes.csv.
Время выполнения на предоставленном объёме (2248 узлов / 3119 рёбер) — менее минуты.
Интерфейс просмотра
streamlit run app.py
Откроется локально (localhost:8501). Вкладки:
- Поиск по gid — вводишь gid, видишь роль, обоснование и интерактивную схему связей узла (входящие/исходящие, до 3 шагов вглубь);
- Топ-лист приоритетов — таблица с сортировкой;
- Кластеры — состав каждого кластера + гипотеза, с визуализацией;
- Вся сеть — общая схема с подсветкой ролей (ограничена по числу узлов для читаемости).
Структура репозитория
data/ -------- исходные .parquet (описание полей — data/README.md)
pipeline.py -- весь расчёт: роли, кластеры, приоритеты → 3 CSV
app.py -------- экран просмотра (Streamlit)
requirements.txt
Роли узлов — критерии и пороги
Правила применяются сверху вниз, срабатывает первое подходящее:
| Роль | Правило |
|---|---|
coordinator | Узел-мост: betweenness centrality в топ-10% по сети, при этом ≥3 входящих и ≥3 исходящих связей |
transit | Отдаёт почти всё полученное дальше: out/in от 0.8 до 1.2, и с момента первого входящего до первого исходящего перевода проходит ≤3 дней |
consolidator | Получает от ≥3 разных плательщиков (или от ≥3 независимых seed-цепочек), и заметно удерживает средства (out/in < 0.6, либо нет исходящих вовсе) |
distributor | ≥5 исходящих связей и ≤2 входящих — веерная раздача без накопления |
terminal | Есть входящие, исходящих в графе нет. Если узел на 4-м колене — уверенность снижена (0.45 вместо 0.85): это может быть не реальный конечный получатель, а артефакт обрыва обхода на максимальной глубине |
peripheral | Не подошёл ни под одно правило выше — недостаточно сигналов |
role_score (0–1) — эвристическая уверенность в присвоенной роли, не вероятность
в статистическом смысле. priority_score — взвешенная комбинация: вес роли ×
уверенность + число независимых seed-цепочек, доходящих до узла + степень
узла (кол-во связей) + бонус, если узел сам является seed.
Почему transit проверяется раньше consolidator
Условие consolidator (≥3 плательщика) само по себе широкое и без
дополнительной проверки поймало бы и узлы, которые просто быстро
пропускают деньги дальше от нескольких источников (чистый транзит).
Чтобы не путать накопление с транзитом, transit проверяется первым,
а в consolidator добавлена проверка удержания средств (ratio < 0.6).
Обоснование для аналитика (evidence / why)
Каждая строка в nodes_roles.csv и top_nodes.csv содержит текстовое
объяснение на естественном языке — конкретные цифры (кол-во контрагентов,
суммы, задержки), а не абстрактный скор. Формулировки намеренно
осторожные («кандидат», «признаки», «требует проверки») — это гипотезы
для дальнейшей проверки аналитиком, а не утверждения о причастности.
Ограничения подхода
- Обрыв на 4-м колене. 444 узла с
depth=4и без исходящих связей — это в значительной части артефакт глубины обхода (граф просто не прослеживался дальше), а не доказательство того, что деньги там осели. Учтено понижениемrole_scoreдля таких узлов в ролиterminal. - Только исходящие переводы. Входящие потоки на узлы вне выборки не видны — полный баланс узла посчитать нельзя, работаем только с тем, что видно внутри графа.
- У seed-клиентов входящие занижены — граф собран от них, а не к ним; соотношение «отдал/получил» для seed интерпретировать буквально нельзя.
- Порог 5 000 KZT. Дробление переводов ниже порога в данных не видно — возможна намеренная фрагментация транзакций, скрытая от графа.
- Сеть не монолитна — 16 слабосвязных компонент, часть узлов вне главной компоненты; кластеризация (Louvain) не объединяет их искусственно.
- Нет ground truth и атрибутов клиента. Оценка идёт по обоснованности критериев, а не по accuracy; никакие данные о личности клиентов не используются и не восстанавливаются.
Масштабирование до ~1 млн узлов
При росте графа на два-три порядка текущий подход потребует изменений:
- Betweenness centrality считается точно за O(V·E) — на 1 млн узлов
это неприемлемо долго. Нужна аппроксимация (например,
k-sampling в networkx/igraph) или переход на приближённые меры центральности. - Louvain на всём графе в памяти упрётся в лимиты pandas/networkx — нужно либо переходить на графовую БД с инкрементальной кластеризацией (Neo4j GDS, igraph на диске), либо партиционировать граф по слабосвязным компонентам и кластеризовать каждую отдельно.
upstream_seeds(счётчик независимых seed-цепочек) считается за один проход по рёбрам, отсортированным поdepth— остаётся линейным по числу рёбер и масштабируется нормально, но при 1 млн узлов данные стоит хранить не в parquet-файлах целиком в памяти, а в графовой БД с индексами поsrc/dst.- Интерфейс. Полная отрисовка сети в pyvis нежизнеспособна на
миллионах узлов — уже сейчас
app.pyограничивает схему топ-N узлами по приоритету; при росте графа этот подход остаётся единственным рабочим — рендерить только релевантный подграф вокруг искомого gid, а не всю сеть целиком.
Данные
Repository: https://github.com/BAITC-Hacks/hack-3bb6f822-ghost-in-the-shell
Presentation: [https://docs.google.com/presentation/d/1PCglSGLlLyTean3qFoHPjy5VmfYUaGBy/edit?usp=sharing&ouid=115657269000839204838&rtpof=true&sd=true]
Demo:
локальный запуск через streamlit run app.py
Описание полей и параметров сбора графа — в data/README.md.
Авторы коммитов
История коммитов
- 2026-09-23 17:48Update README with repository and demo informationBahittosan
- 2026-09-23 17:24Revise README for clarity and updated instructionsBahittosan
- 2026-09-23 17:19Refactor role classification logic in pipeline.pyBahittosan
- 2026-09-23 17:16Add files via uploadBahittosan
- 2026-09-23 17:11add data filesBahittosan
- 2026-09-23 17:02Delete transactions.parquetBahittosan
- 2026-09-23 17:02Delete edges.parquetBahittosan
- 2026-09-23 17:02Delete nodes.parquetBahittosan
Все коммиты (18)
- 2026-09-23 17:01Improve formatting and clarity in README.mdBahittosan
- 2026-09-23 16:39Refactor README for better structure and readabilityBahittosan
- 2026-09-23 16:16Enhance README with project details and instructionsBahittosan
- 2026-09-23 15:20add data folderBahittosan
- 2026-09-23 15:18Delete transactions.parquetBahittosan
- 2026-09-23 15:18Delete nodes.parquetBahittosan
- 2026-09-23 15:18Delete edges.parquetBahittosan
- 2026-09-23 15:12Update README with project details and setup instructionsBahittosan
- 2026-09-23 14:24feat: add dataBahittosan
- 2026-09-23 13:59init: project structure, pipeline stub, READMEBahittosan
Структура репозитория (7 файлов)
README.md app.py data/edges.parquet data/nodes.parquet data/transactions.parquet pipeline.py requirements.txt
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.