AAYMA
RU
Войти

Граф денег

Воспроизводимый пайплайн и веб-интерфейс для AML-аналитика: роль, role_score, evidence и rule_id у каждого из 2248 узлов, 72 кластера Louvain с…

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

О проекте

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

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

Суть

Воспроизводимый пайплайн и веб-интерфейс для AML-аналитика: роль, role_score, evidence и rule_id у каждого из 2248 узлов, 72 кластера Louvain с гипотезами, топ-30 приоритетов с обоснованием, оценка устойчивости сети и вопросы к графу словами.

Как устроено

Три Parquet собираются в направленный взвешенный граф, для узлов считаются степени, обороты, pass_through, PageRank, betweenness, HITS, точки сочленения, циклы и временные паттерны (сквозной транзит за 2 суток, синхронный сбор, дробление). Для 444 узлов 4-го колена, обрезанных обходом, логистическая регрессия на 10 признаках входящего профиля оценивает terminal_p. Дальше 12 правил ролей с порогами из квантилей, кластеризация Louvain (seed=42) и приоритет как взвешенная сумма перцентилей, скор seed умножается на 0.5. ask.py отвечает на вопросы детерминированно по графу, LLM (если задан ключ) только переформулирует ответ.

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

  • PageRank
  • betweenness
  • HITS
  • articulation points
  • Louvain
  • logistic regression (censoring model)
  • quantile thresholds
  • cycle detection
  • robustness via node removal

Метрики

terminal_p AUC 0.64 на невиданном колене против 0.73 in-sample; изъятие топ-20 отрезает 9,4% оборота против 1,7% у случайных 20; пересчёт ~15 с

Особенности

Учтена ловушка цензурирования: отсутствие исходящих у узлов 4-го колена объясняется глубиной обхода, а не тем, что деньги осели. Для этих узлов отдельная модель terminal_p с проверкой переносимости. Пороги выводятся из квантилей данных, у каждого узла указан rule_id, ранжирование проверено изъятием против случайной базы, пайплайн выполняет 17 самопроверок требований ТЗ.

Стек

Python · JavaScript · HTML/CSS · Parquet


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

README

README.md

Граф денег

Кого из 2248 клиентов AML-аналитику смотреть первым и почему — роли, кластеры и ранжированный список с обоснованием в числах, одной командой из транзакционной сети.

→ Живое демо: zhetysu-team.kz

Открывается без регистрации и без наших аккаунтов.


1. Название проекта

Граф денег — восстановление финансовой структуры организованной группы по транзакционной сети. Команда Zhetysu · HackAlem AI, 23 сентября 2026 · кейс «Граф денег».

Что этопайплайн + веб-интерфейс: роли участников сети, кластеры, топ-лист приоритетов
Для когоAML-аналитик подразделения финансового мониторинга банка второго уровня
Клиентов в сети2 248, из них 81 известен следствию (seed)
Связей / транзакций3 119 / 4 840
Оборот в графе365,9 млн KZT, июль 2026
Полный пересчёт~15 секунд от сырых .parquet до выгрузок (лимит ТЗ — 5 минут)
Ключи и интернетне нужны для запуска и проверки

2. Краткое описание: какую проблему решает и для кого

Для кого. AML-аналитик подразделения финансового мониторинга банка второго уровня.

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

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

Методическое ядро: почему «нет исходящих» не значит «деньги осели»

Граф собран обходом от 81 seed по исходящим переводам на 4 колена, поэтому у 444 узлов последнего колена исходящих нет по построению. Наивное out_deg == 0 ⇒ terminal дало бы 444 ложных «конечных получателя». Узлы разделены по наблюдаемости (terminal_status):

СтатусУзловСмысл
observed_sink1091деньги пришли и остались; исходящие проверены обходом
observed_forwarder694деньги пришли и ушли дальше
unknown_truncated4444-е колено, исходящие никто не выгружал
no_edges19seed без единого ребра в выгрузке

Для обрезанных роль по отсутствию рёбер не назначается — работает модель terminal_p с высоким порогом (подробности и цифры — в таблице ниже). Вторая ловушка — заниженный вход у seed: правила транзита и осаждения по доле пропуска (R3a, R3b, R3d, R4b) к seed не применяются, а seed с исходящими без других признаков получает transit с уверенностью 0.55.

