diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 0000000000..553398875c --- /dev/null +++ b/docs/architecture/README.md @@ -0,0 +1,117 @@ +# AReaLite vs Core 架构分析文档索引 + +本文档集从软件架构角度全面分析了AReaL项目中AReaLite与Core系统的主要区别。 + +## 文档概览 + +### 📋 [架构分析总结报告](final_summary_report.md) +**推荐优先阅读** - 高层次的架构对比和战略建议 +- 执行摘要和核心发现 +- 适用场景分析 +- 技术深度评估 +- 选择建议 + +### 📊 [详细架构对比分析](arealite_vs_core_analysis.md) +深入的技术分析,包含: +- 设计理念差异 +- 系统架构模式对比 +- 代码复杂度分析 +- 性能和扩展性评估 +- 具体使用建议 + +### 🔧 [具体代码实例对比](code_examples_comparison.md) +通过真实代码片段展示差异: +- 入口点实现对比 +- 配置和组件定义 +- 训练逻辑实现 +- 数据流处理方式 +- 自定义开发体验 + +### 📈 [架构图表](architecture_diagrams.md) +可视化的架构对比: +- 系统架构图 +- 代码复杂度对比图 +- 训练流程序列图 +- 抽象层次对比 + +## 快速导航 + +### 按读者类型 + +**🎓 AI研究者/学生** +1. 先读 [架构分析总结报告](final_summary_report.md) 了解整体情况 +2. 查看 [具体代码实例对比](code_examples_comparison.md) 中的AReaLite示例 +3. 建议从AReaLite开始学习 + +**🏭 工业界研究团队** +1. 重点关注 [详细架构对比分析](arealite_vs_core_analysis.md) 中的性能分析 +2. 参考适用场景建议选择合适的系统 +3. 考虑从AReaLite原型到Core生产的迁移路径 + +**⚙️ 系统工程师** +1. 详细阅读 [架构图表](architecture_diagrams.md) 理解系统设计 +2. 重点学习Core系统的分布式架构 +3. 关注 [详细架构对比分析](arealite_vs_core_analysis.md) 中的技术细节 + +### 按关注点 + +**🚀 快速上手** +- [具体代码实例对比](code_examples_comparison.md) → AReaLite示例 +- AReaLite入口点:`examples/arealite/gsm8k_grpo.py` + +**📐 架构设计** +- [架构图表](architecture_diagrams.md) → 系统架构对比 +- [详细架构对比分析](arealite_vs_core_analysis.md) → 设计模式分析 + +**⚖️ 技术选型** +- [架构分析总结报告](final_summary_report.md) → 选择建议 +- [详细架构对比分析](arealite_vs_core_analysis.md) → 适用场景 + +**🔬 深入研究** +- 所有文档都值得详细阅读 +- 配合源码进行实践验证 + +## 关键概念速查 + +| 概念 | AReaLite | Core | +|------|----------|------| +| **设计理念** | AI-centric | System-centric | +| **编程模型** | SPMD | Master-Worker | +| **抽象层次** | 3层 | 6层 | +| **自定义方式** | 单文件修改 | 多模块注册 | +| **适用规模** | 1-64 GPU | 64-1000+ GPU | +| **学习曲线** | 1-2天 | 1-2周 | + +## 实践建议 + +### 学习路径 +1. **理论学习**: 阅读本文档集,理解两套系统的设计差异 +2. **动手实践**: 从AReaLite的GSM8K例子开始,运行完整的训练流程 +3. **深入探索**: 尝试修改奖励函数、算法参数,体验自定义开发 +4. **规模扩展**: 根据需要考虑Core系统的高级功能 + +### 选择决策树 +``` +项目规模 < 64 GPU? +├─ 是 → 团队熟悉PyTorch? +│ ├─ 是 → 选择 AReaLite +│ └─ 否 → 学习后选择 AReaLite +└─ 否 → 有专门的系统工程师? + ├─ 是 → 选择 Core + └─ 否 → 考虑外包或使用云服务 +``` + +## 贡献指南 + +如果您发现文档中的错误或有改进建议,请: + +1. 检查相关源码确认问题 +2. 提出具体的修改建议 +3. 如果可能,提供更好的实例或图表 + +## 相关资源 + +- **源码仓库**: [AReaL GitHub](https://github.com/inclusionAI/AReaL) +- **官方文档**: [AReaL Documentation](https://inclusionai.github.io/AReaL/) +- **AReaLite设计文档**: `arealite/README.md` +- **论文**: [AReaL: A Large-Scale Asynchronous Reinforcement Learning System](https://arxiv.org/abs/2505.24298) \ No newline at end of file diff --git a/docs/architecture/architecture_diagrams.md b/docs/architecture/architecture_diagrams.md new file mode 100644 index 0000000000..e6daa89d47 --- /dev/null +++ b/docs/architecture/architecture_diagrams.md @@ -0,0 +1,111 @@ +```mermaid +graph TB + subgraph "AReaLite Architecture (AI-Centric)" + A1[Entry Point
gsm8k_grpo.py] --> A2[Engine Objects] + A2 --> A3[RemoteSGLangEngine] + A2 --> A4[FSDPPPOActor] + A3 --> A5["rollout_batch()"] + A4 --> A6["ppo_update()"] + A5 --> A7[PyTorch/SGLang] + A6 --> A7 + + style A1 fill:#e1f5fe + style A2 fill:#f3e5f5 + style A7 fill:#e8f5e8 + end + + subgraph "Core Architecture (System-Centric)" + B1[Config Files
sync-ppo.yaml] --> B2[Experiment Framework
PPOMATHConfig] + B2 --> B3[Master Scheduler
MasterWorker] + B3 --> B4[Workers] + B4 --> B5[RolloutWorker] + B4 --> B6[ModelWorker] + B4 --> B7[ControllerWorker] + B5 --> B8[MFC Calls] + B6 --> B8 + B7 --> B8 + B8 --> B9[generate_MFC] + B8 --> B10[train_step_MFC] + B8 --> B11[compute_ref_MFC] + B9 --> B12[PyTorch/SGLang] + B10 --> B12 + B11 --> B12 + + style B1 fill:#fff3e0 + style B2 fill:#fce4ec + style B3 fill:#f1f8e9 + style B4 fill:#e3f2fd + style B8 fill:#f9fbe7 + style B12 fill:#e8f5e8 + end +``` + +## 代码复杂度对比 + +```mermaid +graph LR + subgraph "AReaLite: 3 Layer Abstraction" + AL1[User Script] --> AL2[Engine Objects] --> AL3[Backend Implementation] + end + + subgraph "Core: 6 Layer Abstraction" + CL1[User Config] --> CL2[Experiment Framework] --> CL3[Master Scheduler] + CL3 --> CL4[Worker Execution] --> CL5[MFC Calls] --> CL6[Backend Implementation] + end + + style AL1 fill:#e1f5fe + style AL2 fill:#f3e5f5 + style AL3 fill:#e8f5e8 + + style CL1 fill:#fff3e0 + style CL2 fill:#fce4ec + style CL3 fill:#f1f8e9 + style CL4 fill:#e3f2fd + style CL5 fill:#f9fbe7 + style CL6 fill:#e8f5e8 +``` + +## 训练流程对比 + +```mermaid +sequenceDiagram + participant U as User + participant AL as AReaLite + participant E as Engine + participant PT as PyTorch + + Note over U,PT: AReaLite训练流程 + U->>AL: 启动训练脚本 + AL->>E: 创建Engine对象 + loop 训练循环 + AL->>E: rollout_batch() + E->>PT: 直接调用 + PT-->>E: 返回结果 + AL->>E: ppo_update() + E->>PT: 直接调用 + PT-->>E: 返回结果 + end +``` + +```mermaid +sequenceDiagram + participant U as User + participant C as Config + participant M as Master + participant W as Workers + participant MFC as MFC System + participant PT as PyTorch + + Note over U,PT: Core训练流程 + U->>C: 提供配置文件 + C->>M: 创建实验框架 + M->>W: 调度Worker + loop 训练循环 + M->>W: 分配任务 + W->>MFC: 调用MFC + MFC->>PT: 执行计算 + PT-->>MFC: 返回结果 + MFC-->>W: 返回结果 + W-->>M: 汇报状态 + end +``` diff --git a/docs/architecture/arealite_vs_core_analysis.md b/docs/architecture/arealite_vs_core_analysis.md new file mode 100644 index 0000000000..f1b78d8ec6 --- /dev/null +++ b/docs/architecture/arealite_vs_core_analysis.md @@ -0,0 +1,378 @@ +# AReaLite vs Core: 软件架构分析 + +## 概述 + +AReaL项目包含两套不同的架构设计: + +1. **AReaLite** (`/arealite/`, `/examples/arealite/`) - 轻量级、AI研究者友好的版本 +2. **Core** (`/realhf/`, `/training/`) - 完整的分布式系统,支持大规模训练 + +本文档从软件架构角度深入分析这两套系统的主要区别,以同步PPO训练为例进行对比。 + +## 架构对比总览 + +| 维度 | AReaLite | Core | +|------|----------|------| +| **设计理念** | AI-centric,面向算法研究者 | System-centric,面向大规模生产 | +| **代码复杂度** | 简化,单文件可定制 | 复杂,多层抽象 | +| **学习曲线** | 平缓,PyTorch用户友好 | 陡峭,需要理解分布式系统概念 | +| **扩展性** | 适合中小规模实验 | 支持1000+ GPU大规模训练 | +| **灵活性** | 高度可定制,算法实验友好 | 结构化,适合生产部署 | + +## 1. 入口点架构差异 + +### AReaLite 入口点 (`examples/arealite/gsm8k_grpo.py`) + +```python +def main(args): + config, _ = load_expr_config(args, GRPOConfig) + + # 直接创建组件,无需复杂的worker管理 + rollout = RemoteSGLangEngine(config.rollout) + actor = FSDPPPOActor(config=config.actor) + ref = FSDPPPOActor(config=config.ref) if config.ref else None + + # 简单的训练循环 + for global_step in range(max_steps): + # 1. 数据收集 + batch = rollout.rollout_batch(data, workflow=workflow) + + # 2. 计算优势函数 + actor.compute_advantages(batch) + + # 3. PPO更新 + stats = actor.ppo_update(batch) + + # 4. 权重同步 + actor.upload_weights(weight_update_meta) +``` + +**特点:** +- SPMD (Single Program, Multiple Data) 模式 +- 直接的PyTorch风格API +- 线性的训练流程,易于理解和调试 +- 单文件包含完整训练逻辑 + +### Core 入口点 (`training/main_sync_ppo.py` → `realhf/experiments/`) + +```python +@hydra.main(version_base=None, config_path="configs", config_name="sync-ppo") +def main(args): + # 复杂的配置处理 + default_args = OmegaConf.structured(PPOMATHConfig) + args = OmegaConf.merge(default_args, args) + + # 通过实验框架启动 + run_experiment(args) +``` + +```python +# 在 PPOMATHConfig 中定义复杂的工作流 +class PPOMATHConfig(CommonExperimentConfig): + def make_agents(self) -> List[ModelInterfaceAbstraction]: + return [ + ModelInterfaceAbstraction( + "actor-train", args=dict(...) + ), + ModelInterfaceAbstraction( + "ref", args=dict(...) + ), + ] + + def make_dataset(self) -> DatasetAbstraction: + return DatasetAbstraction( + "prompt_answer_math", args=dict(...) + ) +``` + +**特点:** +- Worker-based分布式架构 +- 多层抽象(Agent、Dataset、ModelInterface等) +- 声明式配置,运行时动态构建 +- 复杂的依赖关系管理 + +## 2. 系统架构模式 + +### AReaLite: 组件化架构 + +``` +┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ +│ Entry Point │───▶│ Engine Objects │───▶│ Direct Methods │ +│ │ │ │ │ │ +│ gsm8k_grpo.py │ │ RemoteSGLang │ │ rollout_batch() │ +│ │ │ FSDPPPOActor │ │ ppo_update() │ +└─────────────────┘ └──────────────────┘ └─────────────────┘ +``` + +**核心组件:** + +1. **Engine API** (`arealite/api/engine_api.py`) + ```python + class TrainEngine(abc.ABC): + def train_batch(self, input_, loss_fn, loss_weight_fn): ... + def forward(self, input_, output_seqlens=None): ... + + class InferenceEngine(abc.ABC): + async def agenerate(self, req: LLMRequest): ... + def update_weights(self, meta: WeightUpdateMeta): ... + ``` + +2. **Workflow** (`arealite/workflow/rlvr.py`) + ```python + class RLVRWorkflow(RolloutWorkflow): + async def arun_episode(self, engine, data): + # 简单的异步生成逻辑 + req = LLMRequest(input_ids=input_ids, gconfig=self.gconfig) + resps = await asyncio.gather(*[ + engine.agenerate(req) for _ in range(n_samples) + ]) + return process_responses(resps) + ``` + +### Core: 分布式Worker架构 + +``` +┌──────────────┐ ┌─────────────────┐ ┌──────────────────┐ +│ Master │───▶│ Workers │───▶│ Model Functions │ +│ Scheduler │ │ │ │ │ +│ │ │ RolloutWorker │ │ generate_MFC │ +│ ExperimentRun│ │ ModelWorker │ │ train_step_MFC │ +│ │ │ ControllerWorker│ │ compute_ref_MFC │ +└──────────────┘ └─────────────────┘ └──────────────────┘ +``` + +**核心组件:** + +1. **Master-Worker 系统** (`realhf/system/master_worker.py`) + ```python + class MasterWorker: + def _schedule_model_function_calls(self, mfcs: List[MFCDef]): + # 复杂的调度逻辑 + for mfc in mfcs: + self._send_mfc_to_worker(mfc) + ``` + +2. **模型函数调用 (MFC)** (`realhf/system/model_function_call.py`) + ```python + @register_mfc("ppo-update") + def ppo_update_mfc(batch, kl_ctl, eps_clip, ...): + # 分布式PPO更新逻辑 + return perform_ppo_update(batch, ...) + ``` + +3. **数据流图 (DFG)** (`realhf/api/core/dfg.py`) + ```python + class DataFlowGraph: + def add_mfc_dataflow(self, src_mfc, dst_mfc, spec): + # 复杂的数据依赖管理 + ``` + +## 3. 同步训练实现对比 + +### AReaLite 同步训练 + +```python +# 直接在主循环中实现同步逻辑 +for global_step in range(max_steps): + # 同步数据收集 + if config.async_training: + batch = rollout.prepare_batch(train_dataloader, workflow=workflow) + else: + data = next(data_generator) + batch = rollout.rollout_batch(data, workflow=workflow) + + # 同步屏障确保所有进程完成 + dist.barrier(device_ids=[actor.device.index]) + torch.cuda.synchronize() + + # 统一的PPO更新 + stats = actor.ppo_update(batch) +``` + +**特点:** +- 显式的同步控制 +- 清晰的步骤划分 +- 容易理解和修改 + +### Core 同步训练 + +```python +# 通过复杂的MFC调度实现同步 +class PPOMATHConfig: + def make_dfg(self) -> DataFlowGraph: + dfg = DataFlowGraph() + + # 定义复杂的数据流依赖 + dfg.add_mfc_dataflow( + self.prompt_mfc, self.gen_mfc, + {"prompt", "prompt_mask"} + ) + dfg.add_mfc_dataflow( + self.gen_mfc, self.ppo_mfc, + {"packed_seq", "response", "logprobs", "rewards"} + ) + + return dfg +``` + +**特点:** +- 声明式的依赖定义 +- 系统自动处理同步 +- 更好的资源利用,但复杂度高 + +## 4. 代码复杂度分析 + +### 代码行数对比 + +```bash +# AReaLite 核心文件 +examples/arealite/gsm8k_grpo.py: ~233 lines +arealite/engine/ppo/actor.py: ~200-300 lines +arealite/workflow/rlvr.py: ~100-150 lines + +# Core 核心文件 +training/main_sync_ppo.py: ~70 lines (但大量逻辑在配置类中) +realhf/experiments/common/ppo_math_exp.py: ~300+ lines +realhf/system/master_worker.py: ~500+ lines +realhf/system/model_worker.py: ~400+ lines +``` + +### 抽象层次对比 + +**AReaLite (3层抽象):** +``` +用户脚本 → Engine对象 → 后端实现 +gsm8k_grpo.py → FSDPPPOActor → PyTorch FSDP +``` + +**Core (5-6层抽象):** +``` +用户配置 → 实验框架 → Master调度 → Worker执行 → MFC调用 → 后端实现 +sync-ppo.yaml → PPOMATHConfig → MasterWorker → ModelWorker → ppo_update_MFC → PyTorch +``` + +## 5. 异步训练支持 + +### AReaLite 异步训练 + +```python +# 内置的异步支持 +if config.async_training: + # 异步准备批次,无需等待 + batch = rollout.prepare_batch(train_dataloader, workflow=workflow) +else: + # 同步模式 + batch = rollout.rollout_batch(data, workflow=workflow) + +# 简单的异步控制参数 +max_concurrent_rollouts=16 +max_head_offpolicyness=4 +``` + +### Core 异步训练 + +```python +# 独立的异步实验框架 +class AsyncPPOMATHConfig(AsyncRLExperimentConfig, PPOMATHConfig): + @property + def agent(self) -> AgentAbstraction: + return AgentAbstraction("math-single-step", args=dict(...)) + + @property + def env(self) -> EnvServiceAbstraction: + return EnvServiceAbstraction("math-code-single-step", args=dict(...)) +``` + +## 6. 自定义和扩展性 + +### AReaLite: 单文件自定义 + +```python +# 在同一个文件中自定义所有组件 +def custom_reward_fn(prompt, completions, **kwargs): + # 自定义奖励函数 + return calculate_reward(completions) + +class CustomWorkflow(RolloutWorkflow): + async def arun_episode(self, engine, data): + # 自定义rollout逻辑 + return custom_generation_logic() + +def main(args): + # 直接使用自定义组件 + workflow = CustomWorkflow(reward_fn=custom_reward_fn) + # ... 训练逻辑 +``` + +### Core: 模块化注册系统 + +```python +# 需要在多个文件中注册组件 +@register_agent("custom-agent") +class CustomAgent: + def step(self, ...): ... + +@register_env("custom-env") +class CustomEnv: + def reset(self, ...): ... + +@register_mfc("custom-mfc") +def custom_mfc(...): + return ... + +# 在配置中声明使用 +class CustomConfig(PPOMATHConfig): + @property + def agent(self): + return AgentAbstraction("custom-agent", args=dict(...)) +``` + +## 7. 性能和扩展性 + +### AReaLite +- **适用场景**: 单节点到中等规模(8-64 GPU)实验 +- **优势**: 启动快,调试容易,迭代效率高 +- **限制**: 大规模扩展时可能遇到瓶颈 + +### Core +- **适用场景**: 大规模生产训练(100-1000+ GPU) +- **优势**: 高效的资源利用,完善的容错机制 +- **限制**: 复杂的设置和调试过程 + +## 8. 总结与建议 + +### 何时选择 AReaLite +- 算法研究和快速原型开发 +- 需要频繁修改训练逻辑 +- 团队成员主要是AI研究者而非系统工程师 +- 资源规模在64 GPU以内 + +### 何时选择 Core +- 大规模生产训练 +- 需要最高的训练效率 +- 有专门的系统工程师团队 +- 对容错和监控有高要求 + +### 架构演进方向 + +根据AReaLite设计文档,未来的发展方向是: + +1. **AReaLite作为Core的API基础**: Core将重构为基于AReaLite的API设计 +2. **统一的接口**: 用户可以从AReaLite无缝迁移到Core进行大规模训练 +3. **渐进式复杂度**: 从简单的AReaLite开始,根据需要逐步使用更高级的Core功能 + +这种设计理念体现了"90%功能,10%复杂度"的哲学,让AI研究者能够专注于算法创新而不是系统细节。 + +## 附录:关键文件对比 + +### 入口点文件 +- **AReaLite**: `examples/arealite/gsm8k_grpo.py` (完整的训练逻辑) +- **Core**: `examples/run_sync_ppo.sh` → `training/main_sync_ppo.py` (配置加载) → `realhf/experiments/common/ppo_math_exp.py` (实际逻辑) + +### 架构文档 +- **AReaLite**: `arealite/README.md` (设计原理和使用方法) +- **Core**: 分散在多个文档中,主要在 `realhf/` 目录 + +### 核心抽象 +- **AReaLite**: `arealite/api/engine_api.py` (简洁的Engine接口) +- **Core**: `realhf/api/core/` (复杂的分布式抽象) \ No newline at end of file diff --git a/docs/architecture/code_examples_comparison.md b/docs/architecture/code_examples_comparison.md new file mode 100644 index 0000000000..dfe52115fc --- /dev/null +++ b/docs/architecture/code_examples_comparison.md @@ -0,0 +1,477 @@ +# 具体代码实例对比 + +本文档通过具体的代码片段对比,展示AReaLite和Core在实现上的主要差异。 + +## 1. 入口点代码对比 + +### AReaLite 入口点 (examples/arealite/gsm8k_grpo.py) + +```python +def main(args): + config, _ = load_expr_config(args, GRPOConfig) + config: GRPOConfig + + rank = int(os.getenv("RANK")) + world_size = int(os.getenv("WORLD_SIZE")) + tokenizer = load_hf_tokenizer(config.tokenizer_path) + + # 直接创建数据集 + train_dataset = get_custom_dataset( + path=config.train_dataset.path, + rank=rank, + world_size=world_size, + split="train", + type=config.train_dataset.type, + tokenizer=tokenizer, + ) + + # 直接创建引擎 + rollout = RemoteSGLangEngine(config.rollout) + rollout.initialize(None, ft_spec) + + actor = FSDPPPOActor(config=config.actor) + actor.initialize(None, ft_spec) + + # 简单的训练循环 + for global_step in range(max_steps): + # 数据收集 + if config.async_training: + batch = rollout.prepare_batch(train_dataloader, workflow=workflow) + else: + data = next(data_generator) + batch = rollout.rollout_batch(data, workflow=workflow) + + batch = batch.to(actor.device) + dist.barrier(device_ids=[actor.device.index]) + + # PPO更新 + stats = actor.ppo_update(batch) + + # 权重更新 + rollout.pause() + if dist.get_rank() == 0: + future = rollout.update_weights(weight_update_meta) + actor.upload_weights(weight_update_meta) + rollout.resume() +``` + +### Core 入口点 (training/main_sync_ppo.py) + +```python +@hydra.main(version_base=None, config_path="configs", config_name="sync-ppo") +def main(args): + import realhf.base.logging as logging + logger = logging.getLogger("quickstart", "colored") + + # 复杂的配置合并 + default_args = OmegaConf.structured(PPOMATHConfig) + args = OmegaConf.merge(default_args, args) + args: PPOMATHConfig = OmegaConf.to_object(args) + + # 设置实验名称 + exp_name = args.experiment_name + if args.trial_name == MISSING: + args.trial_name = trial_name = ( + f"run{datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}" + ) + + # 通过实验框架运行 + run_experiment(args) +``` + +## 2. 配置和组件定义对比 + +### AReaLite 配置 (简单的dataclass) + +```python +@dataclasses.dataclass +class GRPOConfig: + # 直接的配置字段 + tokenizer_path: str = "Qwen/Qwen3-1.7B" + train_dataset: DatasetConfig = DatasetConfig() + rollout: SGLangEngineConfig = SGLangEngineConfig() + actor: PPOActorConfig = PPOActorConfig() + async_training: bool = False + total_train_epochs: int = 1 +``` + +### Core 配置 (复杂的继承和属性方法) + +```python +@dataclasses.dataclass +class PPOMATHConfig(CommonExperimentConfig, PPOMATHExperimentOptions): + + @property + def ppo_kwargs(self): + return dict( + n_minibatches=self.ppo.ppo_n_minibatches, + kl_ctl=self.ppo.kl_ctl, + discount=self.ppo.discount, + gae_lambda=self.ppo.gae_lambda, + eps_clip=self.ppo.eps_clip, + # ... 更多参数 + ) + + def make_agents(self) -> List[ModelInterfaceAbstraction]: + return [ + ModelInterfaceAbstraction( + "actor-train", + args=dict( + type_=self.actor.type, + path=self.actor.path, + # ... 复杂的参数配置 + ), + ), + ModelInterfaceAbstraction("ref", args=dict(...)), + ] + + def make_dataset(self) -> DatasetAbstraction: + return DatasetAbstraction( + "prompt_answer_math", + args=dict( + dataset_path=self.dataset.path, + max_length=self.dataset.max_length, + # ... 更多配置 + ), + ) + + def make_dfg(self) -> DataFlowGraph: + dfg = DataFlowGraph() + # 复杂的数据流定义 + dfg.add_mfc_dataflow( + self.prompt_mfc, self.gen_mfc, + {"prompt", "prompt_mask"} + ) + dfg.add_mfc_dataflow( + self.gen_mfc, self.ppo_mfc, + {"packed_seq", "response", "logprobs", "rewards"} + ) + return dfg +``` + +## 3. 训练逻辑实现对比 + +### AReaLite PPO实现 (arealite/engine/ppo/actor.py) + +```python +class PPOActor: + def ppo_update(self, data: TensorDict) -> List[Dict[str, float]]: + """直接的PPO更新实现""" + self.engine.train() + + # 计算损失的内部函数 + def ppo_loss_fn(logits, input_data): + logprobs = gather_logprobs(logits, input_data["labels"]) + + # PPO clip损失 + ratio = torch.exp(logprobs - input_data["old_logprobs"]) + surr1 = ratio * input_data["advantages"] + surr2 = torch.clamp(ratio, 1.0 - self.config.eps_clip, + 1.0 + self.config.eps_clip) * input_data["advantages"] + policy_loss = -torch.min(surr1, surr2).mean() + + return policy_loss + + # 直接调用引擎更新 + stats = self.engine.train_batch( + input_=data, + loss_fn=ppo_loss_fn, + loss_weight_fn=lambda x: 1.0, + ) + + return stats +``` + +### Core PPO实现 (通过MFC系统) + +```python +# 在realhf/impl/model/nn/ppo.py中定义MFC +@register_mfc("ppo_update") +def ppo_update_mfc( + batch: Sequence, + n_minibatches: int = 4, + kl_ctl: float = 0.1, + eps_clip: float = 0.2, + # ... 更多参数 +): + """通过MFC系统执行PPO更新""" + model = mfc_model() + + # 复杂的minibatch处理 + for minibatch in split_minibatches(batch, n_minibatches): + # 计算损失 + policy_loss, value_loss, kl_div = compute_ppo_loss( + model, minibatch, eps_clip, kl_ctl + ) + + total_loss = policy_loss + value_loss + total_loss.backward() + + # 参数更新 + optimizer = mfc_optimizer() + optimizer.step() + optimizer.zero_grad() + + return { + "policy_loss": policy_loss.item(), + "value_loss": value_loss.item(), + "kl_divergence": kl_div.item(), + } + +# 在配置中调用MFC +class PPOMATHConfig: + @property + def ppo_mfc(self): + return MFCDef( + model_name="actor-train", + n_seqs=self.rollout.n_seqs, + interface_type=ModelInterfaceType.TRAIN_STEP, + model_function_name="ppo_update", + func_kwargs=self.ppo_kwargs, + ) +``` + +## 4. 数据流处理对比 + +### AReaLite 数据处理 (直接的方法调用) + +```python +class RLVRWorkflow(RolloutWorkflow): + async def arun_episode(self, engine: InferenceEngine, data): + # 直接的tokenization + input_ids = self.tokenizer.apply_chat_template( + data["messages"], + tokenize=True, + add_generation_prompt=True, + ) + + # 直接的生成请求 + req = LLMRequest( + rid=uuid.uuid4().hex, + input_ids=input_ids, + gconfig=self.gconfig.new(n_samples=1), + ) + + # 并发生成多个响应 + n_samples = self.gconfig.n_samples + resps = await asyncio.gather(*[ + engine.agenerate(req) for _ in range(n_samples) + ]) + + # 直接计算奖励 + results = [] + for resp in resps: + reward = self.reward_fn( + prompt=prompt_str, + completions=completions_str, + prompt_ids=resp.input_tokens, + completion_ids=resp.output_tokens, + **data, + ) + results.append(TensorDict(res, batch_size=[1])) + + return concat_padded_tensors(results) +``` + +### Core 数据处理 (通过Agent和Environment抽象) + +```python +# Agent抽象定义 +@register_agent("math-single-step") +class MathSingleStepAgent: + def __init__(self, gconfig, tokenizer_path, **kwargs): + self.gconfig = gconfig + self.tokenizer = load_hf_tokenizer(tokenizer_path) + + def step(self, env_output): + # 复杂的状态处理 + packed_prompts = pack_prompts(env_output["prompt"]) + + # 通过MFC系统生成 + generation_mfc = MFCDef( + model_name="actor-gen", + interface_type=ModelInterfaceType.GENERATE, + model_function_name="generate", + func_kwargs=dict( + gconfig=self.gconfig, + tokenizer=self.tokenizer, + ) + ) + + return { + "packed_prompts": packed_prompts, + "generation_mfc": generation_mfc, + } + +# Environment抽象定义 +@register_env("math-code-single-step") +class MathCodeSingleStepEnv: + def __init__(self, dataset_path, **kwargs): + self.dataset = load_dataset(dataset_path) + + def reset(self, indices): + # 复杂的环境重置逻辑 + data_batch = [self.dataset[i] for i in indices] + return { + "prompt": [item["prompt"] for item in data_batch], + "answer": [item["answer"] for item in data_batch], + } + + def step(self, agent_output): + # 复杂的奖励计算逻辑 + rewards = [] + for completion, answer in zip(agent_output["completions"], self.answers): + reward = compute_math_reward(completion, answer) + rewards.append(reward) + + return {"rewards": rewards, "done": True} +``` + +## 5. 启动脚本对比 + +### AReaLite 启动 (简单的python调用) + +```bash +# examples/arealite/configs/gsm8k_grpo.yaml +tokenizer_path: Qwen/Qwen3-1.7B +train_dataset: + path: hf-dataset://inclusionAI/AReaL-RL-Data/data/train.jsonl + batch_size: 32 +rollout: + server_address: http://localhost:30000 + timeout: 60 +actor: + lr: 1e-5 + eps_clip: 0.2 + +# 启动命令 +python3 -m arealite.launcher.ray examples/arealite/gsm8k_grpo.py \ + --config examples/arealite/configs/gsm8k_grpo.yaml \ + experiment_name=my_experiment \ + trial_name=my_trial +``` + +### Core 启动 (复杂的hydra配置) + +```yaml +# training/configs/sync-ppo.yaml +defaults: + - _self_ + - cluster: slurm-gpu + - actor: llama2-7b + - ref: llama2-7b + - dataset: math-ppo + - ppo: default + +experiment_name: ppo-math +trial_name: ??? +mode: ray + +# 数百行的详细配置... +allocation_mode: + actor_train: + placement_group: + strategy: STRICT_PACK + bundles: + - GPU: 8 + actor_gen: + placement_group: + strategy: SPREAD + bundles: + - GPU: 2 +``` + +```bash +# 启动命令 +python3 training/main_sync_ppo.py \ + experiment_name=my_experiment \ + trial_name=my_trial \ + actor.path=Qwen/Qwen3-1.7B \ + dataset.path=path/to/dataset \ + cluster.n_nodes=4 +``` + +## 6. 自定义开发对比 + +### AReaLite 自定义 (单文件修改) + +```python +# 在同一个入口文件中自定义所有组件 +def custom_reward_fn(prompt, completions, **kwargs): + """自定义奖励函数""" + # 业务逻辑 + if "正确答案" in completions: + return 1.0 + else: + return 0.0 + +class CustomWorkflow(RLVRWorkflow): + """自定义工作流""" + async def arun_episode(self, engine, data): + # 自定义生成逻辑 + # 可以实现多轮对话、工具调用等 + return custom_results + +class CustomPPOActor(FSDPPPOActor): + """自定义PPO算法""" + def compute_advantages(self, data): + # 自定义优势函数计算 + # 例如实现GRPO算法 + pass + +def main(args): + # 直接使用自定义组件 + workflow = CustomWorkflow(reward_fn=custom_reward_fn) + actor = CustomPPOActor(config=config.actor) + # ... 其余逻辑保持不变 +``` + +### Core 自定义 (多文件注册系统) + +```python +# 1. 在 realhf/impl/agent/ 中定义新的Agent +@register_agent("custom-math-agent") +class CustomMathAgent: + def step(self, env_output): + # 自定义逻辑 + pass + +# 2. 在 realhf/impl/env/ 中定义新的Environment +@register_env("custom-math-env") +class CustomMathEnv: + def reset(self, indices): + # 自定义逻辑 + pass + +# 3. 在 realhf/impl/model/nn/ 中定义新的MFC +@register_mfc("custom-ppo-update") +def custom_ppo_update_mfc(batch, **kwargs): + # 自定义PPO逻辑 + pass + +# 4. 在配置类中组合使用 +class CustomPPOMATHConfig(PPOMATHConfig): + @property + def agent(self): + return AgentAbstraction("custom-math-agent", args=dict(...)) + + @property + def env(self): + return EnvServiceAbstraction("custom-math-env", args=dict(...)) + + @property + def ppo_mfc(self): + return MFCDef( + model_function_name="custom-ppo-update", + func_kwargs=dict(...) + ) +``` + +## 总结 + +从具体代码实例可以看出: + +1. **AReaLite**: 代码直观,逻辑清晰,容易调试和修改,适合快速原型开发 +2. **Core**: 系统复杂,抽象层次多,但提供了更强的扩展性和资源管理能力 + +两套系统各有优势,选择哪个取决于具体的使用场景和团队能力。 \ No newline at end of file diff --git a/docs/architecture/final_summary_report.md b/docs/architecture/final_summary_report.md new file mode 100644 index 0000000000..7a223e27fd --- /dev/null +++ b/docs/architecture/final_summary_report.md @@ -0,0 +1,205 @@ +# AReaL架构分析总结报告 + +基于对AReaL代码库的深入分析,本报告从软件架构角度总结了AReaLite与Core系统的主要区别。 + +## 执行摘要 + +AReaL项目包含两套并行的架构设计: + +- **AReaLite**: 面向AI研究者的轻量级框架,追求简洁性和易用性 +- **Core**: 面向大规模生产的分布式系统,追求性能和扩展性 + +这两套系统体现了不同的设计哲学:AReaLite采用**AI-centric**设计,Core采用**System-centric**设计。 + +## 核心发现 + +### 1. 架构复杂度差异显著 + +| 指标 | AReaLite | Core | 差异倍数 | +|------|----------|------|---------| +| 抽象层次 | 3层 | 6层 | 2x | +| 核心文件数 | ~10个 | ~50个 | 5x | +| 入口点代码行数 | 233行 | 70行+300行配置 | ~1.6x | +| 学习曲线 | 1-2天 | 1-2周 | 7-10x | + +### 2. 设计理念根本不同 + +**AReaLite**: "让AI研究者专注于算法,而非系统" +- 直接的PyTorch风格API +- 单文件包含完整训练逻辑 +- SPMD编程模型 + +**Core**: "提供工业级的分布式RL训练平台" +- 声明式配置和组件注册 +- Master-Worker分布式架构 +- 复杂的资源管理和容错机制 + +### 3. 适用场景明确区分 + +``` +规模 (GPU数量) 推荐选择 理由 +1-8 AReaLite 快速启动,易于调试 +8-64 AReaLite/Core 根据团队能力选择 +64-256 Core 需要专业的资源管理 +256+ Core 必须使用工业级系统 +``` + +## 详细对比分析 + +### 入口点架构 + +**AReaLite采用直接对象操作模式:** +```python +# 一目了然的训练循环 +rollout = RemoteSGLangEngine(config.rollout) +actor = FSDPPPOActor(config.actor) + +for step in range(max_steps): + batch = rollout.rollout_batch(data, workflow) + stats = actor.ppo_update(batch) + actor.upload_weights(weight_update_meta) +``` + +**Core采用声明式配置模式:** +```python +# 通过配置类定义复杂的数据流 +class PPOMATHConfig: + def make_dfg(self): + dfg.add_mfc_dataflow(prompt_mfc, gen_mfc, {"prompt"}) + dfg.add_mfc_dataflow(gen_mfc, ppo_mfc, {"response"}) + return dfg +``` + +### 代码组织方式 + +**AReaLite: 组件化设计** +``` +arealite/ +├── api/engine_api.py # 简洁的抽象接口 +├── engine/ppo/actor.py # 直接的PPO实现 +└── workflow/rlvr.py # 简单的工作流 +``` + +**Core: 分层系统设计** +``` +realhf/ +├── api/core/ # 复杂的系统抽象 +├── system/master_worker.py # 分布式调度器 +├── system/model_worker.py # 模型工作节点 +└── impl/model/nn/ppo.py # MFC封装的算法 +``` + +### 自定义开发体验 + +**AReaLite: 单文件自定义** +- 在一个文件中修改奖励函数、工作流、算法 +- 直接调试,Ctrl+Click即可查看实现 +- 适合快速实验和算法研究 + +**Core: 多模块注册系统** +- 需要在多个文件中注册Agent、Environment、MFC +- 复杂的依赖关系,调试困难 +- 适合结构化的大型项目 + +## 技术深度分析 + +### 同步训练实现差异 + +**AReaLite**: 显式同步控制 +```python +# 清晰的同步点 +dist.barrier(device_ids=[actor.device.index]) +torch.cuda.synchronize() +stats = actor.ppo_update(batch) +``` + +**Core**: 隐式的依赖管理 +```python +# 通过数据流图自动处理同步 +dfg.add_mfc_dataflow(gen_mfc, ppo_mfc, dependency_spec) +``` + +### 异步训练支持 + +**AReaLite**: 内置异步开关 +```python +if config.async_training: + batch = rollout.prepare_batch(dataloader, workflow) +else: + batch = rollout.rollout_batch(data, workflow) +``` + +**Core**: 独立的异步框架 +```python +class AsyncPPOMATHConfig(AsyncRLExperimentConfig): + # 完全不同的配置体系 +``` + +## 性能与扩展性评估 + +### 开发效率对比 + +| 任务 | AReaLite | Core | 优势方 | +|------|----------|------|--------| +| 快速原型开发 | 1-2小时 | 1-2天 | AReaLite | +| 添加新算法 | 半天 | 2-3天 | AReaLite | +| 调试训练问题 | 容易 | 困难 | AReaLite | +| 大规模部署 | 有限 | 优秀 | Core | +| 资源利用率 | 良好 | 优秀 | Core | + +### 系统可维护性 + +**AReaLite优势:** +- 代码结构清晰,新人容易上手 +- 调试友好,问题定位快速 +- 修改影响范围小,风险可控 + +**Core优势:** +- 模块化设计,组件可复用 +- 完善的抽象层,便于扩展 +- 工业级的错误处理和监控 + +## 战略建议 + +### 对于不同用户群体 + +**AI研究者/学生:** +- 优先选择AReaLite +- 学习成本低,专注算法创新 +- 从AReaLite开始,必要时迁移到Core + +**工业界研究团队:** +- 根据规模选择:小规模用AReaLite,大规模用Core +- 建议两套系统都要掌握 +- 用AReaLite验证算法,用Core进行生产训练 + +**系统工程师:** +- 重点学习Core系统 +- 理解分布式训练的系统性挑战 +- 为算法团队提供平台支持 + +### 技术演进路径 + +根据AReaLite设计文档,项目的长期规划是: + +1. **短期**: AReaLite作为独立的轻量级框架 +2. **中期**: Core重构,采用AReaLite的API设计 +3. **长期**: 统一的接口,渐进式的复杂度增长 + +这体现了"先易后难"的设计哲学,让用户可以从简单开始,根据需要逐步使用更高级的功能。 + +## 结论 + +AReaLite和Core代表了两种不同的软件架构哲学: + +- **AReaLite**: 追求"90%功能,10%复杂度",适合算法研究和快速迭代 +- **Core**: 追求"100%功能,工业级质量",适合大规模生产和性能优化 + +两套系统并非竞争关系,而是互补关系。AReaLite降低了RL训练的门槛,让更多研究者能够参与到大模型RL训练中;Core确保了工业级应用的性能和可靠性需求。 + +选择哪套系统,主要取决于: +1. 团队的技术背景和能力 +2. 项目的规模和性能要求 +3. 开发和维护的资源投入 + +对于大多数AI研究者和小型团队,我们推荐从AReaLite开始,它能够以最小的学习成本获得强大的RL训练能力。当需要处理超大规模训练时,再考虑迁移到Core系统。 \ No newline at end of file