# mrGRPO **Repository Path**: rnstaco/mrGRPO ## Basic Information - **Project Name**: mrGRPO - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-01 - **Last Updated**: 2026-03-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## VeRL: 从入门到精通 1. reward计算逻辑 【异步rollout情况下】 * verl/experimental/reward/reward_manager.py * async def compute_score()[line 85] * 请注意,异步rollout使用异步reward计算,而异步reward计算始终只支持单个item(样本,数据,trajectory,无论那种表述) * 在没有Reward Model的情况下,进入 return await self.reward_loop.run_single(data) 分支下(无论哪个都可以,都会进入) * verl/experimental/reward/reward_loop/naive.py * async def run_single() [line 34] * 由于自定义奖励函数(custom reward function in bash)默认是naive的reward manager,因此进naive.py * 调用reward function计算奖励,得到一个标量 * 返回一个字典 `{"reward_score": reward, "reward_extra_info": reward_extra_info}` * verl/experimental/reward/reward_manager.py * 直接返回run_single()的标量奖励,无其他操作 * 有一点需要注意,艹,忘了 * verl/experimental/agent_loop/agent_loop.py * async def _agent_loop_postprocess() [line 433] * reward计算属于后处理过程,拿到scalar奖励后,添加到batch(DataProto)中 * ```result = await self.reward_loop_worker.compute_score.remote(data) output.reward_score = result["reward_score"] output.extra_fields["reward_extra_info"] = result["reward_extra_info"]``` * async def _run_agent_loop() [line 431] * 得到sequence输出结果并计算奖励后,返回 * async def generate_sequences() [line 320] * 回到最初的async generate_sequences() 的异步rollout里,此部分属于是创建的异步任务,gather后得到结果 * _postprocess(outputs) 注意,之前得到的都是标量reward,因此还要有一步后处理(和前面的generate的后处理不要搞混),这一步的后处理是同时操作的batch里的所有数据 * 在第633行,执行了token-level的奖励分配 * 就是直接创建一个[bsz,max_reponse_len]的张量,然后计算有效的response位置,把标量奖励对应填进去,其他都是0 * response的后面的token也有0奖励,但因为有loss mask的存在,不会造成影响。 * def generate_sequence() [line 817] * 被trainer直接调用的generate sequence()方法,收集到了所有的sequence以及reward(token-level的张量形式) * 那么就正式回到最初的AgentLoopManager总类,带着输出和奖励返回到trainer,继续执行优势计算等操作 2. 修改了RLHF Dataset的构成 由于原有的build messages不能更改system prompt,因此加了一个if分支逻辑,如果在配置了指定了config.data.adjust_sys_prompt,那么会使用自定义的system prompt,而不是默认的。 3. 数据集处理流程 1. 下载APPS+.jsonl文件 2. 在另一个项目,dataset,先执行make dataset来为每一个数据添加计划字段,目前使用Qwen3max来根据问题生成计划,这会生成一个batch API的jsonl文件,调用阿里云的处理。生成result.jsonl后,在paste batch文件将原数据与新生成的计划进行合并,合并的key是文件索引。最终生成一个大json文件,包含原始数据以及生成的计划。-- APPS+_plan.json 3. 回到本项目,并在data process文件夹里的data process里处理上一步的APPS+_plan.json,转为符合verl格式的parquet文件,这一步还会打上special的标记给apps+数据集里四不像数据。 4. 然后顺便调用read parquet里的parquet to json,转为json格式 5. 不要问以上步骤为什么脱裤子放屁,huggingface的Dataset转为json比较麻烦,至少GPT写的代码看起来一坨。 6. 调用data process里的add plan来进一步将verl格式的数据的prompt部分,build init prompt来转为推理时第一轮直接可用的prompt,也不要问为什么,verl的rollout第一轮输入已经是batch了,在verl里处理起来比较麻烦,不如提前处理好,没办法。最终生成带init前缀的训练数据(json格式) 7. 再调用read parquet里的json to parquet,转为parquet训练数据。