AAYMA
RU
Войти

Граф денег

Локальный MVP для AML-анализа на FastAPI и React.

Доведённый продукт
Команда «TRIO» 12💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: TRIO
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Доведённый продукт

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

Суть

Локальный MVP для AML-анализа на FastAPI и React. Он присваивает клиентам роли и приоритет проверки, кластеризует сеть переводов и показывает направленные подграфы и ego-сети. AML Copilot отвечает на вопросы аналитика через безопасные инструменты без внешней LLM.

Как устроено

Pipeline проверяет Parquet, считает метрики узлов, кластеризует (компоненты, для крупных Louvain с весом log1p(sum)+0.25×log1p(n_tx), resolution 1.15, seed 42) и выставляет score по шести ролям. Transit определяется через FIFO-сопоставление: не меньше 15% входа уходит за 1–2 дня. role_score = (0.6×лучший + 0.4×отрыв от второго)×Q. priority = Q×Σ(вес×нормализованный фактор) по 9 факторам. Copilot по намерению вопроса вызывает разрешённые инструменты: trace_money_flow, find_common_recipients, explain_priority и другие.

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

  • Louvain
  • FIFO-сопоставление транзита
  • ролевые scores с отрывом от второго
  • фактор полноты наблюдения Q
  • ранговая нормализация факторов
  • ego-сети
  • intent-based copilot с whitelisted tools

Особенности

Copilot работает офлайн без LLM: распознаёт намерение и вызывает только разрешённые инструменты, произвольные Python, SQL и команды не выполняются. Ограничения данных описаны подробно (depth=4 как обрыв обхода, нет межбанка). В metadata.json сохраняются SHA256 входных данных. Синтетика подставляется только тогда, когда нет всех трёх файлов.

Стек

Python 3.12 · FastAPI · Uvicorn · React · TypeScript · Vite · Docker Compose · Parquet


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

README

README.md

Граф денег

Локальный MVP исследования AML-графа: объяснимые роли, кластеры, очередь проверки клиентов, направленные подграфы и AML Copilot без ключей и внешних сервисов. Все выводы — признаки и гипотезы для проверки.

Реальный набор уже распакован: 2 248 клиентов, 3 119 связей, 4 840 операций, 81 seed, 365 890 012,01 KZT за июль 2026. Исходные parquet включены в репозиторий; дублирующие ZIP-архивы остаются только локально. Описание организаторов — data/README.md, аудит — docs/data-audit.md.

Для жюри

Репозиторий команды: BAITC-Hacks/hack-0601d926-trio. Исходный код, данные, готовые CSV-результаты, тесты и документация доступны в одном месте.

git clone https://github.com/BAITC-Hacks/hack-0601d926-trio.git
cd hack-0601d926-trio

Далее выполните команду запуска для своей ОС ниже. Для быстрой оценки: сценарий демонстрации, результаты проверок, методология, приоритетные клиенты, роли всех клиентов, кластеры.

Запуск одной командой

Требования: Python 3.12+, Node.js 22 LTS+ с npm. Версии зависимостей закреплены в lock-файлах. При первом запуске нужен интернет для установки пакетов. После установки приложение и Copilot работают без сети и GPU. На этой машине Windows-скрипт также обнаруживает уже установленный runtime Codex.

Windows PowerShell из корня проекта:

powershell -ExecutionPolicy Bypass -File .\scripts\start.ps1

Unix/macOS:

bash scripts/start.sh

Открыть http://127.0.0.1:8000. OpenAPI — http://127.0.0.1:8000/docs. Скрипт создаёт .venv, устанавливает зависимости, собирает frontend и запускает FastAPI. Pipeline выполняется автоматически при старте. Остановка — Ctrl+C. Windows: -Port 8001 меняет порт; -SkipInstall пропускает установку имеющихся зависимостей, но выполняет сборку.

Если установлен Docker:

docker compose up --build

Адрес тот же; данные монтируются read-only, CSV сохраняются в outputs/. На текущей Windows-машине Docker отсутствует: контейнерный запуск не проверялся. Dockerfile и Compose подготовлены. Unix-скрипт в этой среде также не исполнялся.

Отдельный pipeline и данные

