AAYMA
RU
Войти

Граф денег

Локальная платформа для аналитика: загрузка банковской выгрузки, построение графа переводов, роли участников с объяснением, приоритеты проверки…

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

О проекте

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

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

Суть

Локальная платформа для аналитика: загрузка банковской выгрузки, построение графа переводов, роли участников с объяснением, приоритеты проверки, кластеры и симуляция исключения узлов. Результаты собираются в дело и печатное HTML-досье.

Как устроено

Пайплайн mg/ (ingest → quality → features → roles → clusters → taint/cutoff → explain → export) работает по parquet, CSV или XLSX с мастером сопоставления колонок. Роли назначаются по настраиваемым порогам (абсолютным и адаптивным), приоритет — нормируемые веса. Учитывается граница выгрузки max_depth и хронологический анализ потока (taint). Симуляция удаляет выбранные узлы или топ-N и сравнивает эффект со случайным выбором по компонентам и кластерам. FastAPI с фоновыми задачами обслуживает React/Vite/Tailwind-интерфейс с графом, мета-графом кластеров, инспектором правил и таймлайном. Опциональный ассистент на OpenAI gpt-4.1-mini, основной анализ работает офлайн.

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

  • правила ролей с абсолютными и адаптивными порогами
  • кластеризация сети
  • taint/анализ хронологического потока
  • симуляция удаления узлов против случайного baseline
  • учёт обрыва выгрузки
  • валидация схемы выгрузок

Особенности

Универсальный инструмент, а не скрипт под один датасет: мастер импорта CSV/Parquet/XLSX с проверкой качества данных. Сравнение адаптивных и абсолютных порогов, калибровка по обратной связи аналитика, сценарии «что если убрать узлы». Экспорт досье, README на трёх языках (ru/en/kk), тесты доступности и производительности.

Стек

Python · FastAPI · pandas · Parquet · React · TypeScript · Vite · Tailwind CSS · Playwright · Docker Compose

Модели

gpt-4.1-mini


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

README

README.md

Граф денег — роли и приоритеты финансовой сети

Русский | English | Қазақша

Локальная платформа для исследования переводов. Загрузите банковскую выгрузку, подтвердите назначение колонок и проверьте качество данных — приложение построит граф, объяснит предполагаемые роли участников, расставит приоритеты проверки и позволит сравнить сценарии исключения узлов. Результаты можно сохранить в дело и выгрузить в печатное досье.

Текущая версия — универсальный MVP для одного аналитика на своём компьютере. Аутентификации и личных кабинетов нет. Роли и оценки потока — аналитические гипотезы, которые требуют проверки, а не выводы о вине или доказательство происхождения конкретных денег.

Экран расследования: граф переводов и инспектор выбранного узла

Содержание

Возможности и рабочий процесс

  1. Создать проект. «Открыть пример» копирует поставляемый набор хакатона и запускает расчёт; «Новый анализ» открывает мастер загрузки своих файлов.
  2. Подготовить данные. Мастер проводит через файлы, сопоставление колонок, параметры и качество. Автопредложения можно исправить; расчёт начинается после подтверждения.
  3. Исследовать сеть. Обзор показывает показатели, топ-10, роли, кластеры, устойчивость и ограничения данных. В расследовании доступны окружение узла на 1–3 перехода, мета-граф кластеров, инспектор правил, переводы по ребру, временная шкала и проигрывание периода.
  4. Проверить гипотезу. Симуляция исключает выбранные узлы или топ-N, сравнивает эффект со случайным выбором и показывает изменения компонент и кластеров. Исключение меняет расчётный сценарий, а не банковские операции.
  5. Сохранить результат. Дело объединяет узлы, заметки и сценарии. HTML-досье содержит снимок версии расчёта, связи, основания выводов, трассировку, запросы недостающих данных и конфигурацию. Для PDF откройте досье и выберите печать браузера → «Сохранить как PDF».

Граф поддерживает поиск, фильтры, геометрические формы ролей, пиктограммы или круги, перемещение, закрепление и скрытие узлов, мини-карту, новую раскладку, полный экран и PNG. Вывод до 3 000 узлов выполняется по явному запросу. Таблица узлов использует виртуализацию, серверный поиск, сортировку и пагинацию; доступны настройка колонок, сохранённый вид, экспорт и массовое добавление в сценарий или дело. Карточки кластеров показывают мини-подграфы до 24 узлов, состав и гипотезу. Выбранный узел и фильтры сохраняются в ссылке.

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

Интерфейс доступен на русском, казахском и английском, со светлой и тёмной темой и учётом системного предпочтения уменьшенной анимации. Основное рабочее место — настольный браузер; мобильный вид предназначен прежде всего для обзора и карточек.

Горячие клавиши: Ctrl/⌘+K или / — поиск; E — раскрыть соседей; B — добавить узел в симуляцию; A — добавить в дело; Esc — закрыть диалог, инспектор или полный экран; ? — помощь и глоссарий. E/B/A действуют вне полей ввода. Поиск и таблица позволяют выбирать узлы без мыши; вкладки инспектора поддерживают стрелки и Home/End.

Быстрый запуск в Docker

Нужны Git и Docker с Linux-контейнерами: Docker Desktop на Windows/macOS или Docker Engine с Compose на Linux. Версия Docker Compose — 2.24.0 или новее: используется необязательный файл окружения. Python и Node.js на компьютере для этого способа не нужны.

git clone --branch main https://github.com/BAITC-Hacks/hack-61c5ca4c-orbit-digital-ako.git
cd hack-61c5ca4c-orbit-digital-ako
docker compose version
docker compose up --build -d
docker compose ps

Откройте http://127.0.0.1:8000 и нажмите «Открыть пример». API и его локальная документация доступны на /api/docs, проверка работоспособности — на /api/health.

