AAYMA
RU
Войти

Tuzet

Локальная AML-платформа по графу переводов: каждому из 2 248 клиентов назначает структурную роль с role_score, приоритет проверки из пяти вкладов…

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

О проекте

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

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

Суть

Локальная AML-платформа по графу переводов: каждому из 2 248 клиентов назначает структурную роль с role_score, приоритет проверки из пяти вкладов, находит мотивы (fan-in/out, циклы, scatter-gather, транзитные цепочки), показывает сообщества, устойчивость и чувствительность рейтинга.

Как устроено

Parquet-данные загружаются в направленный граф NetworkX. Считаются PageRank, betweenness и сообщества Louvain на ненаправленной проекции. Роли (consolidator, transit, distributor, terminal, coordinator, peripheral) назначаются по явным правилам с порогом 0.50, для transit учитывается FIFO-совместимость за 1–2 дня. Приоритет складывается из структуры, связи с seed, потока, типологии и времени; веса лежат в scoring.yaml. Запуски публикуются атомарно с хешами входа, выхода и конфига. FastAPI отдаёт данные в React/Cytoscape UI. LLM (опционально) только выбирает разрешённый тип вопроса, числа и доказательства формирует backend.

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

  • NetworkX
  • PageRank
  • betweenness
  • Louvain
  • детекция мотивов (fan-in, fan-out, scatter-gather, циклы)
  • FIFO-совместимость по времени
  • анализ чувствительности весов
  • сценарии структурной устойчивости (disruption)
  • детерминированные хеши артефактов

Метрики

Полный пересчёт 49,08 с (лимит 300 с); 52 pytest, 2 Vitest, 6 Playwright-сценариев пройдены; воспроизводимые хеши выходов

Особенности

Деньги считаются в целых тиынах, запуски воспроизводимы (одинаковые хеши при повторе) и публикуются атомарным указателем. Роль, мотив, приоритет и evidence разведены как отдельные сущности, есть анализ чувствительности рейтинга к весам. Код импортирован одним коммитом за час до конца, поэтому история разработки в репозитории не видна.

Стек

Python · uv · pandas · PyArrow · NumPy · SciPy · NetworkX · FastAPI · Pydantic · React · TypeScript · Vite · TanStack Query · Cytoscape.js · Recharts · pytest · Vitest · Playwright

Модели

gpt-4.1-mini


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

README

README.md

Tuzet

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

Исходные материалы кейса лежат в data/ и starter/ и не изменяются расчётом. Формулы и ограничения описаны в методике, границы модулей — в архитектуре, короткий сценарий показа — в демо.

Что решает продукт

Аналитик получает один завершённый расчёт и может за минуту открыть любого клиента по gid.

  • Сохраняет всех клиентов из исходной выборки, включая изоляты и узлы на границе наблюдения.
  • Назначает одну основную структурную роль и отдельный role_score: соответствие правилу, а не вероятность нарушения.
  • Считает приоритет проверки из пяти вкладов: структура, связь с seed, поток, типология и время.
  • Находит мотивы: fan-in, fan-out, схождение нескольких seed, цепочка транзита, цикл, scatter-gather и повторяющийся маршрут. У каждого мотива есть статус временной совместимости и внутренние ID операций.
  • Показывает направленное окружение, операции, сообщества, сценарии структурной устойчивости и чувствительность рейтинга к весам.
  • Публикует три обязательные выгрузки и полный набор артефактов с хешами входа, выхода и конфигурации.
  • Опционально отвечает на ограниченный вопрос ассистента фактами из уже посчитанного запуска. Без ключа модели поиск, граф и карточки продолжают работать.

Наблюдение неполное: граф собран исходящими переводами от seed не дальше четырёх переходов, суммы ниже 5 000 KZT отсутствуют, даты известны до дня. Поэтому terminal означает наблюдаемую конечную точку, а coordinator — структурную гипотезу, а не «организатора».

Каждый клиент получает роль с наибольшим score среди тех, что достигли 0.50. Если ни одна роль порог не достигла, ставится peripheral.

РольПравило
consolidatorНе менее 3 входящих контрагентов. Score учитывает степень, сумму, число входящих операций и охват seed.
transitНе seed; есть вход и выход; исходящий оборот составляет 0.80–1.20 от входящего. Score: 70% баланса оборота и 30% FIFO-совместимости за 1–2 дня.
distributorНе менее 5 получателей. Score: число получателей 50%, исходящие операции 30%, оборот 20%.
terminalЕсть вход, нет наблюдаемых исходящих, depth < 4, после последнего поступления прошло минимум 2 дня. Score начинается с 0.50 и ограничен 0.75.
coordinatorBetweenness не ниже 90-го процентиля положительных значений и достижимость от 2+ seed либо связи с 2+ соседними сообществами.
peripheralНи одна основная роль не набрала 0.50. При обрезке по глубине или времени score ограничен 0.49.

Какие технологии используются

