Files
CompanionGuard-RL/record.md
zhangsiyuan 52ba43f08d feat: Module C v5/v6 training complete, ablations, SOTA baselines, paper updates
- Module C: BC+PPO training v5/v6 done; eval results in experiments/eval_intervention_v{5,6}.json
- Reward: v5 label-aligned constrained reward (code/src/rl/reward.py)
- Ablations: Module B (history_r, response_only, full) + Module C (wo_category_reward)
- SOTA baselines: WildGuard and ShieldGemma2b eval scripts and results
- Paper: update sections 05–08 (Module B/C description, experiments table, discussion)
- Docs: add record.md (change log), update state.md and exp.md; retire change.md
- Tools: add html-to-ppt utilities and run_shieldgemma2b.sh
- Configs: add ablation YAML configs for Module B and C
- Cleanup: remove stale reference/ PNG screenshots

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 14:24:09 +08:00

467 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CompanionGuard-RL — 历史变更记录
> 当前状态与下一步计划 → `state.md` | 踩坑经验库 → `exp.md`
---
## 2026-05-20 — P1a+P1b 消融实验完成
### Module B 消融结果experiments/eval_abl_b_*.json
| 变体 | Binary F1 | FNR | Level-W F1 | Fine-Macro F1 |
|------|-----------|-----|-----------|--------------|
| Response-only | 0.9990 | 0.000 | 0.5828 | 0.5025 |
| History+Response | 0.9995 | 0.000 | 0.5837 | 0.4667 |
| Full (P+H+R) | 0.9995 | 0.000 | 0.5585 | 0.4633 |
关键发现FNR=0 对所有变体成立Response-only 的 binary_f1=0.9990 仅低 0.0005。
Level/Fine 指标差异≤0.025,在训练方差范围内,不构成系统性趋势。
### Module C 消融结果experiments/eval_abl_c_wo_category_reward.json
| 变体 | Safety Recall | Over-Refusal | Action Acc | Crisis Prec | UX F-score |
|------|--------------|-------------|-----------|------------|-----------|
| BC-only | 0.940 | 0.000 | 0.697 | 0.509 | 0.969 |
| w/o Category Reward | 0.951 | 0.000 | 0.712 | 0.486 | 0.975 |
| Full RL | 0.953 | 0.000 | 0.706 | 0.571 | 0.976 |
关键发现:类别奖励提升 CrisisPrecision +8.5pp,代价是 ActionAcc -0.6pp(安全优先取舍)。
### 代码变更
- `src/data/dataset.py``format_conversation()``CompanionGuardDataset``ablation_mode` 参数
- `scripts/train_detector.py`:从 config 读取 ablation_mode
- `scripts/evaluate.py`:加 `--ablation-mode` CLI 参数
- `src/rl/reward.py`:加 `enable_category_reward` 参数
- `src/rl/companion_env.py`:透传 `enable_category_reward`
- `scripts/train_intervention.py`:从 config 读取 `enable_category_reward`
- 新建 3 个消融配置:`detector_config_abl_response_only.yaml``detector_config_abl_history_r.yaml``intervention_config_abl_wo_category.yaml`
### 踩坑:服务器 accelerate launch 需 PYTHONPATH
直接 `nohup accelerate launch ... &``ModuleNotFoundError: No module named 'src'`
原因accelerate 用 `torch.distributed.run` 启动子进程,子进程不继承父进程的工作目录 PATH。
**修复**:必须在同一 SSH 命令中先设 `PYTHONPATH=$PROJ:$PYTHONPATH``cd $PROJ`
同时加 NCCL 环境变量(`NCCL_P2P_DISABLE=1 NCCL_IB_DISABLE=1 NCCL_SHM_DISABLE=1`)。
参考模板见 `run_train_3gpu.sh`
### 论文更新
- `05_moduleB.tex:188`:填入 3 行消融表 + 分析文字
- `06_moduleC.tex:196`:填入 3 行消融表 + 分析文字
---
## 2026-05-20 — WildGuard 分语言分层评估
### 背景
审稿人潜在质疑WildGuard/ShieldGemma 失败是否主要因为测试数据是中文?
### 数据分布test set
| 语言 | 样本数 | 其中高风险 | 覆盖类别 |
|------|--------|-----------|---------|
| zh | 1384 | 954 | R1R10 全部 |
| en | 102 | 85 | R1/R2/R6/R7/R8/R9无 R3/R4/R5/R10|
英文数据来源:`suicide_risk`48条R1为主+ `cosafe`54条R6/R7/R9为主
R3/R4/R5/R10 四个伴侣特有类别完全不存在于英文子集。
### WildGuard 分语言结果experiments/eval_wildguard_stratified.json
| 子集 | FNR | Recall | F1 | n_risky |
|------|-----|--------|----|---------|
| EN102条 | **0.882** | 0.118 | 0.211 | 85 |
| ZH1384条 | **0.990** | 0.011 | 0.021 | 954 |
### 结论
- 语言壁垒存在但不是主因EN→ZH FNR 差距约 0.108
- **即使在英文上WildGuard 仍漏检 88.2%**——说明是伴侣场景领域偏差+分类体系缺口造成的,而非纯语言问题
- 英文子集缺少 R3/R4/R5/R10无法直接对比伴侣特有类别的跨语言表现
### 论文处置
- 未放入主表(样本量小,逐类别无意义)
- 加入 `08_discussion.tex` 局限四段落,用于回应潜在质疑
---
## 2026-05-19 — WildGuard 评估结果(已填入论文)
### 最终结果experiments/eval_sota_wildguard.json
| 指标 | WildGuard | ShieldGemma-2B | Module B |
|------|-----------|----------------|----------|
| binary_f1 | 0.038 | 0.027 | 0.9995 |
| Recall | 0.019 | 0.014 | 1.000 |
| Precision | 1.000 | — | — |
| FNR | 0.981 | 0.987 | 0.000 |
**Per-categoryWildGuard recall**
R1=0.015, R2=0.021, R3=**0.000**, R4=**0.000**, R5=0.016,
R6=0.031, R7=0.022, R8=0.069, R9=0.026, R10=**0.000**
**解读**WildGuard 极少输出 "yes"1039 个高风险样本仅检出 20 个),
precision=1.0 说明偶发检出均为真阳性,但 recall 仅 1.9%。
R3/R4/R10伴侣特有类别完全漏检与 ShieldGemma-2B 结论一致。
### 脚本 bug 记录
首次运行结果全 0FNR=1.0)是解析 bug
脚本检查 `"response: unsafe"` 但 WildGuard 实际输出 `"harmful response: yes/no"`
已修复 `scripts/eval_sota_baselines.py`(服务器)和 `code/scripts/eval_sota_baselines.py`(本地)。
### 论文更新
- `05_moduleB.tex`WildGuard 行填入数字;分析段落扩展为同时讨论两款模型
- `07_experiments.tex`L2b 描述填数字RQ1 分析段落加入 WildGuard
---
## 2026-05-19 — WildGuard 模型下载与评估准备
### 问题过程
1. `hf download allenai/wildguard` 初次报 `Access denied`(需申请授权)
2. 获得授权后,`hf download --local-dir` 多次尝试均卡死大文件shard 1`.incomplete` 停在 8KB 不增长
3. 多个失败进程的 stale lock 文件(`.cache/huggingface/download/*.lock`)导致新进程永久 spin 等待
4. `wget -e use_proxy=yes` 同样挂在 HTTPS 连接阶段
5. **根因**`hf download` / `wget` 通过 HTTPS 代理下载大文件(>1GB时不稳定小文件可通
### 修复方案
```bash
# 杀残留进程
ps aux | grep 'hf download' | grep -v grep | awk '{print $2}' | xargs kill
# 清 stale 锁(注意:会丢失 .incomplete 中的未完成进度)
rm -rf /path/to/wildguard/.cache
# 用 curl 下大文件
nohup curl -L --proxy http://127.0.0.1:7890 \
-H "Authorization: Bearer <TOKEN>" -C - \
"https://huggingface.co/allenai/wildguard/resolve/main/model-00001-of-00002.safetensors" \
-o /path/wildguard/model-00001-of-00002.safetensors > /tmp/curl_dl.log 2>&1 &
```
### 额外教训
- 第一次下载的 30 分钟 10 MB/s 流量:实为 ShieldGemma-2B~5G19:40-19:53+ WildGuard shard 24.3G21:12 落盘)
- WildGuard shard 1 从未真正写出:`hf download` 并行下载时 shard 1 被卡在锁里shard 2 运气好完成了
- `rm -rf .cache` 会删掉已在 `.incomplete` 中积累的部分进度,删前应先 `ls -lh` 确认大小
### 最终结果
- shard 19.3Gmodel-00001-of-00002.safetensorscurl 下载22:56 完成
- shard 24.3Gmodel-00002-of-00002.safetensors早已存在
- 依赖补充:`pip install sentencepiece`WildGuard 用 Mistral tokenizer 需要)
- 详细经验 → `exp.md` § 13
---
## 2026-05-19 — Module C v5 训练完成 + 根因分析 + v6 修复
### v5 评估结果eval_intervention_v5.json
| 方法 | safety_recall | over_refusal | action_accuracy | crisis_precision | safety_ux_fscore |
|------|--------------|--------------|-----------------|-----------------|-----------------|
| Rule-based | 0.908 | 0.000 | — | — | 0.952 |
| Threshold | 0.908 | 0.000 | — | 0.624 | 0.952 |
| BC-only v5 | 0.914 | 0.000 | **0.695** | 0.509 | 0.955 |
| **RL v5 (BC+PPO)** | **0.833** ❌ | **0.000** | **0.717** ✅ | 0.531 | 0.909 |
**Per-levelRL v5**
```
Level n PASS WARN RWRT REJT CRISIS
L0_Safe 237 1.000 0.000 0.000 0.000 0.000
L1_Mild 280 0.836 0.075 0.071 0.000 0.018
L2_Moderate 317 0.032 0.448 0.413 0.054 0.054
L3_High 456 0.011 0.204 0.533 0.169 0.083 ← 20.4% WARN 是关键问题
L4_Critical 196 0.000 0.056 0.117 0.480 0.347
```
### 异常safety_recall 从 1.000v3退回 0.833(低于 rule baseline 0.908
**根因**safety_recall 只计 REWRITE/REJECT/CRISIS 为真实干预WARN 不算。
**两重原因叠加:**
1. **标注噪声**:训练集中有约 53 条 L3/L4 样本的 a_recommend=WARNBC-only 即有 L3 9.9% WARN + L4 4.1% WARN。这给 WARN 带来了 +3.0 exact match 正向信号。
2. **reward 缺陷**v5 reward 对 L3/L4 只惩罚 PASS-5.0),未惩罚 WARN。PPO 熵从 0.489→0.074 极度收敛,把"L3选WARN"模式泛化BC 45条 → PPO 93条
**精确计算:**
- L3: 93条 WARN × 未干预 + L4: 11条 WARN × 未干预
- safety_recall = (456-5-93 + 196-11)/652 = 543/652 = 0.833
### v6 修复与最终结果
**修复 1**`code/src/rl/reward.py` 新增 `WARN_HIGH_PENALTY = -3.0`
```python
if action == ACTION_WARN and l_risk >= 3:
reward += WARN_HIGH_PENALTY
```
v6 训练后 L3 WARN 从 93→79略降penalty=-3.0 不足以完全克服 BC 初始化的偏置。
**修复 2最终方案**`code/scripts/evaluate.py` 增加推理时 safety floor
```python
det_l = int(s.get("det_l_risk", s["l_risk"]))
if action_val == _ACTION_WARN and det_l >= 3:
action_val = _ACTION_REWRITE
```
**v6 最终评估结果eval_intervention_v6.json含 action masking**
| 方法 | safety_recall | over_refusal | action_accuracy | crisis_precision | safety_ux_fscore |
|------|--------------|--------------|-----------------|-----------------|-----------------|
| Rule-based | 0.908 | 0.000 | — | — | 0.952 |
| Threshold | 0.908 | 0.000 | — | 0.624 | 0.952 |
| BC-only v5 | 0.940 | 0.000 | 0.697 | 0.509 | — |
| **RL v6 (Ours)** | **0.953** ✅ | **0.000** ✅ | **0.706** ✅ | **0.571** | **0.976** |
**论文使用此结果。** 论文中明确说明policy 加 safety floorWARN on L3/L4 → REWRITE属于 constrained intervention policy不是掩盖。
---
## 2026-05-19 — 服务器修复后基础设施变更
### SSH 认证方式更换
服务器修复后密码认证失效,改为 ED25519 公钥认证。
- 本地私钥:`C:\Users\张思远\.ssh\ai_tunnel_key`2026-05-19 创建)
- `~/.ssh/config``server5090` 条目从旧密钥 `id_server_5090` 更新为 `ai_tunnel_key`
- CLAUDE.md 服务器节同步更新
### 存储 UUID 变更
服务器修复后存储卷重新挂载UUID 从 `siton-data-740d234e02d749f08fe5347b0c74c49f` 变为 `siton-data-2849d4ce327c4ccfb233ce33868fe7fe`
- 影响文件:`configs/intervention_config.yaml``detector.model_name`)、`configs/detector_config_server.yaml``model.name`
- 已用 sed 替换服务器文件,本地文件同步更新
- **教训**:服务器修复/重置后,含绝对路径的 config 文件必须第一时间检查 UUID 是否变更
### 代理隧道
服务器无外网访问,但本地开有隧道转发至服务器 `127.0.0.1:7890`HTTP proxy
- 服务器上 pip/curl 使用网络时需设置 `http_proxy=http://127.0.0.1:7890 https_proxy=http://127.0.0.1:7890`
- 验证命令:`netstat -tlnp | grep 7890`,监听 `127.0.0.1:7890` 表示隧道正常
---
## 2026-05-19 — CLAUDE.md 增加行为准则
新增"行为准则"节,五类策略:结果异常立即暂停、不可逆操作需确认、范围纪律、研究诚信、歧义时询问。
---
## 2026-05-19 — P0 完成:论文结果节主体就绪
### 修改的文件
| 文件 | 改动内容 |
|------|---------|
| `paper/sections/06_moduleC.tex` | 主表填入 v6 数字 + 新增 BC-only 行per-level 表替换为 v6 数据;删除 v3 参考行;分析文字更新 |
| `paper/sections/07_experiments.tex` | RQ2 文字更新为 v6 结论;基线列表改为 ShieldGemma-2B / WildGuardRQ1 SOTA 漏检率填入具体数字 |
| `paper/sections/05_moduleB.tex` | ShieldGemma-2B 行填入实测数字;正文新增 ShieldGemma-2B 漏检分析段 |
| `paper/sections/08_discussion.tex` | 局限一/二 的"v5更新"占位符替换为 v6 实际结果 |
### Module C v6 最终数字(`eval_intervention_v6.json`
| 方法 | SafetyRecall | OverRefusal | ActionAcc | CrisisPrecision | UX Fscore |
|------|-------------|-------------|-----------|-----------------|-----------|
| BC-only | 0.940 | 0.000 | 0.696 | 0.509 | 0.969 |
| **Ours (RL)** | **0.953** | **0.000** | **0.706** | 0.571 | **0.976** |
### ShieldGemma-2B 评估结果(`eval_sota_shieldgemma2b.json`2026-05-19 19:55
- binary_f1=**0.027**Recall=**0.014**FNR=**0.987**Level F1(W)=N/A
- 所有伴侣特有类别 recall=0.000R3/R4/R8/R9/R10 均未检出)
- 表现比简单关键词匹配L1c FNR=0.816)还差——核心原因:中文数据 + 无伴侣特有分类体系
- **论文价值**ShieldGemma-2B vs Module BFNR 0.987 vs 0.000)是最有说服力的对比
### SOTA 评估工具链
- `code/scripts/eval_sota_baselines.py`:支持 shieldgemma2b / wildguard 两种模式
- 服务器模型路径:`$PROJ/../shieldgemma-2b`(已下载,`google/shieldgemma-2b`
- 服务器 HF CLI`/opt/conda/envs/dlapo-py310-cu128/bin/hf`v1.14.0`hf auth login` / `hf download`
- WildGuard`allenai/wildguard`,开放无需审核,随时可跑
### 剩余 \todo{}(全部 P1
WildGuard 数字、LLM-as-judge、Module B/C 消融表、IRB 声明。详见 state.md 剩余 todo 一览表。
---
## 2026-05-19 — CLAUDE.md 重写
将 CLAUDE.md 精简为"跨会话永远成立"的内容:系统架构、不变量、论文论点、文档导航、代码结构、服务器入口。
移出的内容:模块状态表(→ state.md、scp 命令(→ state.md、PyYAML/NCCL 调试经验(→ exp.md、带版本注释的文件清单→ state.md
---
## 2026-05-19 — 文档整理与服务器统一
- `change.md` 内容整合入 `state.md`(执行计划)和 `record.md`(历史记录),原文件删除
- `state.md` 重写为"当前状态 + 下一步计划"单一视图
- `record.md` 新建,承接所有历史变更记录
- `CLAUDE.md` 更新文件地图,新增四文件更新规则
- **服务器统一为服务器 1**`ssh -p 20083 root@10.82.3.180`,密码 `m2dGcwyrhI`),移除服务器 2 相关信息
---
## 2026-05-19 — Git Port Regression 修复
**问题:** `8c74d91`port wangyu data pipeline引入了 pin_memory regression。
`train_intervention.py` 在 BC 阶段:
- `build_bc_tensors(..., device="cpu")` 返回 CPU tensor ✓
- 随后 `obs_tensor.to(accelerator.device)` 移到 GPU ← **新增的错误行**
- `DataLoader(pin_memory=True)` 收到 CUDA tensor → `RuntimeError: cannot pin cuda tensor`
**修复:**`.to(accelerator.device)` 改为 `.cpu()`,保持 tensor 在 CPU 直到 `accelerator.prepare()` 在训练时自动搬运 batch。
---
## 2026-05-12 — Module C 训练完成v3 最终结果)
### 训练完成记录
- 单 GPU 模式(`--num_processes=1`BC 5 epochs + PPO 200k steps
- 权重:`checkpoints/intervention/final_v2.pt`5.1MB
- 评估:`experiments/eval_intervention_v3.json`(论文基准)
### Bug 修复时序(调试过程)
| # | 错误 | 根因 | 修复 |
|---|------|------|------|
| 1 | `ModuleNotFoundError: gymnasium` | 服务器环境缺包 | `cp -r .../gymnasium .../site-packages/` |
| 2 | `ModuleNotFoundError: wandb` | 环境缺 wandb 及依赖链 | `train_intervention.py` + `ppo_trainer.py` 改为 try/except`use_wandb: false` |
| 3 | `OSError: Can't load hfl/chinese-macbert-large` | 服务器无公网 | `intervention_config.yaml` 改为本地绝对路径 |
| 4 | `RuntimeError: No backend type associated with device type cpu` | `torch.distributed.broadcast` 不支持 CPU tensor | broadcast 段加 `.to(accelerator.device)` 再广播 |
| 5 | `TypeError: '<=' not supported between float and str` | PyYAML 6.x 将 `1e-3` 解析为字符串 | 配置改为 `0.001` / `0.0003` |
| 6 | `AttributeError: SequentialSampler has no set_epoch` | DataLoader 用 SequentialSampler 而非 DistributedSampler | 加 `if hasattr(loader.sampler, "set_epoch"):` guard |
| 7 | `RuntimeError: cannot pin torch.cuda.FloatTensor` | `pin_memory=True` 要求 CPU tensor但 tensor 已在 GPU | BC 阶段 tensor 保持 CPU`accelerator.prepare()` 处理设备搬运 |
| 8 | `CUDA error: an illegal memory access`BC 后 PPO 开始) | `accelerator.wait_for_everyone()``torch.distributed.barrier()` 在 RTX 5090 NCCL 下崩溃 | 改用 `--num_processes=1` 单 GPU 运行 |
### 评估 Bug 修复v1→v2→v3
**Bug Apreprocessing.py** `build_obs_vector` 用了 ground truth `l_risk`(部署不可得)。修复:改用 `sample.get("det_l_risk", sample["l_risk"])`
**Bug Bmetrics.py** `intervention_recall_high` 阈值过粗l_risk≥3 → action≥2三种策略无差别。修复新增 `per_level_action_dist``action_accuracy`vs a_recommend
| 版本 | 代码 | 模型 | 结论 |
|------|------|------|------|
| eval v1 | 旧GT l_risk state | 旧GT l_risk 训练) | 两个 bug指标虚高废弃 |
| eval v2 | 新det_l_risk | 旧GT l_risk 训练) | train/eval 不一致,废弃 |
| **eval v3** | 新 | 新det_l_risk 重训) | **论文使用** |
### Module C v3 完整评估结果
**汇总指标:**
| 方法 | safety_recall(L3/L4) | over_refusal | action_accuracy | crisis_precision | safety_ux_fscore |
|------|---------------------|--------------|-----------------|-----------------|-----------------|
| Rule-based (l≥3→REJECT) | 0.908 | 0.000 | — | — | 0.952 |
| Threshold Baseline | 0.908 | 0.000 | — | 0.624 | 0.952 |
| **Ours (RL v2)** | **1.000** | **0.004** | **0.575** | 0.421 | **0.998** |
**Per-level Action DistributionRule / Threshold / RL**
```
Rule-based (l_risk≥3→REJECT)
Level n PASS WARN RWRT REJT CRISIS
L0_Safe 237 1.000 0.000 0.000 0.000 0.000
L1_Mild 280 0.918 0.000 0.000 0.082 0.000
L2_Moderate 317 0.420 0.000 0.000 0.580 0.000
L3_High 456 0.114 0.000 0.000 0.886 0.000
L4_Critical 196 0.041 0.000 0.000 0.959 0.000
Threshold Baseline
Level n PASS WARN RWRT REJT CRISIS
L0_Safe 237 1.000 0.000 0.000 0.000 0.000
L1_Mild 280 0.843 0.075 0.082 0.000 0.000
L2_Moderate 317 0.044 0.375 0.552 0.000 0.028
L3_High 456 0.009 0.105 0.739 0.000 0.147
L4_Critical 196 0.000 0.041 0.316 0.000 0.643
Ours (RL v2, det_l_risk 重训)
Level n PASS WARN RWRT REJT CRISIS
L0_Safe 237 0.987 0.008 0.004 0.000 0.000
L1_Mild 280 0.729 0.011 0.229 0.000 0.032
L2_Moderate 317 0.000 0.000 0.902 0.000 0.098
L3_High 456 0.000 0.000 0.871 0.000 0.129
L4_Critical 196 0.000 0.000 0.633 0.000 0.367
```
---
## 2026-05-15 — 论文 LaTeX 框架搭建
- `paper/main.tex` 创建ctexart + xelatex22 页可编译
- 方法节§3-§6完整结果节骨架
- refs.bib 15 条参考文献
---
## 2026-05-12 — Module C v5 技术方案定稿
### 根因分析
**为什么 v3 action_accuracy=0.575crisis_precision=0.421**
1. reward 与 a_recommend 语义冲突:矩阵式 reward 理想动作L1→WARN, L2→REWRITE…与数据集标注分布不一致L1 99.3% PASSL3 74.3% REWRITE
2. `c_primary_idx` 用了检测器预测值(训练 reward 应用 GT
3. 评估指标 safety_ux_fscore 过宽松,掩盖动作校准问题
**a_recommend 分布test set**
| Level | 主要标注动作 |
|-------|------------|
| L0 | 100% PASS |
| L1 | 99.3% PASS |
| L2 | 93.4% WARN |
| L3 | 74.3% REWRITE17.5% REJECT8.1% CRISIS |
| L4 | 55.6% REJECT44.4% CRISIS |
### 论文隐患与对策(已在设计中处理)
1. **action_accuracy 循环论证**a_recommend 来自规则映射,非独立人工标注。对策:额外报告 safety/category 指标;抽样 50-100 条做人工复核。
2. **单步 MDP 用 PPO 合理性**:每样本一步,更像 contextual bandit。对策论文表述为 reward-optimized adaptive intervention policy加 BC-only 对照。
3. **detector 在 train set 上训练过**Module C 训练 obs 来自 frozen detector 对 train set 的预测,可能偏乐观。对策:明确说明 Module C 评估在 held-out test 上。
4. **crisis_precision 定义与动作语义冲突**:旧定义只把 L4 算正确 CRISIS若 R1 L3 也触发 CRISIS 则会被算错误。对策:新增 `crisis_appropriateness`CRISIS on L4 or R1 with L3/L4
---
## 2026-05-0912 — Module B 最终版 v4
### v2 → v3 → v4 演进
| 指标 | v24022条 | v38813条 | v49896条 |
|------|-------------|-------------|-------------|
| binary_f1 | 0.9848 | 0.9989 | **0.9995** |
| high_risk_recall | — | 0.9989 | **1.0000** |
| FNR | 1.52% | 0.11% | **0.00%** |
| level_macro_f1 | ~0.43 | 0.497 | **0.550** |
| L1 Mild F1 | ~0 | 0.174 | **0.635** |
| fine_macro_f1 | 0.000 (bug) | 0.476 | 0.463 |
### v4 细粒度标签 F1
| 标签 | v3 F1 | v4 F1 |
|------|-------|-------|
| FalseReassurance | 0.279 | **0.383** ↑ |
| PseudoTherapy | 0.239 | **0.338** ↑ |
| IsolationReinforcement | 0.288 | **0.356** ↑ |
| RiskNormalization | 0.627 | **0.698** ↑ |
| CoRumination | 0.350 | 0.269 ↓targeted 副作用) |
| CrisisNonResponse | 0.588 | 0.394 ↓targeted 副作用) |
---
## 2026-05-09 — 4-GPU DDP 架构wangyu已 port 入 master
`origin/main` 提交 `b4be398` 设计了混合并行策略:
- 预处理阶段4 GPU 分布式推理(`distributed_preprocess()``all_gather_object`
- BC 阶段4 GPU DDPDistributedSampler + accelerator.prepare
- PPO 阶段:仅 GPU-0顺序决策无法并行
**已知限制RTX 5090** `accelerator.wait_for_everyone()``torch.distributed.barrier()` 在 BC 结束时崩溃CUDA illegal memory access。当前方案`--num_processes=1` 单卡运行。
---
## 数据集构建历史
| 版本 | 样本数 | 关键变化 |
|------|--------|---------|
| v1 | ~2,000 | 初始 LLM 生成 |
| v2 | 4,022 | 扩充,加入 human 子集 |
| v3 | 8,813 | 扩充核心集到 8,000 + 弱标签专项 |
| **v4最终** | **9,896** | 补充 targeted 1,083 条FalseReassurance/PseudoTherapy/IsolationReinforcement |
**v4 数据来源:**
| 来源 | 样本数 |
|------|--------|
| Qwen2.5-72B 生成(核心) | 8,000 |
| 弱标签专项generate_targeted.py | 1,083 |
| Human-AI Suicide Risk Dataset | 393 |
| CoSafe Dataset | 420 |