← 全部研究

NexRL:追求极致易用的RL训练框架

Boyu Tian,与朝闻道团队共同完成

Head Picture

引言

在大语言模型(LLM)与强化学习(RL)深度融合的当下,后训练框架作为技术落地的核心载体,其易用性直接影响研发效率与创新速度。NexRL 正是在这样的背景下诞生的LLM 后训练框架。我们试图追求模块化、松耦合、生态友好的架构设计,通过标准化接口封装,无缝利用开源社区在推理和训练侧的极致优化,并屏蔽硬件差异;通过模块间解耦,使能高效的算法迭代实验,扩展训练场景,助力Agent时代的强化学习研究与工程落地。

背景:为什么又一个强化学习框架?

强化学习框架是热门领域,之前已经有很多成功的开源框架,例如verl,slime,AReal等。他们在设计上各具独到之处,大大繁荣了开源社区的生态。我们内部的强化学习训练框架一开始也基于verl打造。因此,在设计NexRL之前,首要的问题是,为什么又要造一个强化学习框架?为了回答这个问题,我们先尝试从系统和算法两个角度来分析RL框架的本质。

RL 框架的本质:胶水层与试验田

系统角度

从系统角度出发:RL训练框架是连接推理系统和训练系统的胶水层。RL包含Rollout和Optimization两个核心步骤,其中Rollout需要与环境交互生成数据,本质是一个推理过程;Optimization则需要消费数据、计算梯度并更新模型,本质是一个训练过程。

RL Infra View

图1:从系统角度看待RL框架

训练和推理框架优化、算子优化、模型适配都是机器学习系统领域的热门核心课题,拥有完善的生态和繁荣的社区。一个优秀的 RL 框架不应该重复造轮子去实现底层的推理或训练内核,而是应该充分利用社区的力量。在推理侧,我们有vLLM、SGLang这样极致优化的引擎;在训练侧,我们有Megatron-LM、FSDP这样成熟稳定的分布式训练方案。因此,一个天然的想法是,RL框架不应该将胶水层与具体的训练/推理实现深度绑定。NexRL 的目标是作为一个极致易用的胶水层,将这些顶尖的组件有机地粘合在一起,让开发者能够站在巨人的肩膀上,专注于算法和 Agent 本身,并根据模型和底层可用硬件等限制灵活切换训练和推理框架。

算法角度

从算法角度出发,RL训练框架是快速迭代、小步快跑的试验田。与预训练不同,预训练通常具有极长的周期,属于重量级工程,核心关注点在于scale的突破,包括数据量、模型参数规模的持续扩大,以此追求更通用的基础能力,其整个流程从数据准备到最终训练完成需要耗费数周甚至数月时间,且一旦启动后难以频繁调整。而后训练则更为轻量,其核心目标是在预训练模型的基础上进行针对性优化,适配特定任务或场景,因此允许并需要更多快速迭代的尝试,单个实验的极致性能往往并非首要追求,后训练的周期通常以天为单位,显著短于预训练,研究者的大部分时间都投入在算法的设计、实现与验证环节。

RL Algorithm View

图2:从算法角度看待RL框架

从算法研究者视角来看,RL框架需要完成的核心工作集中在四个方面:

  • 数据整理:将推理生成的采样轨迹转换为训练所需的batch数据。由于训练需要统一且对齐的数据格式,RL框架需对单次生成的轨迹进行合并、padding、格式转换等处理;受底层采样算法、智能体输入输出格式差异影响,这部分代码需要频繁修改适配。

  • 强化学习算法处理:根据不同的RL算法对训练前的batch数据进行差异化处理,例如GRPO需要根据组内差异计算优势估计与梯度权重,PPO需要通过裁剪目标函数来限制策略更新幅度以保证训练稳定性,DAPO则需要引入判别器学习数据分布特征并引导策略优化。这部分是强化学习算法的核心实现,需要研究者反复迭代验证。

  • 流程协调:管理采样-训练-权重同步的循环流程,以及配套的实验日志管理、信息上报、分布式资源管理等机制,保障训练过程的有序推进和可追溯。

  • 训推编排:整合模型训练和推理过程,充分利用GPU资源,将训推环节融入整体工作流,实现计算资源的高效利用和训练流程的顺畅衔接。