Windows, с установкой зависимостей при необходимости:

powershell -ExecutionPolicy Bypass -File .\scripts\start.ps1 -PipelineOnly

После установки окружения:

.\.venv\Scripts\python.exe -X utf8 -m backend.app.analytics --data data --out outputs

Unix: bash scripts/start.sh --pipeline-only либо .venv/bin/python -m backend.app.analytics --data data --out outputs.

Все три файла nodes.parquet, edges.parquet, transactions.parquet должны находиться в data/. Они обнаруживаются автоматически при запуске и пересчёте. Отсутствующие колонки, отрицательные/нечисловые суммы, неизвестные nodes и несогласованность операций с агрегатами дают понятную ошибку. Частичный набор никогда не подменяется синтетикой.

Отсутствие всех трёх файлов включает явно обозначенный небольшой синтетический набор. Отдельный генератор для разработки:

.\.venv\Scripts\python.exe -m backend.app.analytics --generate-demo demo-data
.\.venv\Scripts\python.exe -m backend.app.analytics --data demo-data --out demo-outputs

Генератор не перезаписывает parquet; принадлежность к синтетике хранится внутри файлов, в API, UI и выгрузках. Эти результаты не являются выводами по реальной сети.

Выгрузки

  • outputs/nodes_roles.csv: все клиенты, роль, role_score, cluster_id, priority_score, evidence, суммы, глубина и source.
  • outputs/clusters.csv: все кластеры, размер, seed, внутренний/внешний оборот, top_gids, роли и гипотеза.
  • outputs/top_nodes.csv: 100 приоритетных клиентов с рангом и объяснением.
  • outputs/metadata.json: источник, время, статистика, ограничения, параметры, версии библиотек, SHA256 исходных parquet и конфигурации.

CSV: UTF-8 BOM, стабильная сортировка и восемь десятичных знаков. В UI есть меню экспорта. gid содержит 18 цифр: при импорте CSV в Excel выбирайте текстовый тип, иначе ID округлится. JSON API передаёт клиентские ID строками; Python сохраняет точные целые.

Интерфейс и Copilot

Обзор показывает статистику, временной оборот, роли, качество и очередь проверки. Граф предлагает top-N, агрегированные кластеры и ego-сеть. Стрелки показывают перевод, цвет — роль, обводка — seed, размер — приоритет. Есть фильтры ролей, кластеров, глубины, seed и суммы; поиск, zoom/pan/fit, соседи, входящее/исходящее направление и глубина ego.

Приоритеты используют сортировку и серверную пагинацию. Карточка показывает потоки, все role scores, вклады факторов, временные признаки, ограничения и следующий шаг. Кластеры имеют мини-граф и ключевые gid. Методология доступна непосредственно в продукте.

Copilot распознаёт типовые вопросы и вызывает разрешённые инструменты: get_node_profile, get_neighbors, trace_money_flow, find_common_recipients, find_shared_senders, get_cluster_profile, compare_nodes, get_top_nodes, explain_priority, suggest_next_data_request. Ответы содержат наблюдения, гипотезы, ограничения, ссылки и журнал инструментов. Произвольный Python, SQL и команды ОС не исполняются. Необязательная внешняя LLM не подключена.

Примеры: «Почему gid 100000004400305100 находится в топе?», «Какие узлы похожи на транзитные?», «Куда дальше уходят деньги от gid 100000008730846100?», «Каких данных не хватает для проверки этой гипотезы?».

Роли, приоритет и воспроизводимость

Все параметры — в config.json; полные формулы, пороги и словарь — docs/methodology.md. Правила не содержат конкретных gid.

РольОсновной признак и ограничение
consolidator≥3 отправителя; fan-in, входящий объём, агрегация
transitдвусторонний поток; FIFO-сопоставление ≥15% входа через 1–2 дня; исключены seed
distributor≥3 получателя; fan-out, исходящий объём, распределение контрагентов
terminalнаблюдаемый out/in ≤10%; исключены seed и depth=4
coordinator≥4 ветки, ≥2 связанных seed, центральность ≥0,60 и межкластерные связи; кандидат
peripheralнедостаточно выраженных признаков остальных ролей

