AAYMA
RU
Войти

TRACE — Граф денег

AML-приложение: восстанавливает направленный граф денежных потоков (2 248 клиентов, 3 119 рёбер, 81 seed), определяет роли и кластеры и выдаёт…

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

О проекте

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

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

Суть

AML-приложение: восстанавливает направленный граф денежных потоков (2 248 клиентов, 3 119 рёбер, 81 seed), определяет роли и кластеры и выдаёт Top-50 на проверку с числовым обоснованием.

Как устроено

Три Parquet-файла → пайплайн (features, flow от seed, roles: 6 ролей кейса + frontier, clusters, temporal-паттерны и короткие циклы, scoring с вкладами факторов, sensitivity, resilience-анализ удаления узлов) → CSV-артефакты (nodes_roles, top_nodes, clusters) → FastAPI + веб-интерфейс на vanilla JS (граф в web worker, карточки, кластеры, устойчивость). AI-ассистент вызывает инструменты графа и ссылается только на существующие gid.

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

  • directed weighted graph
  • role classification
  • community detection
  • seed flow attribution
  • temporal pattern / cycle detection
  • resilience (node removal) analysis
  • sensitivity analysis
  • tool calling

Особенности

Анализ устойчивости: кривые крупнейшей компоненты и достижимости от seed при удалении узлов по приоритету, степени и случайно. Роль frontier для обрыва наблюдения на дальних коленах. Выводы подаются как проверяемые гипотезы, есть детерминированные карточки и перечень на проверку с CSV-экспортом. Тесты проверяют идентичность CSV при повторном расчёте.

Стек

Python 3.11 · FastAPI · uvicorn · pyarrow · JavaScript · Docker Compose · Makefile · pytest

Модели

meta/llama-3.3-70b-instruct (NVIDIA) · gpt-4o-mini


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

README

README.md

TRACE — Граф денег

Объяснимая аналитика транзакционной сети для AML-аналитика. TRACE восстанавливает наблюдаемую структуру денежных потоков, определяет роли участников, выделяет сообщества и формирует список клиентов для первоочередной проверки с числовым обоснованием.

Основной вопрос продукта: «Кого из 2 248 клиентов смотреть первым и почему?» Аналитик получает направленный граф, Top-50, карточки узлов и следующие шаги проверки из одной локальной обработки трёх Parquet-файлов. Каждая роль и позиция в рейтинге связана с рассчитанными признаками. Выводы формулируются как гипотезы для проверки.

Архитектура решения

Возможности

Задача аналитикаВозможность TRACEГде проверить
Восстановить движение средствНаправленный взвешенный граф, суммы и количество переводов, входящие и исходящие связи«Граф», карточка узла
Понять роль клиентаШесть ролей кейса и дополнительная роль frontier, числовое evidence, оценка уверенностиout/nodes_roles.csv, карточка
Выбрать приоритет проверкиTop-50 с объяснением и вкладами факторов в итоговый балл«Топ», out/top_nodes.csv
Выделить структуру сетиКластеры, состав ролей, seed-участники, внутренний оборот и гипотеза«Кластеры», out/clusters.csv
Разобрать связи конкретного клиентаПоиск по полному gid, префиксу и последним цифрам, переход к соседямПоиск и карточка
Найти дополнительные сигналыБыстрые сопоставимые переводы, синхронные поступления, суммы у порога, короткие циклыПризнаки, флаги, API
Оценить структурную значимостьСравнение удаления узлов по приоритету, степени и случайному выбору«Устойчивость»
Подготовить дальнейшую проверкуДетерминированная карточка с фактами и следующими действиями, перечень на проверку с CSV-экспортомКарточка, «Перечень на проверку»
Задать вопрос по сетиAI-ассистент с вызовом инструментов графа и ссылками на существующие gid«Ассистент», при настройке провайдера

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

Все команды выполняются из корня репозитория. Исходные data/nodes.parquet, data/edges.parquet и data/transactions.parquet включены в репозиторий.

git clone https://github.com/BAITC-Hacks/hack-5844ba02-dna.git
cd hack-5844ba02-dna

Подключение LLM через .env

Для работы AI-ассистента загрузите подготовленный файл .env в корень проекта рядом с docker-compose.yml или создайте его из .env.example и заполните ключ провайдера. Файл должен называться именно .env, без расширения .txt. Если файл уже предоставлен командой, сохраните его значения и не заменяйте шаблоном.

Создание файла из шаблона (только если собственного .env ещё нет):

# Linux / macOS
cp .env.example .env
# Windows PowerShell
Copy-Item .env.example .env

Пример содержимого для NVIDIA:

LLM_PROVIDER=nvidia
NVIDIA_API_KEY=<действующий ключ NVIDIA>
NVIDIA_MODEL=meta/llama-3.3-70b-instruct
OUT_DIR=out
DATA_DIR=data

