reward 函数设计
Day 102 学了 GRPO 怎么算 advantage、Day 103 学了 RLVR 怎么用确定性 grader 给 0/1、Day 104 比了 DPO/GRPO 权衡。但所有这些的输入都是 reward——reward 函数设计错了,优化器再好也是把模型往坑里推。今天是 B11 的「奖励工程」核心日:多目标 reward 如何组合、为什么任何 grader 漏洞都会被 RL 利用(rew
阶段: B11 · GRPO/后训练机理 + 首跑(Day 101-110) 标签: #reward-design #reward-hacking #verifiable-reward #aml
今日导引(由浅入深)
Day 102 学了 GRPO 怎么算 advantage、Day 103 学了 RLVR 怎么用确定性 grader 给 0/1、Day 104 比了 DPO/GRPO 权衡。但所有这些的输入都是 reward——reward 函数设计错了,优化器再好也是把模型往坑里推。今天是 B11 的「奖励工程」核心日:多目标 reward 如何组合、为什么任何 grader 漏洞都会被 RL 利用(reward hacking)、GRPO 对哪类噪声鲁棒哪类敏感。落到本仓的杀手作品上,今天给 AML 任务写一个可验证 reward——SAR 字段完整性评分,去替掉「自评闭环」这一典型 reward hacking 反模式。这是 B1→B18 曲线上「把训练能力接到自己的金融域作品」的关键缝合点。今天的「最小可判定产出」:amlReward 模块 + 通过单测(确定性产出)。
为什么是今天、为什么接 AML?前四天的 GRPO/RLVR 都用 math 这类「硬可验证」任务举例;但 AISA 求职叙事的杀手作品是 AML Copilot,它的「好坏」是「软可验证」(有 FinCEN/FFIEC 标准但无唯一答案)。今天就是把通用奖励范式落到自己的金融域作品——这一步做完,「我能为合规任务设计可验证奖励」就从口号变成可链接代码 + 单测。
1. 机理精读
多目标 reward 通常按权重组合多个子信号:格式合规 + 答案正确 + 长度惩罚。 因为现实任务很少能用单一 0/1 概括「好」——一份 SAR 既要字段齐全、又要事实可溯源、又要不啰嗦。组合方式就是加权平均(本仓 composeRewards),权重编码了你对各目标的优先级。
但任何 grader 漏洞都会被 RL 利用——这就是 reward hacking。 RL 的本质是「最大化 reward」,它不在乎你想要什么,只在乎 reward 函数奖励什么。如果 reward 给「含 <think> 标签」加分,模型可能学会只满足格式拿分而内容空洞;如果给「答案越长越像在推理」隐性加分,模型会刷长度。grader 的每一个可被钻的空子,RL 都会精确地钻进去——这是 reward 设计最危险的陷阱。
GRPO 对噪声的鲁棒性是分层的。 因为组内归一化(Day 102),GRPO 对绝对噪声较鲁棒:reward 整体加个常数、或有零均值随机扰动,不改组内相对排序,advantage 基本不变。但对系统性偏置仍敏感:如果 reward 系统性偏好长答案,组内长样本会一致地拿高分,归一化救不了它——advantage 会被长度污染,模型学会刷长度。所以系统性偏置(长度、格式、位置)必须显式去偏,不能指望归一化抵消。
这条鲁棒性结论怎么落到 amlReward?
- 好消息:rubric 的各条 check 都是布尔结果(过/不过),不存在「越长分越高」的连续偏置——天然规避了 GRPO 最敏感的长度系统性偏置。
- 仍要防的:「锚点越多分越高」会诱导乱塞锚点。本仓用
rubric_anchors_resolve(锚点必须解析)把它从「数量」拉回「正确性」——多塞无效锚点反而触发不过。 - 设计原则:让每条 check 的「拿分路径」唯一等价于「真的做对」,这样 reward 就没有可被 GRPO 探索利用的捷径。
「自评闭环」是 reward hacking 的一个隐蔽变种。 用「同一个模型/同一套规则既做预测又做评分」,评分会系统性地偏向预测者自己的口味——这不是随机噪声,是系统性偏置,且没有外部 ground truth 可纠偏。本仓 src/aml/evalBaseline.ts 的结构性弱点正是此类:它用规则引擎 assessCase 做预测(evalRuleBaseline 里 const predicted = assessCase(c).topTypology ?? 'normal',evalBaseline.ts:27),又用同一作者的合成 generator 产出的金标 c.label 去算 recall/混淆矩阵。src/aml/groundTruthEval.ts 文件头一字不差地点名了这个「circular weakness」——「the SAME rule engine that predicts is graded against the SAME author's synthetic generator」。换句话说,预测源和金标源同根,分数好看但不代表对外部真实数据有效。groundTruthEval.ts 的 binaryEval / binaryEvalWithCI(groundTruthEval.ts:38/65)就是为打破这个闭环而建的——它接受 {label, predicted} 对,两边都可来自外部源(公开标注集 + 真实 LLM)。今天给训练用的 reward 也走同样的「外部可判定 grader」思路:用 rubric 代码检查(有 FinCEN/FFIEC 这个外部标准)而非让模型/规则自评。资源:GRPO 原论文(arXiv:2402.03300,2024-02)。
一个具体的 reward hacking 场景(SAR 写作):若 reward 只看「段落数 ≥5」,模型会学会把一段拆成五段空壳拿满分;若只看「含 [Txxxx] 锚点」,模型会乱塞锚点甚至编造 T999。本仓 rubric 正是用多条相互制衡的 check 堵这些洞:rubric_min_sections(段落数)配 rubric_5w1h_headings(必须有 Who/What/Why/How 实义标题),rubric_citation_present(要有锚点)配 rubric_anchors_resolve(锚点必须解析到真实交易)——单刷一条拿不到分,必须真的写对。这就是 reward 设计的核心手艺:每个可被钻的洞,都要有另一条 check 把它堵上。
2. 推导 / 手算 / 代码走读
为 AML 任务写可验证 reward——SAR 字段完整性评分,复用本仓既有确定性基建:
src/aml/sarQualityRubric.ts的runRubricCodeChecks(c, sar, assessment)(sarQualityRubric.ts:235):跑一组确定性子检查,每条返回{ checkId, dimension, passed, detail },覆盖:rubric_min_sections:段落数 ≥5(5W1H 结构)→completeness;rubric_5w1h_headings:Who/What/Why/How 标题齐全 →completeness;rubric_anchors_resolve:所有[Txxxx]引用锚点指向真实交易 →factual_faithfulness;rubric_citation_present:有判定就必须有证据锚点 →typology_citation;rubric_disclosure_present:含 AI 披露 + 人工复核声明 →regulatory_language。
src/aml/evalChecks.ts的runCodeChecks(c, assessment, sar)(evalChecks.ts:37):另一组确定性断言(段落数、citedTxIds全部存在于本案交易集等),每条带relatedFailure归桶。
amlReward 设计(基于上述 rubric 代码检查):
- 跑
runRubricCodeChecks/runCodeChecks,得一组passed布尔。 - 把通过率映射成 0..1 子奖励:如
completeness维 = 该维内通过的 check 数 / 总 check 数。 - 用
composeRewards(grpo.ts:26)按 rubric 权重组合——可直接借SAR_RUBRIC各维weight(completeness 0.3 / factual_faithfulness 0.35 / typology_citation 0.2 / regulatory_language 0.15,和为 1)。 - 关键:这套全是确定性代码检查,不调任何 LLM——这正是「可验证 reward」对「LLM 自评 reward」的取代点。语义型质量(细粒度幻觉、叙述流畅度)才留给 LLM-judge(
buildSarJudgePrompt构造 prompt,无 key 时诚实降级source='code-only')。
手算示例(演示口径):某 SAR 草稿,completeness 维 2 条 check 全过(=1.0),factual_faithfulness 维锚点解析过但有 1 处定性越界(代码检查只判锚点,判过 =1.0),typology_citation 过(=1.0),regulatory_language 缺人工复核声明(=0.0)。则 amlReward = 0.3×1.0 + 0.35×1.0 + 0.2×1.0 + 0.15×0.0 = 0.85。这是 RLVR 风格的「软可验证」reward:每一分都能追到一条确定性 check,可单测、可对拍。
第二个手算(残缺草稿,验证单调可分):另一份草稿,段落仅 3 段(rubric_min_sections 不过)、缺 Why 标题(rubric_5w1h_headings 不过)→ completeness 维 0/2=0.0;有一个锚点指向不存在的 T999(rubric_anchors_resolve 不过)→ factual_faithfulness=0.0;有判定但无交易锚点(rubric_citation_present 不过)→ typology_citation=0.0;披露齐全 → regulatory_language=1.0。则 amlReward = 0.3×0 + 0.35×0 + 0.2×0 + 0.15×1.0 = 0.15。
对比:齐全草稿 0.85 > 残缺草稿 0.15——reward 单调可分,这正是单测要断言的核心性质(好的拿高分、差的拿低分,且差距来自可追溯的 check)。注意 factual_faithfulness 权重最高(0.35),所以一个杜撰锚点的扣分比缺披露(0.15)更狠——这是把「AML 场景杜撰零容忍」编码进了权重。
走读 runRubricCodeChecks 的判定细节(sarQualityRubric.ts:235 起):
- 段落数检查取
sar.sections.length >= 5(sarQualityRubric.ts:247)。 - 5W1H 标题用
SECTION_KEYWORDS(Who/What/Why/How)逐个headings.includes(k.key),缺哪个报哪个(sarQualityRubric.ts:256-265)。 - 锚点解析:
anchors.filter(a => !a.resolved),未解析的列出txId(sarQualityRubric.ts:268-278)——这是「无杜撰交易」的确定性闸门。 - 披露检查用两个正则:
/人工复核|复核|review/i和/AI 生成|生成式 AI|规则模板|来源标注/,两者都命中才过(sarQualityRubric.ts:296-305)。 这些都是纯字符串/集合判定,无 LLM,所以 reward 完全确定、可 deep-equal 单测。
amlReward 如何接进 GRPO 组采样(把本 block 前四天串起来):
- 对一条 AML 案件 prompt,采样 G=8 个 SAR 草稿(Day 104 的在线采样,待 GPU)。
- 每个草稿过
amlReward得标量 r_i(今天建,确定性)——8 个 r 组成一组。 - 把这组 r 喂
groupRelativeAdvantage(Day 102),得 8 个 advantage,advantage>0 的草稿被强化(grpoScore的reinforce)。 - RLVR 的「V」在这里就是
amlReward这套确定性 grader(Day 103 的 RLVR 思想落到合规域)。
也就是说:今天的 amlReward 是把 Day 101-104 的优化器+奖励范式,真正接到本仓金融域作品上的那块奖励板。 训练循环(采样+更新)是 Day 107 的事且待 GPU;但奖励板今天就能建成、单测绿、可对拍——这是「确定性部分立即完成」的纪律。
3. 今日实战
- 新增
amlReward模块(如src/aml/amlReward.ts),输入(c, assessment, sar),输出 0..1 标量 + 各维明细。 - 内部复用
runRubricCodeChecks(sarQualityRubric.ts:235)与runCodeChecks(evalChecks.ts:37)的passed结果,按维度聚合成子奖励。 - 用
composeRewards(grpo.ts:26)按SAR_RUBRIC权重组合成总 reward。 - 用这个有外部可判定标准的 grader,替换
src/aml/evalBaseline.ts自评闭环式的打分逻辑(其循环弱点见groundTruthEval.ts头注)。 - 补单测:构造「字段齐全」和「缺披露/缺锚点」两类 SAR,断言 reward 单调可分(齐全 > 残缺),且确定性可 deep-equal。
- 写入
docs/aipa/day105-reward-design.md。
reward 设计自查清单(写完 amlReward 逐条过):
- 每个高权重维度都有 ≥2 条相互制衡的 check 吗?(防单刷)
- 「拿满分」是否必须真的做对,而非满足某个表面信号?
- 有没有一条 check 能被「越长越好/越多锚点越好」刷分?若有,加去偏。
- 全程确定性、可 deep-equal 单测吗?(任何 LLM 调用都破坏可复现)
- 语义质量是否已外包给 LLM-judge,而非硬塞确定性层?
- reward 区间是否归一到 0..1,便于和其他子奖励
composeRewards?
4. 今日实测 / 产出
docs/aipa/day105-reward-design.md+amlReward(基于sarQualityRubric.ts) + 通过单测。- SAR rubric / HITL 基建已建(
src/aml/sarQualityRubric.ts、src/aml/hitl.ts)。 amlReward单测为确定性产出(无需 key、无需 GPU)。- 状态如实:
evalBaseline.ts的循环自评本身命中「自评 reward hacking」,本日正是用可验证 grader 替换它;reward 模块 + 单测可立即完成。 - 范围诚实:今天只建奖励板 + 单测(确定性,可立即完成);用它驱动的真实 GRPO 训练在 Day 107-110(待 GPU),不在本日声称「已训练」。
- 不臆造数字:本日产出是「reward 单调可分」这一结构性质的单测断言,不预填任何训练后的 Δ 准确率(那是 Day 109/110 的事,且需先完成训练)。
5. 常见误区 / 陷阱
- 保留无 ground truth 的自评闭环当 reward:让模型/规则自评自己,是系统性偏置不是噪声,归一化救不了——必须换成有外部可判定标准的 grader(2026 共识)。
- 以为 GRPO 归一化能抵消一切:它只抵消绝对噪声,对长度/格式/位置等系统性偏置无能为力,须显式去偏。
- reward 给「格式」过高权重:模型会学会只满足格式拿分、内容空洞(典型 reward hacking)。本仓
SAR_RUBRIC把factual_faithfulness设最高权重(0.35),正是防「读着顺就给高分」。 - 把语义质量也塞进确定性 grader:细粒度幻觉、叙述流畅度不是代码能确定判的,硬塞会误判;留给 LLM-judge(无 key 诚实降级),别让确定性层越权。
- 单条 check 一票否决式硬扣分:把某条 check 设成「不过则总 reward=0」会让训练信号过稀疏(组内全 0 无区分度,见 Day 103);用加权而非一票否决,保留梯度。
- 误读
evalBaseline.ts的「循环」:它的循环不在代码逻辑(它是正确的 recall/混淆矩阵计算),而在数据来源同根(预测引擎与金标 generator 同作者)。修法不是改算法,是换外部数据源(groundTruthEval的设计意图)。 - rubric 权重拍脑袋:权重编码业务优先级。AML 把
factual_faithfulness设 0.35(最高)是因为杜撰零容忍;换场景必须重新论证权重,不能照抄。 - reward 调 LLM 破坏可复现:一旦
amlReward内部调 LLM-judge,它就不再确定、不能 deep-equal 单测、训练也引入 judge 噪声。语义 judge 留给评测层(Day 109),训练 reward 层保持纯确定性。 - 忘了 normal 案件的负向 reward:只奖励「写得好的 SAR」会诱导模型对所有案件都写 SAR(过度上报);reward 需覆盖「该不上报时不写」的克制(呼应 tasks.ts 的
aml-restraint类)。
6. 学习资源(每条带 YYYY-MM)
- DeepSeekMath《GRPO》原论文(arXiv:2402.03300,2024-02)——组内归一化对噪声/偏置的鲁棒性边界。
- Reward hacking 谱系综述(arXiv:2604.15149,再验当周)——reward hacking 最新分类,Day 112 深入。
- FFIEC BSA/AML 手册 Appendix L「SAR 质量指引」(监管文档;amlwatcher 2026 复核口径)——SAR 完整性的字段依据。
- 「Co-Investigator AI」(arXiv:2509.08380,2025-09)——SAR 叙述 Agent-as-a-Judge 双层(规则型 + 语义型)。
- Hamel/Shreya evals 工作流「代码型检查」层(hamel.dev evals-faq;Lenny's 2025-09)——「能确定性判的别浪费 LLM」的方法论,本仓
evalChecks.ts头注引用。 - Aman Khan 三类 evals(2025-06 首发 / 2026-04 更新)——code-based eval 的定位,对应本仓确定性 reward 层。
- 项目源码
src/aml/sarQualityRubric.ts(runRubricCodeChecks)、src/aml/evalChecks.ts(runCodeChecks)、src/agent/train/grpo.ts(composeRewards)、src/aml/groundTruthEval.ts(点名 evalBaseline 循环弱点)。
一句话总结今天:reward 设计的手艺 = 「每个可被钻的洞都用另一条 check 堵上」;amlReward 用相互制衡的 rubric 代码检查(外部 FinCEN/FFIEC 标准),把本仓 AML 作品从「自评闭环」升级成「可验证 grader」,确定性、可单测、可接进 GRPO 组采样。
SOTA检查 (2026-06 更新)
- 当前主流:用确定性 rubric grader 替代 LLM 循环自评是 2026 共识(规避自评 hacking);可验证 + rubric 混合 reward 是 SAR/合规这类「软可验证」任务的主流做法。
- 过时黑名单:保留无 ground truth 的自评闭环作为 reward(系统性偏置,不可纠偏);把语义质量硬塞确定性层。
- 下次复查点:再验时关注 reward hacking 谱系最新综述(arXiv:2604.15149);rubric-as-reward 是否有新标准化框架(与 Day 112 reward hacking 谱系一并复查)。
- 过程奖励 vs 结果奖励:本日是结果级 rubric reward;2025-2026 过程奖励模型(PRM)在多步推理上仍有研究热度,再验是否对 SAR 多步起草也适用。
衔接
- 昨天:Day 104 — DPO vs GRPO 机理:偏好优化 vs 在线采样权衡 + Unsloth 单卡环境冒烟(待 GPU)
- 今天:reward 工程——多目标组合 + reward hacking + GRPO 噪声/偏置边界;给 AML 写可验证
amlReward替换自评闭环,过单测 - 明天:Day 106 — 数据集与 prompt 构造:GRPO 训练集是「prompt+verifier」而非「prompt+答案」,复用 tasks.ts 模板造 64 条样本导出 jsonl