Первая сборка скачивает базовые образы, Python-зависимости и npm-пакеты. Dockerfile собирает React-интерфейс в этапе Node.js 22, затем запускает Python 3.12 от пользователя без прав root. SDK OpenAI уже включён; ключ для обычного анализа и локальных действий ассистента не нужен. Приложение работает одним процессом API, поскольку реестр фоновых задач находится в памяти процесса.

Compose публикует порт только на 127.0.0.1 и хранит проекты в отдельном томе. Не меняйте привязку на публичный интерфейс для совместной работы: в текущем MVP нет аутентификации. После установки основной анализ работает без интернета; сеть нужна для внешних вопросов к OpenAI и обновлений.

Управление из корня репозитория:

docker compose logs --tail=100 app
docker compose stop app
docker compose start app

docker compose down удаляет контейнер и сеть, сохраняя том с данными. docker compose down -v удаляет и том с проектами — не используйте этот вариант при обычном обновлении.

Запуск без Docker: Windows, macOS, Linux

Рекомендуется Python 3.12. Готовая сборка интерфейса включена в money_graph/web/dist/, поэтому Node.js для обычного запуска не требуется. Устанавливайте зависимости в отдельное виртуальное окружение.

Windows, PowerShell

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

py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r money_graph/requirements.txt
cd money_graph
..\.venv\Scripts\python.exe serve.py

Команды используют интерпретатор напрямую и не требуют разрешать выполнение Activate.ps1. Если Python установлен без команды py, создайте окружение через python -m venv .venv, предварительно проверив python --version.

macOS и Linux

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

python3.12 -m venv .venv
.venv/bin/python -m pip install -r money_graph/requirements.txt
cd money_graph
../.venv/bin/python serve.py

На Linux пакет для создания виртуальных окружений может устанавливаться отдельно через пакетный менеджер дистрибутива. Запускайте serve.py из папки money_graph: приложение импортируется как api.main:app. Адрес — http://127.0.0.1:8000. Остановка — Ctrl+C в терминале.

Настройки и переменные окружения

Файл money_graph/config.json задаёт исходные пороги, веса ролей и приоритета, параметры кластеризации, расчёта потока и ограничения загрузки. Новый проект получает свою копию настроек; для существующего проекта меняйте параметры через интерфейс или API. Граница выгрузки max_depth и порог сбора collection_threshold в новом пользовательском проекте остаются неизвестными до явного указания аналитиком, даже если исходный набор хакатона имеет такие значения.

Переменные сервера:

  • OPENAI_API_KEY — необязательный ключ для внешних вопросов. Хранится только на сервере. Без него работают анализ и локальные инструменты ассистента.
  • OPENAI_MODEL — модель внешнего ассистента; пример настройки использует gpt-4.1-mini.
  • MONEY_GRAPH_PROJECTS — каталог рабочих проектов. Без Docker по умолчанию используется money_graph/projects. Задавайте эту переменную в окружении процесса до запуска сервера; не полагайтесь на её загрузку из .env. В Compose она явно установлена в /data/projects.
  • MONEYGRAPH_PORT — только для Compose: порт компьютера, по умолчанию 8000. Внутри контейнера остаётся порт 8000; serve.py эту переменную не использует.

Файл money_graph/.env.example содержит пустой ключ. Для настройки OpenAI скопируйте его в необязательный money_graph/.env, только если файл ещё не существует.

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

if (-not (Test-Path money_graph/.env)) { Copy-Item money_graph/.env.example money_graph/.env }

Bash, из корня репозитория:

test -f money_graph/.env || cp money_graph/.env.example money_graph/.env

Добавьте ключ в этот локальный файл. Не отправляйте его в чат, не вводите в браузере и не добавляйте в Git. .env исключён из Git и контекста Docker-сборки; Compose читает его при создании контейнера. Для применения изменений окружения:

docker compose up -d --force-recreate app

При запуске без Docker дополнительно установите SDK из папки money_graph и перезапустите сервер:

python -m pip install -r requirements-ai.txt

Здесь и далее python означает интерпретатор вашего виртуального окружения: активируйте его или подставляйте путь из раздела запуска. У Docker-образа SDK уже установлен.

Чтобы выбрать другой порт Compose, в PowerShell задайте $env:MONEYGRAPH_PORT="8001", затем выполните docker compose up -d. В Bash используйте MONEYGRAPH_PORT=8001 docker compose up -d. После этого адрес приложения — http://127.0.0.1:8001.

Форматы импорта и качество данных

Поддерживаются CSV, Parquet и XLSX. Для CSV распознаются UTF-8, UTF-8 BOM, Windows-1251 и разделители ,, ;, табуляция, |. Для XLSX выбирается лист; формулы и макросы не выполняются. По умолчанию можно загрузить до 20 файлов на проект, до 500 МБ каждый; размер задаётся через upload_limit_mb в конфигурации. Размер распакованного XLSX ограничен четырьмя лимитами файла.

Названия исходных колонок могут отличаться: мастер предлагает соответствия по русским и английским синонимам и типам значений, показывает уверенность, исходные строки и результат преобразования. Аналитик подтверждает сопоставление перед анализом.

Канонические таблицы:

  • Транзакции: src — отправитель, dst — получатель, amount — положительная сумма; date — необязательная дата. Для анализа нужна эта таблица или таблица агрегированных связей.
  • Связи: src, dst, amount — сумма переводов между парой; n_tx — число переводов, при отсутствии принимается равным 1. Если загружены транзакции, связи пересчитываются из них.
  • Узлы: id, необязательные depth и is_seed. Таблица необязательна: недостающие участники добавляются из связей.
  • Исходные участники (seed): необязательная таблица с id. Их также можно отметить через is_seed или ввести списком. Seed задаёт исходную точку исследования и допущение модели потока.

Минимальный пример CSV с транзакциями:

src,dst,amount,date
A001,B002,12500.00,2026-09-01
B002,C003,7000.00,2026-09-02