Для OpenAI укажите LLM_PROVIDER=openai, OPENAI_API_KEY=<действующий ключ OpenAI> и OPENAI_MODEL=gpt-4o-mini. Достаточно настроить одного провайдера. Ключи хранятся только в локальном .env, который исключён из Git; файл с ключами не нужно отправлять в репозиторий.

Docker Compose: после размещения .env выполните docker compose up --build --wait. Compose прочитает настройки LLM и передаст их серверу. После изменения ключей повторите эту команду для применения конфигурации.

Прямой запуск Python / Make: загрузите переменные из .env командами раздела «Загрузка .env при локальном запуске», затем запустите сервер. Само наличие файла не загружает его в Python-процесс.

После запуска откройте /api/health: llm_available: true означает, что ключ выбранного провайдера настроен. Затем откройте «Ассистент» и задайте вопрос — успешный ответ проверяет доступность ключа и модели у провайдера. В карточке узла также доступна кнопка «Сформировать справку ИИ».

Docker Compose

Требуются установленный и запущенный Docker с Compose v2, свободный порт 8000 и доступ к сети для первоначальной сборки образа.

docker compose up --build --force-recreate --wait

Compose устанавливает зависимости в образе Python 3.11, выполняет полный расчёт, записывает результаты в out/ и запускает API. Каталог data/ подключён только для чтения. Команда ожидает успешной проверки здоровья сервиса.

Открыть приложение: http://localhost:8000/. Docker копирует актуальный web/ при --build; после изменений фронтенда повторяйте эту команду.

Проверить состояние сервиса: ожидаются "status":"ok" и "out_loaded":true. Основной сценарий работает без .env, API-ключей, личных аккаунтов и платных подписок.

docker compose logs --tail=100 money-graph
docker compose down

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

Linux или macOS

Требуются Python 3.11+ с venv и pip, GNU Make и современный браузер. Версии прямых Python-зависимостей зафиксированы в requirements.txt.

make install && make all

make install создаёт .venv и устанавливает зависимости; make all последовательно рассчитывает данные и запускает сервер. Для выбора интерпретатора можно выполнить make install PYTHON=python3.13.

Только пересчёт, без сервера:

make pipeline

Повторный запуск приложения с готовыми результатами:

make serve

Windows PowerShell

Требуется Python 3.13 с pip и venv. Активация виртуального окружения не нужна: команды используют его интерпретатор напрямую.

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
$env:PYTHONUTF8 = "1"
.\.venv\Scripts\python.exe -m pipeline --data data --out out
.\.venv\Scripts\python.exe -m uvicorn api.main:app --host 127.0.0.1 --port 8000

После запуска открыть http://localhost:8000/. Сервер работает до Ctrl+C. Команда python -m pipeline --data data --out out, выполненная интерпретатором окружения, воспроизводит все аналитические артефакты без ручного редактирования данных.

Для расчёта используется CPU; GPU, облачный кластер, Node.js и сборка frontend не требуются. Основной интерфейс, библиотеки визуализации и шрифты поставляются локально. Интернет нужен для установки зависимостей и, при подключении, внешнего LLM-провайдера.

Проверка решения за пять минут

  1. Запустить расчёт и приложение одним из способов выше. Проверить out_loaded: true в /api/health. Открыть /api/summary: исходный граф содержит 2 248 узлов, 3 119 рёбер и 81 seed.
  2. Открыть «Топ». Проверить ранжированный список и объяснение приоритета. Первые 20 записей доступны также по адресу /api/top?limit=20.
  3. Найти 100000003115284100. Изучить роль, число плательщиков, наблюдаемые суммы, связи с seed и составляющие приоритета. Перейти из карточки к контрагенту.
  4. Сопоставить с 100000004156082100 и 100000005767403100. Первый пример показывает признаки координации, второй — интерпретацию обрыва наблюдения на четвёртом колене.
  5. Открыть «Кластеры» и «Устойчивость». Проверить гипотезу о сообществе и сравнить стратегии удаления 20 узлов. В карточке сформировать следующий шаг проверки и добавить клиента в перечень на проверку.
  6. Проверить выгрузки. В nodes_roles.csv должны быть все 2 248 уникальных gid, в top_nodes.csv — 50 ранжированных записей, а в clusters.csv — описание каждой группы, включая группу изолированных клиентов.

На графе стартовый рабочий срез содержит 180 приоритетных вершин. Для просмотра произвольного gid на схеме установите «Активных вершин» в 2248, минимальные сумму и приоритет в 0 и включите все роли, затем используйте поиск. Стрелки показывают направление перевода; цвет узла — роль, золотая обводка — seed. Для полного идентификатора используйте карточку.

