AAYMA
RU
Войти

Flow Atlas

Streamlit-пространство для исследования графа денежных потоков: роли, Louvain-кластеры, рейтинг приоритетов, интерактивный граф и опциональный…

Рабочий MVP
Команда «GosKZ» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: GosKZ
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Рабочий MVP

Задача кейса: «Граф денег»: восстановить структуру организованной группы по сети транзакций (AML)

Суть

Streamlit-пространство для исследования графа денежных потоков: роли, Louvain-кластеры, рейтинг приоритетов, интерактивный граф и опциональный AI-ассистент аналитика с инструментами над графом.

Как устроено

starter.py проверяет согласованность трёх parquet и строит направленный граф в NetworkX с взвешенным PageRank. Роли назначаются правилами сверху вниз (distributor → transit → consolidator → terminal → coordinator → peripheral). Priority = 0.5·role_score + 0.3·норм. log-оборот + 0.2·норм. PageRank. Louvain работает на неориентированной проекции. AMLAnalystAgent ведёт цикл OpenAI Responses API с function calling по allowlist детерминированных инструментов (карточка узла, обход вверх и вниз, общие получатели, пути, кластер), найденные узлы подсвечиваются на графе Plotly.

Ключевые решения

  • NetworkX
  • PageRank
  • Louvain
  • rule-based roles
  • function calling
  • tool registry allowlist

Особенности

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

Стек

Python · NetworkX · pandas · PyArrow · Streamlit · Plotly · D3.js · OpenAI SDK

Модели

gpt-4.1-mini


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-bbfda7b2-goskz.

README

README.md

Flow Atlas — исследование графа денежных потоков

Flow Atlas — аналитическое рабочее пространство для изучения переводов между клиентами. Проект создан для кейса «Граф денег» HackAlem AI и помогает аналитику исследовать структуру финансовой сети, находить примечательные узлы и проверять гипотезы по наблюдаемым данным.

Все назначенные роли и приоритеты — объяснимые эвристики по загруженной выборке. Они не устанавливают факт нарушения и не заменяют расследование.

Что реализовано

  • Загрузка и проверка согласованности nodes.parquet, edges.parquet и transactions.parquet; Streamlit также принимает полный набор этих трёх Parquet-файлов для отдельного анализа в памяти.
  • Построение направленного графа переводов с суммами и числом транзакций на ребре.
  • Расчёт входящих и исходящих связей, оборотов, числа транзакций и взвешенного PageRank.
  • Назначение каждой записи одной поведенческой роли: distributor, transit, consolidator, terminal, coordinator или peripheral. Для роли сохраняются краткое объяснение длиной до 200 символов и эвристическая оценка поддержки.
  • Поиск сообществ алгоритмом Louvain на неориентированной проекции графа и формирование рейтинга приоритетных клиентов.
  • Экспорт результатов в out/nodes_roles.csv, out/clusters.csv, out/top_nodes.csv и интерактивный out/network.html.
  • Streamlit-интерфейс с обзором сети, графом переводов, фильтрами по роли и кластеру, рейтингом и карточкой клиента.
  • Необязательный AI-ассистент, который отвечает на вопросы о данных через ограниченный набор детерминированных инструментов графа. Вызовы инструментов можно раскрыть в интерфейсе.

Как работает решение

  1. Пайплайн читает данные о клиентах, агрегированных направленных рёбрах и отдельных транзакциях. Перед расчётом он проверяет, что агрегаты переводов согласуются с edges.parquet по парам отправитель–получатель.
  2. По графу рассчитываются метрики узлов и распределяются эвристические роли. Для сообществ направленный граф временно проецируется в неориентированный; суммы взаимных потоков используются как веса.
  3. На основе роли, логарифма наблюдаемого оборота и PageRank вычисляется приоритетный рейтинг. Результаты сохраняются в out/.
  4. Веб-приложение загружает граф и выгрузки. Пользователь выбирает узел на графе, в рейтинге или по GID, изучает его контрагентов и показатели, а при настроенном OpenAI API задаёт вопрос ассистенту. Ответ ассистента строится на результатах зарегистрированных инструментов, а найденные узлы и потоки могут подсвечиваться на графе.

