О проекте
Команда: 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_sink | 1091 | деньги пришли и остались; исходящие проверены обходом |
observed_forwarder | 694 | деньги пришли и ушли дальше |
unknown_truncated | 444 | 4-е колено, исходящие никто не выгружал |
no_edges | 19 | seed без единого ребра в выгрузке |
Для обрезанных роль по отсутствию рёбер не назначается — работает модель 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 ◄── приоритет и топ-лист ◄─┘
- Загрузка и проверка данных (
data.py): 2248 узлов, 3119 рёбер, 4840 транзакций. Суммы рёбер сверяются с транзакциями; при битых данных прогон останавливается с понятным сообщением. - Граф и признаки (
graphbuild.py,features.py): направленный взвешенный граф, степени, обороты, доля пропускаpass_through = out_kzt / in_kzt, PageRank, betweenness, HITS, точки сочленения, циклы, достижимость вниз по потоку. - Модель обрыва (
censoring.py): вероятностьterminal_pдля 444 узлов 4-го колена. - Временные паттерны (
patterns.py): по датам транзакций. - Роли (
roles.py): правила применяются в фиксированном порядке, первое сработавшее побеждает. Значения порогов на этих данных:
| Правило | Роль | Условие | Узлов |
|---|---|---|---|
| R0 | peripheral | нет ни одного ребра в выгрузке | 19 |
| R1 | distributor | out_deg >= 11 (квантиль 0.975) | 54 |
| R2 | consolidator | in_deg >= 4 (квантиль 0.975) и (out_deg <= max(2, in_deg/2) или pass_through <= 0.5) | 43 |
| R3a | transit | 0.8 <= pass_through <= 1.2 | 67 |
| R3b | transit | pass_through > 1.2 — отдал больше, чем получил: приток извне выборки | 249 |
| R3c | transit | seed с исходящими: вход у seed занижен, роль по исходящему профилю | 40 |
| R3d | transit | ≥60% исходящей суммы ушло в пределах 2 суток и pass_through >= 0.6 | 25 |
| R4a | terminal | исходящих нет, и они проверены обходом (depth <= 3) | 1069 |
| R4b | terminal | дальше уходит ≤26% полученного (квантиль 0.2) — сумма осела | 105 |
| R4c | terminal | обрезан 4-м коленом и terminal_p >= 0.70 | 86 |
| R5 | peripheral | смешанный профиль ниже всех порогов | 464 |
| R6 | coordinator | ≥2 плательщика-сборщика (in_deg >= 4) или ≥2 seed-плательщика, in_kzt в верхних 5% (614 тыс. KZT), не seed | 27 |
- Кластеры (
clusters.py): Louvain на неориентированной проекции, вес — сумма, гипотеза собирается из состава кластера. - Приоритет (
priority.py): взвешенная сумма перцентилей — объём потока 0.25, число плательщиков 0.18, позиция в сети 0.14, связь с seed 0.12, роль 0.12, временные паттерны 0.10, осевшая сумма 0.09. Скор seed умножен на 0.5: их следствие уже знает, инструмент нужен, чтобы показать невидимую часть сети. - Выгрузки и самопроверка (
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, ставятся одной командой выше.
| Библиотека | Версия при проверке | Зачем |
|---|---|---|
| pandas | 2.3.3 | таблицы, чтение parquet |
| numpy | 2.2.6 | метрики, модель terminal_p |
| networkx | 3.4.2 | граф, PageRank, посредничество, сообщества |
| pyarrow | 25.0.1 | чтение .parquet |
| scipy | 1.15.3 | требуется networkx для PageRank и betweenness |
| fastapi | 0.141.1 | сервер демонстрации |
| uvicorn | 0.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.parquet | 2 248 | клиент: gid, depth, is_seed |
edges.parquet | 3 119 | пара плательщик→получатель за период: src, dst, sum_kzt, n_tx, depth |
transactions.parquet | 4 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. Ссылка на развёрнутую версию
Открывается без регистрации и без наших аккаунтов.
Авторы коммитов
История коммитов
- 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 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.