QwenGyre 跑在线强化学习,先分清采样与训练两条链路

文章导读
跑 QwenGyre 的在线强化学习,先要回答的是配置顺序问题:采样侧和训练侧由谁负责,先配哪一侧。通常的分工是,采样侧负责按当前策略与环境或模型交互、产出轨迹;训练侧负责消费轨迹、算损失、更新参数;在线意味着更新后的参数要回传给采样侧。判断顺序建议是:先定位两侧模块,再确认是同进程还是跨进程,然后跑最小闭环,最后用计数项验收交接面。
📋 目录
  1. A 在仓库文档里定位采样模块与训练模块
  2. B 对照配置项看两侧是否在同一进程启动
  3. C 用一个最小骨架把两条链路串起来
  4. D 在日志里确认轨迹真的到了训练侧
A A

跑 QwenGyre 的在线强化学习,先要回答的是配置顺序问题:采样侧和训练侧由谁负责,先配哪一侧。通常的分工是,采样侧负责按当前策略与环境或模型交互、产出轨迹;训练侧负责消费轨迹、算损失、更新参数;在线意味着更新后的参数要回传给采样侧。判断顺序建议是:先定位两侧模块,再确认是同进程还是跨进程,然后跑最小闭环,最后用计数项验收交接面。

采样侧产出轨迹,训练侧消费轨迹并更新参数,两侧用一份约定的数据形态交接。建议先确认是同进程还是跨进程,再按「采样产出→交接→训练消费→权重回传」的顺序最小化接入。是否跑通,看采样条数、消费条数、训练步数三项计数是否对得上;对不上先查交接面,而不是先调超参。跨进程结构下,进程存活不等于链路连通,需单独验证。

在仓库文档里定位采样模块与训练模块

QwenGyre 里哪部分负责在线采样、哪部分负责参数更新,先不要凭文件名猜,按 README、示例目录、入口脚本三类文件依次查。路径以仓库实际结构为准,下面给的是查找方法而不是固定路径。

  1. 先看 README:找模块划分、目录说明、快速开始一类段落,确认是否有独立的采样入口和训练入口。README 里如果只写一个启动命令,就要往下看示例目录。
  2. 再看示例目录:通常在 examples、scripts、configs 一类目录下,会有采样脚本、训练脚本或两者组合的启动脚本。示例里引用了哪些模块,往往就是两侧的边界。
  3. 最后看入口脚本:找到真正被执行的入口文件,顺着 import 和配置读取往下追,确认采样循环和参数更新分别落在哪个模块。

加速定位可以用关键词搜索,命令里的关键词需要替换成仓库中实际出现的命名:

grep -rn -l `--include`=*.py -e rollout -e sample -e trajectory -e generate .
grep -rn -l `--include`=*.py -e trainer -e update -e optimizer -e advantage .

搜索结果的交集文件通常是交接面,两侧各自独有的文件则分别是采样逻辑和训练逻辑。这一步只做定位,不改代码,风险边界在于不要因为某个文件同时被两侧引用就认定它属于某一侧,要看它对外提供的函数语义。

对照配置项看两侧是否在同一进程启动

采样和训练是进程内协作还是分进程通信,直接决定接入方式,需要看三类配置:进程类、端口类、通信方式类。配置文件名以仓库实际为准,但类别通常跑不掉。

  • 进程类:进程数量、worker 数、rank 或设备分配,用来判断是单进程起全部逻辑,还是采样和训练各起一组进程。
  • 端口类:监听端口、服务地址、主节点地址,出现这类配置项,基本可以倾向跨进程。
  • 通信方式类:队列、共享内存、文件落盘、RPC 或消息中间件,决定轨迹是怎么从采样侧走到训练侧的。

两类结构在启动日志上的表现不一样。同进程协作时,日志里往往只有一个 PID,采样与训练信息交替打印,参数更新前后能看到采样阶段的输出。跨进程时,日志里会出现两个及以上 PID,能看到监听地址、连接建立、等待队列或等待数据这类信息;如果训练侧先起,通常会停在等待输入的状态,采样侧先起则可能等不到消费者而先缓存。看到「等待连接」「队列为空」这类日志,说明两侧已经在通信层交互,只是数据还没到。

QwenGyre 跑在线强化学习,先分清采样与训练两条链路

用一个最小骨架把两条链路串起来

确认结构后,先跑通一次采样到训练的最小闭环,不要一上来就调采样规模或训练超参。通用骨架如下,仅作结构示意,接口名以仓库实际为准,需要替换成仓库中真实的构造与调用方式:

# 结构示意,接口名以仓库实际为准
sampler = build_sampler(cfg.sample)      # 采样侧:持有当前策略
batch = sampler.rollout(prompts)         # 产出轨迹,字段见交接说明
trainer = build_trainer(cfg.train)       # 训练侧:读取同一份配置约定
stats = trainer.consume(batch)           # 消费轨迹,计算损失
new_state = trainer.update()             # 参数更新
sampler.load_state(new_state)            # 权重回传,决定是否真的在线

每步的验证信号:sampler.rollout 之后,日志或返回结构里应能数出轨迹条数;trainer.consume 之后,训练侧应打印本批消费条数;trainer.update 之后,训练步数加一;load_state 之后,采样侧应能看到策略版本号或时间戳变化。四步中任何一步没有信号,先停在这一步排查,不要继续往下堆配置。

在日志里确认轨迹真的到了训练侧

交接面是这类链路最容易静默断掉的地方。建议固定观察三个计数项:采样条数、消费条数、训练步数。采样条数是采样侧产出的轨迹数量,消费条数是训练侧实际读到的轨迹数量,训练步数是参数更新次数。三者对不上时,按顺序做第一步检查。

  1. 先看消费条数是否为 0。如果采样有输出而消费为 0,问题在交接面,不在训练逻辑。
  2. 查交接载体本身:分进程看队列长度、连接状态或落盘目录是否有新文件;同进程看缓冲区是否被消费。
  3. 再看数据形态:轨迹字段是否齐全,序列化或反序列化是否报错,长度或 batch 维度是否与训练侧预期一致。
  4. 最后才看训练侧消费逻辑:是否因为过滤、丢弃无效样本或条件判断把整批数据跳过。

采样条数大于消费条数,通常是批量策略或过滤策略造成,属于预期内的差额,需要结合配置确认;消费条数长期为 0 或训练步数不增长,才是链路问题。风险边界在于,把超时和重试配置调大只能掩盖交接面的问题,不能替代对字段和载体本身的确认。验证方式建议固定为:改一次配置、只看一次日志、确认三个计数项的相对关系,再决定下一步动哪里。