StoneyTECH/discipline-patch
GitHub: StoneyTECH/discipline-patch
一种通过失败评估驱动的纠正性微调方法,以 MITRE ATT&CK 安全调查为案例演示如何修复 LLM 的行为纪律而非补充知识。
Stars: 0 | Forks: 0
# discipline-patch
**修复行为,而非知识。** 本仓库演示了一种我称之为 **Discipline Patch**(纪律补丁)的技术:当微调后的 LLM 表现不佳时,不要盲目去寻找更多训练数据。应将模型自身*未通过的评估(failed evals)*重写为你期望行为的纠正示例,并仅针对这些示例进行重新训练。
演示领域是安全调查:通过 QLoRA 微调、困难负样本(hard-negative)拒绝训练,以及一个由失败驱动的评估和修复循环,教导 LLM 像纪律严明的 SOC 分析师一样基于 [MITRE ATT&CK®](https://attack.mitre.org/) 进行调查。
这是一个研究实验室,而不是一个产品。这里有趣的问题不在于教模型 ATT&CK 框架——基础模型已经知道了。困难的部分是教它*表现得*像一个细心的分析师:将观察结果映射到某项技术,然后指出还缺少什么证据;保持数据所显示的内容与其未显示的内容相互独立(不草率得出关于攻击者、归因或严重性的结论);并拒绝像 `T9999.123` 这样凭空捏造的技术 ID,而不是编造一个自信的答案。这些都不是知识——而是行为,这也是此类模型不仅仅是“看起来很厉害”,而是真正“有用”的全部原因。这个仓库真正展示的是一种可重复的方法,用于衡量并改进这种行为。
## 实战案例:拒绝薄弱的映射
提示词被刻意设计成一个陷阱——一个看似可以映射、但实际并不行的日常网络事件:
通用模型往往无论如何都会试图给出一个映射:
自信、看似合理,但却错了。DHCP 租约是普通的网络活动;它本身什么都不是——而将其映射到对手技术是一种过度推断,会用噪音淹没 SOC 队列。经过纪律调优(discipline tuning)后,模型守住了底线:
两个版本都了解该框架。区别在于**行为**——拒绝薄弱的映射,指出缺失的证据,并将观察与推断区分开来。
## 包含内容
```
data/
build_attack_sft.py # deterministic SFT rows from the public ATT&CK STIX corpus
# (explainers, concise cards, mapping-boundary, mitigation,
# procedure→technique, and fake-ID rejection hard-negatives)
build_discipline_patch.py # turn FAILED eval rows into targeted corrective training data
run_training_row_arbiter.py # deterministic data-quality gate over training rows
mitre_probe_suite.v1.jsonl # 12 analyst-discipline smoke probes (mapping, fake-ID rejection,
# evidence boundaries, weak-evidence triage, defensive playbooks)
scripts/
train_qwen_lora.py # QLoRA / LoRA trainer (PEFT + HF Trainer)
verify_train_gate.py # fail-closed pre-train micro-gate
eval/
run_sft_coverage_suite.py # coverage eval engine + scoring (evidence, boundaries, refusal, format)
score_mitre_answer.py # score a single answer against the coverage rubric
analyze_mitre_eval_failures.py# failure taxonomy over an eval run
```
## 工作原理
整个项目建立在一个理念之上:只要你能干净利落地捕捉到模型的失败,这些失败就是你拥有的最佳训练数据。因此,它是以循环而非一次性任务的方式运行的——
1. **构建** 监督微调(SFT)数据,这些数据从公开的 MITRE ATT&CK 企业 STIX bundle 中确定性地生成——每种技术包含六种行类型,外加模型必须拒绝的伪造 ID 拒绝行。
2. **把关** 在允许任何数据进入训练之前,通过确定性的质量检查(溯源、格式、无捏造 ID)对每一行进行把关。
3. **训练** QLoRA adapter(4-bit,PEFT + HF `Trainer`)。
4. **评估纪律,而非召回率** —— 引用的证据是否充分?是否守住了边界?是否拒绝了伪造 ID?答案是否简洁?
5. **修复** —— 找出所有未通过的内容,将其转化为有针对性的纠正示例,重新训练,并再次运行相同的关卡,以确认行为确实发生了改变。
使这一切奏效的规则——也是让我最惊讶的一点——是,只有当一个未通过的评估被重写为你期望行为的明确示例后,它才能成为训练数据。你不是用*更多*的数据来修复行为不当的模型;而是用针对*特定*失败(从模型自身的评估中捕获)的*特定*数据来修复它。如果说这个仓库有一个值得借鉴的理念,那就是它了。
这个循环在推理时有一个“双胞胎”:在 [stoneytech-trinity-gvar-engine](https://github.com/StoneyTECH/stoneytech-trinity-gvar-engine) 中,失败的验证会将其失败的解释反馈到下一次生成过程中。同样的招数,不同的应用点。在上下文中,会话结束后,经验教训也就烟消云散了。而在权重中,它会被固化下来。
## 结果(v1 试点 —— 基础模型 `Qwen3.6-27B`)
| 阶段 | 结果 |
|---|---|
| 基础模型 | **0 / 12** 冒烟测试 |
| 朴素的 v1 adapter | 1 / 12 — *了解映射,但缺乏分析师纪律* |
| 应用了纠正性的 **discipline patch** 之后 | **12 / 12** 冒烟测试 (平均 0.969) → 在 v1 预留的 *technique-explainer* 评估集上达到 **71 / 71** (平均 0.972) |
纠正补丁仅包含 72 行数据和大约 18 分钟的重新训练,我发现最能说明问题的一点是,修复后的答案变得更*短*且更结构化,而不是更长——这种纪律使模型更加精简,而不是更啰嗦。大多数测试在 256-token 预算下即可通过。
### 这目前还不能证明什么
我会直言不讳地指出边界所在:这是一个经过验证的试点,而非生产环境。那 71/71 的成绩特指的是 v1 预留的 *technique-explainer* 评估集——更广泛的覆盖范围(特别是 procedure→technique 的消歧,以及简洁的卡片、缓解计划和大规模的伪造 ID 拒绝)仍在进行中,而且 procedure 行是真正困难的类别。早期的重复崩溃失败(`T1590.003.003…`)已被捕获,并通过确定性的防重复解码机制进行了修补。在所有关卡完全通过之前,adapter 仍将保持 `experimental` 状态。
## 训练设置
对于偏好机器学习的读者,以下是 adapter 的配方(所有默认值都在 `scripts/train_qwen_lora.py` 中,且每一个均可覆盖):
| 参数 | 值 |
|---|---|
| 方法 | QLoRA:4-bit nf4 基础模型 (double-quant, bf16 计算) + 通过 PEFT 和 HF `Trainer` 实现的 LoRA adapter |
| Rank / alpha / dropout | r=16, α=32, dropout 0.05 |
| 目标模块 | `q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj` (完整注意力 + MLP) |
| 序列长度 | 2048 |
| Batch | 1 × 梯度累积 8 (有效批大小为 8), lr 2e-4, bf16, 梯度检查点 |
| 补丁训练 | 恢复现有的 adapter (`--resume-adapter-dir`) 并仅对纠正行进行训练 |
| DoRA | 可通过 `--use-dora` 启用,便于在相同的评估关卡下进行等效对比 |
这里使用的基础模型是 `Qwen3.6-27B`,在单张 GB10(128 GB 统一内存)上本地训练。没有任何内容与这一选择绑定:训练器可以接受任何 HF 因果模型,这才是关键所在。补丁方法才是可移植的部分。
## 运行说明
```
pip install -r requirements.txt
# 1) 从公开的 ATT&CK STIX bundle 构建训练数据,然后对其进行门控
python data/build_attack_sft.py --help
python data/run_training_row_arbiter.py --help
# 2) 训练一个 QLoRA adapter
python scripts/train_qwen_lora.py --help
# 3) 评估分析师的 discipline
python eval/run_sft_coverage_suite.py --help
```
*(有意将参数标志留给每个脚本的 `--help` 来说明——基础模型是可替换的,且整个流水线与模型无关。)*
## 数据与溯源
每一行训练数据都是从公开的 MITRE ATT&CK® STIX 语料库(`enterprise-attack`)中确定性地生成的。出于设计考虑,本仓库中没有任何私有、客户或专有数据。
## 许可证
[MIT](LICENSE)。MITRE ATT&CK® 是 The MITRE Corporation 的注册商标;本项目是独立的,未与 MITRE 建立附属关系或获得其认可。
更多关于构建纪律严明、可审计的 AI 的思考:**[stoneytech.net](https://stoneytech.net)**。
标签:DLL 劫持, QLoRA, 大语言模型, 安全运营(SOC), 微调, 模型评估, 行为纠正, 逆向工具