AAYMA
RU
Войти

Money Graph

Объяснимый AML-пайплайн: каждому узлу сети переводов присваивается структурная роль (coordinator, consolidator, transit, distributor, terminal…

Рабочий MVP
Команда «Brazhers» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Brazhers
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Рабочий MVP

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

Суть

Объяснимый AML-пайплайн: каждому узлу сети переводов присваивается структурная роль (coordinator, consolidator, transit, distributor, terminal, peripheral), граф делится на сообщества, строится очередь проверки с числовыми обоснованиями. Есть самодостаточный HTML-интерфейс с графом и поиском по gid.

Как устроено

pipeline.py загружает nodes/edges/transactions (Markdown или Parquet через pyarrow) и строго проверяет схему, типы и совпадение агрегатов транзакций с рёбрами. Затем считает степени, суммы и долю пересылки (Decimal), PageRank с весом sum_kzt (затухание 0.85) и betweenness методом Brandes с Dijkstra (длина ребра 1/log(1+sum_kzt)). Роли назначаются упорядоченными правилами с порогами по квантилям P75/P90, priority_score складывается из пяти вкладов. На выходе nodes_roles.csv, clusters.csv, top_nodes.csv, analysis_summary.json и out/index.html; отдельный verify.py перепроверяет результаты.

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

  • PageRank
  • Brandes betweenness
  • Dijkstra
  • rule-based role classification
  • quantile thresholds
  • community clustering

Особенности

Строгая валидация входа: транзакции сверяются с рёбрами по суммам (math.isclose), деньги копятся в Decimal, 18-значные gid в JS хранятся строками. Правила ролей и пороги полностью задокументированы, role_score подан как сила правила, а не вероятность нарушения. Работает на стандартной библиотеке без pandas/networkx.

Стек

Python · pyarrow · HTML · JavaScript · unittest


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

README

README.md

Money Graph — объяснимый анализ транзакционной сети

Инструмент для AML-аналитика банка: по обезличенным переводам назначает каждому узлу структурную роль, выделяет сообщества и формирует очередь проверки с числовыми обоснованиями. В браузере можно найти полный gid, увидеть прямых плательщиков и получателей, суммы, количество переводов, правило роли и состав приоритета.

Результаты — гипотезы для проверки по наблюдаемому графу. Имена, возраст, доход и другие отсутствующие атрибуты клиента не добавляются. role_score показывает заданную силу правила, а не вероятность правонарушения.

Инструкция и сценарий выступления: HOWTO.md. Текущая проверка и исправления: FINAL_CHECK.md. Предыдущий аудит: AUDIT_REPORT.md, SECURITY.md.

Запуск одной командой

Нужен Python 3.10 или новее. Для предоставленных Markdown-таблиц достаточно стандартной библиотеки. Команды выполняются в текущем репозитории C:\hackalemai\submission. Одна команда генерирует результаты; следующие независимо проверяют их, запускают тесты и открывают локальный сервер:

python -B pipeline.py
python -B verify.py --data data --out out
python -B -m unittest discover -s tests -v
python -m http.server 8765 --bind 127.0.0.1 --directory out

После запуска сервера откройте http://127.0.0.1:8765/; остановка — Ctrl+C. В текущем приватном репозитории таблицы data/nodes.md, data/edges.md, data/transactions.md и результаты out/ отслеживаются Git и уже присутствуют. Запуск пайплайна пересоздает результаты без ручных промежуточных действий; если out/ отсутствует, каталог создается автоматически. Текущие результаты проверки приведены в FINAL_CHECK.md.

Успешный запуск возвращает код 0, печатает число строк, распределение ролей, пороги, пять первых кандидатов и пути результатов. Ожидаются 2 248 узлов, 3 119 направленных пар, 4 840 транзакций и 91 кластер.

РезультатСостав
out/nodes_roles.csvВсе узлы: gid, role, role_score, cluster_id, priority_score, evidence
out/clusters.csvВсе сообщества: cluster_id, n_nodes, n_seed, sum_kzt_internal, top_gids, hypothesis
out/top_nodes.csvОчередь проверки: rank, gid, role, priority_score, why; по умолчанию 100 строк
out/index.htmlСамодостаточный интерфейс со встроенным графом
out/analysis_summary.jsonЧисла проверки данных, фактические пороги, роли и время расчета

Пути и размер очереди задаются явно:

python pipeline.py --data data --out out --top 100

--top ограничивается снизу значением 20; если всего узлов меньше 20, выводятся все имеющиеся. Контракт хакатона проверяется на полном наборе из 2 248 узлов.

Вход из Parquet

Для Parquet нужна одна прямая зависимость: pyarrow==25.0.1, закрепленная в requirements.txt. Однократная подготовка окружения:

python -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt

Поместите разрешенные nodes.parquet, edges.parquet, transactions.parquet в parquet_data/. Полный пересчет выполняется одной командой:

.venv\Scripts\python.exe pipeline.py --data parquet_data --out parquet_out

Загрузчик предпочитает полный набор Markdown, если в каталоге есть все три .md; иначе использует полный набор Parquet. Смешанный набор форматов не объединяется. Отдельный каталог устраняет неоднозначность выбора.

При предыдущем аудите путь Parquet проверен на локально преобразованных копиях всех предоставленных Markdown-строк. Оригинальные Parquet-файлы организаторов отсутствовали. Результаты преобразованного набора совпали с Markdown. pandas не требуется: его нативная библиотека тогда была заблокирована Windows Application Control, поэтому загрузчик использует Arrow напрямую. Политика Windows не изменялась. Команды установки выше относятся к отдельной подготовке Parquet; текущий Markdown-запуск и стандартные тесты установки пакетов не требуют. Пути .venv относятся к окружению, созданному в текущем каталоге репозитория.

Просмотр и локальное размещение

Проверенный способ просмотра — локальный сервер по команде ниже. Введите полный gid, например 100000003684369100, нажмите «Найти» или Enter. Карточка показывает входящие и исходящие связи, суммы, количество переводов и правило роли. Есть поиск изолированных узлов, раскраска по ролям/кластерам, фильтр кластеров, перемещение и масштабирование. В разделе «Правило роли и расчёт приоритета» видны условия и пять вкладов в приоритет.

Для localhost запускается сервер, корнем которого служит только каталог результатов:

python -m http.server 8765 --bind 127.0.0.1 --directory out

Адрес: http://127.0.0.1:8765/. Остановка — Ctrl+C. Для результатов Parquet замените out на parquet_out. Интернет для такого просмотра не нужен. Альтернатива — открыть самодостаточный out/index.html напрямую; запуск через file:// в этой сессии не проверен из-за ограничения браузерной автоматизации. Публичное размещение на GitHub Pages или Vercel не выполнялось.

В браузере 18-значные gid хранятся строками, чтобы JavaScript не округлял идентификаторы. При открытии CSV в Excel задавайте для gid текстовый формат: автоматическое преобразование может потерять цифры. Положение точек на экране помогает читать граф и не является аналитической метрикой.

Данные и валидация

Контракт фиксирован для этого кейса: 1–31 июля 2026 года, внутрибанковские переводы от 5 000 KZT, обход исходящих связей от seed на четыре шага.

ТаблицаДопустимые исходные поля
nodesgid, depth, is_seed
edgessrc, dst, sum_kzt, n_tx, depth
transactionssrc, dst, date, sum_kzt

load_tables, normalize_tables и validate_inputs в pipeline.py проверяют точный состав колонок, int64-идентификаторы без преобразования из float, глубины и согласованность seed с глубиной 0. Для Parquet проверяются типы: идентификаторы и n_tx — int64, глубины — знаковые целые, суммы — float64, seed — bool, дата — календарная дата либо timestamp без часового пояса ровно в полночь.

Проверяются уникальность узлов и направленных пар, наличие концов каждого ребра в nodes, конечность положительных сумм, положительное количество переводов, даты июля и порог 5 000 KZT для транзакций. Агрегаты транзакций обязаны совпасть с ребрами по парам, количеству и суммам. Суммы сравниваются через math.isclose с rel_tol=1e-10, abs_tol=1e-6. Чрезмерные значения, способные переполнить расчет, отвергаются. Неизвестные клиентские колонки не принимаются.

В наборе 81 seed: 19 без ребер и еще 12 только с входящими. Все сохранены в итогах. Оборот — 365 890 012.01 KZT; максимальная разница суммы транзакций и ребра — 5.820766091346741e-11 KZT. Указанные в описании 16 слабосвязных компонент содержат ребра; вместе с 19 изолированными seed полный граф имеет 35 компонент.

Метрики и точные правила ролей

in_deg/out_deg — число разных плательщиков/получателей; in_tx/out_tx — количество отдельных переводов; in_kzt/out_kzt — наблюдаемые суммы. Денежные суммы для правил накапливаются через Decimal(str(amount)); pass_through получается делением этих Decimal-сумм с единственным преобразованием результата в float. Это сохраняет бизнес-границы доли 0.50, 0.70 и 1.30 без предварительного двоичного округления накопленных сумм. Если входящая сумма нулевая, доля отсутствует. Эта доля не является полным балансом счета.

PageRank следует направлению «плательщик → получатель» с весом sum_kzt, затуханием 0.85, пределом 200 итераций и остановкой при сумме абсолютных изменений меньше 1e-12. Betweenness рассчитывается методом Brandes с Dijkstra по направленному графу: длина ребра 1 / log(1 + sum_kzt), нормировка (N-1)*(N-2). Крупный перевод получает меньшую условную длину; это модель структурной связи, не время прохождения денег.

Квантили вычисляются заново. В отсортированных N значениях позиция равна (N-1)*q; между соседями применяется линейная интерполяция. Точные пороги текущего analysis_summary.json:

ПорогЗначение
P75(in_deg)1.0
P90(in_deg)2.0
P75(out_deg)1.0
P90(out_deg)3.0
P75 положительных betweenness9.738917745675346e-05
P75 PageRank по всем узлам0.00046046328200250765

Для betweenness берутся положительные значения, поскольку множество нулей скрывает различия между посредниками. Нижняя граница степени — max(1, квантиль), чтобы нулевой квантиль сам по себе не создавал сигнал. Константы доли пересылки и силы правил — заданные эвристики; они не подгоняются под конкретные gid.

Правила в build_features (pipeline.py:596) применяются сверху вниз; первое совпадение завершает выбор:

№Роль и точное условиеrole_score
1terminal: out_deg == 0 и depth == 40.45
2terminal: out_deg == 0 и in_deg > 0; после правила 1 глубина меньше 40.82 для не-seed; 0.50 для seed
3coordinator: in_deg >= max(1, P75(in_deg)), out_deg >= max(1, P75(out_deg)), betweenness > 0 и betweenness >= P75(положительных betweenness)0.76
4consolidator, не-seed: in_deg >= max(1, P90(in_deg)), доля пересылки существует и < 0.500.72
5consolidator, seed: in_deg >= max(1, P90(in_deg)) и pagerank >= P75(pagerank)0.62
6transit, не-seed: in_deg >= max(1, P75(in_deg)), доля пересылки существует и 0.70 <= pass_through <= 1.300.68
7distributor: out_deg >= max(1, P90(out_deg))0.66
8peripheral: ни одно предыдущее правило не сработало0.50

У правила 5 наличие исходящего ребра следует из порядка терминальных правил. Для seed накопление — более слабая гипотеза по степени и PageRank, поскольку доля пересылки искажена неполными входящими. Изолированный seed получает peripheral: наблюдений о потоках нет.

evidence содержит реальные числа и оговорки seed/глубины 4, максимум 200 символов. Повторные переводы учитываются в in_tx/out_tx и объяснении; самостоятельного порога по их количеству для назначения роли нет. В правилах счетный сигнал задается числом разных контрагентов, денежный — долей пересылки и взвешенными метриками. Множество операций одного плательщика не приравнивается к множеству независимых плательщиков.

Распределение: consolidator — 88, transit — 92, distributor — 85, terminal — 1 535, coordinator — 147, peripheral — 301. Среди терминальных 444 имеют score 0.45 из-за границы четвертого шага. Все значения role_score — фиксированная сила правила, не калиброванная вероятность.

Четыре ловушки данных

ЛовушкаОбработкаУказатель на код
Обрыв на четвертом шагеdepth == 4 и нулевой исходящий degree дают truncated_by_depth, score 0.45 и явную оговорку. Ранние не-seed с входом и без выхода получают 0.82; вывод ограничен выгрузкой.build_features, pipeline.py:554, pipeline.py:596
Заниженные входящие seedRatio-правила исключают seed. Отдельное правило использует degree и PageRank. Все 81 evidence содержат оговорку о входящих.build_features, pipeline.py:607, pipeline.py:621
Сумма и число операцийОтдельно считаются суммы, количество переводов и контрагентов; degree и суммы участвуют в роли, количество переводов — в evidence.build_features, pipeline.py:538
Направление и весPageRank, betweenness и потоки сохраняют направление. Ненаправленная проекция применяется к Louvain и близости к seed.pagerank, pipeline.py:339; weighted_directed_betweenness, pipeline.py:359; louvain_partition, pipeline.py:426

Кластеры и гипотезы

Многоуровневый Louvain работает на ненаправленной проекции с весом sum_kzt, разрешением 1 и генератором перестановок seed 41; встречные веса суммируются. Пределы реализации — 20 уровней, 100 проходов на уровень. После Louvain каждое сообщество разбивается на компоненты связности собственного индуцированного подграфа: путь через узлы другого сообщества не делает его связным. Затем применяется прежняя нумерация по убыванию размера и минимальному gid. Сообщество группирует связанные потоки, его состав сам по себе не доказывает единую организацию. Изолированные узлы остаются отдельными сообществами; при изменении данных номера могут измениться.

make_cluster_rows (pipeline.py:731) считает sum_kzt_internal по исходным направленным ребрам с обоими концами внутри сообщества. top_gids содержит до пяти участников по полному приоритету; при равенстве выбирается меньший gid. Число структурных сигналов — сумма числа consolidator, coordinator, distributor и transit.

Текст hypothesis выбирается по составу в таком порядке:

  1. Есть seed и consolidator/coordinator — связь seed с накоплением или координацией.
  2. Есть consolidator/coordinator — накопление или координация в наблюдаемой сети.
  3. Есть distributor — веерное распределение.
  4. Есть transit — пересылка средств.
  5. Иначе — фрагмент без выраженного сигнала.

Каждый текст начинается с Hypothesis, содержит число seed / число узлов, число структурных сигналов и измеренный внутренний оборот, завершаясь предложением проверить транзакции. Оборот в тексте округлен до целого KZT; числовая колонка сохраняет расчетное значение. Глобальная оптимальность разбиения не заявляется.

Формула приоритета

build_features (pipeline.py:562) использует процентильные ранги:

priority_score = 0.30 * rank(pagerank)
               + 0.25 * rank(in_deg)
               + 0.25 * rank(betweenness)
               + 0.10 * rank(out_deg)
               + 0.10 * rank(seed_reach)

Для N > 1 ранг — средняя позиция среди равных значений, считая с нуля, деленная на N-1. Равные значения получают одинаковый ранг; для единственного узла он равен 0.5. Ранги лежат в [0,1], веса суммируются в 1. Формула объединяет значимость получателя, число связей, посредничество и близость к seed без сложения исходных величин разных шкал.

seed_reach — число разных seed на расстоянии не более двух шагов в ненаправленном соседстве. Seed учитывает себя на расстоянии 0 (seed_reach_within_two_hops, pipeline.py:404). Это близость в графе, не число направленных денежных маршрутов.

Сортировка — по полному приоритету по убыванию, затем числовому gid по возрастанию. CSV хранит шесть знаков после запятой: визуально одинаковые оценки могут иметь разные полные значения. why включает приоритет и объяснение роли. role_score и номер кластера в формулу не входят.

Самостоятельная проверка

python verify.py
python verify.py --gid 100000003684369100
python verify.py --report .audit/verification.json

verify.py заново читает данные и независимо рассчитывает агрегаты, направленные метрики, правила и приоритет, не импортируя функции пайплайна. Проверяются точные CSV-схемы, все узлы, числовые утверждения evidence, оговорки, связность/состав кластеров, суммы, рейтинг и данные внутри HTML, включая идентификаторы и прямые ребра. Код 0 и PASS означают успех; при расхождении выводятся FAIL и ненулевой код. Проверка связности и учета кластеров не доказывает глобальный максимум Louvain.

--gid печатает сырые входящие/исходящие ребра и сработавшее правило. --report сохраняет JSON только внутри проектного .audit/; он тоже содержит графовые данные. Для Parquet:

.venv\Scripts\python.exe verify.py --data parquet_data --out parquet_out

Проверки ошибочных входов, файловых перенаправлений и поврежденных выгрузок:

python -B -m unittest discover -s tests -v

В текущем Python 3.14 выполнено 29 тестов: 27 прошли, 2 пропущены. Причины пропуска: отсутствует PyArrow для проверки типов Parquet; Windows запрещает создание настоящего symlink (WinError 1314). Подробности — в FINAL_CHECK.md. Исторический аудит с 26 тестами относится к предыдущему состоянию. Браузерный поиск проверяется отдельно от встроенного JSON; сценарий — в HOWTO.

Измеренная воспроизводимость

Исторические замеры предыдущего аудита с Python 3.14.0, включая запуск процесса; актуальный прогон — в FINAL_CHECK.md:

ПроверкаВремяРезультат
Копия исходников и данных в новый каталог без out/, Markdown0.9094104 сВсе результаты созданы, независимая проверка прошла
Полный локально преобразованный набор Parquet, первый запуск17.1664882 сУспех
Тот же Parquet-набор, повторный запуск1.0734238 сУспех

Установка зависимостей не входит в лимит пересчета. Все исторические замеры укладывались в пять минут; скорость другого компьютера может отличаться. Тогда проверялась файловая копия в родительском каталоге без .git, и три CSV с HTML совпали с исходными побайтово. Сейчас свежий запуск в .audit/final_fresh и независимая проверка подтвердили 2 248 узлов, 3 119 ребер, 4 840 транзакций, 91 кластер и top 100. Все три CSV побайтово совпали с исходным коммитом 5fbb73e: роли и позиции очереди не изменились. Подробности — в FINAL_CHECK.md. Время в analysis_summary.json измеряется внутри процесса и меняется между запусками.

Схема решения

Markdown / Parquet
        |
        v
Схема, типы, даты, суммы, узлы, сверка transactions <-> edges
        |
        v
Направленный взвешенный граф, включая изолированные nodes
        |
        +--> degree, KZT, количество операций, PageRank, betweenness
        |                         |
        |                         +--> правила --> роли + evidence
        |                         +--> ранги --> приоритет
        |
        +--> ненаправленная проекция --> Louvain --> кластеры + гипотезы
                                      |
                                      v
                  3 CSV + контрольный JSON + локальный HTML

Ограничения и масштабирование

Отсутствуют межбанковские переводы, входящие из-за границ выборки, суммы ниже 5 000 KZT и продолжение обхода после глубины 4. Полный баланс, последовательность прохождения конкретных денег и дробление ниже порога установить нельзя. terminal до четвертого шага означает отсутствие захваченного исходящего потока в этой выгрузке.

Размеченных истинных ролей нет: accuracy, полнота обнаружения и вероятность роли не оценены. Фиксированные scores не калиброваны. Квантили степени на разреженном графе могут быть малы; порядок правил может скрывать вторую подходящую роль. Месячная доля пересылки не подтверждает быстрый транзит. Seed-правило консолидации — более слабый структурный признак, без утверждения об остатках денег.

Даты и минимальная сумма привязаны к июлю 2026 и этому контракту; для другого периода требуется осознанная настройка кода. Временные паттерны, циклы, удаление узлов и внешние сведения сейчас не рассчитываются. Номера кластеров нельзя сравнивать между снимками без сопоставления. Весь граф хранится в памяти и HTML. Многопользовательский публичный сервис с разграничением доступа не реализован.

При росте до примерно 1 млн узлов точная betweenness по всем источникам станет узким местом. Потребуются графовая БД или другое хранилище с индексами, разбиение по компонентам/периодам, приближенная betweenness по выборке источников и PageRank на подходящем вычислительном движке. Обновления следует считать для затронутых областей; глобальные квантили — версионировать по снимкам. Интерфейс должен запрашивать ограниченное соседство и сводки сообществ вместо полного графа в HTML. Эти изменения описаны как план, не заявлены реализованными.

Безопасность и публикация

Организаторы разрешили данные исключительно для хакатона. Текущий submission — рабочая копия приватного репозитория BAITC-Hacks/hack-ef42c09b-brazhers, с .git и настроенным origin; исходный снимок main — 5fbb73ecc6ba30839991abe0e83541a79da9d9f5. Доступная локальная история ограничена shallow-снимком. Сведения предыдущего аудита об отсутствии Git относятся к родительской папке и не описывают этот репозиторий.

В исходном снимке отслеживаются 19 файлов, включая data/ и out/; отслеживаемого .gitignore нет. Поэтому эти данные нельзя считать исключенными из Git. index.html содержит весь граф: его публикация раскрывает набор переводов. Сохраняйте приватность репозитория; перед публичным размещением отдельно согласуйте условия с организаторами. Исторический SECURITY.md дополнен актуальным состоянием в FINAL_CHECK.md.

Секреты в проверенных исходниках и данных не найдены. Пайплайн не требует API-ключей, GPU или внешних сервисов, не использует eval, pickle либо команды из входных строк. JSON экранирует HTML-разделители, интерфейс выводит текст через textContent.

--out означает явно выбранный пользователем каталог. Существующие symlink, junction, reparse point, специальные файлы и многократно связанные файлы результатов отвергаются. Каждый файл заменяется атомарно из временного файла в том же каталоге. Это не транзакция для пяти файлов одновременно и не защита от владельца, враждебно меняющего каталог во время записи; используйте доверенную локальную папку.

Подробные находки, исправления и ограничения: SECURITY.md, AUDIT_REPORT.md.

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

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

HeLL0-yt 16mediaenthusiast 12

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

  • 2026-09-23 17:36Add files via uploadHeLL0-yt
  • 2026-09-23 17:36Delete HOWTO.mdHeLL0-yt
  • 2026-09-23 17:36Delete FINAL_CHECK.mdHeLL0-yt
  • 2026-09-23 17:35Delete DEMO.mdHeLL0-yt
  • 2026-09-23 17:35Delete AUDIT_REPORT.mdHeLL0-yt
  • 2026-09-23 17:35Delete tests directoryHeLL0-yt
  • 2026-09-23 17:35Delete out directoryHeLL0-yt
  • 2026-09-23 17:35Delete data directoryHeLL0-yt
Все коммиты (28)
  • 2026-09-23 17:34Add files via uploadHeLL0-yt
  • 2026-09-23 16:34Add files via uploadHeLL0-yt
  • 2026-09-23 16:11Delete out directoryHeLL0-yt
  • 2026-09-23 16:11Delete data directoryHeLL0-yt
  • 2026-09-23 17:36Delete README.mdmediaenthusiast
  • 2026-09-23 17:36Delete SECURITY.mdmediaenthusiast
  • 2026-09-23 17:36Delete pipeline.pymediaenthusiast
  • 2026-09-23 17:35Delete requirements.txtmediaenthusiast
  • 2026-09-23 17:35Delete verify.pymediaenthusiast
  • 2026-09-23 17:35Delete viewer.htmlmediaenthusiast
  • 2026-09-23 15:16v1HeLL0-yt
  • 2026-09-23 15:14Delete hello worldHeLL0-yt
  • 2026-09-23 15:14Update hello worldHeLL0-yt
  • 2026-09-23 16:10Delete viewer.htmlmediaenthusiast
  • 2026-09-23 16:10Delete requirements.txtmediaenthusiast
  • 2026-09-23 16:10Delete pipeline.pymediaenthusiast
  • 2026-09-23 16:09Delete README.mdmediaenthusiast
  • 2026-09-23 16:08Delete DEMO.mdmediaenthusiast
  • 2026-09-23 12:48test hello worldHeLL0-yt
  • 2026-09-23 13:52Update hello worldmediaenthusiast
Структура репозитория (21 файлов)
AUDIT_REPORT.md
DEMO.md
FINAL_CHECK.md
HOWTO.md
README.md
SECURITY.md
data/edges.md
data/nodes.md
data/transactions.md
out/analysis_summary.json
out/clusters.csv
out/index.html
out/nodes_roles.csv
out/top_nodes.csv
pipeline.py
requirements.txt
tests/test_final_regressions.py
tests/test_input_safety.py
tests/test_verifier.py
verify.py
viewer.html

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

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

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