Работа в интерфейсе

  • Разделы «Граф», «Топ», «Кластеры», «Устойчивость» и «Ассистент» объединены общей навигацией; выбранные узел и кластер отражаются в адресе страницы.
  • Карточка показывает оценки в процентах, числовое обоснование, вклад факторов, плательщиков, получателей и следующие шаги проверки.
  • Из сообщества можно перейти к его узлам; в рейтинге есть фильтр по gid и роли и выгрузка CSV.
  • Перечень на проверку позволяет добавлять и удалять клиентов и экспортировать trace-review.csv.
  • Раздел устойчивости показывает кривые размера крупнейшей компоненты и достижимости от seed для доступных стратегий.
  • Чат сохраняет контекст текущего диалога, показывает вызванные инструменты и ссылки на узлы. Доступность LLM определяется настройками сервера.

Автоматические проверки

Сначала выполните пайплайн, чтобы API-тесты использовали результаты исходного датасета.

Linux/macOS:

make pipeline
make test

Windows PowerShell:

$env:PYTHONUTF8 = "1"
.\.venv\Scripts\python.exe -m pipeline --data data --out out
.\.venv\Scripts\python.exe -m pytest -q

Проверки выполняются в базовом режиме без настроенных LLM_PROVIDER, OPENAI_API_KEY и NVIDIA_API_KEY. Тесты проверяют полноту выгрузок, диапазоны оценок, числовые объяснения, правила границы обхода, согласованность сумм транзакций и рёбер, API, сохранность идентификаторов и идентичность трёх CSV при повторном расчёте. Контракт пайплайна также проверяет время расчёта менее 300 секунд.

Для Linux/macOS предусмотрена проверка свежего клона с созданием окружения, расчётом и HTTP-запросами:

bash scripts/clean_check.sh

Результаты контрольного расчёта

Контрольный прогон выполнен 23 сентября 2026 года на исходном датасете: Windows, Python 3.13.5, Intel Core i5-7200U 2.50 GHz, 8 ГБ RAM, зависимости из requirements.txt. Все перечисленные ниже значения получены из созданных артефактов.

ПоказательРезультат
Полный расчёт по таймеру пайплайна, включая раскладку и экспорт111.9 секунды
Узлы с ролью, уверенностью, кластером и объяснением2 248 из 2 248
Приоритетный список50 узлов
Сообщества Louvain44 и отдельная группа 19 изолированных клиентов
ROC AUC модели границы, out-of-fold0.684 на 1 723 обучающих узлах
Узлы четвёртого колена336 вероятных terminal, 108 frontier
Средний ARI для пяти сравнений кластеризации0.660
Пересечение Top-20 при порогах −20% / +20%70% / 85%

Время относится к обработке данных после импорта модулей; установка зависимостей и запуск сервера измерением не охватываются. Пайплайн записывает собственное время и длительность каждого этапа в out/summary.json при каждом запуске.

Распределение ролей: 38 consolidator, 22 coordinator, 15 distributor, 62 transit, 1 409 terminal, 108 frontier, 594 peripheral.

На результатах прогона успешно выполнены четыре проверки контракта выгрузок из tests/test_pipeline.py, 12 API-тестов и два теста контроля данных и временного сопоставления. HTTP-проверка подтвердила доступность /web/index.html, его основных ресурсов, /api/health, /api/summary, рейтинга и карточки узла.

После обновления интерфейса и API дополнительно выполнены все 13 API-тестов итоговой версии, включая проверку главной страницы и её ресурсов. Аналитические модули и исходные данные соответствуют контрольному расчёту выше.

Три примера для аналитического разбора

УзелРезультатЧисловое обоснованиеСледующий шаг аналитика
100000003115284100consolidator, приоритет 1.0008 плательщиков, 2 получателя; вход 2 160 500 KZT, выход 517 000 KZT; направленные пути от 4 seed в пределах двух колен; модельная оценка seed-потока около 850 тыс. KZTПроверить происхождение крупных поступлений и контекст наблюдаемого удержания
100000004156082100coordinator, приоритет 0.9625 плательщиков и 26 получателей, сработал S2; вход 377 366.11 KZT, выход 2 319 556 KZTИзучить веер распределения и запросить данные об источниках средств и остатках
100000005767403100frontier, приоритет 0.421Четвёртое колено, 1 плательщик, вход 1 100 000 KZT; p_terminal = 0.563 < 0.65Запросить исходящие переводы за границей четырёхколенного обхода

Примеры получены расчётом; их gid служат навигацией для демонстрации и не задают правила классификации. Для произвольного узла применяется та же цепочка: наблюдаемые факты → правило → роль → вклад в приоритет → действие аналитика.

Данные и контроль качества

ПараметрЗначение
Период1–31 июля 2026 года
Клиенты2 248, включая 81 seed
Направленные пары переводов3 119
Отдельные транзакции4 840
Глубина обходаЧетыре колена по исходящим переводам
Порог включения5 000 KZT
ИсточникОбезличенный датасет организаторов HackAlem AI
ФайлОдна строкаПоля
data/nodes.parquetКлиентgid, depth, is_seed
data/edges.parquetПара плательщик → получатель за периодsrc, dst, sum_kzt, n_tx, depth
data/transactions.parquetОтдельный переводsrc, dst, date, sum_kzt

