OpenClaw-RL框架使用PRM(实为LLMJudge)从环境反馈中提取过程奖励信号,解决稀疏梯度问题。其支持二元RL、OPD及联合方法。PRM通过逐步评估生成密集奖励,采用零样本评判与多数投票降噪,实现了环境无关性和评估标准化。
这个系列的目标是通过阅读OpenClaw-RL源码,梳理强化学习中的关键概念和设计思路。文章中会穿插基础知识扩展,且整个系列环环相扣,部分概念会在不同文章中被反复提及,特此说明。
OpenClaw-RL是一个专注于在线强化学习的框架,专门针对智能体工具使用场景。其核心思想是从环境反馈中提取过程奖励信号来训练语言模型,支持三种主要模式:
长期稳定更新的攒劲资源: >>>点此立即查看<<<
框架
OpenClaw-RL 使用了 PRM,但需要特别指出:它并非传统意义上的“Process Reward Model”。代码中虽命名为“PRM”,实际承担的是“LLM Judge”角色,更接近一个“Outcome Reward Model (ORM)”。
外部环境→AgentServing→SGLang→用户响应 ↓ RolloutCollection→样本构建 ↓ PRM/JudgeEvaluation→奖励生成 ↓ PolicyTraining←训练样本+奖励 ↓ 新策略模型→AgentServing(更新)
本文将对这一部分进行详细拆解。
1.1.1 稀疏梯度的根本原因
不使用PRM时,观察ORM的效果。假设一个5步的episode,只有最后一步获得奖励+1,其余均为0。
step1 step2 step3 step4 step5(终止) 0 0 0 0 r=+1
反向传播时,只有step 5收到梯度信号,step1-4的r=0导致advantage≈0,梯度也≈0。模型完全无法感知前面步骤的质量。
1.1.2 PRM的解决思路
PRM的本质是一个函数r(s_t, a_t),用于评估当前步骤的即时质量。其核心思路是将稀疏信号转化为密集信号。
step1 step2 step3 step4 step5(终止) r1 r2 r3 r4 r5
PRM在每一步评估:“这一步做得是否正确?”从而在episode内每步都产生梯度信号,形成dense reward。
1.1.3 真正的PRM长什么样(数学题/Agent任务)
数学PRM(如Math-Shepherd)会对推导过程每一步打分:
Web Agent PRM:
1.1.4 PRM如何实现密集监督(具体机制)
训练数据构建方式(以数学题为例):
方式1:Human Annotation
方式2:Monte Carlo采样(无监督)
理论依据:P_correct(step_t) = V*(s_t) = E[最终成功 | 到达s_t]
1.1.5 PRM不能完全解决的问题
问题1:PRM本身需要训练数据
问题2:PRM的分布偏移
问题3:PRM可能被“黑”(Reward Hacking 2.0)
1.1.6 PRM和ORM的数学关系
ORM(稀疏):
R_episode = r_terminal(仅episode末端) advantage_t = E[R_episode|s_t,a_t] - V(s_t) = 难以估计
PRM(密集):
R_step = r_PRM(s_t, a_t)(每步即时分)
可选方案:
简单来说,PRM是人工构造的评估机制,环境奖励是自然产生的反馈信号。
PRM(过程奖励模型)定义
环境奖励定义
在MDP形式化中,Environment=(S, A, T, R, γ),其中R是reward function,通常被视为environment的一部分。因此从纯理论角度,Reward Model也可以算作environment的组成部分。
但在现代LLM RL的工程实践中,Environment(信息来自外部)和Reward Model(独立计算的评估)在系统架构上被明确分离。原因在于:
结论:在OpenClaw-RL的架构中,PRM/Judge明确属于Reward Judging。它使用了Environment(用户)产生的next_state作为评估依据,但评分计算本身是一个独立的Reward Judging过程。
OpenClaw的代码中称为“PRM”,但实际是“LLM Judge”或“Outcome Reward Model (ORM)”。
| 属性 | 传统PRM | OpenClaw “PRM” |
|---|---|---|
| 类型 | 训练好的reward model | Zero-shot LLM judge |
| 粒度 | Step-level(每步) | Response-level(整体) |
| 输出 | 连续分数 [0,1] | 离散 {-1, 0, +1} |
| 训练 | 需要标注+训练 | 不需要训练 |
| 评分依据 | 学到的特征 | Prompt 指导 |
OpenClawRL不直接使用传统意义上的环境奖励,而是主要使用PRM,将环境反馈作为PRM评估的输入。PRM/Judge属于Reward Judging,不是Environment。
这种设计体现了OpenClaw-RL的解耦思想:
通过PRM机制,OpenClaw-RL能够:
2.1.1 位置
在OpenClaw-RL的四个阶段中,PRM/Judge属于Reward Judging,不是Environment。
GPU4-5: PolicyServing (SGLang) ← Environment → 为真实用户提供对话服务 Environment = 用户提供的状态转移 → 接收用户消息,生成模型回复 → 捕获next_state(下一条用户消息) GPU6-7: RewardJudging (SGLang PRM) ← RewardJudging → 接收完成的对话turn,独立计算reward,不参与状态转移 → 调用LLM Judge评分×3(多数投票)→ 输出+1/0/-1,设置loss_mask GPU0-3: PolicyTraining (Megatron Actor) → 接收带reward的sample,更新权重
2.1.2 vs 传统PRM
传统PRM (Process Reward Model):
OpenClaw的“PRM”:
OpenClaw-RL采用“环境反馈 → PRM评估 → 奖励信号”的间接模式。虽然不直接使用环境奖励,但项目巧妙地利用环境反馈作为PRM评估的依据:
response = sglang_inference(prompt) # 主策略推理 next_state = get_next_user_input() # 获取环境反馈 prm_score = prm_evaluate(response, next_state) # PRM评估 reward = prm_score # 间接环境奖励
接下来逐一分析,首先探讨为何不直接使用环境反馈。
2.3.1 统一的环境概念
这两种情况均被视为助手所处环境的反馈:
用户(User)作为环境
工具(Tool)作为环境
2.3.2 关键区分
关键区分:Environment提供状态,Reward Judging提供评分。
OpenClaw的Environment(真实用户):
OpenClaw的Reward Judging (LLM Judge):
通用性优势
语义理解能力
实现复杂度平衡
这种“环境反馈→PRM评估→奖励信号”的间接模式,是OpenClaw-RL在通用性和实用性之间找到的最佳平衡点。
过程奖励模型(PRM)会根据这些“下一个状态”来判断助手的响应是否成功实现了用户意图。
2.5.1 下一个状态 next_state
在OpenClaw-RL框架中,“下一个状态”是指来自用户(user)或工具(tool)的反馈,它们共同构成了助手所处的“环境”。在_build_prm_judge_prompt()函数中,明确区分了两种类型的“下一个状态”:
过程奖励模型(PRM)会根据这些“下一个状态”来判断助手的响应是否成功实现了用户意图:
msgs = _build_prm_judge_prompt(response_text, ns_text, ns_role) # next_state是来自Environment的真实信号
但这里有一个容易混淆的地方:人们会误认为next_state用作reward的来源。
OpenClaw的PRM评分中,next_state起了关键作用:这造成了混淆,但本质上:
类比:法庭判决用了犯罪现场的证据(来自“现实世界”),但做出判决的是法官(reward judging),而不是现实世界本身。
2.5.2 分支说明
分支说明(PRM扮演的角色不同)
两条分支都通过self._prm_url(同一个SGLang Judge服务;部署在GPU6-7,与actor/rollout解耦)调用PRM模型。该模型本质是与策略同源的零样本LLM judge,不是单独训练的reward model。区别仅在调用方式。
具体参见如下:
10-分支说明
同一个SGLang服务(GPU 6-7),不同prompt,不同信号路径。
ORM:名义PRM,实为ORM
如1.4小结所述,OpenClaw的“PRM”名义上叫Process Reward Model,实际语义是“Outcome Reward Model for each turn”——它对整条response的整体质量打分(+1/0/-1),并不对response内部哪个句子/词有贡献给分。
OPD:teacher log-prob是隐式PRM
OPD的teacher log-prob实际上是一种“隐式PRM”:OPD的per-token advantage = teacher_lp[t] - rollout_lp[t],相当于“在hint的指导下,teacher对第t个token的评分”。这在token粒度上实现了——正确推导方向的token → teacher高概率 → advantage大;错误token → teacher低概率 → advantage小/负。
换句话说,teacher log-prob是一种软版的Process Reward,在token级别而非step级别。因此OPD绕过了“如何训练PRM”的难题——teacher的log-prob本身就是一个随时可用的过程级信号。
关键差异本质
| 对比项 | Binary RL 用 PRM | OPD 用 PRM |
|---|---|---|
| Prompt | _build_prm_judge_prompt | _build_hint_judge_messages(hint生成prompt) |
| PRM输出直接是训练信号? | 是(±1即reward) | 否(hint是中间产物,要再过teacher forward pass) |
| 输出格式 | boxed{±1/0} | boxed{1} + [HINT_START]...[HINT_END] |
| 信号进入训练的方式 | ±1 score → reward → GRPO advantage | hint text → 注入user message → teacher forward pass → log-probs差异 |
| 信号的信息量 | 1 bit(±1)per response | K bits per token(teacher分布) |
| PRM失效会怎样? | reward全0 → 没梯度 | hint全废 → 没OPD样本,但teacher仍可工作 |
| 同一句话能否同时被两路用? | 在Combine里 — 一次轮次并发跑两种prompt,分别决定是否发RL样本/OPD样本 | 同左 |
| 对PRM能力要求 | 判别能力(好坏二分类) | 生成能力(要写出更好的回答) |
| 失败模式 | 误判 → 错误reward方向 | hint偏离策略 → teacher-student gap噪声大 |
为什么Combine会有效
PRM在两个分支扮演互补角色:
Combine把同一PRM的“判别力”和“生成力”同时榨干:用判别得到密集的scalar监督,用生成得到稀疏的token级方向监督。两条路径用到的PRM服务实例相同,但prompt、解析、聚合、入loss的方式完全不同。
项目中的PRM不是传统训练好的reward模型,而是用LLM(同款Qwen3)做zero-shot评判,通过prompt指导它输出boxed{1} / boxed{0} / boxed{-1}来评分。没有单独训练过reward model。
代码里self._prm_url是同一个SGLang Judge服务(GPU 6-7)。它同时承担两类调用:
| 调用类型 | 目的 | 服务于哪条路径 |
|---|---|---|
| Hint-judge (_query_judge_once) | 解析boxed{1}+[HINT_START]...[HINT_END]提取更优回答提示 | OPD路径(决定是否发OPD样本+注入hint) |
| PRM eval (_prm_evaluate → _majority_vote) | 给当前回答打分+1/0/-1 | RL路径(生成reward) |
两者共享同一个模型权重、同一个router端口,只是prompt模板不同(_build_hint_judge_messages vs _build_prm_judge_prompt),并发执行m次投票。
在OpenClaw-RL中,OPD(On-Policy Distillation)使用了两个关键的服务器组件:
Policy Server(策略服务器)
实现文件:openclaw-opd/openclaw_opd_api_server.py
功能:
启动方式:
PRM Server(Process Reward Model Server,过程奖励模型服务器)
实现方式:基于SGLangRouter的独立服务
功能:
技术架构:
两者的关系数据流:
协同工作:
扩展性:
这种架构设计使得OPD能够有效地利用延迟反馈(hindsight hints)来改进在线策略学习,同时保持系统的可扩展性和模块化。
10-总体流程
You are a process reward model (PRM) evaluating an AI assistant. Your task: decide whether the assistant's output successfully fulfilled the user's intent at that step, using the next state as evidence. ## Scoring rules: - boxed{1} (good): ## next state shows task progressed as expected - boxed{-1} (bad): ## next state shows assistant output was wrong/incomplete - boxed{0} (neutral): ## insufficient information, cannot judge Think step-by-step, then give your final score inside boxed{}.
具体参见下表。
| 维度 | 内容 |
|---|---|
| 调用入口 | _build_prm_eval_prompt → _prm_eval_majority_vote |
| 输入 | (response, next_state) |
| Prompt 类型 | “你是PRM,请评估AI回答的好坏” |
| 输出格式 | boxed{1} / boxed{0} / boxed{-1} |
| 聚合 | m次独立投票多数决;平票→0 |
| 用途 | 直接进入训练损失—作为GRPO的scalar reward |
| 信号粒度 | 序列级标量(整条response一个分数) |
| 信号性质 | 评估性(evaluative):“好/坏” |
| 数据密度 | 所有±1分样本都进训练;0分丢弃(除“at-least-one”保底) |
角色:教练/提示提取器(Hint Extractor)
文件位置:openclaw-opd/openclaw_opd_api_server.py
特点:双重功能,同时实现hint提取(+1/-1 Something wrong happened, please give me more information or retry)
PRM使用精心设计的提示模板确保评估一致性:
def _build_hint_judge_messages(response_text: str, next_state_text: str, next_state_role: str = “user”) -> list[dict]: system = ( “You are a process reward model used for hindsight hint extraction.\n” “You are given:\n” “1) The assistant response at turn t.\n” “2) The next state at turn t+1, along with its **role**.\n\n” “## Understanding the next state's role\n” “- role='user': A reply from the user (follow-up, correction, new request, etc.).\n” “- role='tool': The return value of a tool the assistant invoked.” “This content was NOT available before the assistant's action—” “it exists BECAUSE the assistant called the tool.” “A successful, non-error tool output generally means the assistant's” “action was appropriate; do NOT treat it as information the assistant” “should have already known.\n\n” “Your goal is to decide whether the next state reveals useful hindsight information\n” “that could have helped improve the assistant response at turn t.\n\n” “Output format rules (strict):\n” “- You MUST include exactly one final decision token: boxed{1} or boxed{-1}.\n” “- If and only if decision is boxed{1}, provide a concise, information-dense hint in 1-3 sentences,\n” “wrapped between [HINT_START] and [HINT_END].\n” “- If decision is boxed{-1}, do not provide a hint block.\n” “- Hint must be concrete and actionable for improving the previous response.” ) user = ( f“## Assistant response (turn t)\n{response_text}\n” f“## Next state (turn t+1) [role: {next_state_role}]\n{next_state_text}\n\n” “Now output your decision and (if positive) the hint in the required format.” ) return [{“role”: “system”, “content”: system}, {“role”: “user”, “content”: user}]
具体参见下表。
| 维度 | 内容 |
|---|---|
| 调用入口 | _build_hint_judge_messages → _query_judge_once |
| 输入 | (response, next_state) |
| Prompt类型 | “若回答有问题,请给出更好的版本 [HINT_START]...[HINT_END]” |
| 输出格式 | boxed{1} + 文本hint |
| 聚合 | m次投票,选出最长的有效正样本hint(>10字符) |
| 用途 | 不直接进入损失;hint文本被注入到user message,再喂给teacher做forward pass,真正的训练信号是teacher_log_probs - rollout_log_probs |
| 信号粒度 | token级向量(response中每个token一个advantage值) |
| 信号性质 | 方向性(directional):“应该这样回答” |
| 数据密度 | 只有hint通过的轮次才进训练(更稀疏,但更精细) |
关键点:OPD路径本身的“老师信号”不来自PRM±1分。
OPD真正用于训练的方向性信号是teacher模型对hint增强后,prompt的token级log-prob,再减去student(rollout_log_probs)。PRM评分只起两个作用:
所以:PRM模型权重在OPD路径里被调用(做hint抽取),但PRM的±1分数本身不进入OPD的损失函数——除非跑的是Combine。
接下来看看评分流程,以及其中一些技术细节。
PRM完整评分流程如下。
10-PRM完整评分流程
Majority Vote
Majority Vote = 3,即对同一条response独立发起m=3次异步judge调用,取众数(most common score)。如果三票各不同(平局),返回0.0(中性/跳过)。
这3次Judge调用的特点为:
不足之处为:
Majority Vote算法细节:
def _majority_vote(scores: list[int|None]) -> float: valid = [s for s in scores if s is not None] # 过滤失败的查询 if not valid: return 0.0 # 全部失败→中性 counter = Counter(valid) top = counter.most_common(1)[0] # 关键:若有多个选项并列第一,返回0(保守策略) if list(counter.values()).count(top[1]) > 1: return 0.0 return float(top[0])
示例表格
| votes | 结果 | 原因 |
|---|---|---|
| [1, 1, 1] | +1 | 完全一致 |
| [1, 1, -1] | +1 | 多数票 |
| [1, -1, 0] | 0 | 三方平票 |
| [1, -1, None] | 0 | 2有效,平票 |
| [None, None, 1] | +1 | 唯一有效票 |
At-Least-One Guarantee
# _submit_turn_sample()中的核心逻辑: exclude = not has_next_state or score == 0.0 # 正常情况:score=0 → exclude=True → loss_mask=[0,0,...,0] # 但是!特殊保障: if exclude and has_next_state and self._session_effective.get(session_id, 0) == 0: exclude = False # ← 强制参与训练! # “at-least-one guarantee”
解决的问题场景如下:
用户发了5条消息,但每次都是中性反馈(score=0),导致:
保障机制如下:
第一个被PRM评过(has_next_state=True),但score=0的turn → 强制loss_mask=[1],参与训练 → 至少每个session贡献一个样本。
异步提交
样本提交的异步状态机如下:
10-异步状态机
整体评分行为总结
10-整体评分行为
接下来分析显式PRM和OPD teacher log-prob之间的比较。
显式PRM:“这一步(动作)对最终目标有多大贡献?”
r(s_t, a_t) = P(最终成功 | 经过了这一步)
OPD teacher log-prob:“在看过hint后,teacher对这个token的认可程度?”
adv(t) = logπ_T(a_t | a_1...a_{t-1}, hint) - logπ_old(a_t | ...)
这是两个不同的问题,只是恰好都能产生密集梯度信号。
显式PRM(理想情况):
OPD teacher log-prob:
因此:
场景:response在step5犯了错误,即“the square root of 1764 is 43” ← 错误
显式PRM:
OPD teacher log-prob:
因此:
显式PRM:
r(step_t) = 0.8 → “这一步有80%的可能性是在正确轨道上” = 绝对质量分数,可以跨样本比较
OPD advantage:
adv(t) = teacher_lp - rollout_lp = “相对于当前policy,teacher的偏好差” = 若teacher和student在此token上意见一致 → adv ≈ 0 = 即使这个token“很重要”,只要两者一致,梯度就是0
因此:
显式PRM(标准设计):
OPD teacher(hindsight):
从理论角度分析,显式PRM+OPD的结合使用是否合理。
优劣分析
| 维度 | 显式PRM | OPD teacher log-prob |
|---|---|---|
| 信号密度 | Dense (per step) | Dense (per token, 更细) |
| 反事实推理 | √ 可以定位错误步骤 | × 级联污染 |
| 绝对质量 | √ 绝对分数 | × 只有相对差 |
| 训练成本 | 高(需要标注数据) | 零(teacher直接推理) |
| 分布偏移 | 有(PRM本身需更新) | 无(每次实时计算) |
| 粒度 | Step级(语义) | Token级(sub-word) |
| Reward hacking风险 | 中(model游戏PRM) | 低(teacher足够大且变化慢) |
优势互补
显式PRM回答“哪一步走错了”(诊断),OPD teacher log-prob回答“每个词要往哪里改”(处方)。前者具备反事实定位能力,后者具备零训练成本的优势。两者测量的是不同问题,只是都能产生密集梯度这一性质让它们看起来相似。
因此:
def combined_advantage(response_tokens, step_boundaries, prm_scores, teacher_lp, rollout_lp): adv = torch.zeros(len(response_tokens)) for step_idx, (start, end) in enumerate(step_boundaries): # PRM评估这一步是否正确 prm_score = prm_scores[step_idx] # e.g., +1/-1 if prm_score > 0: # PRM: 这步是对的 → 用OPD精细化内部token adv[start:end] = teacher_lp[start:end] - rollout_lp[start:end] else: # PRM: 这步是错的 → 均匀惩罚(不用被污染的teacher LP) adv[start:end] = -1.0 # ← 关键:从这步开始后面的OPD信号都丢弃(级联阻断) break # 后续步骤advantage=0(不学习级联后的token) return adv
这解决了OPD的核心问题:PRM发现错误步骤后,后续步骤的OPD信号不再被计算,级联污染被切断。
advantage(t) = PRM_step(t) × (teacher_lp(t) - rollout_lp(t)) ↑ ↑ 步骤级“值不值得学习” Token级“往哪个方向学”
语义:PRM决定“这一步的梯度权重”,OPD决定“梯度的方向”。
正确步骤内的好token:PRM=+1 × OPD_adv=+0.5 = +0.5 ← 适度强化 正确步骤内的冗余token:PRM=+1 × OPD_adv≈0 ≈ 0 ← 不动 错误步骤内的token:PRM=-1 × OPD_adv=任意 ← 全部反转为负
当前Combine实际上已经是一种弱版本:
Combine: advantage = w_rl * GRPO_reward + w_opd * OPD ↑ 整条response一个标量(相当于sequence-level PRM = GRPO) PRM+OPD: advantage = w_prm * PRM_step(t) + w_opd * OPD(t) ↑ 每一步一个分数(更细粒度的PRM)
PRM+OPD是Combine的自然升级:把sequence-level reward换成step-level reward。
完整组合的advantage计算流程:
Response: [step_1] [step_2] [step_3] ... [step_N] ↓ PRM识别出step_3开始出错
Advantage分配:
挑战1:PRM的训练数据
挑战2:步骤边界的定义
挑战3:PRM本身的分布偏移
挑战4:两个模型的推理成本
显式PRM+OPD的结合是理论上最优的密集信号方案:PRM负责步骤级诊断和级联阻断,OPD负责步骤内的token级精细处方。这正是Combine方法的自然延伸方向,但工程成本和PRM训练数据是主要障碍。
TransFormer-封面
Your Efficient RL Framework Secretly Brings You Off-Policy RL Training
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述