🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

训练异常审计器 YanKaFei/LLM-Training-Debugger

DeepSeek Harness
YanKaFei19 天前有提交已提供中文文档扫描:无法判定

把 PyTorch 指标异常转成可审计事件,证据不足时主动弃权

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/13 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add YanKaFei/LLM-Training-Debugger
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · dev
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 19 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/13) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
⚪ 扫描:无法判定尚无人工评估
展开查看扫描说明与证据 ↓

已尝试扫描但取不到可分析的源码:仓库或包不存在、已删除,或为非 JS/TS 实现、未随包发布源码。无法判定,不代表安全。

  • · 包内无可扫 JS
  • · TS 源码(可能为非 JS 实现或未发布源码),无法判定
扫描于 2026/11/1(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 指标异常转可审计事件
  • 证据不足时弃权

面向 PyTorch 的证据优先训练监控:把指标异常变成可审计的事件,证据不足时拒绝下结论。用 DeepSeek Harness 构建。

README

由 DeepSeek 最新模型翻译生成
English · 简体中文 · 한국어 · 日本語 · Français 这是什么 一个证据优先的 PyTorch 训练监控库。它盯着训练循环,把指标异常变成事件,而且——这才是关键——证据不足时,它拒绝给出答案。 大多数训练工具回答的是「发生了什么?」。这个库问的问题更窄,也更难: 我到底知道吗?如果不知道,我手上究竟有什么? 这不是什么 先说清楚,因为诚实的边界比功能列表更有用: - 不能替代实验追踪工具。 它向追踪工具上报数据,自己不是仪表盘。 - 不做根因分析。 它报告的是某个 step 和某个指标。它说不出是哪个 kernel、哪个张量、哪一行代码。 - 不是控制器。 它只观察。它不会裁剪你的梯度、重置优化器状态,也不会停掉你的训练。 - 未在大规模场景验证。 这个仓库里的每个数字,都是在 4–6 层模型上测出来的。 - 未经校验。 没有盲测留出集。validated_capabilities 按设计就是空的。 为什么要有它 一次训练跑下来,会得到一条 loss 曲线。曲线出问题时,它不会告诉你问题出在哪,而且重跑一遍往往复现不出来。 这个库的立场是:产品不是那张图,产品是事件——一条有边界、可审计、带时间戳的断言,说明观察到了什么,附上支撑它的证据,并明确写出哪些结论无法得出。
展开完整文档(README 剩余 1 节)
English · 简体中文 · 한국어 · 日本語 · Français

这是什么

一个证据优先的 PyTorch 训练监控库。它盯着训练循环,把指标异常变成事件,而且——这才是关键——证据不足时,它拒绝给出答案。

大多数训练工具回答的是「发生了什么?」。这个库问的问题更窄,也更难:

我到底知道吗?如果不知道,我手上究竟有什么?

这不是什么

先说清楚,因为诚实的边界比功能列表更有用:

- 不能替代实验追踪工具。 它向追踪工具上报数据,自己不是仪表盘。
- 不做根因分析。 它报告的是某个 step 和某个指标。它说不出是哪个 kernel、哪个张量、哪一行代码。
- 不是控制器。 它只观察。它不会裁剪你的梯度、重置优化器状态,也不会停掉你的训练。
- 未在大规模场景验证。 这个仓库里的每个数字,都是在 4–6 层模型上测出来的。
- 未经校验。 没有盲测留出集。validated_capabilities 按设计就是空的。

为什么要有它

一次训练跑下来,会得到一条 loss 曲线。曲线出问题时,它不会告诉你问题出在哪,而且重跑一遍往往复现不出来。

这个库的立场是:产品不是那张图,产品是事件——一条有边界、可审计、带时间戳的断言,说明观察到了什么,附上支撑它的证据,并明确写出哪些结论无法得出。

这个立场贯穿整个设计:

| 原则 | 在代码里的体现 |
| 观察绝不能打断训练 | emit() 从不抛异常;有界的 P0–P3 队列宁可丢弃也不阻塞 |
| 必须先观察到证据,才能断言其机制 | OBSERVED / INFERRED / HYPOTHESIS / UNKNOWN;只有 OBSERVED 可以升级 |
| 没观察到不等于观察到没有 | 每条判定都带 data_quality 和 completeness_warning |
| 宁可弃权,也不编造关联 | INSUFFICIENT_EVIDENCE 是一等判定,不是错误 |
| 有些因果断言本就不该成立 | CAUSED_BY 和 ROOT_CAUSE_OF 在 schema 中不存在,并有测试断言它们永远不会出现 |

环境要求

| Python | 3.9 – 3.13。每个版本都在 CI 中跑过。 |
| 核心 | numpy>=1.23、pyarrow>=12、duckdb>=0.10,<1.5 |
| PyTorch 适配器 | torch>=2.0 —— 可选,通过 torch extra 安装。observer、storage、detectors、episodes、fusion 和命令行都不导入 torch。 |
| 开发 | .[dev] = pytest 和 torch,因为测试套件会导入它。 |

duckdb 的上界是权宜之计,不是偏好。 duckdb 1.5.6 会让
fetch_arrow_table() 报错:SystemError: <built-in function __import__> returned a result
with an exception set。CI 里 23 个失败全出在这一处调用;其余 560 多个测试都通过,import pyarrow 也正常,所以问题在 duckdb 的 Arrow 桥接层,不在 pyarrow。Python 3.9 上看不到这个问题,因为 duckdb 1.5.x 要求 Python >= 3.10,3.9 会解析到 1.4.5,永远碰不到 —— 也就是说,任何用 3.10 或更新版本、又没锁版本的人,构建都是坏的。

有个叫 latest dependencies (informational) 的 CI 任务故意忽略所有上界,允许失败。
它红着的时候,这个上界仍然必要;它转绿之后,就该把上界去掉。 见 KNOWN_LIMITATIONS.md 第 15 条。

快速开始

git clone https://github.com/YanKaFei/LLM-Training-Debugger.git
cd LLM-Training-Debugger
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"

一个完整可运行的示例:

python examples/quickstart.py

或者直接塞进你现有的训练循环:

from training_debugger.adapters.pytorch import PyTorchTrainingAdapter

adapter = PyTorchTrainingAdapter(observer, model, optimizer, model_id="my-model")
adapter.run_start(steps=total_steps)

for step in range(1, total_steps + 1):
with adapter.step(step) as tracker:
loss = model(batch)["loss"]
tracker.record_loss(loss)
loss.backward()
tracker.record_gradients()
with tracker.phase("optimizer"):
optimizer.step()
optimizer.zero_grad(set_to_none=True)
tracker.record_parameters()

adapter.run_end()

你会得到什么

每条 incident 都带一个 reason_code、一个 evidence_state、一个 promotion_disposition,以及 —— 当数据流不完整时 —— 一条 data_quality 警告。事件被丢弃的 run 永远不会被渲染成健康的 run。

命令

training-debugger --root <store> runs # list runs
training-debugger --root <store> verdicts <run> # all verdicts, including abstentions
training-debugger --root <store> incidents <run> # incidents with evidence
training-debugger --root <store> incident <run> <id> # 单条事件,完整输出 training-debugger --root <store> metrics <run> [m] # 查询指标行 training-debugger --root <store> diagnose <run> # 确定性诊断 training-debugger --root <store> compare # 两次运行首次出现分歧的步 training-debugger --root <store> scan <r1> ... # 批量:哪次运行是离群值

compare —— 定位分歧

对齐两次运行的指标序列,把两者一致的前段区域当作零假设模型,然后报告第一个脱离该模型并持续偏离的步。差异中共同的噪声会相互抵消,所以单次运行的阈值做不到的定位,它能做到。

在已知注入步的配对语料上实测:9/9 故障对定位到确切的注入步,3/3 干净对正确弃权。

默认排除墙钟时间和内存指标 —— 时间差异不是算法分歧。

scan —— 在批量中找出离群值

每一对都比较一次;某次运行的得分,就是它与多少个同类发生了分歧。它要求运行之间同质可比:固定随机种子和配置,只变一个因素。如果一批运行混了不同随机种子,它返回 NO_SINGLE_OUTLIER 并说明原因,而不是随便点一个运行。

能力

每项能力都标注了明确的证据等级。这里没有任何一项标为已验证。

| 能力 | 状态 | 证据 |
| 非有限观测(NaN / Inf) | EXPERIMENTAL | 精确;无阈值 |
| 梯度异常检测 | EXPERIMENTAL | 检测边界 ×20 和 ×40 → 6/6;×2 和 ×5 → 0/6 |
| 事件融合与弃权 | EXPERIMENTAL | 运行级精确率 0.947 / 召回率 0.500(42 次运行语料) |
| 双运行分歧定位 | EXPERIMENTAL | 9/9 精确,3/3 弃权(配对语料) |
| 批量离群扫描 | EXPERIMENTAL | 同质可比批量上 5/5 同类支持 |
| 逐模块激活健康度 | EXPERIMENTAL | 在 OBSERVED 1.0 下点名并标注死模块 |
| 优化器调用见证 | EXPERIMENTAL | 冻结;默认关闭 |
| 关系推断(仅排序) | UNSUPPORTED | 默认禁用;一次实测尝试编造了 16 条关联 |

已知局限

公开这些,是因为一个失败情况没有记录的监控器不值得信任:

- 运行级召回率是 0.500。 开发语料里一半的主要故障被漏掉。
- 健康运行的误报事件:7.7 %,而自我设定的门槛是 5 %。这个门槛没达标。
- 观测器开销在 4 层基准负载上没达到自己定的 < 3 % 目标。 开销大致是每步固定的(0.2–0.9 ms),所以负载越大占比越小:+11.0 %(4L)→ +5.2 %(8L)→ +0.4 %(12L)。步耗时超过约 17 ms 后,就在预算之内。这里按失败上报,不找借口。
- 没有盲测留出集;所有数字都来自开发语料。
- 只在 4–6 层模型上验证过。
完整清单:KNOWN_LIMITATIONS.md · 设计记录: DECISIONS.md · 可读索引:DECISIONS_INDEX.md,开头是一张表,列出这个项目所有不得不更正或撤回的结论 ·当前状态:DEVELOPMENT_STATE.md

复现这些数字 bash pytest -q # 584 passing, 1 skipped
python tests/experiments/full_pipeline_smoke.py # 8/8
python examples/quickstart.py
python tests/performance/audit_observer_cost.py # paired overhead, with confidence intervals

现在每个核心数字都由已提交的脚本产出,评分也能重新复现了。tests/experiments/level_scoring.py 可以从一个 store 重新推导质量数字: bash
python tests/experiments/level_scoring.py development # or mixed, adversarial

在冻结版本 9e4550c 上复现:

| 数字 | 原值 | 重新推导 | |
| RUN precision(42-run corpus) | 0.947 | 0.9474 | 一致 |
| RUN recall(42-run corpus) | 0.500 | 0.5000 | 一致 |
| missed_primary_faults | 18 | 18 | 一致 |
| INCIDENT precision(42-run corpus) | 0.720 | 0.7200 | 一致 |
| RUN precision / recall(50-run mixed) | 1.000 / 0.500 | 1.0000 / 0.5000 | 一致 |
| INCIDENT precision(50-run mixed) | 0.500 | 0.5000 | 一致 |

有变化,因为测量之后检测器改过:

| 数字 | 原值 | 重新推导 | |
| EPISODE precision(42-run corpus) | 0.326 | 0.3960 | 变好 |
| EPISODE precision(50-run mixed) | 0.500 | 0.2222 | 变差 |

EPISODE 这一层统计每个注入故障产生了多少 episode,v0.1.8 的两处改动影响了它:T1 层可观测性节奏把 param.layer.norm 的输出频率降到了五分之一,另外注册了一个按模块的激活检测器。当初得出 episode precision 这个数字时,这两处改动都还没测过。原值已作废,重新推导的值才是当前值。

有九个数字来自一份从未提交的输入,在 tests/experiments/level_scoring.py 和 tests/evaluation_truth.py 出现之前,根本无法重新推导。现在两个脚本都有了,而且每个产物都记录了产出它的版本(code_sha,以及限定在源码树范围内的 code_dirty),所以下次再漂移,不用手动 diff 就能看见。见 EVIDENCE_REGENERATION_FINDINGS.md。

项目状态

Alpha。 接口还不稳定。API 可能随时变动。拿它给一次运行做埋点、读一份可审计的判定,确实好用;但还不到能在上面搭生产流水线的程度。

反馈与讨论

这个项目只在 GitHub 上讨论。 没有聊天服务器,没有邮件列表,也没有别的渠道——所以在这里提的任何东西大家都看得见,也一直能搜到。

| 发现 bug? | 提交 issue |
| 有问题,或者想讨论某个设计决策? | 发起 discussion |
| 想要某个功能? | 提交 issue |
| 不认同这里给出的某个结论? | 提交 issue —— 请务必这么做 |

欢迎提出异议,尤其是针对数字的异议。 如果你在本 README 中复现了某项测量,却得到不同的结果,那这就是一份值得提交的 bug 报告。如果这里的某个结论得不到本仓库中证据的支持,那这个结论就是错的,应当更正或撤回。

报告时请附上:你运行的命令、模型形状与步数、你的 PyTorch 版本,以及完整输出。

贡献

见 CONTRIBUTING.md。简单说:让结论变弱的改动,和让结论变强的改动一样受欢迎,而且绝不能为了让测试通过而削弱测试。

许可证

Apache-2.0。

由 DeepSeek Harness 构建。
预览分享卡片长什么样 ↓YanKaFei/LLM-Training-Debugger
分享 · DeepSeek Harness Hub
YanKaFei/LLM-Training-Debugger

把 PyTorch 指标异常转成可审计事件,证据不足时主动弃权

回到顶部