Чем решение отличается от «пайплайн + три CSV»

ЧтоКак подтверждается
Ловушка обрыва на 4-м колене учтена моделью, а не правилом out_deg == 0. 444 узла без исходящих — артефакт обхода. Для них считается terminal_p логистической регрессией на 10 признаках входящего профиля, обученной на коленах 1–3переносимость проверена на невиданном колене: обучение на коленах 1–2, проверка на колене 3 — AUC 0.64 против 0.73 на своей выборке. Поэтому порог высокий: terminal получают 86 из 444, остальные 358 честно остаются peripheral. Отчёт — out/censoring_report.json
Пороги посчитаны из распределений данных, а не заданы рукамив коде (pipeline/config.py) заданы только уровни квантилей; числовые значения порогов считаются на прогоне и выгружаются с формулировкой в out/thresholds.json
rule_id у каждого узла — по любому gid видно, какое из 12 правил сработалоколонка rule_id в out/nodes_roles.csv, таблица правил — раздел 4
Собственное ранжирование проверено изъятиемизъятие топ-20 по нашему приоритету отрезает 9,4% оборота, изъятие 20 случайных узлов (20 повторов) — 1,7%, в 5,7 раза меньше. Кривые для N = 0…50 — out/robustness_report.json
Вопрос словами без выдуманных цифрответ считается по графу детерминированно (ask.py); языковая модель, если ключ задан, только переформулирует готовый текст. Без ключа работает полностью
Результат воспроизводим бит в битдва прогона дают одинаковые nodes_roles.csv, clusters.csv, top_nodes.csv; Louvain и случайная база изъятия — с seed=42

Соответствие обязательным требованиям ТЗ (раздел 7)

№Требование ТЗГде выполненоКак проверить
1Один запуск от .parquet до трёх выгрузок, < 5 минутpipeline/run.pyшаг 1 раздела 8: ~15 с
2Роль, role_score, evidence у всех 2248 узловout/nodes_roles.csvшаг 2 раздела 8
3Формальное правило с порогом для каждой ролиpipeline/roles.py, out/thresholds.json, колонка rule_idшаг 3 раздела 8
4Кластеры: размер, число seed, оборот, гипотезаout/clusters.csvшаг 2 раздела 8
5Топ-лист ≥ 20 узлов с обоснованием + схема сетиout/top_nodes.csv (30 строк), web/шаги 2 и 4 раздела 8

Пайплайн сам проверяет эти требования в конце каждого прогона (функция verify в pipeline/run.py, 17 проверок) и завершается с кодом 1, если хоть одна не прошла.


3. Что реализовано

ФункцияЧто именно
Воспроизводимый пайплайнодна команда от сырых .parquet до выгрузок, без ручных шагов, ~15 секунд
Роль у каждого из 2248 узловроль из словаря ТЗ, role_score, cluster_id, priority_score, evidence (до 200 символов, всегда с числами) и rule_id. Итог: terminal 1260, peripheral 483, transit 381, distributor 54, consolidator 43, coordinator 27
12 правил с порогами из квантилейтаблица правил — раздел 4
Отделение конечных получателей от обрезанных обходоммодель terminal_p — раздел 2, «Методическое ядро»
КластеризацияLouvain, 72 кластера (71 сообщество и кластер -1 для 19 seed без рёбер); по каждому размер, число seed, внутренний оборот, состав по ролям, оборот наружу и внутрь, гипотеза
Топ-лист приоритетов30 узлов; в колонке why — какие факты подняли узел и в какие верхние проценты графа он попал
Временные паттерныпо отдельным транзакциям: сквозной транзит за двое суток — 233 узла, синхронный сбор (3+ плательщика в один день) — 38, дробление — 74; входят в evidence, в приоритет и выгружаются колонками
Возвратные потокивзаимные пары A→B и B→A (mutual_pair, 266 узлов), направленные циклы длиной до 6 (in_cycle, 303 узла)
Оценка устойчивости сетиизъятие топ-N против случайных N в пайплайне и ползунок изъятия с пересчётом компонент в интерфейсе
Вопросы словамиPOST /api/ask и вкладка вопросов: «кого смотреть первым», «кто собирает деньги с X и Y», «куда уходят деньги от X», «откуда деньги у X», «покажи координаторов», «какие есть кластеры», карточка узла по gid
Веб-интерфейссхема сети с направлением потоков и цветом ролей, поиск по gid, досье узла, очередь проверки, сообщества, границы данных, изъятие узлов, вопросы; светлая и тёмная темы, адаптив под телефон
Раскладка схемы в пайплайнеseed в центре, колена кольцами наружу, кластеры клиньями; координаты одинаковы при каждом прогоне