Идентификаторы в ядре, API и браузере — строки. Сохраняйте значимые ведущие нули в исходном файле: Excel может убрать их ещё до импорта. Суммы вида 1 234,50 поддерживаются; при запятой внутри поля используйте корректное CSV-кавычкование или другой разделитель. Для неоднозначных дат выбирается порядок дня и месяца. Валюта задаётся для проекта; конвертации валют приложение не выполняет, поэтому суммы должны быть приведены к общей единице заранее.

В параметрах указываются валюта, seed, известный порог сбора данных, известная максимальная глубина выгрузки и язык текстовых оснований выводов. Вычисленная расстоянием по графу глубина не означает границу выгрузки: без явного max_depth классификация обрезки отключена.

Проверка качества выявляет пропуски, дубли, петли, некорректные суммы и даты, расхождения связей и транзакций, изолированные seed и компоненты графа. Если более 5% строк не содержат обязательных src, dst или amount, расчёт блокируется; при меньшей доле строки исключаются с предупреждением. Отрицательные и нулевые суммы исключаются: возвраты не преобразуются автоматически в обратные переводы. Совпадающие транзакции сохраняются и требуют проверки аналитиком.

При неполных данных приложение сокращает доступный анализ:

  • Без дат временные метрики выключены; транзит оценивается по соотношению сумм. Если даты есть лишь у части переводов, временные метрики используют датированные строки, а обороты — все допустимые строки.
  • Без глубины, но с seed, рассчитывается направленное расстояние BFS. Без глубины и seed обрезка не оценивается.
  • Без seed приоритет опирается на структуру и обороты с перенормированием весов, а симуляция измеряет общий наблюдаемый поток.
  • Модель продолжения за границей выгрузки требует дат, не менее 100 обучающих узлов и обоих классов. Если условия не соблюдены, p_onward отсутствует, а причина доступна в ограничениях.

Доступность расчётов отражена в summary.capabilities, на обзоре и в проверке качества. Неполная выгрузка не становится полной благодаря модели или ассистенту.

Проверка по ТЗ и обязательные выгрузки

Этот раздел отвечает требованиям разделов 7, 9 и 10 предоставленного ТЗ «Граф денег» и README стартового кода. Для исходного набора используются три приложенных Parquet: 2 248 узлов, 3 119 рёбер и 4 840 транзакций. Полный расчёт от этих файлов до выгрузок запускается из корня репозитория одной командой, без ручной разметки и без ключа OpenAI:

docker compose run --build --rm --no-deps app python run.py --out /data/baseline

Результат хранится в постоянном томе. Проверка обязательных схем и исходного числа узлов:

docker compose run --rm --no-deps app python check.py --out /data/baseline

После запуска основного приложения заберите результаты на компьютер командой docker compose cp app:/data/baseline ./baseline-results. Для веб-интерфейса используйте запуск из раздела Docker и «Демо»; произвольные пользовательские проекты не обязаны содержать 2 248 узлов.

Обязательные артефакты:

  • nodes_roles.csv: ровно 2 248 строк исходного набора; gid — int64, role — строка, role_score — число 0–1, cluster_id — целое, priority_score — число 0–1, evidence — непустое числовое объяснение длиной до 200 символов.
  • clusters.csv: cluster_id, n_nodes, n_seed, sum_kzt_internal, top_gids, hypothesis; одна строка на кластер, с размером, числом seed, внутренним оборотом и гипотезой. Louvain применяется к неориентированной проекции; исходные денежные потоки остаются направленными.
  • top_nodes.csv: rank, gid, role, priority_score, why; не менее 20 строк, по умолчанию 30, по убыванию приоритета.
  • Экран просмотра: направление переводов, роли, кластеры, поиск по gid и объяснение выбранного узла. Схема решения и сценарий демонстрации включены в репозиторий.

Требование ТЗ — пересчёт предоставленного набора не более чем за 5 минут. Контрольный запуск 23 сентября 2026 года в Docker на текущем компьютере занял 8,88 секунды от запуска CLI до готовых файлов, после сборки образа; check.py пройден. Скачивание зависимостей и первая сборка в этот замер не входят. Это результат одного прогона исходного набора, а не гарантия времени для любого компьютера или графа.

Правила ролей и пороги

Актуальные источники: mg/explain.py, mg/roles.py и config.json. in_deg/out_deg — количество разных плательщиков/получателей; pass_through = out_kzt / in_kzt учитывает только видимые переводы. При нулевом входящем объёме это отношение не определено. Ниже — исходный режим absolute; срабатывает первое подходящее правило:

  1. Изолированный узел: in_deg = out_deg = 0 → peripheral.
  2. Граница выгрузки: известен max_depth, depth = max_depth и out_deg = 0 → внутренняя роль truncated. В исходном наборе это 444 узла четвёртого колена. В CSV: role=peripheral, role_detail=truncated, is_truncated=True; информация об обрыве сохраняется.
  3. coordinator: in_deg ≥ 5, out_deg ≥ 5, посредничество betweenness > 0 и не ниже 95-го процентиля по узлам.
  4. distributor: out_deg ≥ 10 и out_deg / max(in_deg, 1) ≥ 3.
  5. consolidator: in_deg ≥ 4. Порог pass_through ≤ 0,5 влияет на оценку уверенности, но не является обязательным условием этой роли.
  6. transit: узел не seed, in_deg > 0, out_deg > 0 и либо 0,7 ≤ pass_through ≤ 1,3, либо fast_share ≥ 0,7 при pass_through ≥ 0,5. Быстрая доля использует временное окно до двух дней; без дат работает только ветка отношения сумм.
  7. terminal: out_deg = 0, входящая сумма ≥ 100 000 единиц валюты проекта или in_deg ≥ 2; при известном max_depth дополнительно нужна известная depth < max_depth. При неизвестной границе проверка глубины не применяется, поэтому вывод особенно зависит от полноты данных.
  8. peripheral: остальные узлы.