Правила ролей и рейтинга

Роли назначаются по наблюдаемым рёбрам и суммам в этой выборке. Правила применяются сверху вниз; если узел подходит нескольким правилам, выбирается первое:

  1. distributor — не менее 5 разных исходящих получателей.
  2. transit — узел не является seed-клиентом, имеет входящие и исходящие связи, получил не менее 50 000 KZT и отправил дальше не менее 80% наблюдаемой входящей суммы.
  3. consolidator — не менее 2 входящих контрагентов, положительная наблюдаемая входящая сумма, не более 1 исходящего и отношение исходящей суммы к входящей не выше 0,5. Узлы глубины 4 без исходящих связей сюда не относятся.
  4. terminal — есть входящие связи, нет исходящих связей, а минимальная глубина узла меньше 4. Это наблюдаемый конец в выгрузке, а не подтверждение фактического конечного получателя.
  5. coordinator — есть не менее 2 входящих и 2 исходящих контрагентов. Это гипотеза о многостороннем связующем узле, а не вывод об организаторе.
  6. peripheral — ни одно из предыдущих правил не подошло.

role_score — эвристическая поддержка роли, рассчитанная из её признаков; это не вероятность. Приоритет равен 0.5 × role_score + 0.3 × нормированный log(1 + входящий и исходящий оборот) + 0.2 × нормированный PageRank. Поэтому рейтинг помогает расставить очередь ручной проверки, но не устанавливает нарушение. Для transit отношение сумм считается только по наблюдаемым рёбрам; полнота входящих seed-клиентов ограничена способом построения графа.

Технологии

  • Python — расчёт графа, аналитические инструменты и запуск приложения.
  • Pandas, NumPy, PyArrow — обработка таблиц и чтение Parquet.
  • NetworkX — направленный граф, взвешенный PageRank и сообщества Louvain.
  • Streamlit — интерактивный интерфейс; Plotly — граф сети.
  • OpenAI Python SDK и Responses API с function calling — опциональный диалоговый аналитический ассистент. По умолчанию задана модель gpt-4.1-mini; её можно переопределить через AML_AGENT_MODEL. Модель не рассчитывает метрики напрямую: факты о графе получает через инструменты проекта.
  • python-dotenv — загрузка переменных из .env.
  • В автономной HTML-визуализации используется D3.js 7.9 с jsDelivr CDN; интерфейс запрашивает шрифты DM Sans и Manrope из Google Fonts.

Архитектура