При загрузке проверяются обязательные поля, уникальность узлов и пар, конечность и неотрицательность сумм, наличие участников переводов в таблице узлов. Агрегация транзакций сверяется с рёбрами и по сумме, и по количеству операций. В граф включаются все узлы из nodes.parquet, в том числе 19 изолированных seed.

Архитектура и технологии

nodes.parquet + edges.parquet + transactions.parquet
                         |
              Контроль качества данных
                         |
         Направленный взвешенный граф NetworkX
                         |
       Структурные, потоковые и временные признаки
                         |
        Модель границы наблюдения + правила ролей
                         |
      Louvain + сигналы координации + приоритет
                         |
       Проверка стабильности + устойчивость сети
                         |
             CSV / Parquet / JSON в out/
                         |
              GraphStore → FastAPI
                         |
        TRACE: граф, рейтинг, кластеры, карточки
                         |
        AI-ассистент → инструменты того же графа
КомпонентТехнологии и назначение
ПайплайнPython, pandas, NumPy, PyArrow: загрузка, агрегации, признаки и экспорт
ГрафNetworkX: направленные потоки, PageRank, betweenness, Louvain, циклы и достижимость
Модель границыscikit-learn: StandardScaler, логистическая регрессия, стратифицированная кросс-валидация
КонфигурацияYAML: пороги, веса, параметры алгоритмов и фиксированный seed
BackendFastAPI, Uvicorn, Pydantic; GraphStore читает готовые артефакты
ИнтерфейсJavaScript ES modules, Cytoscape.js 3.33.1, Chart.js 4.5.1, HTML/CSS
AI-ассистентOpenAI-совместимый клиент, провайдеры OpenAI и NVIDIA, вызов инструментов графа
Проверки и запускpytest, HTTPX, Make, Docker Compose

Расчёт отделён от просмотра: интерфейс и API используют общие артефакты из out/. Параметры алгоритмов находятся в pipeline/config.yaml; случайные операции используют фиксированный seed: 42. Пользовательские результаты вычисляются из входных данных.

Объяснимые роли участников

Основные обозначения: in_deg и out_deg — число разных плательщиков и получателей; in_kzt и out_kzt — наблюдаемые суммы; pass_ratio = out_kzt / in_kzt; n_seed_upstream — число seed, от которых есть направленный путь длиной не более двух рёбер. Для seed pass_ratio не рассчитывается из-за особенностей сбора выборки.

Базовые правила применяются последовательно: изолированный узел → граница обхода → distributor → consolidator → transit → terminal → peripheral. Первое совпадение определяет базовую роль. Затем отдельный проход проверяет сигналы coordinator и при их наличии заменяет роль, сохраняя исходную роль и сигналы во флагах.

РольФормальное правило
peripheral, изолированныйin_deg + out_deg = 0; узел сохраняется в выгрузке и группе cluster_id = 0
terminal / frontier, границаdepth = 4 и out_deg = 0: при p_terminal ≥ 0.65 — вероятный terminal, иначе frontier; в объяснении явно указана оценка по аналогам
distributorout_deg ≥ 20 и (is_seed или out_kzt ≥ 0.5 × in_kzt)
consolidator(in_deg ≥ 5 и out_kzt ≤ 0.5 × in_kzt) или (n_seed_upstream ≥ 3 и in_deg ≥ 3)
transitНе seed; 1 ≤ in_deg ≤ 3, 1 ≤ out_deg ≤ 3, 0.8 ≤ pass_ratio ≤ 1.2
terminal, внутри обходаout_deg = 0, depth < 4, in_deg ≥ 1, если не сработало более раннее правило
peripheral, остальныеБолее сильное правило не сработало
coordinatorВыполняется хотя бы один из сигналов S1–S3 ниже

Сигналы координации:

  • S1: переводы как минимум двум seed и не менее трёх плательщиков.
  • S2: не менее пяти плательщиков и двадцати получателей.
  • S3: не менее двух плательщиков с базовыми ролями consolidator/distributor, одновременно не менее пяти плательщиков и пяти получателей.

Пороги задают интерпретируемые признаки сбора, веерного распределения и транзита. Их влияние на рейтинг проверяется повторным расчётом при изменении ролевых порогов на −20% и +20%. Это проверка чувствительности выбранных правил.

Что означает role_score

Для пороговых правил используется линейная оценка от 0.5 на пороге до 1.0 на 99.5-м перцентиле признака с ограничением диапазона. Для консолидации и координации выбирается максимальная из соответствующих оценок. Транзит получает прибавку 0.1 за выраженный быстрый пропуск, с ограничением сверху 1.0. Изолированный узел получает 1.0 за однозначность наблюдаемой изоляции; обычные terminal и peripheral — 0.5.

Для границы обхода оценка равна p_terminal у вероятного terminal и 1 − p_terminal у frontier. role_score характеризует выраженность правила или модельной гипотезы и не является вероятностью нарушения.