В адаптивном режиме минимальные количества связей для координатора, распределителя и консолидатора повышаются до максимума исходного порога и 99-го процентиля соответствующей степени. Инспектор показывает применённые пороги и все условия. role_score — эвристическая оценка силы признаков, а не обученная вероятность правильности роли.

Приоритет объединяет ранги положительных значений: прослеживаемые поступления — 25%, эффект блокировки — 25%, вес роли — 20%, посредничество — 10%, число источников seed — 10%, оборот — 10%. Вес роли: coordinator 1, consolidator 0,9, distributor 0,8, transit 0,6, truncated 0,4, terminal 0,3, peripheral 0. Итог делится на максимальный балл в текущем графе. Без seed соответствующие два компонента отключаются, остальные веса нормируются заново. Поэтому баллы предназначены для сравнения узлов внутри одного расчёта.

Расчёт и его ограничения

CLI и веб-проекты используют общее ядро mg.pipeline.run_pipeline: метрики направленного графа → распространение потока → эффект исключения узлов → оценка обрезки → роли и приоритет → кластеры → устойчивость. Назначение ролей и объяснение правил используют единый интерпретатор, поэтому в инспекторе можно проверить сработавшие условия.

Текущая модель потока — итеративное пропорциональное распределение, haircut. Исходным seed приписывается доля 1; остальные узлы передают долю, полученную из входящих связей. Расчёт идёт по агрегированному графу, не моделирует хронологические остатки на счетах. Даты используются в отдельных признаках и интерфейсе, но не превращают эту модель в последовательное отслеживание переводов. Сумма потока по рёбрам может учитывать одну и ту же условную денежную массу на нескольких переходах; она отличается от поступлений на наблюдаемые конечные узлы, которые показывает Sankey до и после исключения узлов.

Симуляция пересчитывает модель после удаления узлов. Её результат зависит от полноты сети, заданных seed и параметров; это оценка сценария, а не прогноз действий участников. Приоритет — относительный порядок проверки узлов внутри расчёта, не вероятность нарушения. AUC, когда модель обучена, относится к оценке продолжения за границей выгрузки, а не к точности назначения ролей.

Ограничения реализации:

  • При более чем 5 000 узлов посредничество оценивается по воспроизводимой выборке источников, по умолчанию 500 (betweenness_samples).
  • При более чем 20 000 узлов отдельный эффект блокировки вычисляется для ограниченного набора кандидатов, по умолчанию 1 000 (block_top_k). Для остальных значение отсутствует (NaN), а не равно нулю.
  • Короткие циклы ищутся до длины 4 с лимитом по умолчанию 100 000; при достижении лимита число циклов — нижняя оценка.
  • Поиск путей ограничен 12 переходами и 20 000 раскрытиями, пути ранжируются по произведению долей потока. Отдельные инструменты ассистента имеют более узкие лимиты из контракта интеграций.
  • Расчёт устойчивости в ядре использует 20 случайных сравнений, а для графов свыше 20 000 узлов — 5. Размер и плотность сети влияют на время работы и память. Louvain и посредничество могут быть затратными; гарантии расчёта произвольного графа за пять минут нет.
  • Роли и пороги требуют независимой проверки на размеченных данных. Текущий MVP не заявляет измеренную точность выявления нарушений.

Отчёт VALIDATION от 23 сентября 2026 года сохраняет результаты прежнего контрольного прогона и условия синтетического замера. Это исторический отчёт, а не подтверждение повторного выполнения всех проверок или измерения производительности текущей Docker-сборки.

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

Это план изменения подхода, требуемый ТЗ; текущая версия не заявляет проверенную обработку миллиона узлов.

  • Читать и агрегировать переводы пакетами из Parquet, отделить хранение исходных данных от вычислительного графа, сохранять контрольные точки вместо загрузки всех таблиц в память.
  • Заменить объектный граф NetworkX компактным графовым движком и разреженными массивами/матрицами. Перенести итерации потока на разреженные операции; оценивать память с учётом числа рёбер и транзакций, а не только узлов.
  • Оценивать посредничество по выборке источников; дорогие симуляции выполнять для ограниченного списка кандидатов. Ограничить поиск циклов и путей, явно показывать приближённые и нерассчитанные показатели.
  • Разделить API и расчёты через устойчивую очередь с сохранением задач, отменой и ограничением ресурсов. Добавлять воркеры только после замены текущих внутрипроцессных блокировок и реестра задач.
  • Показывать агрегированные кластеры и запрашиваемые окрестности, использовать серверные фильтры и пагинацию. Миллион узлов целиком в браузере не отображать.
  • Проверить время, пиковую память и качество приближений на графах разной плотности и на независимой выборке. Ограничение пяти минут из ТЗ относится к выданному набору из 2 248 узлов; для миллиона нужен отдельный измеримый бюджет.

Ассистент и API

Ассистент связан с сохранённой версией расчёта выбранного проекта. Без ключа и без внешних запросов доступны объяснение узлов, общие получатели, направленный путь и предложение недостающих данных. Можно выбрать от 1 до 5 узлов; для направленного пути нужны ровно два, в порядке «откуда → куда». Ответы содержат ссылки на существующие узлы и связи с переходом на граф; валюта берётся из профиля проекта.

Вопросы на естественном языке используют OpenAI только после настройки сервера и явного подтверждения отправки для каждого запроса. Передаются вопрос, выбранные идентификаторы и ограниченные результаты вызванных инструментов; исходные файлы целиком не отправляются. Ассистент читает рассчитанные факты, не меняет данные, роли или правила, не запускает произвольный код и не выполняет веб-поиск. Его текст всё равно нужно сопоставлять с показанными основаниями.

Ключ не возвращается браузеру и не включается в репозиторий или образ. Использование внешней модели оплачивается по условиям вашего API-аккаунта; наличие ключа не гарантирует доступ к конкретной модели или достаточную квоту. Автоматические проверки с имитацией провайдера не заменяют отдельную проверку реального запроса.