从这个角度来看,RL框架可分为算法实验相关和算法实验无关两部分。前者包括数据整理的处理逻辑、算法核心处理等需要频繁迭代的内容,后者则涵盖流程协调和训推编排等可在不同实验间完全复用的模块。因此,从算法实验的便利性出发,RL框架应将需要密集实现、修改、验证的部分通过明确的接口和模块暴露出来,以支持高效的算法迭代。尤其在Agent时代,一个良好的RL框架更需高效支持智能体训练,妥善处理智能体特定的处理需求。此外,在研究迭代过程中,框架的复杂度会不断累积,新功能与既有模块相互纠缠,随着时间推移,框架代码会变得极度复杂,难以维护,最终增拖慢研究迭代的速度。一个设计良好的框架能够在框架持续演进的过程中始终保持代码的可理解性和可维护性。此外,训练的启动越便捷越好。由于大多数数据整理和算法处理不需要强大的算力资源,最佳体验是能够本地开发,一键运行。

设计目标:极致易用

基于上述分析,我们希望设计一款极致易用的强化学习框架,具体可以拆解为以下目标:

  • 极致轻:框架仅承担协调和抽象职责,不重复实现底层推理/训练逻辑,且能够轻量化启动
  • 极致社区化:通过服务接口深度拥抱vLLM、SGLang、FSDP、Megatron等开源社区方案
  • 极致可扩展:采用可插拔的模块化设计,支持像搭积木一样组合组件,灵活适配智能体训练需求
  • 长期可维护:通过松耦合架构控制复杂度增长,让框架能够持续演进而不会陷入"维护泥潭"

当然,另一个有趣的原因是,如今是vibe coding的时代,重新打造一个RL框架并非难事。受此影响,我们希望实现vibe-coding-native的框架设计,通过模块间清晰的责任划分、明确的接口定义,显著提升vibe coding的效率和正确率,进而加速实验迭代速度。NexRL开发过程中,大量代码使用了vibe-coding。

NexRL介绍:模块化、服务化

NexRL采用了超松耦合的架构设计,核心特点体现在组件模块化和训练推理服务化两大方面。

组件模块化

NexRL将强化学习训练流程分解为独立的模块,各模块通过明确定义的接口实现交互,核心组件及功能如下:

  • DataLoader:提供训练数据,支持自定义数据集,可适配不同格式、不同来源的训练数据输入。

  • RolloutWorker:执行环境交互并生成轨迹,负责衔接数据输入与轨迹输出的转换过程,一般需要调用单次或多次推理服务。在agent训练中,是集成agent的核心载体。

  • TrajectoryPool:管理轨迹收集,对分散的轨迹数据进行汇总、整理,生成符合训练要求的批次数据。

  • Trainer:应用算法逻辑(如GRPO),并调用训练服务完成梯度计算、模型更新等核心训练操作。

  • WeightSyncController:负责管理训练权重和推理权重的同步,确保训练侧更新后的模型权重能按照权重同步策略(同步、batch粒度异步、sample粒度异步)步到推理侧性。

当然,我们还提出了一系列小设计来灵活地管理这些解耦的模块。为了实现全局模块的状态管理和错误上报,我们设计了ActivitiTracker模块来收集全局信息,实现错误统一上报。为避免在分布式环境下(目前NexRL支持基于ray的分布式管理)的资源浪费和模块间通信开销,我们设计了可定义的模块间共享ray actor的资源管理机制,在不侵入模块代码的情况下实现高效的资源管理。可以参考NexRL开源仓库的相关文档,在此不过多赘述细节。

NexRL Architecture

图3:NexRL整体架构

两个关键抽象:RolloutWorker与Trainer

在NexRL中,用户主要需要关注两个核心抽象:RolloutWorker与Trainer。其中RolloutWorker是从数据到轨迹的转换器,其核心职责是接收原始数据,调用推理服务生成响应(或运行Agent),评估响应质量并计算奖励信号,最终输出完整的训练轨迹(trajectory)。其核心接口定义如下:

class RolloutWorker:
    def step(self, data_item: dict) -> Trajectory:
        """
        核心工作:将一个输入的data item转换为训练用的trajectory

        data_item 示例: {"question": "What is 2+2?", "answer": "4"}

        trajectory 示例: {
            "prompt": "Question: What is 2+2?\nAnswer:",
            "response": "The answer is 4",
            "tokens": [1234, 5678, ...],
            "loss_mask": [False, False, True, True, ...],
            "reward": 1.0,
        }
        """
        pass