Как учитывается обрыв четвёртого колена

Для 444 узлов с отсутствующими исходящими на максимальной глубине используется отдельная модель входящего профиля. Она обучается на не-seed узлах глубин 1–3 с наблюдаемым входом; целевая переменная — отсутствие исходящих на этих ранних глубинах.

Признаки модели: логарифмы входящей суммы, среднего платежа и числа входящих транзакций; число плательщиков; первый и последний день поступления. Оценка качества — ROC AUC по out-of-fold прогнозам пяти стратифицированных разбиений. Коэффициенты, число обучающих узлов и AUC сохраняются в out/summary.json.

p_terminal показывает сходство с наблюдаемыми конечными узлами ранних глубин. Даже при присвоении terminal объяснение сохраняет указание на четвёртое колено и модельную природу вывода. Аналитик получает основание для запроса продолжения цепочки.

Приоритет проверки

priority_score объединяет шесть групп сигналов. Числовые признаки и веса ролей преобразуются в процентильные ранги по узлам графа.

КомпонентВесСмысл
seed_flow_kzt25%Модельная оценка потока от исходных seed
n_seed_upstream20%Число seed выше по потоку в пределах двух колен
Роль20%Структурная функция участника
Betweenness15%Посредничество на направленных взвешенных путях
in_deg + out_deg10%Число входящих и исходящих связей
Временные и циклические сигналы10%Быстрые переводы, суммы у порога, циклы, синхронные поступления

Веса ролей до ранжирования: coordinator=1.0, consolidator=0.9, distributor=0.8, transit=0.5, terminal=0.3, frontier=0.2, peripheral=0.0. Временная компонента — среднее рангов fast_pass_share, near_threshold_share, n_cycles и индикатора как минимум трёх плательщиков за день.

После взвешивания для seed применяется множитель 0.7: рейтинг ориентирован на поиск структурных участников за пределами уже известных исходных клиентов. Итог делится на максимальное значение по графу. При равных оценках порядок задаётся gid. Поле score_breakdown содержит конечные вклады, сумма которых воспроизводит priority_score; why поясняет роль и три главных фактора.

Seed-поток оценивается итеративным пропорциональным смешиванием наблюдаемых потоков с контролем сходимости. Для betweenness длина ребра равна 1 / log(1 + sum_kzt). Рейтинг предназначен для приоритизации аналитической проверки; структурный эффект удаления узлов дополнительно исследуется в разделе устойчивости.

Кластеры, временные признаки и устойчивость

Сообщества. Louvain работает на неориентированной проекции с весом log(1 + сумма переводов в обе стороны) и resolution=1.0. Направление сохраняется в исходном графе, потоковых признаках и API. Изолированные клиенты объединяются в отдельную группу 0. Остальные кластеры нумеруются по сумме приоритетов. Для каждого публикуются размер, число seed, внутренний оборот, пять ключевых gid, состав ролей и гипотеза.

Стабильность. Разбиение с seed 42 сравнивается с пятью дополнительными запусками по Adjusted Rand Index. Чувствительность рейтинга оценивается по пересечению Top-20 после изменения ролевых порогов. Метрики сохраняются в summary.json.

Временные сигналы. Быстрый перевод — сопоставимый исходящий платёж в течение 0–2 дней с суммой 50–120% входящего. Один исходящий платёж не используется повторно при сопоставлении внутри узла; учитывается минимум сопоставленных сумм. Дополнительно рассчитываются синхронность плательщиков, всплески активности, доля сумм в диапазоне [5 000; 6 000) KZT и круглых сумм.

Циклы. Рассчитываются направленные циклы длиной до пяти; для взаимной пары применяется минимальная сумма 5 000 KZT. Список циклов доступен в JSON и API с фильтрацией по узлу.

Устойчивость. Для удаления 0, 5, 10, 20 и 50 узлов сравниваются приоритет, степень, обе стратегии без seed и среднее 20 случайных выборок. Измеряются размер крупнейшей слабосвязной компоненты и число достижимых от оставшихся seed узлов.

Выходные файлы

Все артефакты создаются в out/ одним запуском пайплайна.

ФайлСодержание
nodes_roles.csv2 248 строк: все исходные узлы, роли, уверенность, кластер, приоритет, объяснения и признаки
clusters.csvОдна строка на группу: размер, seed, внутренний оборот, ключевые узлы и гипотеза
top_nodes.csvTop-50 по убыванию приоритета с последовательным rank и объяснением why
features.parquetРасширенные структурные, потоковые и временные признаки
graph.jsonУзлы, направленные рёбра, роли, кластеры и рассчитанные координаты
summary.jsonСводка, распределение ролей, пороги, время по этапам, AUC, стабильность, чувствительность и сходимость потока
resilience.jsonСравнение стратегий удаления узлов
cycles.jsonНайденные направленные циклы