Интеграции, контракт API и работа ассистента — настройка OpenAI, запросы и ответы, согласие на передачу и обработка ошибок. Актуальная схема всех маршрутов доступна на локальной странице OpenAPI; её JS и CSS поставляются вместе с приложением.

API охватывает проекты и импорт, сопоставление и качество, запуск и SSE-прогресс задач, обзор и метрики узлов, объяснения, граф и пути, симуляцию, правила, обратную связь, калибровку, дела и экспорты. Основные входы: /api/projects, /api/demo, /api/jobs/{id}/events, /api/assistant/status и /api/projects/{pid}/assistant. Интеграция должна обращаться к локальному серверу; текущий API не является публичным сервисом с разграничением доступа.

Архитектура и структура репозитория

flowchart LR
    Files["CSV / Parquet / XLSX"] --> Import["Сопоставление и качество"]
    CLI["run.py — контракт хакатона"] --> Dataset["Dataset + DatasetProfile"]
    Import --> Dataset
    Dataset --> Kernel["mg.pipeline.run_pipeline"]
    Kernel --> Results["Метрики, роли, приоритет, кластеры, устойчивость"]
    Results --> Storage["Версии проектов и экспорты"]
    Storage --> API["FastAPI + очередь в процессе + SSE"]
    API --> UI["React / TypeScript + Sigma.js"]
    API --> Tools["Локальные инструменты ассистента"]
    Tools -. "вопрос + согласие" .-> OpenAI["OpenAI API"]

Аналитическое ядро использует pandas, NumPy, NetworkX и scikit-learn. mg/dataset.py задаёт нормализованные таблицы и профиль, mg/ingest.py читает файлы, mg/quality.py проверяет данные, mg/pipeline.py выполняет расчёт без HTTP и записи файлов. mg/explain.py объединяет правила назначения ролей и их объяснения; mg/i18n/ содержит локализованные основания и гипотезы.

api/storage.py ограничивает файловые пути, атомарно записывает JSON и хранит версии результатов. api/jobs.py выполняет расчёты в последовательном ThreadPoolExecutor и сообщает прогресс через SSE. api/main.py предоставляет API и локальную статику; server.py оставлен как совместимый импорт приложения. Адаптер api/assistant.py соединяет проекты с инструментами mg/assistant.py.

Интерфейс: React / TypeScript, Sigma.js / graphology, TanStack Query / Table / Virtual, Recharts, Radix Dialog, Tailwind, Zustand и i18next. Шрифт Inter, ресурсы интерфейса и Swagger локальные; CDN и телеметрия для анализа не требуются.

README.md, README.en.md, README.kk.md   Документация на трёх языках
Dockerfile, compose.yaml              Сборка и локальный запуск контейнера
money_graph/docs/INTEGRATIONS.md      Контракты внешних интеграций
tests/                                Проверки исходного контракта и ассистента
money_graph/
  serve.py                            Локальный сервер
  run.py, check.py                     CLI и проверка набора хакатона
  config.json                         Исходные параметры расчёта
  mg/                                 Общее аналитическое ядро
  api/                                FastAPI, хранилище, задачи, ассистент
  web/src/, web/dist/                  React-исходники и готовая сборка
  ui/                                 Ресурсы автономного CLI-viewer
  data/, out/                         Исходный набор и результаты CLI
  projects/                           Пользовательские проекты вне Git
  tests/, tools/                      Проверки, синтетика, замер
  docs/                               Методика, отчёт, демонстрация, снимки

Хранение, обновление и резервная копия

Без Docker проекты сохраняются в money_graph/projects/ либо каталоге MONEY_GRAPH_PROJECTS. В Compose логический том moneygraph_data подключён к /data, проекты лежат в /data/projects. Фактическое имя тома обычно включает имя Compose-проекта. Пересоздание контейнера сохраняет данные; смена имени Compose-проекта может подключить другой, пустой том.

projects/<id>/
  project.json, mapping.json, config.json, quality.json, profile.json
  raw/                              Загруженные исходники
  nodes.parquet, edges.parquet, transactions.parquet
  current.json                      Ссылка на активную версию
  results/<hash>/                    Результаты, снимок данных и настроек
  feedback.json, cases.json          Обратная связь и дела

Кэш зависит от нормализованных данных, конфигурации и версии алгоритма. Дела привязаны к сохранённым результатам. Одновременно допускается одна задача на проект; данные нельзя менять во время расчёта. Общий исполнитель последовательно обрабатывает расчёты. Отмена действует между этапами: выполняющаяся операция NetworkX сначала завершится. Завершённые результаты переживают перезапуск сервера, а незавершённый расчёт нужно запустить заново. Внешней восстанавливаемой очереди задач нет.

Резервная копия

Дождитесь завершения расчётов и остановите приложение, чтобы копия включала согласованный набор файлов. Создайте в корне репозитория папку backups — она исключена из Git — и скопируйте /data в новый подкаталог:

docker compose stop app
docker compose cp app:/data ./backups/moneygraph-backup
docker compose start app

В новой папке backups/moneygraph-backup должен быть каталог projects; проверьте наличие нужных проектов и версий результатов. Если папка назначения уже существует, используйте новое имя для очередной копии. Для локального Python-запуска остановите сервер и скопируйте весь каталог проектов, а не только current.json или CSV. Полные процедуры переноса и восстановления — в руководстве по развёртыванию.

Для восстановления остановите приложение, сохраните отдельную копию текущего состояния и восстановите всю папку проектов из резервной копии. В контейнере файлы должны быть доступны пользователю UID/GID 10001:10001; при переносе между хостами проверьте права. Локальный .env храните отдельно от обычных экспортов в защищённом хранилище секретов. После восстановления откройте несколько проектов и проверьте сохранённые версии и дела.

Обновление

Сначала сделайте резервную копию и сохраните свои изменения исходников. Затем из корня репозитория:

git pull --ff-only
docker compose up --build -d
docker compose ps

При запуске без Docker обновите Python-зависимости в окружении и перезапустите сервер. Если меняли исходники React, заново соберите web/dist. Не используйте удаление тома как способ обновления.

Приватность и удаление

Проекты и .env исключены из Git. У пользовательского каталога, заданного через MONEY_GRAPH_PROJECTS, проверьте политику резервного копирования и исключение из репозиториев отдельно. Приложение проверяет Host и Origin, отклоняет внешние межсайтовые изменения, ограничивает расширения, размеры и распакованный XLSX. Имена файлов используются как подписи, а не пути: на диске загрузки получают случайные идентификаторы. CSV защищены от формул Excel; React и HTML-досье экранируют текст. Обычные HTTP access-логи с идентификаторами отключены в командах запуска.

Это не заменяет аутентификацию или шифрование: любой, кто имеет доступ к локальному API, получает доступ к его проектам. Приложение не шифрует данные на диске; используйте защищённую учётную запись ОС, шифрование диска и контролируемые резервные копии.

Удаление проекта убирает его исходники, версии результатов, обратную связь и дела, а также состояние проекта в текущем браузере. Оно не удаляет скачанные экспорты, снимки, резервные копии и состояние другого браузера. Автономный viewer.html и HTML-досье содержат встроенные данные — передавайте их как чувствительные рабочие материалы.

Разработка и проверки

Интерфейс

Нужен Node.js 20.19+ или 22.12+ совместимой ветки; Docker собирает интерфейс на Node.js 22. Из корня репозитория:

cd money_graph/web
npm ci
npm run dev

Сервер Python должен работать отдельно на порту 8000. Vite предоставляет адрес для разработки в терминале и перенаправляет /api на локальный сервер. Для сборки из той же папки:

npm run build

Команда проверяет TypeScript и создаёт web/dist. В репозитории поддерживаются исходники, lock-файл и готовая сборка; при изменении интерфейса обновляйте их согласованно.

Python и браузерные сценарии

Из папки money_graph, с Python виртуального окружения:

python -m pip install -r requirements-dev.txt
python -m pytest ../tests tests -q

Для браузерных проверок нужны готовый web/dist, синтетические примеры и браузер. Из money_graph/web, с активным Python-окружением:

npm ci
npm run build
python ../tools/make_synthetic.py --out ../.local/synthetic
npx playwright install chromium
npm run test:e2e

Playwright по умолчанию использует установленный им Chromium и запускает Python-сервер на http://127.0.0.1:8000; вне CI может использовать уже работающий сервер. Для своего Chromium/Chrome/Edge задайте PLAYWRIGHT_BROWSER абсолютным путём к исполняемому файлу. На Linux для браузера могут потребоваться системные зависимости: npx playwright install --with-deps chromium.

Чтобы проверить уже запущенный экземпляр, например Docker на другом порту, задайте PLAYWRIGHT_BASE_URL его адресом: это отключит автоматический запуск сервера. Сценарии создают тестовые проекты; удалите их через интерфейс после проверки. Снимки тестов сохраняются в каталоге результатов Playwright, а синтетические данные — в игнорируемой .local/.

CLI и исходный контракт хакатона

Из папки money_graph:

python run.py
python check.py

В out/ создаются nodes_roles.csv, clusters.csv, top_nodes.csv, requests.csv, resilience.csv, summary.json, nodes.parquet и автономный viewer.html. Параметры run.py: --data, --out, --config. Числовые идентификаторы в CLI CSV сохраняются как int64, если преобразование обратимо; в ядре и API остаются строками.

В CSV обязательное поле role содержит только шесть значений стартового кода. Для узлов на границе выгрузки экспортируется role=peripheral, role_detail=truncated, is_truncated=True; role_base совпадает с role. Это техническое отображение в словарь ТЗ, а не утверждение о поведении клиента. Все 444 пограничных узла сохранены. Граф, внутренний Parquet, оценки и расчёт приоритетов по-прежнему различают обрезку данных и конечных получателей. Правило применяется к CLI, отдельным CSV, ZIP и выбранным строкам, включая скачивание старых сохранённых результатов.

check.py проверяет исходную схему и набор из 2 248 узлов хакатона, а не произвольные пользовательские файлы. Для загружаемых проектов используется универсальная проверка качества. BASELINE_METHOD.md описывает исходный метод и предпосылки; старые команды веб-запуска в этой архивной записке заменены инструкциями этого README.

Необязательная проверка на большой синтетике, из money_graph:

python tools/make_synthetic.py --big
python tools/benchmark.py --big

Это отдельный затратный прогон; генератор и отчёт используют игнорируемую .local/. Скрипт проверяет своё условие времени на машине запуска, но его результат нельзя переносить на произвольные сети и оборудование. При публикации нового замера указывайте ревизию, конфигурацию, размеры данных и условия запуска.

Доступность: исправления и границы проверки.