4. Как работает решение: от входных данных до результата

3 × .parquet ──► граф ──► признаки узла ──► модель обрыва ──► правила ролей ──► кластеры
                                                                                  │
         веб-интерфейс ◄── graph.json ◄── выгрузки CSV ◄── приоритет и топ-лист ◄─┘
  1. Загрузка и проверка данных (data.py): 2248 узлов, 3119 рёбер, 4840 транзакций. Суммы рёбер сверяются с транзакциями; при битых данных прогон останавливается с понятным сообщением.
  2. Граф и признаки (graphbuild.py, features.py): направленный взвешенный граф, степени, обороты, доля пропуска pass_through = out_kzt / in_kzt, PageRank, betweenness, HITS, точки сочленения, циклы, достижимость вниз по потоку.
  3. Модель обрыва (censoring.py): вероятность terminal_p для 444 узлов 4-го колена.
  4. Временные паттерны (patterns.py): по датам транзакций.
  5. Роли (roles.py): правила применяются в фиксированном порядке, первое сработавшее побеждает. Значения порогов на этих данных:
ПравилоРольУсловиеУзлов
R0peripheralнет ни одного ребра в выгрузке19
R1distributorout_deg >= 11 (квантиль 0.975)54
R2consolidatorin_deg >= 4 (квантиль 0.975) и (out_deg <= max(2, in_deg/2) или pass_through <= 0.5)43
R3atransit0.8 <= pass_through <= 1.267
R3btransitpass_through > 1.2 — отдал больше, чем получил: приток извне выборки249
R3ctransitseed с исходящими: вход у seed занижен, роль по исходящему профилю40
R3dtransit≥60% исходящей суммы ушло в пределах 2 суток и pass_through >= 0.625
R4aterminalисходящих нет, и они проверены обходом (depth <= 3)1069
R4bterminalдальше уходит ≤26% полученного (квантиль 0.2) — сумма осела105
R4cterminalобрезан 4-м коленом и terminal_p >= 0.7086
R5peripheralсмешанный профиль ниже всех порогов464
R6coordinator≥2 плательщика-сборщика (in_deg >= 4) или ≥2 seed-плательщика, in_kzt в верхних 5% (614 тыс. KZT), не seed27
  1. Кластеры (clusters.py): Louvain на неориентированной проекции, вес — сумма, гипотеза собирается из состава кластера.
  2. Приоритет (priority.py): взвешенная сумма перцентилей — объём потока 0.25, число плательщиков 0.18, позиция в сети 0.14, связь с seed 0.12, роль 0.12, временные паттерны 0.10, осевшая сумма 0.09. Скор seed умножен на 0.5: их следствие уже знает, инструмент нужен, чтобы показать невидимую часть сети.
  3. Выгрузки и самопроверка (export.py, run.py).

Пример строки out/top_nodes.csv (ранг 1, gid 100000003115284100, coordinator): «вход 2.2 млн KZT от 8 плательщиков (seed: 2); выход 517 тыс. KZT на 2 получателей; осело 1.6 млн KZT; 7 плательщиков в один день…»

Полное описание метода — pipeline/METHOD.md; схема решения — docs/solution-map.md и docs/solution-map.svg.


5. Технологии