Trainer则承担从轨迹到模型更新的核心职责,接收一批轨迹后,应用特定的算法逻辑(如计算GRPO advantage),调用训练服务进行梯度更新,最终返回loss、reward_mean等训练指标用于监控。其核心接口定义如下:

class Trainer:
    def train(self, trajectories: list[Trajectory]) -> dict:
        """
        核心工作:将一批trajectories投入训练,返回训练指标

        输入: [trajectory1, trajectory2, ..., trajectoryN]
        输出: {"loss": 0.5, "reward_mean": 0.8, ...}
        """
        pass

这种抽象设计的核心价值在于实现了清晰的责任分离:RolloutWorker专注于Sample World,以单条数据为单位工作,核心关注如何与环境/Agent交互;Trainer专注于Batch World,以批次数据为单位工作,核心关注如何优化模型。两者通过TrajectoryPool实现解耦,使得采样策略和训练算法可以独立优化,不同的Worker和Trainer也能灵活组合,用户只需实现这两个核心组件,其他模块可保持不变。

基于上述设计,用户的核心工作被简化为三项:实现RolloutWorker(或使用内置实现)、实现Trainer(或使用内置实现)以及编写配置文件。其余工作均由框架自动处理。模块间接口保持不变,模块支持独立开发、测试和替换。用户无需修改其他模块,即可实现数据加载策略的更换、自定义轨迹批处理逻辑的实现、新RL算法的集成。这种"改一处不动全局"的特性正是松耦合架构应对复杂度累积的关键——即使经过数十次算法迭代、适配了多种Agent场景,框架核心依然保持简洁清晰,不会因为功能叠加而变得难以理解和维护。

使用优势:动态加载和高效调试

得益于模块化设计,NexRL提供了两个易用性上的小设计,以进一步提升实验效率。

Modular Design Benefit

图4:模块化设计带来的优势——动态加载和辅助调试

首先,NexRL提供了动态加载机制,用户只需将自定义代码文件上传到recipe目录,框架运行时会自动完成加载。以训练自定义Agent任务、需要特殊query格式化逻辑的场景为例,采用NexRL的开发方式极为简洁:只需编写一个Python文件实现自定义逻辑,将其放入recipe目录,在配置文件中指定路径,即可完成开发。

# recipe/my_task/agent_workspace/my_worker.py
class MyCustomRolloutWorker(BaseRolloutWorker):
    """
    自定义Worker - 只需一个文件!
    核心工作:将data item转换为trajectory
    """
    def step(self, data_item: dict[str, Any]) -> str:
        """自定义任务格式化逻辑"""
        query = process_data(data_item)
        output = agent.run(query)
        trajectory = to_trajectory(output)
        self._put_trajectory(trajectory)

# recipe/my_task/my_task.yaml
rollout_worker:
  type: "custom"  # 使用自定义RolloutWorker
  # 动态加载:指定自定义worker的路径和类名

  custom_rollout_worker_module_path: "recipe/my_task/agent_workspace/my_worker.py"
  custom_rollout_worker_class_name: "MyCustomRolloutWorker"

启动训练时,框架即可自动完成加载。类似的动态加载方式也适用于trainer代码,方便算法研究者动态替换GRPO、PPO、DAPO以及前文介绍过的BAPO等强化学习算法实现。无需修改NexRL核心代码,也无需重新构建框架,大幅降低了用户的开发和维护成本,减少框架升级带来的适配工作量。框架负责协调、服务、分布式等底层能力,用户专注于RolloutWorker逻辑和Trainer算法实现,边界清晰且职责明确,提升开发效率。

第二个易用性优势是加速精度对齐调试。在强化学习实验中,精度对齐是调试的关键步骤,往往占用Infra和算法研究者大量时间。其核心痛点在于长链路的强化学习工作流中,缺乏有效的bug定位手段,传统方式多依赖研究者在代码关键位置记录中间结果,并与精度无误的baseline进行对比。NexRL的模块化抽象和服务化解耦设计能够有效助力这一过程,模块间的交互通过固定的交互接口实现,可准确定位精度不一致发生的最早节点。若缺乏这些标准化交互接口,代码改动可能导致baseline与当前代码的记录位置出现差异,使调试手段失效。为进一步提升调试效率,我们还开源了配合NexRL使用的easy-debug仓库,用来便捷地在实验中添加数据dump节点。建立在此基础上,我们可以搭建更完整的可观测体系。过去我们使用的可观测体系仅包含配置文件和实验曲线,在代码发生修改时,只能进行端到端曲线对比,耗时较长,且难以准确定位精度误差发生的位置。在经过模块化拆解后,可观测体系可以保存基础实验的关键节点数值并与配置文件、代码版本打包管理,用来辅助精度调试和后台的main分支定期代码检查。