Основная роль — максимум шести scores; ничья разрешается фиксированным порядком из config. role_score = (0,60 × лучший score + 0,40 × отрыв от второго) × Q, где Q — полнота наблюдения. Scores не являются вероятностями.

priority = Q × Σ(weight × normalized_factor):

ФакторВес
Выраженность и значимость роли0,20
Связанные seed0,16
Центральность0,14
Оборот0,12
Ветвление0,10
Межкластерные связи0,10
Циклы / повторные пары0,06
Быстрый транзит0,06
Полнота наблюдения0,06

Q: 1 по умолчанию, 0,65 при менее трёх участий в операциях, 0,35 для изолированных; дополнительно ×0,90 для seed и ×0,70 для depth=4. Вклады UI включают Q. Положительные значения нормализуются по рангам; нули остаются нулём. Кластеризация: компоненты отдельно, Louvain для больших компонент, вес log1p(sum_kzt)+0,25×log1p(n_tx), resolution 1,15, seed 42. Порядок входа и алгоритмы детерминированы при закреплённых версиях.

Ограничения данных

  1. Depth=4 без выхода может быть обрывом обхода: terminal там запрещён.
  2. Видны исходящие переводы исходной выборки, полный баланс неизвестен.
  3. Входящие seed занижены: out/in и удержание равны null и не используются как балансовое доказательство.
  4. Выход может превышать вход; это допустимо и само по себе не является подозрительным признаком.
  5. Отсутствуют операции менее 5 000 KZT и межбанковские переводы.
  6. Seed без рёбер или только с входящими сохраняются; в данных 19 полностью изолированных узлов.
  7. Кластеры не смешивают несвязанные компоненты.
  8. Нет ФИО, ИИН, возраста, доходов, остатков и назначения платежа; они не придумываются.
  9. Правильные роли не размечены: эвристики дают гипотезы, а не установленную структуру преступной группы.
  10. FIFO и циклы отражают совместимость наблюдений, не трассируют одни и те же деньги. Внутридневной порядок неизвестен; конец месяца скрывает последующее движение.

Архитектура и API

frontend/                 React / TypeScript / Vite
backend/app/analytics/    валидация → метрики → кластеры → роли → приоритет → CSV
backend/app/api/          строгие модели, кэш снимка, ограниченные выборки
backend/app/agent/        локальные намерения и безопасные инструменты
data/                    исходные parquet
outputs/                 результаты и метаданные
tests/                   аналитика, API, реальный набор
scripts/                 запуск и живой smoke test
docs/                    архитектура, методология, демонстрация

Первоначальный расчёт выполняется один раз. Пересчёт — в фоновом потоке; только валидный снимок заменяет кэш. При ошибке предыдущие результаты доступны. Используйте один Uvicorn worker; БД не требуется.

МетодURLНазначение
GET/api/healthготовность, источник, ошибка
GET/api/overviewстатистика, предупреждения, top, временной ряд
POST / GET/api/recalculate / /api/recalculate/statusпересчёт и статус
GET/api/top-nodes?limit=20очередь проверки
GET/api/nodes?q=...&page=1&page_size=25поиск, фильтры, сортировка
GET/api/nodes/{gid}профиль
GET/api/nodes/{gid}/ego?depth=2&direction=outограниченная ego-сеть
GET/api/graph?limit=60ограниченная выборка графа
GET/api/clusters, /api/clusters/{id}, /api/clusters/graphсообщества
GET/api/methodologyактуальные правила
POST/api/copilot{ "message": "...", "context_gid": "..." }
GET/api/exports/{filename}одна из трёх CSV

Фильтры nodes/graph: role, cluster_id, depth, is_seed; для graph также min_amount/max_amount. Response schemas — в /docs. Ошибочные параметры дают 422, неизвестный gid — 404, неготовые данные — 503. CORS разрешает только локальные адреса Vite. Приложение слушает loopback; данные не отправляются наружу. Это локальный инструмент без многопользовательской авторизации.

Проверки и разработка

.\.venv\Scripts\python.exe -m pip install -r backend/requirements-dev.txt
.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe -m ruff check backend scripts tests
.\.venv\Scripts\python.exe -m pip check
cd frontend
npm run lint
npm run typecheck
npm run build
cd ..
.\.venv\Scripts\python.exe scripts/smoke.py