Решение проблем

  • Compose отвергает required: false. Проверьте docker compose version и обновите Compose до 2.24.0 или новее. Используйте docker compose, а не старый отдельный docker-compose.
  • Страница не открывается. Проверьте docker compose ps, затем docker compose logs --tail=100 app. При запуске Python прочитайте ошибку в терминале; запускайте serve.py из money_graph. В Docker открывайте адрес опубликованного порта, а не адрес контейнера.
  • Порт 8000 занят. Остановите другой экземпляр приложения либо задайте MONEYGRAPH_PORT для Compose. Для локального Python можно из money_graph запустить python -m uvicorn api.main:app --host 127.0.0.1 --port 8001 --workers 1 --no-access-log; тесты и Vite по умолчанию ожидают 8000.
  • Проекты исчезли после перезапуска. Проверьте каталог MONEY_GRAPH_PROJECTS или имя Compose-проекта и подключённый том. Пересоздание контейнера само по себе проекты не удаляет; down -v удаляет том. Не создавайте новые данные поверх предполагаемой резервной копии до проверки путей.
  • Нет формы внешнего вопроса. Проверьте серверную настройку ключа, наличие SDK при запуске без Docker и перезапуск после изменения окружения. Для Compose нужен up -d --force-recreate app, поскольку restart не перечитывает env_file. Локальные действия работают независимо от ключа.
  • OpenAI вернул ошибку. Ориентируйтесь на сообщение о настройках, модели, квоте или соединении. Проверьте доступ сервера к API; не публикуйте ключ или содержимое .env в отчёте об ошибке. Подробности — в документации интеграций.
  • Расчёт заблокирован на качестве. Исправьте сопоставление обязательных колонок, форматы сумм и даты, затем повторите проверку. Отсутствие временных метрик или оценки обрезки может быть ожидаемым ограничением данных.
  • Отмена не мгновенная или задача потерялась после перезапуска. Отмена применяется между этапами; дождитесь текущей операции. Незавершённую задачу после перезапуска запустите снова. Не добавляйте несколько Uvicorn workers: состояние задач не разделяется между процессами.
  • Playwright не находит браузер или тестовые файлы. Установите Chromium командой npx playwright install chromium либо задайте PLAYWRIGHT_BROWSER. Создайте синтетику командой из раздела проверок. Если задан PLAYWRIGHT_BASE_URL, сервер по этому адресу нужно запустить самостоятельно.
  • Изменения React не видны в обычном приложении. Выполните npm run build в money_graph/web либо пересоберите Docker-образ.

Документация, планы и участие

Ближайшие направления развития: независимая проверка ролей и порогов на размеченных данных, испытания на других форматах и плотностях сети, восстанавливаемая очередь расчётов с ограничением ресурсов и отменой внутри этапов, оценка качества ответов ассистента. Для нескольких пользователей требуется отдельная работа над аутентификацией, правами доступа, аудитом, хранением и защищённым сетевым развёртыванием.

В истории репозитория, в частности в ab08d0d, есть прежние личные кабинеты и другая хронологическая модель движения денег. Они не входят в текущий универсальный MVP. Ассистент адаптирован к текущим проектам; для переноса остальных возможностей нужны отдельный режим расчёта, согласование API и собственные эталонные проверки.

Изменения оформляйте через ветку и pull request: опишите воспроизводимую проблему, ожидаемое поведение и выполненные проверки. Для правок расчёта добавляйте содержательный пример с ожидаемым результатом; для UI проверяйте сборку, доступность и соответствующие браузерные сценарии. Обновляйте документацию на трёх языках. В issues, тестовых данных и коммитах не должно быть реальных выгрузок, персональных данных и API-ключей.

В корне репозитория нет файла LICENSE. Этот README не предоставляет отдельной лицензии на код; условия использования и распространения следует уточнить у правообладателей. Лицензии включённых сторонних компонентов действуют отдельно.

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

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

korgann 18akezhan kh 11Orkennn 9Your Name 4akezhan96 1

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

  • 2026-09-23 17:54docs: align all READMEs with hackathon acceptance requirementsOrkennn
  • 2026-09-23 17:49Merge latest teammate accessibility improvementsOrkennn
  • 2026-09-23 17:48Merge latest role export contract with Docker and multilingual docsOrkennn
  • 2026-09-23 17:46feat: add portable Docker deployment and trilingual documentationOrkennn
  • 2026-09-23 16:51feat: integrate OpenAI assistant and chronological flow analysisOrkennn
  • 2026-09-23 14:49Merge origin/main: keep offline UI overhaul, fix test data path, add schema testsOrkennn
  • 2026-09-23 17:46Merge latest main schema updates with accessibility fixesakezhan kh
  • 2026-09-23 17:46Fix cluster overview layout and improve keyboard accessibilityakezhan kh
Все коммиты (42)
  • 2026-09-23 17:39fix: enforce hackathon role schema without losing truncation evidenceYour Name
  • 2026-09-23 14:24Add schema validator and role_base safety columnOrkennn
  • 2026-09-23 17:24Merge universal investigation MVP into main with current implementation priorityakezhan kh
  • 2026-09-23 17:20Build universal investigation MVP and document root setupakezhan kh
  • 2026-09-23 13:54Merge remote-tracking branch 'origin/main'Orkennn
  • 2026-09-23 13:54Add data loading, graph building and feature engineering modulesOrkennn
  • 2026-09-23 16:26feat: add private analyst workspaces and evidence reportsYour Name
  • 2026-09-23 15:43Delete README.mdakezhan96
  • 2026-09-23 15:43Merge team transaction drill-down with responsive analyst workspaceYour Name
  • 2026-09-23 15:40fix: make analyst workspace readable and responsiveYour Name
  • 2026-09-23 15:36Redesign analyst workspace and connect transaction drill-downakezhan kh
  • 2026-09-23 15:14Build local case analysis MVP with interactive graphakezhan kh
  • 2026-09-23 14:56Merge schema validation and regenerate secured viewerakezhan kh
  • 2026-09-23 14:54Remove external LLM integration and harden offline viewerakezhan kh
  • 2026-09-23 14:43test: add financial input contract smoke testskorgann
  • 2026-09-23 14:41Unify money graph project and improve offline analyst UIakezhan kh
  • 2026-09-23 14:11Add complete money graph project artifactsakezhan kh
  • 2026-09-23 13:59data: add transaction graph inputskorgann
  • 2026-09-23 13:57feat: add money graph starter.pykorgann
  • 2026-09-23 13:57feat: add money graph README.mdkorgann
  • 2026-09-23 13:57feat: add money graph viewer.pykorgann
  • 2026-09-23 13:57feat: add money graph taint.pykorgann
  • 2026-09-23 13:57feat: add money graph roles.pykorgann
  • 2026-09-23 13:57feat: add money graph llm.pykorgann
  • 2026-09-23 13:57feat: add money graph features.pykorgann
  • 2026-09-23 13:57feat: add money graph cutoff.pykorgann
  • 2026-09-23 13:57feat: add money graph clusters.pykorgann
  • 2026-09-23 13:57feat: add money graph __init__.pykorgann
  • 2026-09-23 13:57feat: add money graph run.pykorgann
  • 2026-09-23 13:57feat: add money graph requirements.txtkorgann
  • 2026-09-23 13:57feat: add money graph config.jsonkorgann
  • 2026-09-23 13:54docs: add demo scriptkorgann
  • 2026-09-23 13:53docs: add project noteskorgann
  • 2026-09-23 13:49Add project READMEakezhan kh