Обязательные колонки CSV:

nodes_roles.csv
gid, role, role_score, cluster_id, priority_score, evidence

clusters.csv
cluster_id, n_nodes, n_seed, sum_kzt_internal, top_gids, hypothesis

top_nodes.csv
rank, gid, role, priority_score, why

role_score и priority_score лежат в [0; 1]. evidence содержит числовое объяснение длиной до 200 символов. top_gids перечислены через ;. Дополнительные колонки раскрывают признаки и вклад факторов. Неопределённый pass_ratio, например у seed, сохраняется пустым как неприменимый показатель; обязательные поля роли заполняются для каждого узла.

В вычислениях идентификаторы сохраняются как int64, в CSV записываются целыми десятичными значениями. В JSON и API gid передаются строками, поскольку значения порядка 10^17 превышают точный целый диапазон JavaScript. При открытии CSV в табличном редакторе импортируйте идентификаторы как текст, чтобы сохранить все цифры.

API и AI-ассистент

Интерактивная документация: Swagger UI, ReDoc, OpenAPI JSON. Контракт и примеры: docs/API.md.

Метод и путьНазначение
GET /api/health, GET /api/summaryГотовность и сводка расчёта
GET /api/graph, GET /api/search?q=...Граф и поиск
GET /api/node/{gid}, GET /api/node/{gid}/cardФакты, связи и карточка
GET /api/node/{gid}/egoОкрестность узла с направлением и ограничением размера
GET /api/top, GET /api/clusters, GET /api/cluster/{id}Рейтинг и сообщества
GET /api/path?src=...&dst=..., POST /api/commonНаправленный путь и общие контрагенты
GET /api/cycles, GET /api/resilienceЦиклы и устойчивость
POST /api/pipeline/run, POST /api/reloadПересчёт и перечитывание артефактов
POST /api/assistant, POST /api/node/{gid}/card/llmВопрос по графу и связное объяснение карточки

Ассистент вызывает семь инструментов: поиск, факты узла, соседи, общие контрагенты, кратчайший направленный путь, кластер и рейтинг. Правила и пороги подставляются из конфигурации. Ответ включает cited_gids и журнал tool_calls; ссылки проверяются на наличие узлов в графе. Число раундов вызова инструментов ограничено шестью. Детерминированные роли, рейтинг, карточки и выгрузки рассчитываются локально независимо от LLM.

Настройка провайдера

ПеременнаяНазначениеЗначение по умолчанию в клиенте
LLM_PROVIDERПредпочтительный провайдер: openai или nvidiaАвтовыбор по доступным ключам
OPENAI_API_KEYКлюч для OpenAIПусто
OPENAI_MODELМодель OpenAIgpt-4o-mini
NVIDIA_API_KEYКлюч для NVIDIAПусто
NVIDIA_MODELМодель NVIDIAmeta/llama-3.3-70b-instruct
OUT_DIRКаталог результатов для API<корень проекта>/out, если переменная не задана
DATA_DIRКаталог данных для пересчёта через API<корень проекта>/data, если переменная не задана

Загрузка .env при локальном запуске

В Docker Compose скопируйте .env.example в .env, выберите провайдера и заполните соответствующий ключ, затем повторите команду запуска. .env исключён из Git. При настройке обоих ключей клиент может переходить к другому провайдеру при ошибке.

Сначала разместите заполненный .env в корне проекта. Для локального запуска задайте в нём OUT_DIR=out и DATA_DIR=data либо абсолютные пути к соответствующим папкам. Эти два параметра определяют каталоги, которые использует API; при самостоятельном вызове пайплайна согласуйте с ними --out и --data. В Docker Compose каталоги уже заданы как /app/out и /app/data.

$env:LLM_PROVIDER = "nvidia"
$env:NVIDIA_API_KEY = "<ключ провайдера>"
$env:NVIDIA_MODEL = "meta/llama-3.3-70b-instruct"
Linux/macOS — загрузить собственный файл окружения и запустить сервер:

```bash
set -a
. ./.env
set +a
make serve

Если артефакты ещё не рассчитаны, после загрузки переменных используйте make all.

Windows PowerShell — загрузить непустые значения из .env в текущий процесс и запустить сервер:

Get-Content .env | ForEach-Object {
    if ($_ -match '^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.+?)\s*$') {
        $name = $matches[1]
        $value = $matches[2].Trim().Trim('"').Trim("'")
        [Environment]::SetEnvironmentVariable($name, $value, 'Process')
    }
}
$env:PYTHONUTF8 = "1"
.\.venv\Scripts\python.exe -m uvicorn api.main:app --host 127.0.0.1 --port 8000
```bash
export LLM_PROVIDER=nvidia
export NVIDIA_API_KEY='<ключ провайдера>'
export NVIDIA_MODEL=meta/llama-3.3-70b-instruct