СлойВыбор
ЯзыкPython 3.10
Ядро анализаpandas 2.3.3, numpy 2.2.6, networkx 3.4.2, pyarrow 25.0.1, scipy 1.15.3
Модель для обрезанных узловлогистическая регрессия, реализована на numpy (без ML-библиотек)
Сервер демонстрацииFastAPI 0.141.1 + uvicorn 0.53.0, файл server.py
ИнтерфейсHTML/CSS/JavaScript без сборки и без внешних CDN, отрисовка на canvas
Языковая модель (необязательно)OpenAI API, gpt-4o-mini — только переформулировка готового ответа, если задан ключ

Версии указаны те, на которых решение проверялось; допустимые диапазоны — в requirements.txt. GPU, облако и платные сервисы для воспроизведения не нужны.


6. Архитектура

case/data/*.parquet          исходные данные организаторов (только чтение)
        │
        ▼
pipeline/                    ядро анализа, запуск: python -m pipeline.run
  config.py                  уровни квантилей и веса приоритета в одном месте
  data.py                    загрузка и проверки консистентности
  graphbuild.py              направленный взвешенный граф
  features.py                признаки узла: степени, обороты, пропуск, посредничество, циклы
  censoring.py               модель terminal_p для узлов, обрезанных обходом
  patterns.py                временные паттерны: сквозной транзит, синхронный сбор, дробление
  roles.py                   12 правил с порогами, rule_id у каждого узла
  clusters.py                сообщества и гипотезы по ним
  priority.py                приоритет проверки и топ-лист
  layout.py                  координаты узлов для схемы
  robustness.py              изъятие топ-N против случайных N
  fmt.py                     форматирование чисел в обоснованиях
  export.py                  выгрузки
  run.py                     единая точка входа и самопроверка
        │
        ▼
out/                         результат (закоммичен, пересоздаётся пайплайном)
  nodes_roles.csv            2248 строк: схема ТЗ + rule_id и признаки, на которых построены правила
  clusters.csv               72 кластера
  top_nodes.csv              30 узлов
  graph.json                 узлы, рёбра, кластеры, топ-лист для интерфейса одним файлом
  thresholds.json            значение и формулировка каждого порога
  censoring_report.json      модель terminal_p: коэффициенты, AUC, калибровка
  robustness_report.json     кривые изъятия топ-N и случайных N
        │
        ▼
server.py  ──►  web/         интерфейс читает /out/graph.json
   │
   └─ ask.py                 POST /api/ask: разбор вопроса, поиск по графу,
                             необязательная переформулировка моделью

Ядро и интерфейс связаны только через out/graph.json; контракт — docs/spec.md. Сервер отдаёт: / — интерфейс, /out/... — выгрузки, POST /api/ask — вопросы, GET /api/health — наличие выгрузок.

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

На таком объёме реализация не проверялась. Ниже — что изменится, по замеренному профилю прогона на 2248 узлах (~14 с): 57% времени — признаки узла, 30% — оценка устойчивости, остальное — меньше секунды на этап.

  • Правила ролей и пороги не меняются. Они заданы квантилями распределений и переносятся на любой объём без ручной настройки; модель terminal_p переобучается на самих данных за один проход.
  • Betweenness — самая дорогая метрика (2,2 с сейчас, O(V·E)). Заменяется приближённым расчётом по выборке источников (k-sample в networkx) или igraph.
  • Построчные признаки (временные паттерны, концентрация входящих) переносятся на групповые операции polars или DuckDB без изменения смысла.
  • Кластеризация — Louvain/Leiden на igraph вместо networkx.
  • Поиск циклов (сейчас 0,1 с) растёт экспоненциально с плотностью — на большой сети запускается только на подграфе кандидатов: топ по приоритету и их соседи.
  • Оценка устойчивости — на подграфе топ-узлов и по разреженной сетке N.
  • Хранение и интерфейс — выгрузки в parquet вместо CSV; браузер показывает не весь граф, а окрестность выбранного узла или кластера, подгружаемую с сервера.

Подробный разбор — pipeline/METHOD.md, раздел «Масштабирование до ~1 млн узлов».


7. Установка и запуск

Нужен Python 3.10 или новее с модулем venv (в Ubuntu: пакет python3-venv).

git clone https://github.com/BAITC-Hacks/hack-f6676a41-zhetysu.git
cd hack-f6676a41-zhetysu
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m pipeline.run --data case/data --out out
.venv/bin/python server.py --port 3300

Пятая команда считает роли и пишет выгрузки в out/. Шестая поднимает интерфейс на http://127.0.0.1:3300 и занимает терминал (остановка — Ctrl+C); команды раздела 8 выполняйте во втором терминале из той же папки.

Переменные окружения: обязательных нет. Единственная необязательная — OPENAI_API_KEY: с ней ответы на вопросы переписываются связным языком, без неё отдаётся тот же ответ шаблоном, цифры и состав не меняются. Ключ можно экспортировать в окружение или записать в .env по образцу .env.example — server.py прочитает файл при запуске.


Зависимости

Все перечислены в requirements.txt, ставятся одной командой выше.

БиблиотекаВерсия при проверкеЗачем
pandas2.3.3таблицы, чтение parquet
numpy2.2.6метрики, модель terminal_p
networkx3.4.2граф, PageRank, посредничество, сообщества
pyarrow25.0.1чтение .parquet
scipy1.15.3требуется networkx для PageRank и betweenness
fastapi0.141.1сервер демонстрации
uvicorn0.53.0запуск сервера

Язык: Python 3.10.12. Интерфейс дополнительных зависимостей не имеет — HTML, CSS и JavaScript без сборки, шрифты лежат локально в web/assets, внешние CDN не используются.


8. Как проверить решение

Около минуты, без наших аккаунтов и ключей. Команды выполняются из корня репозитория после раздела 7.

Шаг 1. Пайплайн.

.venv/bin/python -m pipeline.run --data case/data --out out

Вывод — девять этапов с числами: загрузка, модель обрыва с AUC, пороги, распределение ролей, кластеры, устойчивость. В конце — самопроверка: все пункты пройдены и готово за … с. Время ~15 секунд, код выхода 0.

Шаг 2. Выгрузки по схеме ТЗ.

wc -l out/nodes_roles.csv out/clusters.csv out/top_nodes.csv

Ожидается: 2249 строк в nodes_roles.csv (2248 узлов + заголовок), 73 в clusters.csv, 31 в top_nodes.csv. Проверка колонок, типов и длины evidence:

.venv/bin/python -c "
import pandas as pd
n = pd.read_csv('out/nodes_roles.csv')
req = ['gid','role','role_score','cluster_id','priority_score','evidence']
print('строк', len(n), '| gid', n.gid.dtype, '| пропусков в обязательных', int(n[req].isna().sum().sum()))
print('evidence: пустых', int((n.evidence.str.len() == 0).sum()), '| максимум символов', n.evidence.str.len().max())
print(n.role.value_counts().to_dict())
"

Ожидается: строк 2248 | gid int64 | пропусков в обязательных 0, evidence: пустых 0 | максимум символов 200 и распределение ролей из раздела 3.

Шаг 3. Роль любого узла объяснима.

.venv/bin/python -c "
import pandas as pd
n = pd.read_csv('out/nodes_roles.csv').set_index('gid')
print(n.loc[100000003115284100, ['role','role_score','cluster_id','priority_score','evidence','rule_id']].to_string())
"

Видны роль coordinator, уверенность, кластер, приоритет, evidence с числами и rule_id, начинающийся с R6.coordinator — условие правила в таблице раздела 4. Подставьте любой другой gid из out/nodes_roles.csv. Значение каждого порога — в out/thresholds.json.

Шаг 4. Интерфейс.

.venv/bin/python server.py --port 3300

Откройте http://127.0.0.1:3300 — схема сети. Введите в поиск gid 100000003115284100 (первый в топ-листе): узел подсвечивается, открывается досье со связями.

Шаг 5. Вопрос по графу словами — во втором терминале, пока сервер запущен.

curl -s -X POST http://127.0.0.1:3300/api/ask \
     -H 'Content-Type: application/json' \
     -d '{"q":"кого смотреть первым"}'

Ожидается JSON с полями answer (топ-5 с обоснованием), nodes (упомянутые gid), source (топ-лист приоритетов) и phrasing — правила, если ключ модели не задан.

Состояние выгрузок: http://127.0.0.1:3300/api/health


9. Данные и интеграции

Данные — предоставлены организаторами кейса, лежат в case/data/:

ФайлСтрокСодержимое
nodes.parquet2 248клиент: gid, depth, is_seed
edges.parquet3 119пара плательщик→получатель за период: src, dst, sum_kzt, n_tx, depth
transactions.parquet4 840отдельная транзакция: src, dst, date, sum_kzt

Период 1–31 июля 2026, оборот 365 890 012 KZT, 81 seed-клиент, только внутрибанковские переводы, транзакции ниже 5 000 KZT в выгрузку не попали. Данные обезличены: gid — синтетический идентификатор. Атрибуты клиентов не достраиваются, персональных данных в проекте нет.

Внешние API и сервисы. Для расчёта и проверки не нужны: всё считается локально, без интернета. Единственная необязательная интеграция — OpenAI API (gpt-4o-mini) в ask.py, только при заданном OPENAI_API_KEY и только для переформулировки уже посчитанного ответа. При недоступности API отдаётся шаблонный ответ.

Раскрытие заготовок и open-source

Предоставлено организаторами (выдано всем командам): case/data/*.parquet — данные; case/starter/ — стартовый код, оставлен без изменений как справочный, ядро pipeline/ написано заново и его не импортирует.

Подготовлено командой до старта: сервер, домен с сертификатом, скрипты деплоя и коммитов. Кода решения в этой инфраструктуре нет, в репозиторий она не входит.

Open-source: pandas, numpy, networkx, pyarrow, scipy (BSD), FastAPI, uvicorn (MIT), шрифт Manrope (SIL OFL, лицензия — web/assets/fonts/Manrope-OFL.txt).


10. Ограничения

  • Роли — гипотезы для проверки, а не вывод о виновности. evidence описывает наблюдаемое поведение счёта, и только его.
  • Размеченных ролей в данных нет, поэтому точность измерить нельзя. Проверяема обоснованность: у каждого правила порог из распределения, у каждого узла rule_id.
  • Модель terminal_p переносится хуже, чем работает на своей выборке — AUC 0.64 на невиданном колене против 0.73. Поэтому 358 обрезанных узлов остаются peripheral, хотя часть из них, вероятно, конечные получатели (модель ожидает 266 из 444).
  • Входящие потоки видны не полностью — граф собран по исходящим переводам: полный баланс узла недостижим: 354 узла отдают больше, чем по данным получили (pass_through > 1), ровно как указано в ТЗ.
  • Дробление ниже 5 000 KZT невидимо — такие транзакции в выгрузку не попали.
  • Louvain теряет направление рёбер на шаге кластеризации.
  • Кластер -1 — 19 seed без единого ребра: сообщество для них не определить, они собраны в отдельную строку clusters.csv.
  • Только внутрибанковские переводы за июль 2026 — выводы за эти рамки не переносятся.
  • Нет аутентификации и разграничения прав — это демонстрационный прототип.
  • Граф в миллион узлов не проверялся — план изменений в разделе 6.


11. Ссылка на развёрнутую версию

https://zhetysu-team.kz

Открывается без регистрации и без наших аккаунтов.

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

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

Olzhas Nursainov 12Yerkin Khamidullov 12

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

  • 2026-09-23 17:57README: добавлен раздел зависимостей с версиями, убрано дублирование таблицы соответствияOlzhas Nursainov
  • 2026-09-23 17:54README: таблица соответствия требованиям и артефактам ТЗ с указанием, чем проверить каждоеYerkin Khamidullov
  • 2026-09-23 17:45убраны отладочные скрипты проверок из интерфейсаOlzhas Nursainov
  • 2026-09-23 17:45убран мёртвый код интерфейса: в репозитории остались только используемые файлыYerkin Khamidullov
  • 2026-09-23 17:28ревизия перед сдачей: временные паттерны и циклы в README, загрузка .env, доводка ответов ассистентаOlzhas Nursainov
  • 2026-09-23 17:19.env.example теперь в репозитории: правило исключений глушило его, жюри бы его не увиделоYerkin Khamidullov
  • 2026-09-23 17:12пересчёт выгрузок и проверка самопроверкой перед сдачейOlzhas Nursainov
  • 2026-09-23 17:11новый интерфейс: перенос утверждённого дизайна, схема, досье, очередь приоритетовYerkin Khamidullov
Все коммиты (24)
  • 2026-09-23 16:33утверждён единый дизайн интерфейса, пробные варианты и их адреса убраныOlzhas Nursainov
  • 2026-09-23 16:23интерфейс главной: доводка схемы сети и поведения при выборе узлаYerkin Khamidullov
  • 2026-09-23 16:08интерфейс главной: рабочая поверхность разбора, стиль под заказчика; служебные файлы проверок вне репозиторияOlzhas Nursainov
  • 2026-09-23 15:41схема решения и сценарий демо: обязательные артефакты по разделу 10 ТЗYerkin Khamidullov
  • 2026-09-23 15:17сервер отдаёт параллельные варианты интерфейса по отдельным адресам, перезапуск через pid-файлOlzhas Nursainov
  • 2026-09-23 14:50README: описан поиск по графу и раскладка схемы, устранено расхождение про переменные окруженияYerkin Khamidullov
  • 2026-09-23 14:48поиск по графу вопросом словами: детерминированный ответ по данным, модель только формулируетOlzhas Nursainov
  • 2026-09-23 14:36обоснования ролей: склонения и читаемые формулировки, временные паттерны в evidenceYerkin Khamidullov
  • 2026-09-23 14:23временные паттерны и устойчивость сети в ядре, экран ловушки 4-го колена в интерфейсеOlzhas Nursainov
  • 2026-09-23 14:17.env.example: явно сказано, что переменные окружения не требуютсяYerkin Khamidullov
  • 2026-09-23 14:15README с инструкцией запуска и разделом проверки, выгрузки пайплайна, .gitignore; убран мусор __pycache__Olzhas Nursainov
  • 2026-09-23 14:03интерфейс: схема сети, поиск по gid, досье узла; ядро: модули пайплайна ролейYerkin Khamidullov
  • 2026-09-23 13:51контракт: gid строкой в graph.json — 18-значные идентификаторы не переживают JSON.parseOlzhas Nursainov
  • 2026-09-23 13:48сервер демонстрации, контракт дорожек, живая ссылка на доменеYerkin Khamidullov
  • 2026-09-23 13:46кейс выбран: «Граф денег» — данные и стартовый код организаторов, убран общий архив трековOlzhas Nursainov
  • 2026-09-23 13:25пульс 13:25: промежуточный результатYerkin Khamidullov
Структура репозитория (52 файлов)
.env.example
.gitignore
README.md
ask.py
case/data/edges.parquet
case/data/nodes.parquet
case/data/transactions.parquet
case/starter/README.md
case/starter/requirements.txt
case/starter/starter.py
docs/demo.md
docs/solution-map.md
docs/solution-map.svg
docs/spec.md
out/censoring_report.json
out/clusters.csv
out/graph.json
out/nodes_roles.csv
out/robustness_report.json
out/thresholds.json
out/top_nodes.csv
pipeline/METHOD.md
pipeline/__init__.py
pipeline/censoring.py
pipeline/clusters.py
pipeline/config.py
pipeline/data.py
pipeline/export.py
pipeline/features.py
pipeline/fmt.py
pipeline/graphbuild.py
pipeline/layout.py
pipeline/patterns.py
pipeline/priority.py
pipeline/robustness.py
pipeline/roles.py
pipeline/run.py
requirements.txt
server.py
web/approved-graph.js
web/approved-inspector.js
web/approved-views.js
web/approved.css
web/approved.js
web/assets/fonts/Manrope-FONTLOG.txt
web/assets/fonts/Manrope-OFL.txt
web/assets/fonts/manrope-cyrillic-ext.woff2
web/assets/fonts/manrope-cyrillic.woff2
web/assets/fonts/manrope-latin-ext.woff2
web/assets/fonts/manrope-latin.woff2
web/index.html
web/simulation.js

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

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

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