Структура репозитория (134 файлов)
.dockerignore
.gitignore
Dockerfile
README.en.md
README.kk.md
README.md
compose.yaml
money_graph/.env.example
money_graph/DEMO_SCRIPT.md
money_graph/PROJECT_NOTES.md
money_graph/README.md
money_graph/api/__init__.py
money_graph/api/assistant.py
money_graph/api/jobs.py
money_graph/api/main.py
money_graph/api/schemas.py
money_graph/api/storage.py
money_graph/check.py
money_graph/config.json
money_graph/data/README.md
money_graph/data/edges.parquet
money_graph/data/nodes.parquet
money_graph/data/transactions.parquet
money_graph/docs/ACCESSIBILITY.md
money_graph/docs/BASELINE_METHOD.md
money_graph/docs/DEMO_SCRIPT.md
money_graph/docs/DEPLOYMENT.md
money_graph/docs/INTEGRATIONS.md
money_graph/docs/VALIDATION.md
money_graph/docs/screens/assistant.png
money_graph/docs/screens/cases.png
money_graph/docs/screens/cluster-overview.png
money_graph/docs/screens/clusters.png
money_graph/docs/screens/dark.png
money_graph/docs/screens/investigate.png
money_graph/docs/screens/mapping.png
money_graph/docs/screens/mobile.png
money_graph/docs/screens/nodes.png
money_graph/docs/screens/overview.png
money_graph/docs/screens/projects.png
money_graph/docs/screens/quality.png
money_graph/docs/screens/settings.png
money_graph/docs/screens/simulation.png
money_graph/docs/ui-overview.png
money_graph/mg/__init__.py
money_graph/mg/assistant.py
money_graph/mg/clusters.py
money_graph/mg/cutoff.py
money_graph/mg/dataset.py
money_graph/mg/explain.py
money_graph/mg/export.py
money_graph/mg/features.py
money_graph/mg/i18n/en.json
money_graph/mg/i18n/kk.json
money_graph/mg/i18n/ru.json
money_graph/mg/ingest.py
money_graph/mg/paths.py
money_graph/mg/pipeline.py
money_graph/mg/provider_errors.py
money_graph/mg/quality.py
money_graph/mg/report.py
money_graph/mg/roles.py
money_graph/mg/taint.py
money_graph/mg/validation.py
money_graph/mg/viewer.py
money_graph/out/clusters.csv
money_graph/out/nodes.parquet
money_graph/out/nodes_roles.csv
money_graph/out/requests.csv
money_graph/out/resilience.csv
money_graph/out/summary.json
money_graph/out/top_nodes.csv
money_graph/out/viewer.html
money_graph/requirements-ai.txt
money_graph/requirements-dev.txt
money_graph/requirements.txt
money_graph/run.py
money_graph/serve.py
money_graph/server.py
money_graph/starter/README.md
money_graph/starter/requirements.txt
money_graph/starter/starter.py
money_graph/tests/test_api_workflow.py
money_graph/tests/test_container_runtime.py
money_graph/tests/test_universal.py
money_graph/tools/benchmark.py
money_graph/tools/make_synthetic.py
money_graph/ui/app.js
money_graph/ui/index.html
money_graph/ui/styles.css
money_graph/web/e2e/accessibility.spec.ts
money_graph/web/e2e/assistant.spec.ts
money_graph/web/e2e/performance.spec.ts
money_graph/web/e2e/workspace.spec.ts
money_graph/web/favicon.svg
money_graph/web/index.html
money_graph/web/package-lock.json
money_graph/web/package.json
money_graph/web/playwright.config.ts
money_graph/web/postcss.config.js
money_graph/web/public/fonts/OFL.txt
money_graph/web/public/fonts/inter-cyrillic-400-normal.woff2
money_graph/web/public/fonts/inter-cyrillic-600-normal.woff2
money_graph/web/public/fonts/inter-cyrillic-ext-400-normal.woff2
money_graph/web/public/fonts/inter-cyrillic-ext-600-normal.woff2
money_graph/web/public/fonts/inter-latin-400-normal.woff2
money_graph/web/public/fonts/inter-latin-600-normal.woff2
money_graph/web/src/AnalysisTools.tsx
money_graph/web/src/App.tsx
money_graph/web/src/Assistant.tsx
money_graph/web/src/Dashboard.tsx
money_graph/web/src/GraphCanvas.tsx
money_graph/web/src/Inspector.tsx
money_graph/web/src/Investigation.tsx
money_graph/web/src/NodeTable.tsx
money_graph/web/src/Projects.tsx
money_graph/web/src/api.ts
money_graph/web/src/components.tsx
money_graph/web/src/i18n.ts
money_graph/web/src/main.tsx
money_graph/web/src/overviewLayout.ts
money_graph/web/src/store.ts
money_graph/web/src/styles.css
money_graph/web/src/types.ts
money_graph/web/tailwind.config.js
money_graph/web/tsconfig.json
money_graph/web/vite.config.ts
tests/test_assistant.py
tests/test_data_contract.py
tests/test_mvp_contract.py
tests/test_output_schema.py
tests/test_provider_errors.py
tests/test_role_exports.py
tests/test_strict_role_contract.py
Ветки (2)

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

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

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