Расчёт и API:

  • Python 3.11, uv и зафиксированный uv.lock
  • pandas и PyArrow для Parquet и CSV
  • NumPy и SciPy для числовых признаков
  • NetworkX для направленного графа, PageRank, betweenness и Louvain на ненаправленной проекции сообществ
  • PyYAML и типизированная модель конфигурации config/scoring.yaml
  • FastAPI, Pydantic и Uvicorn для локального API и раздачи интерфейса
  • httpx для опционального запроса к OpenAI-compatible API

Интерфейс:

  • React 18 и TypeScript
  • Vite для сборки
  • TanStack Query для запросов к API
  • Cytoscape.js для направленного графа
  • Recharts для дневной динамики операций

Проверки:

  • pytest и Ruff для Python
  • Vitest и ESLint для интерфейса
  • Playwright и Chromium для сквозных сценариев в браузере

Деньги считаются в целых тиынах. Аналитические модули не зависят от HTTP, интерфейса и языковой модели. API только читает уже завершённый запуск.

Как запустить

Нужны Python 3.11+, Node.js 20.19+ и uv. Команды выполняются из корня репозитория.

Установка и сборка интерфейса выполняются один раз:

cd frontend && npm ci && npm run build && cd ..
uv sync --locked --extra dev --no-editable

Один запуск пересчитывает data/ и открывает Tuzet на http://127.0.0.1:8000:

uv run --locked --no-editable money-graph demo --data data --out artifacts/latest

Расчёт и просмотр можно разделить:

uv run --locked --no-editable money-graph analyze --data data --out artifacts/latest
uv run --locked --no-editable money-graph serve --artifacts artifacts/latest

--config path/to/scoring.yaml у analyze и demo подставляет другую версию порогов и весов. Без параметра используется config/scoring.yaml. После изменения Python-кода или повторной сборки frontend пакет нужно обновить:

uv sync --locked --extra dev --reinstall-package money-graph --no-editable

Сборка wheel не запускает npm. Сначала соберите frontend, затем выполните uv build. Сборка завершится ошибкой, если нет index.html или указанных в нём JS/CSS. Готовый wheel содержит интерфейс и стандартную конфигурацию.

artifacts/latest — атомарный указатель на каталог в artifacts/.money_graph_runs/. Неудачная публикация не затирает предыдущий успешный запуск. Чтобы открыть новый расчёт, сервер перезапускают. В интерфейсе доступны обзор, поиск по gid, фильтры, направленный граф на 1–2 перехода, карточка клиента, операции, мотивы, сообщества, устойчивость, чувствительность, ассистент и ссылки на CSV. Тёмная тема включена по умолчанию, светлая переключается в верхней панели. Схема API открывается на /docs.

AI-ассистент

По умолчанию ассистент выключен. Ключ хранится только в .env, этот файл не попадает в Git.

cp .env.example .env

В .env заполните MONEY_GRAPH_LLM_API_KEY. Пример указывает на https://api.openai.com/v1/chat/completions и модель gpt-4.1-mini. Для другого совместимого endpoint измените MONEY_GRAPH_LLM_URL и MONEY_GRAPH_LLM_MODEL. Переменные загружаются до запуска сервера:

set -a
source .env
set +a
uv run --locked --no-editable money-graph demo --data data --out artifacts/latest

Модель выбирает только разрешённый тип вопроса. Числа и доказательства формирует backend из текущего запуска. Провайдеру передаются вопрос и выбранный gid.

Какие шаги нужны для проверки решения

1. Подготовить окружение

Повторите установку из раздела «Как запустить»: npm ci, npm run build, затем uv sync --locked --extra dev --no-editable. Для браузерных тестов один раз установите Chromium:

cd frontend && npx playwright install chromium && cd ..

2. Прогнать автоматические проверки

uv run --locked --no-editable ruff check src tests
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 uv run --locked --no-editable pytest -q
cd frontend && npm run build && npm run lint && npm run test && npm run test:e2e

Pytest проверяет контракт данных, роли, мотивы, денежные агрегаты, публикацию артефактов и API. Vitest проверяет клиент API. Playwright открывает собранный интерфейс на готовом artifacts/latest и проходит обзор, карточку, граф, мотивы, сообщества, устойчивость, чувствительность, состояние выключенного ассистента и скачивание трёх CSV. Для E2E каталог artifacts/latest уже должен существовать, поэтому перед ним нужен хотя бы один analyze или demo.

Если менялись Python или интерфейс, перед тестами снова выполните сборку frontend и uv sync --locked --extra dev --reinstall-package money-graph --no-editable.

3. Пересчитать данные и сверить выгрузки

/usr/bin/time -p uv run --locked --no-editable money-graph analyze --data data --out artifacts/latest

Ограничение задания — 300 секунд на предоставленном наборе, включая запись и переключение указателя. После расчёта проверьте:

  • artifacts/latest/nodes_roles.csv содержит все 2 248 клиентов и колонки gid,role,role_score,cluster_id,priority_score,evidence.
  • artifacts/latest/clusters.csv содержит cluster_id,n_nodes,n_seed,sum_kzt_internal,top_gids,hypothesis.
  • artifacts/latest/top_nodes.csv содержит не меньше 20 строк и колонки rank,gid,role,priority_score,why.
  • artifacts/latest/manifest.json содержит конфигурацию и её хеш, хеши входа и выхода, версии, предупреждения и длительности фаз.
  • Повторный запуск даёт те же хеши выходных файлов.
  • В выборке сохранены 4 840 операций.