parquet/*.parquet
       │
       ▼
starter.py ──► NetworkX-граф ──► метрики, роли, кластеры, рейтинг
       │                              │
       └──────────────► out/*.csv, out/network.html
                                      │
                                      ▼
                         interface/network_app.py (Streamlit)
                           │                     │
                           │                     └──► AMLAnalystAgent
                           │                               │
                           └──► GraphToolService ◄── ToolRegistry
                                           ▲               │
                                           └──── OpenAI Responses API
  • starter.py содержит загрузку и проверку данных, построение графа, расчёт признаков, назначение ролей и экспорт. Обычный запуск python starter.py сначала проверяет окружение и запускает интерфейс; --analyze-only пересчитывает выгрузки.
  • agent_tools.py реализует детерминированные операции: получить карточку узла и его связи, пройти граф вверх или вниз, найти общих получателей, сравнить клиентов, посмотреть кластер, отфильтровать узлы и найти ограниченные по длине пути.
  • tool_registry.py описывает доступные AI-ассистенту инструменты и выполняет вызовы из allowlist.
  • aml_agent.py управляет циклом вызовов OpenAI Responses API и возвращает ответ, список вызванных инструментов и данные для подсветки на графе. prompts.py задаёт инструкции модели.
  • interface/network_app.py объединяет обзор, визуализацию и чат. Сервис графа кэшируется и используется интерфейсом и ассистентом.

Установка и запуск

Требуются Python и доступ к терминалу. Данные кейса уже находятся в parquet/.

Windows PowerShell

Из корневой папки репозитория выполните:

py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txt

Если команда py недоступна, используйте python -m venv .venv.

Запустить проверки путей и зависимостей:

python starter.py --check

Запустить приложение одной командой после установки зависимостей:

python starter.py

Откройте адрес, который Streamlit напечатает в терминале. При первом запуске или после изменения Parquet-файлов приложение создаст либо обновит выгрузки в out/.

Чтобы исследовать другой набор данных, в боковой панели загрузите вместе edges.parquet, nodes.parquet и transactions.parquet с той же схемой, что в поставке. Приложение проверит идентификаторы, пары переводов, суммы и количество транзакций, пересчитает анализ в памяти и предложит скачать три CSV-выгрузки. Загруженные файлы не перезаписывают данные проекта.

Пересчитать выгрузки без запуска интерфейса:

python starter.py --analyze-only

AI-ассистент (необязательно)

Для работы чата нужен ключ OpenAI API. Его можно задать в текущем PowerShell-сеансе перед запуском:

$env:OPENAI_API_KEY = "ваш-ключ"
# Необязательно: выбрать модель, отличную от gpt-4.1-mini
$env:AML_AGENT_MODEL = "gpt-4.1-mini"
python starter.py

Либо создайте .env в корне проекта (он исключён из Git):

OPENAI_API_KEY=ваш-ключ
AML_AGENT_MODEL=gpt-4.1-mini

Без OPENAI_API_KEY интерфейс аналитики доступен, но чат-ассистент отключён.

Как проверить решение

  1. Установите зависимости и запустите python starter.py.
  2. В боковой панели откройте Top Customers и выберите строку рейтинга либо вставьте GID 100000002224132100 в поле поиска клиента.
  3. На карточке клиента изучите роль, приоритет, входящие и исходящие связи и основания назначения роли. Этот GID присутствует в текущей выгрузке out/top_nodes.csv.
  4. Откройте вкладку Network: выбранный клиент и прямые контрагенты должны быть видны на графе. Используйте фильтры по роли или кластеру и переключатель фокуса на окружение выбранного клиента.
  5. Если задан OPENAI_API_KEY, спросите в чате: «Объясни роль и приоритет клиента 100000002224132100». В раскрывшемся разделе вызовов можно посмотреть, какие данные инструментов использованы для ответа.

Сценарий демо на 5 минут

Запустите python starter.py и используйте поставленный набор данных:

  • 0:00–0:45 — обзор. Покажите размер сети, оборот, число seed-клиентов и ограничения наблюдаемой выборки.
  • 0:45–1:30 — карта. Покажите направление переводов, окраску по ролям и кластерам, затем найдите клиента по GID и откройте его окружение.
  • 1:30–3:45 — три клиента из рейтинга. Сравните транзитный узел 100000002224132100 (ранг 1), распределителя 100000007747786100 (ранг 2) и консолидатора 100000004892144100 (ранг 27). Для каждого прочитайте why, покажите роль и контрагентов в карточке клиента.
  • 3:45–4:30 — проверка границ вывода. Покажите оговорку о неполных входящих потоках seed-клиентов и о глубине 4; роли являются гипотезами для проверки.
  • 4:30–5:00 — результат для аналитика. Покажите скачивание трёх CSV. Если настроен API-ключ, задайте вопрос ассистенту и раскройте использованные инструментальные данные.

GID в сценарии взяты из текущего рейтинга поставленного набора; после изменения данных используйте GID из его нового top_nodes.csv.

Данные и интеграции

  • parquet/nodes.parquet — записи о клиентах, включая GID, глубину обхода и seed-признак.
  • parquet/edges.parquet — агрегированные направленные пары переводов с суммой (sum_kzt) и количеством транзакций (n_tx).
  • parquet/transactions.parquet — транзакции с отправителем, получателем, суммой и датой; используется для проверки агрегатов и временных сведений в графовых инструментах.
  • OpenAI Responses API используется только при включённом AI-чате. Проект не указывает другие внешние источники финансовых данных.
  • Для D3.js и веб-шрифтов браузеру нужен доступ к указанным CDN. Основные расчёты графа выполняются локально по файлам Parquet.

Ограничения текущей версии

  • Анализ относится только к предоставленной выгрузке. Seed-клиенты могут иметь неполную историю входящих переводов.
  • Узел без исходящих рёбер на глубине 4 может быть концом обхода, а не реальным конечным получателем. Роль terminal означает только наблюдаемый конец потока внутри выборки.
  • Роли, role_score и рейтинг приоритета эвристические. role_score не является вероятностью, а кластерные гипотезы — подтверждением нарушения.
  • Louvain работает на неориентированной проекции, поэтому при выделении кластеров направление потоков теряется.
  • Трассировка графа ограничена пятью переходами и 500 узлами; списки результатов инструментов ограничены 200 записями. AI-ассистент ограничен шестью раундами и двенадцатью вызовами инструментов на запрос.
  • Чат требует отдельного ключа и доступного OpenAI API. Без них доступны остальные функции приложения.
  • Данные, выдаваемые OpenAI, зависят от ответа внешней модели; фактические сведения о графе должны поступать через инструменты, но формулировки ответа создаёт модель.

Масштабирование примерно до 1 млн узлов

Текущая реализация хранит граф как объекты NetworkX в памяти, что удобно для набора из 2 248 узлов, но создаёт большой накладной расход памяти на миллионных графах. Для такого объёма следует перейти на компактное CSR-представление рёбер и векторизованные разреженные операции для степеней, оборотов и PageRank; Louvain считать библиотекой, рассчитанной на крупные графы, либо по связным компонентам, если их независимость подтверждена. CSV-выгрузки нужно формировать пакетно, а для просмотра показывать выбранный узел, его окрестность и агрегаты вместо одновременного рендеринга миллиона вершин. Потребление памяти и время пересчёта следует измерить на целевом оборудовании до выбора размера пакета и параметров.

Развернутая версия

Ссылка на deployed-версию в текущем репозитории не указана.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
22
Авторы
2
Файлы
18
Ветки
1

Авторы коммитов

Aisul_Alp 12taz 10

История коммитов

  • 2026-09-23 17:59YEsAisul_Alp
  • 2026-09-23 17:30Readme file updatedAisul_Alp
  • 2026-09-23 17:22deleted app.py and changed the ai assitant locationAisul_Alp
  • 2026-09-23 16:53Changes to starter.pyAisul_Alp
  • 2026-09-23 16:49Merge branch 'main' of https://github.com/BAITC-Hacks/hack-bbfda7b2-goskzAisul_Alp
  • 2026-09-23 16:46Changes to interfaceAisul_Alp
  • 2026-09-23 16:02Changes to interfaceAisul_Alp
  • 2026-09-23 15:45Some ChangesAisul_Alp
Все коммиты (22)
  • 2026-09-23 17:05AI + Interfacetaz
  • 2026-09-23 14:41Add loading interface and a folderAisul_Alp
  • 2026-09-23 16:36messagetaz
  • 2026-09-23 16:31Merge branch 'main' of https://github.com/BAITC-Hacks/hack-bbfda7b2-goskztaz
  • 2026-09-23 16:27tools connectionstaz
  • 2026-09-23 14:19added some interface and added my env to detected by git ignoreAisul_Alp
  • 2026-09-23 13:29From data zipAisul_Alp
  • 2026-09-23 13:25From the starter fileAisul_Alp
  • 2026-09-23 14:44convcsvtaz
  • 2026-09-23 14:43Merge branch 'main' of https://github.com/BAITC-Hacks/hack-bbfda7b2-goskztaz
  • 2026-09-23 14:41convcsvtaz
  • 2026-09-23 13:43outtaz
  • 2026-09-23 13:32reqtaz
  • 2026-09-23 13:12requirementstaz
Структура репозитория (18 файлов)
.gitignore
README.md
agent.py
agent_tools.py
aml_agent.py
docs/agent_tools.md
docs/aml_agent.md
interface/network_app.py
parquet/edges.parquet
parquet/nodes.parquet
parquet/transactions.parquet
prompts.py
requirements.txt
starter.py
tests/test_agent_tools.py
tests/test_aml_agent.py
tests/test_starter.py
tool_registry.py

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.