训练推理服务化(Training/Inference as a Service)

NexRL Service Architecture

图5:NexRL的训练推理服务化架构

NexRL的第二个核心特点是服务化抽象,通过统一的API接口,实现不同训练和推理后端的无缝切换。其中,训练服务通过轻量级适配器支持多种后端,既包括FSDP、Megatron等自托管训练框架,也涵盖Tinker、Weaver等Training API,切换后端时无需修改上层训练逻辑。推理服务则采用标准的OpenAI API作为统一接口,支持SGLang、vLLM、TGI等多种推理引擎,切换推理引擎时无需修改Rollout Worker代码,极大提升了框架的灵活性和兼容性。

NexRL Service Benefits

图6:训练推理服务化带来的好处:硬件差异屏蔽和任务统一抽象

使用优势:生态兼容、计算抽象和本地使用

首先,NexRL的服务化设计可以屏蔽底层硬件差异,拥抱开源生态。随着算力芯片的快速发展,多种不同架构的算力芯片不断涌现,且可能各自依赖独特的软件生态。同时,针对不同使用场景的训推框架也不断增多,如适配端侧的MLC-LLM等。NexRL通过将底层训推软件抽象为标准化服务,能够在不修改代码的情况下无缝对接各类开源生态,有效屏蔽底层硬件差异,让用户无需关注硬件适配细节即可充分利用各类算力资源。

第二,服务化封装使能了计算任务统一抽象,为高效调度提供了便利。在系统领域研究中,调度策略是核心研究课题之一,而调度算法的有效性高度依赖于合适的任务抽象。NexRL通过服务化架构,天然将API服务调用封装为统一的计算任务,在后端计算平台中,这些标准化的计算任务封装能够使能更激进的调度机会,显著打开调度空间。例如,可基于统一的任务抽象实现训推任务的动态资源调度,根据任务优先级和资源占用情况,实时调整GPU、内存等资源的分配,在保证关键实验进度的同时,提升整体资源利用率。

第三,将训练和推理封装为标准化API调用,使得训练框架本地一键启动成为可能。由于需要使用大量算力的训练和推理被抽象出去,强化学习框架本身变得更加轻量化,算法研究者的本地机器往往已经足够启动训练,进一步提升了实验的便捷性。

使用案例

我们展示三个与传统RL训练不同的训练场景,以说明模块化、服务化架构在扩展性方面带来的便利。

Use Case

图7:NexRL架构使能的使用案例

Agent训练