Три CSV для сдачи обновляются так:

for name in nodes_roles clusters top_nodes; do cp "artifacts/latest/$name.csv" deliverables/; done

4. Проверить интерфейс вручную

Запустите money-graph serve --artifacts artifacts/latest или demo и откройте http://127.0.0.1:8000.

  1. На обзоре видны число клиентов, связей и операций, а также первые клиенты для проверки.
  2. Поиск по gid открывает карточку: роль, evidence, пять вкладов priority, правила и ограничения.
  3. В графе видны направленные связи на 1 и 2 перехода. Фильтры меняют список и не пересчитывают оценки.
  4. У клиента открываются операции и мотивы с подтверждающими рёбрами.
  5. Разделы сообществ, устойчивости и чувствительности открываются без нового расчёта.
  6. Без ключа в .env ассистент показывает, что AI отключён, а остальные разделы работают.
  7. Со страницы «О расчёте и выгрузки» скачиваются nodes_roles.csv, clusters.csv и top_nodes.csv.
  8. На ширине экрана телефона доступны обзор, граф и карточка.

Интерактивная схема запросов доступна на http://127.0.0.1:8000/docs. Ответ /api/health содержит run_id открытого запуска.

5. Что считать успешным результатом

Решение готово, если сохранены все 2 248 клиента и 4 840 операций, три CSV валидны, топ содержит минимум 20 строк, любой gid находится в браузере, а полный расчёт укладывается в 300 секунд. Роль, мотив, приоритет и evidence остаются разными сущностями. Тексты интерфейса не утверждают вину.

Проверка 23.09.2026 на предоставленных данных: 52 Python-теста, 2 Vitest-теста и 6 Playwright-сценариев прошли; Ruff и ESLint прошли; npm audit сообщил 0 уязвимостей. Полный пересчёт с публикацией занял 49,08 секунды при повторном запуске; хеши всех 11 выходных файлов, включая три CSV, совпали между двумя запусками. Сохранены 2 248 клиентов, 4 840 операций и 19 изолятов. Методика в manifest — 1.2.2, формат артефактов — 4. Реальный сетевой ответ LLM в той проверке не выполнялся: ключ провайдера не был задан.

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

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

qrlbk 5

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

  • 2026-09-23 17:24Truncate the mobile topbar title so it stays beside the search field.qrlbk
  • 2026-09-23 17:15Rename the interface to Tuzet and refresh assistant status while the page stays open.qrlbk
  • 2026-09-23 17:14Describe what Tuzet solves, how to run it, and how to verify the result.qrlbk
  • 2026-09-23 16:58Keep the project README when merging the hackathon stub.qrlbk
  • 2026-09-23 16:58Import the money-graph analysis app for the hackathon repository.qrlbk
Структура репозитория (69 файлов)
.env.example
.gitignore
AGENTS.md
Document 6.pdf
MANIFEST.in
README.md
agentic.md
config/scoring.yaml
data/edges.parquet
data/nodes.parquet
data/transactions.parquet
deliverables/clusters.csv
deliverables/nodes_roles.csv
deliverables/top_nodes.csv
docs/architecture.md
docs/demo.md
docs/development-plan.md
docs/methodology.md
frontend/.eslintrc.cjs
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/playwright.config.ts
frontend/postcss.config.cjs
frontend/src/App.tsx
frontend/src/Graph.tsx
frontend/src/api.test.ts
frontend/src/api.ts
frontend/src/components/ClientList.tsx
frontend/src/components/Shell.tsx
frontend/src/components/UI.tsx
frontend/src/data/ui.ts
frontend/src/main.tsx
frontend/src/pages/CatalogPages.tsx
frontend/src/pages/ClientPages.tsx
frontend/src/pages/ExperimentPages.tsx
frontend/src/pages/InfoPages.tsx
frontend/src/styles.css
frontend/tests/app.spec.ts
frontend/tests/assistant.spec.ts
frontend/tsconfig.json
frontend/vite.config.ts
pyproject.toml
setup.py
src/money_graph/__init__.py
src/money_graph/analytics.py
src/money_graph/api.py
src/money_graph/assistant.py
src/money_graph/cli.py
src/money_graph/config_model.py
src/money_graph/disruption.py
src/money_graph/evidence.py
src/money_graph/exports.py
src/money_graph/features.py
src/money_graph/ingestion.py
src/money_graph/motifs.py
src/money_graph/scoring.py
src/money_graph/scoring.yaml
src/money_graph/temporal.py
starter/README.md
starter/requirements.txt
starter/starter.py
tests/conftest.py
tests/test_analytics.py
tests/test_api.py
tests/test_assistant.py
tests/test_contracts.py
tests/test_corrections.py
uv.lock

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

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

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