Используйте формат ИМЯ=значение, как в .env.example, без комментариев после значения. После изменения .env остановите сервер, повторно загрузите переменные и запустите его. При наличии обоих ключей клиент может перейти к другому провайдеру при ошибке.

Проверочный вопрос: «Почему узел 100000003115284100 получил высокий приоритет? Покажи его плательщиков и объясни роль». При использовании внешнего LLM вопрос и результаты вызванных инструментов передаются выбранному провайдеру. Для базовой проверки проекта ключи и внешние обращения не нужны.

Интерпретация данных

TRACE учитывает границы исходной выборки в расчётах и объяснениях:

  • Четвёртое колено: отсутствие исходящих интерпретируется через модель аналогов с явным указанием границы наблюдения.
  • Неполный вход: наблюдаемые суммы описывают выгрузку. У seed отношение выхода к входу не рассчитывается; превышение выхода у других узлов отмечается отдельным флагом.
  • Порог 5 000 KZT: сигналы у порога относятся к видимым операциям. Операции ниже порога не наблюдаются.
  • Период и охват: анализ относится к внутрибанковским переводам июля 2026 года; точность даты — день. Сопоставимость переводов по времени и сумме является аналитическим сигналом.
  • Объяснимость: роли и приоритеты обоснованы наблюдаемыми признаками. AUC модели границы относится к её целевой переменной на ранних глубинах, а не к точности выявления нарушений или всех ролей.

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

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

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

КомпонентИзменение на масштабе около 1 млн узлов
Загрузка и признакиПакетная обработка и партиционированный Parquet, вычисления по компонентам и периодам
Графовые алгоритмыКомпактное представление графа и специализированный вычислительный движок вместо объектов NetworkX
ЦентральностиПриближённая betweenness по выборке источников, пересчёт затронутых подграфов
СообществаКластеризация по частям с контролем стабильности и сохранением межкластерных связей
Циклы и устойчивостьОграниченные по глубине и размеру подграфы, отдельные фоновые задания
API и интерфейсСерверная выборка окрестностей, агрегированный обзор сообществ и уровни детализации вместо передачи всего графа
ЭксплуатацияВерсионирование артефактов, кэширование, очередь расчётов и аудит аналитических действий

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

Структура репозитория и использованные компоненты

data/                  исходные данные организаторов
pipeline/              проверки, признаки, роли, модель границы, кластеры и экспорт
pipeline/config.yaml   пороги, веса и параметры воспроизводимого расчёта
api/                   FastAPI, GraphStore, карточки и AI-ассистент
web/                   интерфейс TRACE и локальные frontend-зависимости
out/                   результаты, создаваемые пайплайном
tests/                 проверки пайплайна и API
scripts/               вспомогательные сценарии и проверка свежего клона
starter/               исходный стартовый код организаторов
docs/                  схема решения, API и дополнительные материалы

Проект использует датасет организаторов из data/; описание входных файлов находится в docs/DATASET.md. При разработке использован предоставленный организаторами стартовый код. Аналитические модули решения находятся в pipeline/, сервер и инструменты ассистента — в api/, интерфейс — в web/. При подготовке документации использован AI-агент Codex для анализа реализации, проверки запуска и оформления README.

Python-компоненты и версии раскрыты в requirements.txt. Источники, версии, контрольные суммы и лицензии включённых frontend-компонентов и шрифтов перечислены в web/vendor/VERSIONS.md: Cytoscape.js и Chart.js — MIT, Inter и JetBrains Mono — OFL-1.1, SVG-иконки по формам Lucide — ISC. Внешние LLM-сервисы перечислены в разделе настройки; основной расчёт использует только предоставленные данные.

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

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

Aibek 30kuznargi 21KapDan04 5januzaj2018 1

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

  • 2026-09-23 17:54newAibek
  • 2026-09-23 17:49docs: update final interface and explain LLM env setupKapDan04
  • 2026-09-23 17:43fix: refine frontendAibek
  • 2026-09-23 17:33docs: document TRACE setup, methodology and verified resultsKapDan04
  • 2026-09-23 17:28chore: normalize project folder layoutAibek
  • 2026-09-23 17:27integration: verify merged backend and frontendAibek
  • 2026-09-23 17:11web: preserve string GIDs in graph searchkuznargi
  • 2026-09-23 17:11web: refine graph node and edge visualskuznargi
