О проекте
Команда: EPIQ
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Доведённый продукт
Задача кейса: «Граф денег»: восстановить структуру организованной группы по сети транзакций (AML)
Суть
AML-инструмент строит граф транзакций, назначает участникам объяснимые роли (аккумулятор, распределитель, транзит, координатор и др.) и приоритет проверки. Результаты показываются в Streamlit с визуализацией маршрутов денег и AI-ассистентом.
Как устроено
Три Parquet-файла (узлы, связи, транзакции) проходят валидацию, затем строится направленный взвешенный граф NetworkX. Для узлов считаются оборот, связность, PageRank, приближённое посредничество и достижимость от seed-узлов. Кластеры выделяются алгоритмом Louvain внутри слабосвязных компонент. Роли назначаются правилами, priority_score взвешивает охват seed 30%, оборот 25%, посредничество 20%, связность 15% и силу роли 10%. Дополнительно ищутся повторяющиеся цепочки A→B→C с задержкой 1–2 дня и отношением выхода ко входу 0,8–1,2, циклы через сильносвязные компоненты и проводится стресс-тест удаления топ-узлов. AI-ассистент на GPT-5 mini вызывает только разрешённые функции чтения графа.
Ключевые решения
- NetworkX
- Louvain
- PageRank
- betweenness centrality
- SCC cycles
- rule-based roles
- weighted priority score
- repeated A→B→C chains
- robustness stress-test
- function calling
Особенности
Для каждой позиции в рейтинге видна разбивка приоритета на пять слагаемых и сравнение с другим кандидатом. Для подозрительных связей показываются даты и суммы. Примеры для защиты выбираются из результатов автоматически. Всё запускается одной командой python run.py. LLM видит только результаты разрешённых функций, аргументы проверяются по JSON Schema.
Стек
Python · pandas · NumPy · PyArrow · DuckDB · NetworkX · SciPy · Streamlit · PyVis · OpenAI SDK · pytest · GitHub Actions
Модели
GPT-5 mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-144ec83b-epiq.
README
README.mdГраф денег — EpiQ
От исходных клиентов — к цепочке переводов и обоснованному списку проверок.
О проекте
MVP для кейса Freedom на HackAlem AI. Инструмент помогает AML-аналитику исследовать обезличенную транзакционную сеть до четырёх колен: найти точки сбора и распределения денег, изучить связи и выбрать участников для углублённой проверки.
Аналитик получает приоритетный список, числовое обоснование роли, историю операций и рекомендации следующего запроса. Результаты — гипотезы по наблюдаемым данным, а не установление личности, виновности или фактического руководства группой. Это прототип команды, а не официальный сервис банка.
Что реализовано
- Проверка трёх Parquet-файлов: обязательные поля, уникальность узлов и пар связей, положительные суммы, наличие участников, согласованность сумм и числа операций.
- Направленный взвешенный граф; признаки оборота, связности, PageRank, приближённого посредничества и достижимости из исходных узлов — seed.
- Кластеры Louvain внутри слабосвязных компонент.
- Шесть объяснимых ролей: аккумулятор, распределитель, транзит, конечный узел, координатор, периферия. Приоритет и краткое обоснование для каждого узла.
- Топ-20 в CSV; до 200 кандидатов после фильтров в интерфейсе; поиск по
gid. - Фильтры ролей, приоритета и сигналов; сценарии поиска сборщиков, дальнейшего движения денег и границы наблюдения.
- Восемь представлений: «Сеть», «След денег», «Общие получатели», «Операции», «Маршруты», «Устойчивость», «Связи», «Кластеры».
- Граф окружения на один или два шага, до 60 связей, масштабирование и перемещение. Цвет узлов обозначает роль; связи с сигналами подсвечиваются и имеют пояснения.
- Маршруты A→B→C с примерами дат, сумм и задержек; неизвестный порядок операций одного дня явно отмечается.
- Общие получатели для 2–5 выбранных seed: направленные пути до четырёх переходов из каждого исходного клиента, суммы связей и экспорт доказательных путей.
- Повторяющиеся цепочки: минимум два непересекающихся эпизода A→B→C, задержка 1–2 дня, отношение выхода ко входу 0,8–1,2; даты и суммы каждого эпизода.
- Разбор места в рейтинге: вклады пяти факторов и сравнение с другим кандидатом из топ-20.
- Три примера для защиты автоматически выбираются из результатов и сохраняются в
out/demo_cases.md. - Временные сигналы, синхронные плательщики, дневные всплески, аномальность относительно своего колена и участие в сильносвязных группах с циклами.
- Стресс-тест связности после удаления топ-1, 5, 10 и 20 узлов.
- Карточка участника с пробелами данных и рекомендацией следующего запроса.
- Перечень клиентов для проверки и/или запроса в правоохранительные органы, который аналитик формирует вручную и скачивает в CSV.
- AI-ассистент OpenAI: вопросы обычным языком, контекст выбранного узла, короткая история диалога и ссылки на результаты разрешённых функций анализа. Локальный режим по ключевым словам доступен без API.
Как работает решение
- Организатор предоставляет узлы, агрегированные связи и отдельные транзакции.
- Пайплайн проверяет вход, строит граф и рассчитывает признаки.
- Правила назначают роли, кластеры, приоритеты и объяснения.
- Результаты сохраняются в CSV; сайт читает их и историю транзакций.
- Аналитик выбирает сценарий и участника, изучает граф, путь от seed и операции.
- Для связей с сигналами видит суммы и даты, проверяет ограничения.
- Принимает решение, добавляет участника в перечень и выгружает его.
Система не отправляет запросы в правоохранительные органы и не блокирует счета.
Правила и приоритет
priority_score лежит в диапазоне 0–1 и объединяет охват seed (30%), оборот (25%),
посредничество (20%), связность (15%) и силу роли (10%).
Изолированным узлам назначается нулевой приоритет.
В карточке «Почему такое место в топе» показаны слагаемые, их максимумы и разница
с выбранным кандидатом. Охват ограничен пятью seed; остальные структурные
признаки нормируются по перцентилям среди положительных значений. При одинаковом
приоритете применяется порядок по gid. Слагаемые сохранены в node_features.csv.
| Роль | Основные условия допуска |
|---|---|
| Аккумулятор | Не менее 3 разных плательщиков |
| Распределитель | Не менее 5 разных получателей |
| Транзит | Есть вход и выход; выход/вход 0,8–1,2; не seed и не depth=4 |
| Конечный узел | Выход до 10% входа; ещё 2 дня наблюдения после последнего входа; не seed и не depth=4 |
| Координатор | Достижим из 2+ seed, верхние 10% по посредничеству, связывает 2+ соседних кластера |
| Периферия | Ни одно содержательное правило не выполнено |
Это условия допуска: при нескольких подходящих ролях учитывается сила правил. Формулы находятся в scoring.py, пояснения — в архитектуре.
Технологии
| Компонент | Назначение |
|---|---|
| Python 3.10+ | Расчётное ядро и запуск |
| pandas, NumPy | Обработка таблиц и вычисления |
| PyArrow, DuckDB | Чтение Parquet; DuckDB — резервный способ чтения в ядре |
| NetworkX, SciPy | Графовые алгоритмы и расчётная поддержка |
| Streamlit 1.64+ | Локальный веб-интерфейс |
| PyVis / vis-network | Интерактивный граф и свечение связей |
| OpenAI SDK / Responses API, GPT-5 mini | Опциональный AI-ассистент с вызовом локальных функций анализа |
| JSON Schema | Проверка аргументов инструментов, типов и лимитов |
| pytest | Автоматические проверки |
| GitHub Actions | CI с pytest на Python 3.12 / Ubuntu |
Диапазоны версий: requirements.txt, pyproject.toml.
Роли и приоритеты рассчитываются правилами, модели на данных проекта не обучались.
Для AI-ассистента используется gpt-5-mini через OpenAI Responses API; нужен
отдельный API-ключ, интернет и доступные кредиты. Расчёт, граф и локальный режим
помощника работают без ключа и внешних API.
Архитектура
flowchart LR
A[Три Parquet-файла] --> B[Проверка входных данных]
B --> C[Граф и признаки]
C --> D[Кластеры и правила ролей]
C --> E[Маршруты и устойчивость]
D --> F[CSV и отчёты JSON]
E --> F
F --> G[Streamlit]
A --> G
G --> H[Решение аналитика и CSV перечня]
G --> I[AI-ассистент OpenAI]
I --> J[Разрешённые функции чтения графа]
F --> J
J --> I
Расчёт отделён от сайта. Интерфейс читает готовые результаты и дополнительно проверяет временные сигналы на маршрутах показанного окружения для подсветки связей.
run.py подготовка окружения, расчёт и запуск сайта
app.py интерфейс аналитика
.streamlit/config.toml тема интерфейса
src/money_graph/
io_validation.py чтение, валидация и хеши входных файлов
graph_features.py граф, признаки, кластеры
scoring.py роли, приоритеты, обоснования
advanced_analysis.py двухшаговые маршруты и устойчивость
route_evidence.py проверка пар операций и сигналы связей
repeated_routes.py повторения цепочек с независимыми окнами дат
investigations.py общие получатели и ограниченный обход от seed
investigation_ui.py интерфейс общих получателей и повторений
demo_cases.py выбор проверяемых примеров из текущих данных
assistant_tools.py проверяемые функции чтения графа для AI
ai_assistant.py ограниченный цикл вызовов OpenAI Responses API
assistant_ui.py диалог, разрешение передачи данных, источники ответов
pipeline.py оркестрация и запись результатов
cli.py командный интерфейс расчёта
tests/ проверки правил, результатов и маршрутов
docs/ архитектура, аудит ТЗ и сценарий защиты
Установка и запуск
1. Подготовьте окружение и репозиторий
Нужны Python 3.10+ с pip и venv, файлы данных организатора и интернет
для первой установки зависимостей. Git нужен только для клонирования;
вместо него можно скачать и распаковать ZIP репозитория.
git clone https://github.com/BAITC-Hacks/hack-144ec83b-epiq.git
cd hack-144ec83b-epiq
2. Подготовьте данные
Создайте папку data и распакуйте в неё три файла. Ниже показана структура,
это не команды терминала:
data/
nodes.parquet
edges.parquet
transactions.parquet
3. Запустите одной командой
Из папки репозитория:
python run.py
Скрипт проверит наличие данных и свободного порта, создаст .venv при необходимости,
установит недостающие зависимости, рассчитает результаты и запустит сайт.
Активация окружения не нужна. Откройте локальное приложение.
Остановка — Ctrl+C. На Linux/macOS при необходимости используйте python3.
Повторный запуск использует установленные пакеты, если их версии подходят,
и заново рассчитывает результаты. После установки пакетов расчёт работает без интернета.
Установка зависимостей и расчёт проверены в отдельной копии без .venv и без
готовых результатов на Windows / Python 3.14.7. Использовался тот же компьютер
и доступный кэш pip; это не проверка на отдельной чистой ОС. Подробности —
в отчёте проверки.
Дополнительные команды
# Только расчёт, без сайта
python run.py --no-ui
# Свои каталоги данных и результатов
python run.py --data "C:/dataset" --out "C:/results"
# Если порт 8501 занят
python run.py --port 8502
Если приложение уже работает на 8501, откройте его вместо запуска второй копии.
Сообщение Missing data означает, что нужно проверить папку data или --data.
При ошибке установки проверьте доступ к пакетам и совместимость версии Python.
Подключение AI-ассистента — необязательно
Создайте локальный .streamlit/secrets.toml по примеру
secrets.toml.example:
OPENAI_API_KEY = "ваш_API_ключ"
OPENAI_MODEL = "gpt-5-mini"
secrets.toml исключён из Git. Также поддерживаются переменные окружения с теми
же именами; они имеют приоритет. Код активации API-кредитов не является API-ключом.
Официальная процедура — в OpenAI Quickstart.
Откройте «Ассистент аналитика» → «AI · OpenAI». После разрешения передачи данных введите вопрос, например «Почему выбранный участник в топе и что запросить дальше?». OpenAI получает вопрос, последние сообщения диалога, выбранный gid и ограниченные результаты функций — идентификаторы, суммы, даты и пути. Полные файлы не загружаются. При отсутствии разрешения поле AI-вопроса отключено; локальный режим остаётся доступен.
Ответ содержит ссылки [D1] и раскрываемые данные. Модель не выполняет произвольный
код, не меняет граф и не отправляет запросы в другие организации. Подробнее:
устройство и проверка AI-ассистента.
Как проверить решение — сценарий для жюри
- Подготовьте данные и выполните
python run.py. - Проверьте
out/nodes_roles.csv,out/clusters.csv,out/top_nodes.csv. Для исходной поставки кейса ожидается 2 248 узлов и 20 строк топа; на другом наборе количество узлов определяется входом. - На сайте выберите «Кто собирает деньги», затем участника из списка. Проверьте обоснование, число плательщиков, роль и приоритет.
- Откройте «След денег» и «Операции». Для достижимого из seed участника будет показан путь; если пути нет или выбран сам seed, появится пояснение.
- В «Сети» наведите на подсвеченную связь, если она есть. Янтарный означает операции в окне 0–2 дня, коралловый — также известный порядок по дням и сопоставимые суммы. Для операций одного дня порядок неизвестен.
- Раскройте «Почему такое место в топе»: сумма пяти вкладов должна совпадать с итогом, а сравнение — объяснять разницу с другим кандидатом.
- Откройте
out/demo_cases.md: там находятся реальныеgid, seed и даты для трёх примеров. В «Общих получателях» выберите 2–5 указанных seed, найдите сборщика и проверьте пути из каждого seed. - В «Маршрутах» выберите повторяющуюся цепочку из демо и сравните даты и суммы её эпизодов с «Операциями». В «Устойчивости» изучите изменение связности.
- Выберите решение в карточке, нажмите «Добавить в перечень» и скачайте CSV.
- Откройте
run_manifest.json: время расчёта, версии и SHA-256 входа. Лимит ТЗ — менее пяти минут на исходном наборе; оценивается фактический расчёт, без времени установки зависимостей.
При пустом списке ослабьте фильтры. Наличие сигнала зависит от данных. Тайминг защиты — в сценарии демо.
Автоматические тесты
После подготовки .venv, в Windows PowerShell:
.\.venv\Scripts\python.exe -m pip install -r requirements-dev.txt
.\.venv\Scripts\python.exe -m pytest -q
Linux/macOS:
.venv/bin/python -m pip install -r requirements-dev.txt
.venv/bin/python -m pytest -q
Тесты используют синтетические примеры и не требуют данных организатора. Проверяются ограничения ролей, согласованность топа, временные пары, циклические связи, устойчивость и отсутствие переноса сигнала на посторонние рёбра. Это не измерение точности обнаружения преступных схем.
После расчёта на реальных данных можно также проверить все восемь экранов, вклады рейтинга, выбор seed, эпизоды и добавление решения:
.\.venv\Scripts\python.exe scripts/smoke_ui.py
На Linux/macOS используйте .venv/bin/python scripts/smoke_ui.py.
Отдельная проверка настоящего API на полностью вымышленных данных (расходует кредиты):
.\.venv\Scripts\python.exe scripts/smoke_ai.py --live --synthetic
Обычные pytest и smoke_ui.py не вызывают платный API.
Данные и интеграции
Вход — локальная обезличенная выгрузка организатора. Parquet-файлы и результаты
исключены из Git через .gitignore.
| Файл | Обязательные поля |
|---|---|
nodes.parquet | gid, depth, is_seed |
edges.parquet | src, dst, sum_kzt, n_tx, depth |
transactions.parquet | src, dst, date, sum_kzt |
gid — идентификатор участника; src / dst — отправитель / получатель;
sum_kzt — сумма в тенге; n_tx — число операций; depth — колено;
is_seed — исходный клиент. Пары связей и суммы должны совпадать с агрегацией
транзакций. Совпадающие строки операций сохраняются с предупреждением:
без transaction_id нельзя доказать, что это технические дубли.
| Выходной файл | Содержание |
|---|---|
nodes_roles.csv | gid, role, role_score, cluster_id, priority_score, evidence |
clusters.csv | Размер, seed, внутренний оборот, лидеры и гипотеза кластера |
top_nodes.csv | Первые 20 узлов или все узлы, если их меньше 20 |
node_features.csv, edges.csv | Признаки и связи для интерфейса |
route_patterns.csv | До 200 крупнейших структурных маршрутов с проверкой примеров операций |
repeated_routes.csv, route_episodes.csv | Повторяющиеся маршруты и отдельные датированные эпизоды, без лимита топ-200 |
resilience.csv | Результаты удаления топовых узлов |
demo_cases.md, demo_cases.json | Примеры сборщика, повторяющегося маршрута и границы наблюдения, если они есть в данных |
quality_report.json | Проверки входа, предупреждения и сводные показатели |
run_manifest.json | Версия правил, SHA-256 входа, версии библиотек и длительность |
Банковские API и внешнее обогащение клиентов не подключены. OpenAI — опциональная внешняя интеграция помощника; включается пользователем. Ресурсы PyVis встраиваются в HTML. Локальный запуск не является интеграцией с инфраструктурой Freedom.
Ограничения текущей версии
- Наблюдение ограничено выгрузкой: четвёртое колено обрывается, вход seed неполон, отсутствующие переводы не восстанавливаются.
- Порог исключения переводов ниже 5 000 KZT описан для исходной поставки кейса; приложение само такой фильтр при загрузке не применяет.
- Нет размеченных ролей: точность, полнота обнаружения и снижение потерь не измерены. Оценки правил не являются вероятностями виновности.
- Путь от seed структурный: хронология всей цепочки не проверяется. Проверка времени реализована для A→B→C и не доказывает движение одной и той же суммы.
- Порядок внутри дня неизвестен. Сопоставимость 80–120% — экспертная эвристика; разбиение и объединение нескольких платежей не сопоставляются.
- Повторения считаются консервативно: один и тот же маршрут, непересекающиеся окна дат, без увеличения счётчика от совпадающих строк. Одна операция может поддерживать разные альтернативные маршруты; их суммы нельзя складывать.
- Общий получатель определяется по направленной достижимости из каждого seed. Это не доказательство совместного управления счетами или хронологии всей цепочки.
cycle_size— размер сильносвязной группы, а не длина одного простого цикла. Хронология полного кольца не проверяется.- Граф показывает ограниченное окружение; подсветка проверяет только его двухшаговые маршруты. Отсутствие подсветки не означает безопасность.
- Локальный помощник понимает ключевые слова. AI-режим использует LLM и семь ограниченных функций чтения; неподдерживаемые фильтры требуют уточнения. Ответы модели могут ошибаться и должны сверяться с раскрываемыми данными. Автоматически проверяются полные gid и ссылки на источники, но не вся семантика текста.
- AI отправляет часть данных внешнему провайдеру после разрешения пользователя. До трёх вызовов функций и четырёх API-запросов на вопрос; ошибки не повторяются автоматически. История хранится только в текущей сессии.
- Решения хранятся в сессии Streamlit; перечень нужно выгружать в CSV. Нет постоянного хранилища дел, авторизации, разграничения прав и журнала действий.
- Нет потоковой обработки, банковских интеграций и автоматической отправки запросов.
- Миллионы узлов не тестировались. Зависимости заданы диапазонами версий, полноценного lock-файла окружения нет.
Развёрнутая версия
Публичный адрес deployed-версии в репозитории не указан. Доступен локальный сайт, который работает только на компьютере, где запущен проект.
Переход к миллиону узлов
Это направление развития, не реализованный результат. Потребуются колонночная обработка Parquet, графовый движок с меньшими накладными расходами вместо NetworkX, пакетный расчёт признаков и приближённое посредничество. Поиск временных пар нужно ограничить индексом по узлу и дате, лимитами кандидатов и фоновыми задачами; на больших узлах число пар быстро растёт. В интерфейс передаются агрегаты и локальные подграфы. Для эксплуатации также нужны авторизация, журнал действий, постоянное хранилище дел и проверка качества с аналитиками банка.
Дополнительные материалы
- Архитектура и направления масштабирования.
- Чек-лист технического задания.
- Сценарий демонстрации.
- Обзор открытых проектов и происхождение идей.
- Продуктовая адаптация к кейсу Freedom.
В обзоре источников отделены идеи от собственной реализации. Использование стандартных алгоритмов и библиотек не означает подтверждённый результат проверки на антиплагиат.
Авторы коммитов
История коммитов
- 2026-09-23 17:21feat: connect analyst assistant to OpenAI graph toolslowqrst
- 2026-09-23 16:45feat: add evidence-based investigations and reproducible jury demolowqrst
- 2026-09-23 16:18fix: render node tooltips with plain text line breakslowqrst
- 2026-09-23 16:08docs: write complete Russian README for hackathon jurylowqrst
- 2026-09-23 16:02feat: add one-command environment setup analysis and app launchlowqrst
- 2026-09-23 15:58feat: glow suspicious graph edges with dated transaction evidencelowqrst
- 2026-09-23 15:54style: redesign graph with Obsidian-inspired muted palettelowqrst
- 2026-09-23 15:51feat: adapt Freedom-inspired theme and investigation scenarioslowqrst
Все коммиты (17)
- 2026-09-23 15:45feat: validate route evidence and document open-source researchlowqrst
- 2026-09-23 15:39feat: complete specification audit and graph analysislowqrst
- 2026-09-23 15:15feat: add transaction tracing investigation toolslowqrst
- 2026-09-23 15:01feat: add analyst review shortlist workflowlowqrst
- 2026-09-23 14:52style: apply industrial dashboard design systemlowqrst
- 2026-09-23 14:46feat: redesign Streamlit investigation dashboardlowqrst
- 2026-09-23 14:17fix: preserve large gids in dashboard tableslowqrst
- 2026-09-23 14:12test: validate analysis outputs and app runtimelowqrst
- 2026-09-23 14:00feat: implement explainable money graph MVPlowqrst
Структура репозитория (41 файлов)
.github/workflows/ci.yml .gitignore .streamlit/config.toml .streamlit/secrets.toml.example README.md app.py docs/ai-assistant.md docs/architecture.md docs/demo-script.md docs/freedom-product-fit.md docs/open-source-review.md docs/release-verification.md docs/tz-compliance.md pyproject.toml requirements-dev.txt requirements.txt run.py scripts/smoke_ai.py scripts/smoke_ui.py src/money_graph/__init__.py src/money_graph/advanced_analysis.py src/money_graph/ai_assistant.py src/money_graph/assistant_tools.py src/money_graph/assistant_ui.py src/money_graph/cli.py src/money_graph/demo_cases.py src/money_graph/graph_features.py src/money_graph/investigation_ui.py src/money_graph/investigations.py src/money_graph/io_validation.py src/money_graph/pipeline.py src/money_graph/repeated_routes.py src/money_graph/route_evidence.py src/money_graph/scoring.py tests/test_advanced_analysis.py tests/test_ai_assistant.py tests/test_ai_ui.py tests/test_investigations.py tests/test_pipeline.py tests/test_route_evidence.py tests/test_scoring.py
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.