Smoke требует работающий сервер: пересчёт → top20 → профиль → ego → объяснение Copilot. Тесты проверяют контролируемые роли, цензуру, seed, FIFO, валидацию, детерминированность, CSV, изолированных, компоненты, API и точные 18-значные ID. Фактические итоги и измерения — в STATUS.md.

Development: backend python -m uvicorn backend.app.main:app --reload, отдельно npm run dev в frontend. Аудит известных уязвимостей: python -m pip_audit -r backend/requirements.txt --no-deps --disable-pip и npm audit. Передаются только названия/версии пакетов.

Типичные проблемы

  • Нет python/npm: установите Python 3.12+ и Node.js 22 LTS+ и откройте новую консоль.
  • Windows запрещает ps1: используйте приведённую команду с -ExecutionPolicy Bypass без изменения системной политики.
  • Порт 8000 занят: завершите предыдущий запуск либо передайте -Port 8001.
  • Ошибка parquet: прочитайте диагностику; все три файла должны относиться к одной выборке. После исправления нажмите «Пересчитать».
  • Синтетический режим: проверьте каталог data и наличие всех трёх parquet.
  • gid округлился в Excel: повторно импортируйте CSV как текст; не копируйте округлённый номер в поиск.
  • Ошибка установки: проверьте доступ к PyPI/npm registry. Клиентские данные для установки не передаются.
  • API-сообщение вместо UI: соберите frontend или запустите общий скрипт.

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

NetworkX заменить на igraph/Graph-tool/Spark GraphFrames либо графовую БД по профилю запросов. Использовать колоночное хранение и lazy execution Polars/DuckDB, предварительные агрегации и индексы, фоновые задания с версионированными снимками, приближённые centrality-алгоритмы, серверную выборку подграфов и многоуровневую визуализацию. Полный граф не передавать браузеру. Этот масштаб в MVP не реализован.

Демонстрация: docs/demo-script.md. Дополнительно: SPEC.md, PLAN.md, архитектура, Mermaid.

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

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

Danial 1

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

  • 2026-09-23 17:28Add complete Money Graph AML MVP, dataset, results and documentationDanial
Структура репозитория (69 файлов)
.dockerignore
.env.example
.gitignore
Dockerfile
PLAN.md
README.md
SPEC.md
STATUS.md
backend/__init__.py
backend/app/__init__.py
backend/app/agent/__init__.py
backend/app/agent/copilot.py
backend/app/agent/tools.py
backend/app/analytics/__init__.py
backend/app/analytics/__main__.py
backend/app/analytics/config.json
backend/app/analytics/demo.py
backend/app/analytics/pipeline.py
backend/app/analytics/validation.py
backend/app/api/__init__.py
backend/app/api/models.py
backend/app/api/routes.py
backend/app/api/store.py
backend/app/main.py
backend/requirements-dev.txt
backend/requirements.txt
compose.yaml
data/README.md
data/edges.parquet
data/nodes.parquet
data/transactions.parquet
docs/architecture-diagram.md
docs/architecture.md
docs/data-audit.md
docs/demo-script.md
docs/methodology.md
frontend/eslint.config.js
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/pnpm-lock.yaml
frontend/pnpm-workspace.yaml
frontend/src/App.tsx
frontend/src/CopilotPage.tsx
frontend/src/DataPages.tsx
frontend/src/GraphPages.tsx
frontend/src/api.ts
frontend/src/components.tsx
frontend/src/main.tsx
frontend/src/styles.css
frontend/tsconfig.json
frontend/vite.config.ts
outputs/clusters.csv
outputs/dependency-audit-frontend.json
outputs/dependency-audit.json
outputs/metadata.json
outputs/nodes_roles.csv
outputs/top_nodes.csv
pyproject.toml
scripts/lock_python.py
scripts/smoke.py
scripts/start.ps1
scripts/start.sh
starter/README.md
starter/requirements.txt
starter/starter.py
tests/test_analytics.py
tests/test_api.py
tests/test_real_dataset.py

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

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

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