Все коммиты (57)
  • 2026-09-23 17:11feat: added frontend partkuznargi
  • 2026-09-23 17:05out ignoreAibek
  • 2026-09-23 16:57fix: make Docker startup reproducibleAibek
  • 2026-09-23 16:40docs: add Swagger API documentationAibek
  • 2026-09-23 16:32merge main into backend integrationAibek
  • 2026-09-23 16:19backend: add acceptance tests and submission docsAibek
  • 2026-09-23 16:12backend: ground AI assistant in graph storeAibek
  • 2026-09-23 16:10backend: harden reproducible startupAibek
  • 2026-09-23 16:08backend: complete cards and graph navigationAibek
  • 2026-09-23 16:06backend: complete graph API coreAibek
  • 2026-09-23 16:01docs: add team audit and review evidenceKapDan04
  • 2026-09-23 16:00feat: added updated datakuznargi
  • 2026-09-23 15:55pipeline: finalize resilience validation and docskuznargi
  • 2026-09-23 15:43pipeline: scope sensitivity thresholdskuznargi
  • 2026-09-23 15:42pipeline: tighten coordinator S3 rulekuznargi
  • 2026-09-23 15:40pipeline: mark isolated peripheral nodeskuznargi
  • 2026-09-23 15:39chore: add repository checkpointKapDan04
  • 2026-09-23 15:39pipeline: align runtime configkuznargi
  • 2026-09-23 15:20merge main into stage2 integrationAibek
  • 2026-09-23 15:11stage 2Aibek
  • 2026-09-23 15:11stage2: verify integration candidateAibek
  • 2026-09-23 15:05stage2: add deterministic layout fallbackAibek
  • 2026-09-23 15:05stage2: keep pipeline portable without scipyAibek
  • 2026-09-23 15:02chore: remove outdated duplicate md filekuznargi
  • 2026-09-23 15:02stage2: frontier modelkuznargi
  • 2026-09-23 15:02stage2: resiliencekuznargi
  • 2026-09-23 15:02stage2: seed flow attributionkuznargi
  • 2026-09-23 15:02stage2: temporal patterns and cycleskuznargi
  • 2026-09-23 15:02stage2: stabilitykuznargi
  • 2026-09-23 15:02stage2: tighten coordinator signal s3kuznargi
  • 2026-09-23 15:02feat: last updateskuznargi
  • 2026-09-23 15:02stage2: pin binary-compatible pyarrowAibek
  • 2026-09-23 15:00stage2: fix clean-check portabilityAibek
  • 2026-09-23 14:55stage2: block E grounded assistantAibek
  • 2026-09-23 14:51stage2: block D ego networks and pathsAibek
  • 2026-09-23 14:49stage2: block C resilience and summaryAibek
  • 2026-09-23 14:46stage2: block B node cards and review actionsAibek
  • 2026-09-23 14:40stage2: block A reproducible startupAibek
  • 2026-09-23 14:27fix: complete must-have pipeline contractkuznargi
  • 2026-09-23 14:23fix: duplicate mdAibek
  • 2026-09-23 14:19Merge pull request #1 from BAITC-Hacks/must-have-viewerjanuzaj2018
  • 2026-09-23 14:16feat: added out, starter and etckuznargi
  • 2026-09-23 14:14mockAibek
  • 2026-09-23 14:14feat: add must-have money graph pipelinekuznargi
  • 2026-09-23 13:59feat: added config.yamlkuznargi
  • 2026-09-23 13:55yamlAibek
  • 2026-09-23 13:51.gitignoreAibek
  • 2026-09-23 13:48docs: describe project structure and expected deliverablesKapDan04
  • 2026-09-23 13:38reqAibek
Структура репозитория (74 файлов)
.dockerignore
.env.example
.gitignore
Dockerfile
Makefile
README.md
agent-docs/config.yaml
api/__init__.py
api/assistant.py
api/cards.py
api/graph_store.py
api/llm.py
api/main.py
data/edges.parquet
data/nodes.parquet
data/transactions.parquet
docker-compose.yml
docs/API.md
docs/BREV_SETUP.md
docs/DATASET.md
docs/DEMO_NODES.md
docs/METHODOLOGY.md
docs/STAGE2_INTEGRATION_REPORT.md
docs/solution-diagram.svg
pipeline/FIX_REPORT_20260923.md
pipeline/__init__.py
pipeline/__main__.py
pipeline/clusters.py
pipeline/config.yaml
pipeline/export.py
pipeline/features.py
pipeline/flow.py
pipeline/frontier.py
pipeline/layout.py
pipeline/load.py
pipeline/resilience.py
pipeline/roles.py
pipeline/scoring.py
pipeline/sensitivity.py
pipeline/temporal.py
requirements.txt
scripts/clean_check.sh
scripts/make_mock_out.py
tests/conftest.py
tests/test_api.py
tests/test_pipeline.py
web/PERF.md
web/app.js
web/index.html
web/js/api.js
web/js/assistant.js
web/js/card.js
web/js/clusters.js
web/js/format.js
web/js/graph.js
web/js/mock.js
web/js/resilience.js
web/js/state.js
web/js/top.js
web/js/worker.js
web/mocks/assistant.json
web/mocks/card.json
web/mocks/clusters.json
web/mocks/graph.json
web/mocks/health.json
web/mocks/node.json
web/mocks/path.json
web/mocks/pipeline-run.json
web/mocks/resilience.json
web/mocks/search.json
web/mocks/summary.json
web/mocks/top.json
web/stage2-layout.js
web/style.css
Ветки (6)

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

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

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