在Nex生态中,我们开源了通用智能体框架NexAU(https://github.com/nex-agi/NexAU),该框架支持通过配置文件或Python代码高效开发智能体,具备多轮对话、工具调用、skills、sub-agent、轨迹记录等丰富特性。NexRL实现了对NexAU开发智能体的无缝训练支持,用户无需在NexRL中额外开发适配代码,仅需提供智能体轨迹的奖励计算函数,即可完成RL训练。

具体而言,对NexAU智能体训练的支持通过替换RolloutWorker实现,即专用的NexAURolloutWorker。该Worker负责将输入数据转换为智能体所需的输入格式,调用智能体运行,并将智能体返回的轨迹整理为训练所需的标准格式;同时,NexAURolloutWorker会将NexRL使用的推理服务透传给智能体,从而精准截取训练所需的token ID、logprobs等关键字段。这种模块化抽象设计大幅降低了智能体训练的适配难度,且无需侵入整体训练代码。类似机制同样适用于其他框架开发的智能体,仅需针对性修改RolloutWorker即可。我们将在后续博客中详细介绍NexAU的设计及其背后的思考,欢迎持续关注。

同策略蒸馏

训练服务化之后,NexRL的拓扑结构具备极强的弹性,能够灵活适配复杂的训练场景。以On-Policy Distillation场景为例,该场景需要强大的Teacher模型指导Student模型学习。在NexRL中,可通过配置文件灵活初始化一个或多个Teacher Training/Inference Service以及一个或多个Student Train Service,RolloutWorker能够同时向Teacher请求指导信号、向Student请求当前策略动作。这种复杂的多模型交互场景,无需大规模侵入框架代码,仅通过配置文件编排服务即可实现,显著提升了复杂实验的落地效率。

Training-API 使用

自Thinking Machines Lab发布Tinker以来,Training API训练模式受到广大研究者的广泛欢迎。在该模式下,研究者可专注于数据、算法和Agent的核心设计,将分布式训练的复杂性交由云端处理。在前文中,我们发布了Training API产品Weaver,并分享了大模型后训练基础设施建设的系列思考。

NexRL天然兼容这种Training API训练模式,仅需在NexRL接口中对Training API提供的训练/推理API进行简单封装,即可实现无缝适配。在该模式下,模型的训练和推理运行在云端的Weaver/Tinker服务中,其他模块均运行在本地,大幅降低了本地环境部署和维护成本。目前,NexRL已开源Weaver/Tinker的适配代码,可以使用NexRL更好地体验这些产品,欢迎大家试用。

研究机会

NexRL的服务化架构不仅致力于简化强化学习算法的实验和工程实践,也希望为相关领域的研究探索提供便利。下面列举两个可能的相关研究方向,期待能够辅助社区的研究工作。如果您是相关领域的研究者,或NexRL能够为您的研究提供便利,欢迎联系我们。

面向强化学习的体系结构/芯片研究

随着大语言模型及其上层应用的日益普及,学界和工业界已提出多种专用加速器与体系结构设计,专门适配大语言模型的训练与推理需求。然而,如何借助这些芯片与体系结构研究成果,端到端加速具有复杂工作流的强化学习任务,仍是有趣的学术研究方向。而由于真实硬件存在开发周期长、成本高昂的问题,体系结构和芯片研究往往依赖模拟器开展验证。NexRL的服务化解耦架构恰好能够为这类研究提供高效的实验验证平台:其核心优势在于将训练与推理过程均抽象为标准化服务接口,研究人员可便捷地将后端从真实训推框架替换为硬件模拟器,在精准匹配真实强化学习工作流的基础上,高效开展端到端的体系结构与芯片验证实验。

线上服务与训练的接入

未来的Agent一大发展趋势是具备在线学习(Online Learning)能力,而NexRL的Agent训练本身基于服务化设计,能够轻松接入线上运行的Agent。线上用户的真实交互数据可实时流向Trajectory Pool,后台的NexRL持续进行训练更新,再将优化后的新权重推送到线上的Inference Service,从而自然实现真实数据交互、A/B测试等在线学习场景的落地。基于此,可开展一系列后续研究工作,例如,在线学习算法优化:探索如何在数据分布动态变化的数据流上实现稳定训练,解决非平稳数据分布下的模型漂移问题。探索与利用平衡机制设计:研究如何在保障用户服务质量的同时进行有效的策略探索,平衡短期服务效果与长期模型性能提升。训练安全性保障技术:防范对抗性用户输入对模型训练造成的负面影响,构建鲁棒的在线训练安全防护机制。

Nex生态

Nex Ecosystem

图8:Nex生态的关键组件

NexRL是Nex开源生态的一部分,之前我们已陆续开源了Nex-N1模型系列(Huggingface、OpenRouter、技术报告),智能体框架NexAU,后训练API Weaver(产品页、博客、使用文档)。Nex的开源组件可以分别使用,也可以高效联动。例如,如前所述,NexRL可以支持基于Weaver的训练后端和NexAU Agent的无缝训练。我们追求构建可持续迭代的能动性闭环开源生态,欢迎持续关注。

结语

在内部研究与工程落地实践中,我们当前沉淀的核心认知是:优秀的强化学习(RL)框架需具备极致轻量化、深度社区化、高度可扩展、长期可维护的核心特质,以高效支撑算法研究者的使用需求,灵活适配研发与科研工作的动态变化。NexRL 正朝着这一目标持续迭代优化。当前,NexRL已服务于大量内部训练需求,通过其松耦合模块化和训练推理服务化的设计,有效支撑了训推硬件更换、Agent训练、Training-API使用、On-Policy Distillation等多种实验探索。我们将持续探索面向新时代的大规模后训练基础设施,追求极致的性能、灵活性与易用性。如果您对这些问题同样充满热情,欢迎加入我们。

如果您觉得这篇文章有帮助,请引用它。
@misc{2026-nexrl,
  title   = {NexRL Towards a More User-Friendly RL Training Framework},
  author  = {Boyu Tian in collaboration with others at Dawning Road},
  year    = {2026},
  url     = {/blog/nexrl/},
  note    = {Blog post},
  urldate = {2026-10-24},
}
← 返回全部研究