← 所有项目

Contribution Tasks

NVIDIA-NeMo/labs-molt

候选人擅长 GPU kernel / 训练性能,但当前无 GPU。Molt 的 agents / utils / tests 层是纯 Python + torch CPU 可跑区,与候选人「算子数值正确性、调度器/内存管理纯逻辑层、测试基建」方向匹配;kernel/CUDA 路径在 Mac 上无法验证,暂不产出。

当前方向:团队处于功能可用、工程收尾阶段:密集补 tests/unit、CI、README;热点在 agents 稳定性(event-loop offload)、loss 聚合扩展、rollout router。CPU 可验证的测试/文档缺口是最佳切入点。

★ 1167Fork 1135 个候选任务Gemini:LongCat-2.0

更新于 2026-10-08T07:37:23+00:00 · 打开仓库 ↗

一、项目定位

Molt 是 NVIDIA NeMo 实验室维护的一个 agentic-first 强化学习训练框架,定位是研究导向、PyTorch / HuggingFace 原生、面向 1T 级 MoE 规模的全异步 agentic RL。它把整个栈压到三个薄层:Ray 负责 placement 与 rollout↔trainer 之间的异步队列,vLLM 负责 rollout 生成,NVIDIA AutoModel + FSDP2 负责纯 PyTorch 训练。README 自称「~9.2K LOC of RL code」,并强调同一份脚本可以从 8B 一路跑到 DeepSeek-V3 级别(--fsdp.ep_size 256),且支持多轮、工具调用、VLM、LLM-as-judge 等任意 Python reward。 项目目前处于 快速迭代但尚未稳定 的阶段:最近三周连发 v0.1.8 / v0.1.9 / v0.1.10(2026-09-14 → 0.9-28),提交热点集中在 tests/unit、.github/workflows、README.md、molt/trainer、examples/python,说明团队在同步补测试、CI 与文档;最近 10 个 commit 里一半是 fix(agents 上的 event-loop 阻塞、rollout router 转换、grading 逻辑、loss 聚合),一半是 docs/ci 打磨,属于「功能基本可用、工程收尾中」的状态。README 没有给自己贴 Experimental / Beta 标签,但 PyPI 包明确写「not a supported install path right now」,且默认依赖 git-pinned 的 AutoModel 特定 commit(8f73178ca),因此实际成熟度介于「可用」与「研究预览」之间。 与同类(OpenRLHF / verl / slime)相比,Molt 的差异点是:训练栈坚持 PyTorch/FSDP2 原生而非 Megatron-LM,runtime 坚持 Ray + vLLM 而非自研,且把 agent 接口抬到一等公民(Gymnasium 对齐的 Env.step() / ChatAgent.run()),让环境与 reward 用纯 Python 写、trainer 不动。它同时维护了一个 automodel-slim 分支,把上游 AutoModel 从 758 文件 / 282k 行裁到 252 文件 / ~97k 行,只保留 molt 实际用到的模型族与并行栈,作为可选轻量后端。

解决什么问题、给谁用

Molt 解决的是 大规模 agentic RL 训练的基础设施碎片化 问题:现有 RL 训练栈要么绑定 Megatron-LM 这类重型后端、要么 rollout 与训练紧耦合、要么对多轮 / 工具 / VLM 等 agentic 场景支持薄弱。Molt 把栈收敛成 Ray + vLLM + AutoModel/FSDP2 三件套,用 token-first 的 contract(token ids / logprobs / action ranges / rewards / 多模态张量全程对齐)统一多轮、多模态、工具调用轨迹;同时通过 fully-async 队列、partial rollout、weight sync 重叠,让 DeepSeek-V3 级别的 MoE actor 在 vLLM rollout 下不被饿死。它面向的是需要 在纯 PyTorch 里 hack 模型和环境、又要跑到百卡级 MoE 的研究团队。

目标用户是做 LLM / 多模态 agentic RL 研究 的算法研究员与系统工程师,典型场景包括: - 用 GRPO / RLOO / REINFORCE-baseline / FlashREINFORCE / on-policy distillation 等算法训对话、数学、代码、工具-use agent; - 在 Env.step() 或 ChatAgent.run() 里写自定义 grader、多轮工具、VLM 环境、LLM-as-judge,reward 用任意 Python; - 从 8B Dense 一路扩展到 1T-class MoE(DeepSeek-V3、Qwen3.8 等),不改脚本只改 --fsdp.ep_size / TP / CP; - 用 vLLM 做 rollout 并需要 partial rollout、async queue、rollout dump/replay、weight-update 覆盖检查等调试能力; - 用 molt.cli.train_sft 做与 RL 同模型加载路径的 SFT 预训练 / 蒸馏。 对「资深 GPU kernel / 训练性能工程师」而言,切入点主要在 rollout-trainer 重叠、MoE dispatch(DeepEP/HybridEP)、FSDP2 并行策略、以及 vLLM 权重同步这些系统层。

同类项目与差别

核心能力

能力在哪成熟度

阶段:快速迭代的研究级框架:v0.1.8–v0.1.10 三周三连发,功能基本可用但工程仍在收尾(测试/CI/文档提交密集),PyPI 包暂不支持,默认依赖 git-pinned AutoModel commit。

技术栈:Python 3.10+;PyTorch 2.13+cu130(CUDA 13 硬依赖);Ray(runtime / placement / async queue);vLLM(rollout);NVIDIA AutoModel(nemo-automodel,git-pinned 或 automodel-slim 分支);FSDP2 + TransformerEngine attention(THD packing);DeepEP / HybridEP(MoE dispatch);flash-attn、mamba、TransformerEngine、Dion/Muon 优化器;setuptools + pyproject.toml 构建;pytest(unit/integration/system/acceptance 四级 marker)+ ruff + black + isort + pre-commit;GitHub Actions CI + Jenkins(部分 job 在 Jenkins);Docker(多架构 amd64+arm64,CUDA forward-compat)

规模:自称 ~9.2K LOC RL 代码;仓库目录树显示 molt/ 55 入口、tests/ 38(含 e2e 与 unit)、examples/ 23、.github 19;最近提交热点 tests/unit(7)、.github/workflows(5)、README.md(5)、molt/trainer(3)、examples/python(3);Release v0.1.8 / v0.1.9 / v0.1.10 于 2026-09-14 / 09-17 / 09-28 三连发,最近提交 2026-10-04;AutoModel 上游 758 文件 / 282k 行,slim 分支裁到 252 / ~97k;Docker 镜像 hijkzzz/molt:latest。

二、架构与代码地图

Molt 的代码组织成四个薄层,从上到下分别是: 1) 接入层(Entry / CLI):molt/cli/train_rl_ray.py 与 molt/cli/train_sft.py 是唯二的用户入口,molt/cli/common_args.py 把 FSDP、checkpoint、optimizer 等共享参数收敛成一块,避免两个 CLI 漂移。这一层只做 argparse、Ray 初始化、placement 计算,然后向下调用 trainer。 2) 调度层(Orchestration):molt/trainer/rl_trainer.py 持有主训练循环,molt/trainer/placement.py 把 TP/EP/CP/PP 映射成 Ray placement group,molt/trainer/workers/actor_group.py、policy_actor.py、critic_actor.py 把 actor / reference / critic 包成 Ray actor,molt/trainer/rollout/router.py 与 experience_maker.py 负责 rollout 路由和经验构造。这一层是 Ray async queue 真正干活的地方。 3) 执行层(Execution / Rollout & Train Step):rollout 侧由 molt/trainer/vllm/vllm_engine.py + vllm_worker_wrap.py 拉起 vLLM 引擎,molt/trainer/rollout/samples_generator.py 把 prompt 变成生成请求;训练侧由 molt/trainer/fsdp/strategy.py、checkpoint.py、refit.py、packing.py、optimizer_offload.py、muon.py 承接 FSDP2 下的 checkpoint、THD packing、CPU offload、Muon 优化器;算法侧 molt/trainer/algorithm/ 放 advantage / KL controller / replay buffer / experience。 4) Agent & Model 层(User-facing Kernel):molt/agents/base.py、chat_agent.py、distill_agent.py、_chat_server.py 提供 Gymnasium 对齐的 Env.step() / ChatAgent.run() 抽象,是用户唯一需要写的扩展面;molt/models/actor.py、critic.py、loss.py、base.py 定义可训练模型与损失;molt/datasets/ 与 molt/utils/ 提供 prompt dataset、分布式采样、VLM 工具等支撑。 硬件层不在仓库内——它通过 Ray placement group 与 vLLM engine 透传给 NVIDIA AutoModel / FSDP2,仓库自己不碰 CUDA kernel。

接入层调度层执行层用户扩展层cli → trainer:配置配置cli → trainer.vllm:引擎创建引擎创建trainer → trainer.workers:拉起 actor拉起 actortrainer → trainer.rollout:rollout 调度rollout 调度trainer.vllm → trainer.rollout:生成请求生成请求agents → trainer.rollout:reward/trareward/tradatasets → trainer.rollout:promptprompttrainer.rollout → trainer.algorithm:ExperienceExperiencetrainer.algorithm → models:advantage/advantage/models → trainer.fsdp:FSDP2 训练FSDP2 训练trainer.fsdp → trainer.vllm:weight synweight synutils → agents:VLM/日志utils → trainer:配置/工具配置/工具cliclitrainertrainertrainer.vllmtrainer.vllmtrainer.workerstrainer.workerstrainer.rollouttrainer.rollouttrainer.fsdptrainer.fsdptrainer.algorithmtrainer.algorithmdatasetsdatasetsmodelsmodelsutilsutilsagentsagents
Molt 四层架构:CLI 接入 → Ray+vLLM+Workers 调度 → Rollout/Algorithm/FSDP 执行 → Agents/Utils 扩展
模块 / 路径职责 · 入口 · 依赖
cli
molt/cli
3 文件
用户入口与参数面,把 argparse 收敛成策略对象交给 trainer
入口:molt.cli.train_rl_ray:train, molt.cli.train_sft:main(需验证), molt.cli.common_args:add_fsdp_args
依赖:trainer, utils
train_rl_ray.py 同时负责 Ray init、vLLM engine 创建、placement 计算,是事实上的 main orchestrator 入口
trainer
molt/trainer
~15 文件
训练主循环、placement、rollout↔trainer 异步桥
入口:molt.trainer.rl_trainer:RLTrainer(需验证类名), molt.trainer.sft_trainer:SFTTrainer, molt.trainer.placement:model_placement_strategy
依赖:trainer.vllm, trainer.workers, trainer.algorithm, models, utils
README 自称 ~9.2K LOC RL code 的核心分布区;commit 热点集中在 trainer 目录
trainer.vllm
molt/trainer/vllm
3 文件
vLLM 引擎封装,把 vLLM 挂到 Ray placement group 上
入口:molt.trainer.vllm.vllm_engine:RolloutRayActor, create_vllm_engines(需验证)
依赖:trainer.placement, utils
vllm_engine.py 显式检查 vLLM >= 0.21.0,区分 ray / mp backend 的 GPU bundle 语义
trainer.workers
molt/trainer/workers
~5 文件
把 actor / reference / critic 包成 Ray actor,承载 FSDP2 训练
入口:molt.trainer.workers.actor_group:RayActorGroup, ReferenceModelActor, molt.trainer.workers.policy_actor:PolicyModelActor, molt.trainer.workers.critic_actor:CriticModelActor(部分需验证)
依赖:models, trainer.fsdp, trainer.algorithm
workers 是 Ray actor 壳,真正训练逻辑在 models + fsdp + algorithm
trainer.rollout
molt/trainer/rollout
~4 文件
rollout 路由、experience 构造、样本生成
入口:molt.trainer.rollout.router:(需验证类名,最近提交 #190 修 payload 转换), molt.trainer.rollout.experience_maker:make_experience(需验证), molt.trainer.rollout.samples_generator:(需验证)
依赖:trainer.vllm, agents, datasets
commit #190 修 router 在 event loop 上做 payload 转换的 bug,是最近热点
trainer.algorithm
molt/trainer/algorithm
~5 文件
advantage、KL controller、replay buffer、experience 数据结构
入口:molt.trainer.algorithm.advantage:(含 reinforce / rloo / grpo / dr_grpo / flash_reinforce / on_policy_distill 等 estimator,需验证), molt.trainer.algorithm.kl_controller:(需验证), molt.trainer.algorithm.experience:Experience(需验证)
依赖:models.loss
experience.py 暴露 get_model_parallel_size 被 cli/train_rl_ray.py 直接 import
trainer.fsdp
molt/trainer/fsdp
~7 文件
FSDP2 策略、checkpoint、THD packing、CPU offload、Muon、refit
入口:molt.trainer.fsdp.strategy:(需验证), molt.trainer.fsdp.checkpoint:(需验证), molt.trainer.fsdp.packing:(需验证), molt.trainer.fsdp.optimizer_offload:(需验证), molt.trainer.fsdp.muon:(需验证), molt.trainer.fsdp.refit:(需验证)
依赖:models, utils
tests/unit 里 test_fsdp_packing / test_muon_param_classify / test_refit_* 直接对应;README 把 Adam CPU offload 与 THD packing 列为关键能力
agents
molt/agents
5 文件
用户扩展面:Gymnasium 对齐的 Env / ChatAgent 抽象
入口:molt.agents.base:Env, Result, Runner, StepEnvRunner, Trajectory, molt.agents.chat_agent:ChatAgent, ChatAgentRunner, ChatContext, molt.agents.distill_agent:DistillationEnv
依赖:utils
commit #185/#186/#191 都在 agents 里把 grading / image loading 迁出 event loop;_chat_server.py 是内部 chat forwarder
models
molt/models
5 文件
可训练模型与损失函数
入口:molt.models.actor:(需验证), molt.models.critic:(需验证), molt.models.loss:(含 prompt-mean-token-mean 聚合,commit #184), molt.models.base:(需验证)
依赖:utils
loss.py 最近加 prompt-mean-token-mean,是 loss 聚合扩展点
datasets
molt/datasets
~3 文件
prompt dataset、SFT dataset、数据工具
入口:molt.datasets.prompts_dataset:(需验证), molt.datasets.sft_dataset:(需验证)
依赖:utils
examples/python/utils/prepare_dapo.py 与 prepare_geo3k.py 是配套数据脚本
utils
molt/utils
~8 文件
配置、分布式工具、VLM 工具、日志
入口:molt.utils.config:(需验证), molt.utils.get_strategy(被 train_rl_ray 直接 import), molt.utils.vlm_utils:process_prompt_with_images, molt.utils.seqlen_balancing:(需验证)
依赖:无内部依赖
utils 是公共基础,被 trainer / agents / datasets 广泛依赖
目录树(按文件数)
  • molt/ 55 个文件
    __init__.py, agents, cli, datasets, models, trainer, utils
  • tests/ 38 个文件
    __init__.py, e2e, unit
  • examples/ 23 个文件
    python, scripts
  • .github/ 19 个文件
    CODEOWNERS, ISSUE_TEMPLATE, actions, copy-pr-bot.yaml, workflows
  • docs/ 9 个文件
    fern, index.md, index.yml
  • dockerfile/ 4 个文件
    Dockerfile, deepep.patch, docker-entrypoint.sh, sqsh_to_docker.sh
  • .claude/ 3 个文件
    settings.json, skills
  • .gitignore/ 1 个文件
  • .pre-commit-config.yaml/ 1 个文件
  • AGENTS.md/ 1 个文件
  • CLAUDE.md/ 1 个文件
  • CONTRIBUTING.md/ 1 个文件
  • LICENSE/ 1 个文件
  • NOTICE/ 1 个文件
  • README.md/ 1 个文件
  • SECURITY.md/ 1 个文件

一次调用怎么流过这些模块

一次典型 RL step 的数据流(以 python3 -m molt.cli.train_rl_ray 为主线): 1) CLI 解析:molt/cli/train_rl_ray.py:train() 通过 molt/cli/common_args.py 把 --fsdp.*、--actor.*、--vllm.*、--rollout.*、--algo.* 等参数收敛成 strategy 对象,并调用 ray.init()。 2) Placement 计算:train() 调用 molt/trainer/placement.py:model_placement_strategy(),根据 TP/EP/CP/PP 与 actor/ref/critic 角色生成 Ray placement group bundle,再调用 molt/trainer/vllm:create_vllm_engines() 在对应 bundle 上拉起 vLLM engine(RolloutRayActor)。 3) Worker 拉起:RayActorGroup、PolicyModelActor、ReferenceModelActor 在各自 placement group 上实例化,底层通过 NVIDIA AutoModel + FSDP2 加载模型;molt/trainer/fsdp/strategy.py 决定分片、packing、CPU offload 策略。 4) Rollout 生成:molt/trainer/rollout/samples_generator.py 从 molt/datasets/prompts_dataset.py 取 prompt batch,交给 molt/trainer/rollout/router.py 路由到 vLLM engine;同时 agent(molt/agents/base.py 的 Env 或 chat_agent.py 的 ChatAgent)在 rollout runner actor 上执行,产生 reward / trajectory。DistillationEnv 走 StepEnvRunner 路径,由框架拥有生成回路;自定义 ChatAgent 走 ChatAgentRunner 路径,通过 loopback FastAPI server(_chat_server.py)捕获 token trace。 5) Experience 构造:molt/trainer/rollout/experience_maker.py 把 vLLM 返回的 token ids、logprobs、action ranges、reward、multimodal tensors 压成 molt/trainer/algorithm/experience:Experience,这是 README 强调的「token-first」契约。 6) 异步队列:Experience 通过 Ray async queue(--train.async_queue_size)从 rollout 侧流向 trainer 侧,--train.partial_rollout_enable 允许 rollout 在 weight sync 期间继续生成。 7) 训练步:molt/trainer/rl_trainer.py 主循环从队列捞 Experience,调 molt/trainer/algorithm/advantage.py 算 advantage(reinforce / grpo / flash_reinforce / on_policy_distill 等),kl_controller.py 调 KL 系数,molt/models/loss.py 算 policy / value loss(支持 prompt-mean-token-mean 聚合),再通过 FSDP2 backward + molt/trainer/fsdp/optimizer_offload.py / muon.py 做 optimizer step。 8) Checkpoint / Weight Sync:molt/trainer/fsdp/checkpoint.py 写 DCP checkpoint,refit.py 把 FSDP 权重合并 / LoRA merge 后广播到 vLLM engine(--train.check_weight_update_equal 校验覆盖率),开始下一轮 rollout。 关键调度点:rollout↔trainer 之间的 Ray async queue、placement.py 的 bundle 分配、experience_maker 的 token 对齐、fsdp/checkpoint 的 weight broadcast。关键数据结构:Experience(token ids / logprobs / action ranges / reward / multimodal tensors)、Trajectory(agents 侧累积)、Result(Gymnasium 风格 step 返回)。

1CLI 解析train · molt/cli/train_rl_ray.py2Ray init + placementmodel_placement_strategy · molt/trainer/placement.py3拉起 vLLM enginecreate_vllm_engines / RolloutRayActor · molt/trainer/vllm/vllm_engine.py4拉起 actor/ref workerRayActorGroup / PolicyModelActor · molt/trainer/workers/actor_group.py5rollout 生成router / samples_generator / agent · molt/trainer/rollout/router.py6构造 Experiencemake_experience · molt/trainer/rollout/experience_maker.py7异步队列流向 trainerRLTrainer 主循环 · molt/trainer/rl_trainer.py8advantage + loss + optimadvantage / loss / optimizer_offload · molt/trainer/algorithm/advantage.py9checkpoint + weight synccheckpoint / refit / vllm broadcast · molt/trainer/fsdp/checkpoint.py

关键类型与函数

名称路径用途
Envmolt/agents/base.py
ChatAgent / ChatContextmolt/agents/chat_agent.py
Resultmolt/agents/base.py
Trajectorymolt/agents/base.py
StepEnvRunner / ChatAgentRunnermolt/agents/base.py, molt/agents.chat_agent.py
DistillationEnvmolt/agents/distill_agent.py
Experiencemolt/trainer/algorithm/experience.py
RolloutRayActormolt/trainer/vllm/vllm_engine.py
RayActorGroup / PolicyModelActor / ReferenceModelActormolt/trainer/workers
model_placement_strategymolt/trainer/placement.py
RLTrainer(需验证类名)molt/trainer/rl_trainer.py
SFTTrainer(需验证类名)molt/trainer/sft_trainer.py
advantage estimator(reinforce/grpo/flash_reinforce/on_policy_distill 等)molt/trainer/algorithm/advantage.py
loss(含 prompt-mean-token-mean)molt/models/loss.py
process_prompt_with_imagesmolt/utils/vlm_utils.py

扩展点

最近在动的地方

建议阅读顺序

  1. README.md — 全局定位、架构图、quick start、scaling knobs
  2. molt/cli/train_rl_ray.py — 入口,看 train() 如何串起 Ray / vLLM / placement / trainer
  3. molt/cli/common_args.py — 共享参数面,理解 FSDP / optimizer / checkpoint 选项
  4. molt/trainer/rl_trainer.py — 主训练循环,看 async queue / rollout / train step 衔接
  5. molt/trainer/placement.py — placement group 与 TP/EP/CP/PP 映射
  6. molt/trainer/vllm/vllm_engine.py — vLLM engine 的 Ray actor 壳
  7. molt/trainer/rollout/router.py + experience_maker.py + samples_generator.py — rollout 路由与 Experience 构造
  8. molt/trainer/algorithm/experience.py + advantage.py + kl_controller.py — token-first 数据结构与算法
  9. molt/trainer/workers/actor_group.py + policy_actor.py + critic_actor.py — Ray actor 壳
  10. molt/trainer/fsdp/strategy.py + checkpoint.py + packing.py + optimizer_offload.py + muon.py + refit.py — FSDP2 执行层
  11. molt/agents/base.py + chat_agent.py + _chat_server.py + distill_agent.py — 用户扩展面
  12. molt/models/actor.py + critic.py + loss.py + base.py — 模型与损失
  13. molt/datasets/ + molt/utils/ — 数据与工具
  14. tests/unit/ — 按阅读顺序对应的测试,验证理解

三、本地跑起来(没有 GPU 的 Mac)

安装

  1. # 1. 克隆仓库(默认分支 main,当前最新 tag v0.1.10)
  2. git clone https://github.com/NVIDIA-NeMo/labs-molt.git
  3. cd labs-molt
  4. # 2. 创建 Python 3.10+ 虚拟环境(Apple Silicon 推荐 conda / venv)
  5. python3.11 -m venv .venv && source .venv/bin/activate
  6. # 3. 安装 PyTorch CPU/MPS 版本(Mac 上没有 CUDA,必须覆盖 setup.py 里的 cu130 pin)
  7. # 证据:README 要求 torch==2.13.0+cu130,但 PyPI 现在提供 2.13.0 mac 版;
  8. # 这里先装非 CUDA 版本,避免 pip 去拉 cu130 wheel 失败。
  9. pip install torch==2.13.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
  10. # 如果希望走 MPS 后端(部分算子仍会回退 CPU):
  11. # pip install torch==2.13.0 torchvision torchaudio
  12. # 4. 安装 molt 本身(跳过 vllm 与 AutoModel 的 GPU 依赖)
  13. # 证据:setup.py 中 AUTOMODEL 默认 git-pinned 上游 commit,requirements.txt 含 vllm;
  14. # vLLM 0.21.0 在 macOS 上无 wheel 且依赖 CUDA,必须跳过。
  15. # 方法 A:只装 molt 核心(不装 [vllm] extra)
  16. pip install -e .
  17. # 方法 B:如果 requirements.txt 里 vllm 是硬依赖导致失败,则手动裁剪:
  18. # grep -v '^vllm' requirements.txt > requirements-nogpu.txt
  19. # pip install -r requirements-nogpu.txt
  20. # pip install -e .
  21. # 5. 安装 AutoModel(可选,仅当你需要跑含训练/rollout 的 e2e 时)
  22. # 证据:setup.py AUTOMODEL 字典默认 'upstream' 指向 git commit 8f73178ca;
  23. # AutoModel 本身依赖 TransformerEngine / flash-attn 等 GPU 库,Mac 上大概率装不上。
  24. # 纯读代码 / 跑 CPU-only 单元测试可跳过此步。
  25. # pip install nemo-automodel @ git+https://github.com/NVIDIA-NeMo/Automodel.git@8f73178ca51d4c1e55ccf05df5da6540a9e24f7e
  26. # 6. 安装 pre-commit(CONTRIBUTING.md 要求,PR 会被卡住)
  27. pip install pre-commit
  28. pre-commit install
  29. # 7. 验证基础 import 链(不触发 CUDA 初始化)
  30. python -c "import molt; from molt.agents import Env, ChatAgent; print('import ok')"

哪些路径能真跑

['✅ 可在 CPU / MPS 上真正执行(无需 GPU,不触发 CUDA):', ' - molt/agents/base.py — Env / ChatAgent / Result / Trajectory 抽象基类,纯 Python + torch 张量', ' - molt/agents/__init__.py — 公开接口导出', ' - molt/datasets/prompts_dataset.py / sft_dataset.py / utils.py — 数据集加载与 tokenize(用 HF tokenizer,CPU 可用)', ' - molt/models/loss.py — policy loss / value loss 计算(torch 算子,CPU 可跑)', ' - molt/models/actor.py / critic.py / base.py / utils.py — 模型定义(forward 可在 CPU 跑小模型)', ' - molt/trainer/algorithm/ — advantage / kl_controller / experience / replay_buffer(纯 torch 张量)', ' - molt/trainer/fsdp/packing.py — THD packing 逻辑(test_cp_thd_packing.py 在 CI 里 CPU 跑)', ' - molt/trainer/rollout/router.py、samples_generator.py、experience_maker.py — 路由与经验构造(不依赖 vLLM 实例化)', ' - molt/utils/ — config / logging / distributed_sampler / seqlen_balancing / vlm_utils', ' - molt/cli/common_args.py — argparse 定义', ' - examples/python/agents/ — math.py / geo3k.py / chat_minimal.py / chat_geo3k.py(agent 逻辑本身可 import 看)', ' - examples/python/utils/ — math_grader.py / prepare_dapo.py / prepare_geo3k.py', ' - tests/unit/ 大部分测试 — 见 smoke_test 与 test_suite', '', '⚠️ 只能读代码 / 静态分析,无法在 Mac 上真正执行(依赖 CUDA / vLLM / NCCL):', ' - molt/cli/train_rl_ray.py — 入口会 ray.init() + create_vllm_engines(),需要 GPU placement group', ' - molt/cli/train_sft.py — torchrun + FSDP2,需要 CUDA', ' - molt/trainer/rl_trainer.py — 主训练循环,依赖 Ray actor + vLLM + FSDP2', ' - molt/trainer/sft_trainer.py — 同上', ' - molt/trainer/placement.py — Ray placement group → GPU bundle 映射', ' - molt/trainer/vllm/vllm_engine.py + vllm_worker_wrap.py — vLLM 引擎封装,硬依赖 CUDA(_MIN_VLLM_VERSION=0.21.0)', ' - molt/trainer/workers/actor_group.py / policy_actor.py / critic_actor.py — Ray actor,内部 CUDA 操作', ' - molt/trainer/fsdp/checkpoint.py / refit.py / strategy.py / optimizer_offload.py / muon.py — FSDP2 + TransformerEngine + CPU offload,需 GPU', ' - molt/trainer/rollout/router.py 中与 vLLM 交互的运行时路径(import 可看,运行需引擎)', ' - tests/e2e/ — 端到端测试,需多 GPU', '', '🔶 需 Colab 免费 T4 验证(单卡几十分钟):', ' - 任何含 --vllm.num_engines 1 的 RL quick start', ' - SFT torchrun --nproc_per_node=1 的小模型实验', ' - tests/unit/test_vllm_engine.py(需 vLLM 实例化)']

最小可运行

  1. # 冒烟测试 1:验证公开 agent 接口可 import 且抽象方法签名正确(CPU,<10s)
  2. python -c "from molt.agents import Env, ChatAgent, ChatAgentRunner, ChatContext, Result, StepEnvRunner, Trajectory; print('agents import ok')"
  3. # 冒烟测试 2:跑 agents 基类单元测试(CPU,纯 Python 逻辑,~30s)
  4. python -m pytest tests/unit/test_agents_base.py -v -m unit
  5. # 冒烟测试 3:跑 chat agent 单元测试(CPU,~1min)
  6. python -m pytest tests/unit/test_chat_agent.py -v -m unit
  7. # 冒烟测试 4:跑 rollout router 单元测试(CPU,不依赖 vLLM 实例化,~1min)
  8. python -m pytest tests/unit/test_router.py tests/unit/test_routing_replay.py -v -m unit
  9. # 冒烟测试 5:跑算法层单元测试(advantage / KL / experience / loss,CPU,~2min)
  10. python -m pytest tests/unit/test_gae_value_loss.py tests/unit/test_group_advantage.py tests/unit/test_kl_controller.py tests/unit/test_experience.py tests/unit/test_policy_loss.py tests/unit/test_global_token_loss.py -v -m unit
  11. # 冒烟测试 6:跑 FSDP packing 单元测试(CPU,THD packing 逻辑,~30s)
  12. python -m pytest tests/unit/test_cp_thd_packing.py tests/unit/test_fsdp_packing.py -v -m unit

测试

['# 测试框架:pytest(pyproject.toml [tool.pytest.ini_options] 配置)', '# addopts = "--verbose --pyargs --durations=0 --strict-markers"', '# testpaths = ["./tests"]', '# markers: unit / integration / system / acceptance / docs / skipduringci / pleasefixme', '#', '# 目录结构:', '# tests/unit/ — 38 个文件,CPU 可跑(主要目标)', '# tests/e2e/ — 仅 summarize_metrics.py,需 GPU', '#', '# 跑全量 CPU 单元测试(Mac 上推荐,约 5-15min,取决于模型加载):', 'python -m pytest tests/unit -m unit -v --timeout=120', '#', '# 只跑纯 CPU、不加载 HF 模型的子集(最快,<2min):', 'python -m pytest tests/unit/test_agents_base.py tests/unit/test_router.py tests/unit/test_routing_replay.py tests/unit/test_cp_thd_packing.py tests/unit/test_fsdp_packing.py tests/unit/test_muon_param_classify.py tests/unit/test_logging_utils.py tests/unit/test_prompts_dataset.py tests/unit/test_sft_dataset.py -m unit -v', '#', '# 跳过已知 broken 测试(marker pleasefixme):', 'python -m pytest tests/unit -m "unit and not pleasefixme" -v', '#', '# 跑单个测试文件示例:', 'python -m pytest tests/unit/test_chat_agent.py -v -m unit', '#', '# 覆盖率(需 pip install pytest-cov):', 'python -m pytest tests/unit -m unit --cov=molt --cov-report=term-missing']

调试

CI

['# CI 系统:GitHub Actions(.github/workflows/,commit_hotspots 显示 5 次提交在此)', '#', '# 主要 workflow(根据目录推断,需验证具体文件名):', '# - python-package.yml 或类似:PyPI 构建(MOLT_PYPI_BUILD=1)', '# - cicd.yml 或类似:PR 检查(copyright + unit tests)', '# - docs.yml 或类似:文档站构建', '#', '# PR 会被以下检查卡住(证据:CONTRIBUTING.md + 最近 commit):', '# 1. pre-commit hooks:black / ruff / isort(line_length=119)', '# 2. Copyright header check(最近 commit 74573e45 修复 docs-only push 不失败)', '# 3. DCO sign-off:git commit -s 必须有 Signed-off-by 行', '# 4. Unit tests:至少 tests/unit 子集在 CI 容器里跑(CUDA 环境)', '# 5. Marker 检查:--strict-markers 要求所有 @pytest.mark.X 必须在 pyproject.toml 注册', '#', '# 本地预检(提交前必跑):', 'python -m compileall -q molt examples/python tests # AGENTS.md 要求', 'pre-commit run --all-files # 格式 + copyright', 'python -m pytest tests/unit -m "unit and not pleasefixme" -q # 快速回归']

坑

四、维护者与社区

Release 节奏很快:最近三周连发 v0.1.10(2026-09-28)、v0.1.9(2026-09-17)、v0.1.8(2026-09-14),约每 5–7 天一个 tag。Commit 频率同样高,最近 10 个 commit 集中在 2026-09-29 → 10-04,其中一半是 fix(agents 上的 event-loop 阻塞、rollout router 转换、grading 逻辑、loss 聚合),另一半是 docs/ci 打磨(README 排版、copyright-check、PR 镜像分支预览)。提交热点:tests/unit、.github/workflows、README.md、molt/trainer、examples/python、molt/agents,说明团队在同步补测试、CI 与文档,属于「功能基本可用、工程收尾中」的密集迭代阶段。

谁角色依据
hijkzzz疑似核心 maintainer / 发布 ownerREADME 容器镜像 tag 用 hijkzzz/molt:latest 与 hijkzzz/molt:0.1.10,且 README 安装章节直接引用该镜像作为推荐路径,说明此人掌控镜像发布与 install 文档。
Jianh活跃 contributor(算法侧)PR #182「Jianh/score centering v2」作者,涉及 advantage / score 计算的核心算法改动。
NVIDIA-NeMo 团队(集体)维护者与 CI/文档 owner仓库归属 NVIDIA-NeMo/labs-molt;setup.py 作者字段为 NVIDIA CORPORATION & AFFILIATES;LICENSE / NOTICE / THIRD_PARTY_NOTICES 均为 NVIDIA 标准模板;.github/workflows、CODEOWNERS、SECURITY.md 等由团队维护。
外部 contributors(社区)零散功能 / fix 贡献者PR #7「feat(tutorial): add a CPU-first RL walkthrough」、PR #57「feat(peft): LoRA support for SFT」、PR #58「Enable Liger layers」、PR #52「Enable dynamic batching」、PR #119「perf(models): bound autograd storage for low-precision log probabilities」均来自非 NVIDIA 内部账号,说明社区贡献已被合并。

流程与 Review 风格

贡献流程在 CONTRIBUTING.md 中写得极简: 1. 克隆仓库后先装 pre-commit:pip install pre-commit && pre-commit install(仓库根有 .pre-commit-config.yaml)。 2. 强制 DCO sign-off:所有 commit 必须 git commit -s,附 Signed-off-by: Name <email>,否则不予合并;CONTRIBUTING 全文附上 Developer Certificate Origin 1.1。 3. 没有看到 CLA 或模板化的 Issue/PR 流程文件(AGENTS.md 是给 AI 编码助手的规则,不是给人)。 4. 从 commit 消息看,团队使用 Conventional Commits 前缀:fix(rollout):、fix(agents):、feat(loss):、docs:、ci(copyright-check):、refactor(review):。 5. 没有显式的「先开 Issue 再提 PR」强约束,但 bug fix(如 #185/#186/#191/#192)都对应 issue 编号。 6. automodel-slim 分支的 PR 用 /review 请求评审,遗留的 /claude review 评论只收到迁移指引(见 commit #189「refactor(review): migrate legacy reviews to /review」)。

从最近 PR 与 commit 推断: - 响应速度快:fix 类 PR(如 #185/#186/#188/#190/#191/#192)集中在 2026-10-02–10-04 提交并合并,说明 review 周期在小时到天级别。 - 关注 event-loop 阻塞与正确性:最近一半的 fix 都是「keep X off event loop」(math grading、chat image loading、tool parsing、router payload),review 明显在盯 async 路径上的阻塞点。 - 文档与 CI 同步打磨:commit #173–#177 连续修 copyright-check、README 排版、scaling knobs 表格,说明 review 对 docs 细节也较真。 - 有 AI 辅助评审痕迹:commit #189 把遗留的 /claude review 评论迁移到 /review,说明仓库接入了某种自动化 review bot(可能基于 Claude Code),且团队在统一评审入口。 - 没有看到长篇 review 讨论,风格偏「小 diff 快速合并」。

渠道

这里的规矩

维护者现在最想要的帮助

五、切入方案

建议长期负责:molt/agents/ + molt/utils/vlm_utils.py + tests/unit/agent* 与 tests/unit/vlm* 测试簇,长期负责「agent contract + 多模态 token 对齐」这条 CPU 可验证的薄层。
README 把「agentic-first」与「token-first contract」并列为最大差异点,而 agent 层恰好是整栈里对 GPU 依赖最低、对纯 Python 正确性最敏感的部分:Env.step() / ChatAgent.run() / _chat_server.py 的 token-exact 拼接、VLM image placeholder 展开、event-loop offload 都是 CPU 可测。commit 热点显示团队最近连续在 agent 层修 event-loop 阻塞(#185/#186/#191),说明这是当前活跃且缺人手的区域。你擅长算子融合与 kernel 正确性验证,把「token 对齐」当作 kernel 来审,正好对口。路径:先补测试与 CPU fixture → 再补 VLM 测试 → 再主导 agent contract 的 slim/upstream 双后端 parity。

它现在缺什么(你无 GPU 也能补)

缺口依据为什么是你
CPU-first 开发/测试路径几乎空白:README 安装章节只给 container 与 pip install -e ".[vllm]" 两条 GPU 路径,没有 Apple Silicon / CPU-only 的文档、CI 或 import 隔离。README 安装章节仅 container 与 local install;setup.py 默认 AUTOMODEL 指向 git-pinned 上游 commit,requirements.txt 含 vllm;pyproject.toml 的 coverage source 只覆盖 molt;tests/unit 下虽有 38 个测试文件,但无 conftest 或 marker 把 GPU-only 测试与 CPU 可跑测试分开,也没有 CI job 在 CPU runner 上跑。你当前只有 MacBook Air(Apple Silicon,16GB),这条 gap 直接决定你能不能开工。把「CPU 能跑什么、GPU 才能跑什么」用 fixture/marker 显式化,是你能立刻产出、且所有后续 PR 都能复用的基础设施。
Agent 层测试覆盖薄且缺多轮/VLM 路径:tests/unit/test_chat_agent.py、test_chat_server.py、test_agents_base.py 存在,但 examples/python/agents/chat_geo3k.py、chat_minimal.py、distill_agent.py 没有对应 unit test。commit 热点里 tests/unit 7 次、molt/agents 2 次,最近 fix 集中在「keep … off event loop」(#185/#186/#191);tests/unit 目录下列出的 agent 相关测试只有 4 个,而 molt/agents/ 有 base/chat_agent/distill_agent/_chat_server 四个文件、examples/python/agents/ 有 chat_geo3k/chat_minimal/geo3k/math 四个 env。agent 是 Molt 对外「agentic-first」定位的门面,测试缺口正好是 CPU 可验证的纯 Python 逻辑(token 对齐、event-loop offload、image placeholder 展开),不需要 GPU。
AutoModel-Slim 分支与主仓库的切换/对照缺少自动化:README 给了 MOLT_AUTOMODEL=slim 用法,但没有 CI 跑 slim vs upstream 的 parity,也没有脚本输出「当前 commit 与 upstream 8f73178ca 的 diff」。README「Optional backend: AutoModel-Slim」章节;setup.py AUTOMODEL 字典含 upstream 与 slim 两个 key;commit 列表最近一次 slim 相关改动不在近 10 条内;.github/workflows 5 次 commit 但未在 README 提 slim CI。这是「纯 Python + 配置」层面的工作:写一个 scripts/compare_automodel.py 或在现有 CI 里加一个 slim job,验证 import nemo_automodel 路径、API surface、forward bit-exact 声明。全部可在 CPU 上跑。
Loss/advantage 聚合模式缺独立 benchmark:PR #184 刚合 prompt-mean-token-mean,README 给了三种 loss_agg_mode,但没有脚本对比 seq-mean-token-mean / token-mean / prompt-mean-token-mean 在相同 batch 下的 loss 曲线与梯度 norm。commit feat(loss): prompt-mean-token-mean aggregation (#184);README Quick Start 表格列出三种 mode;molt/models/loss.py、molt/trainer/algorithm/advantage.py 是热点路径;tests/unit/test_global_token_loss.py、test_policy_loss.py 存在但只测形状。这是训练性能工程师的核心区。写一个 examples/python/utils/bench_loss_agg.py,用随机 logits + 不同 prompt 长度分布跑三种 mode,输出 token 数 vs 有效梯度贡献。纯 PyTorch CPU 即可。
Rollout dump/replay 缺端到端示例与验证脚本:README 给了 --train.rollout_dump_dir / --rollout_replay_dir,但 examples/scripts/quick_start/ 下没有对应脚本,也没有 CI 验证 dump→replay 的 bit-exact。README Quick Start 末段列出 dump/replay flags;tests/unit/test_routing_replay.py 存在(说明 router replay 有单测),但 e2e 脚本 tests/e2e/summarize_metrics.py 只做 metrics 汇总;examples/scripts/quick_start/ 目录存在但内容未在证据中确认。dump/replay 是纯数据通路(token ids + logprobs + rewards),CPU 可跑。写一个 examples/scripts/quick_start/rollout_dump_replay.sh + 一个验证脚本,既补文档缺口又补测试缺口。
FSDP/CPU-offload 路径在 CPU 机器上不可观测:--fsdp.offload optimizer|full 是 Qwen3.6 MoE 的关键 knob,但 molt/trainer/fsdp/optimizer_offload.py 没有 CPU-only 的 smoke test。molt/cli/common_args.py 定义了 --fsdp.offload 三档;molt/trainer/fsdp/ 含 checkpoint/muon/optimizer_offload/packing/refit/strategy 六个文件;tests/unit/test_fsdp_packing.py、test_muon_param_classify.py 存在,但无 test_optimizer_offload.py。CPU offload 的参数分类、hook 注册、state dict 路径是纯 Python 逻辑,可以用 mock device 测。这是你「训练性能工程师」背景能立刻看懂的模块。
VLM 多模态 token 对齐缺独立单测:molt/utils/vlm_utils.py 提供 process_prompt_with_images、estimate_vllm_input_expansion_delta 等函数,但 tests/unit/ 下没有 test_vlm_utils.py。molt/utils/vlm_utils.py 在 code_paths 中;molt/agents/base.py 的 _tokenize_observation 调用 process_prompt_with_images;_chat_server.py 也调用 estimate_vllm_input_expansion_delta;tests/unit/ 38 个文件里无 test_vlm_utils*。VLM 是 README 主打的「multi-turn, VLM, tool-call traces share one format」卖点之一。image placeholder 展开与 token 对齐是 CPU 可测的纯函数,补测试即可贡献。
CONTRIBUTING 与 PR 模板缺「CPU-only 贡献」指引:CONTRIBUTING.md 只要求 sign-off + pre-commit,没说「没有 GPU 怎么跑测试」「哪些 marker 是 CPU-safe」。CONTRIBUTING.md 全文只提 sign-off / pre-commit;.github/ISSUE_TEMPLATE 存在但内容未披露;AGENTS.md 强调 simplicity-first 但没提硬件门槛;PR #7 标题是「feat(tutorial): add a CPU-first RL walkthrough」说明社区有 CPU-first 需求但尚未落地。你自己在踩这个坑,把「CPU 能跑哪些测试、怎么标记 GPU-only」写成文档/PR 模板改进,是低风险高可见度的贡献。

第 1–30 天:看懂并露面

第 31–60 天:稳定产出

第 61–90 天:接管一块

第一批 PR

题目范围为什么安全
test(agents): add CPU-only conftest fixtures and mark GPU-only agent teststests/unit/conftest.py + tests/unit/test_agents_base.py, test_chat_agent.py, test_chat_server.py只动测试基础设施,不改 molt/ 源码;用 skipif 隔离 CUDA 依赖,失败也只会让原本就跑不了的测试显式 skip,不会破坏任何现有 GPU CI。
test(agents): unit tests for DistillationEnv and chat_minimal envtests/unit/test_distill_agent.py + tests/unit/test_chat_minimal.py(新建)纯 Python 逻辑测试,覆盖 Result 形状、terminated 默认值、reward=0.0 placeholder;不触碰 vLLM 或 FSDP,CPU 可跑。
test(vlm): unit tests for vlm_utils image placeholder expansiontests/unit/test_vlm_utils.py(新建)用 PIL.Image.new 或 torch.zeros 构造假图片,测 process_prompt_with_images 与 estimate_vllm_input_expansion_delta 的纯函数逻辑;不依赖 GPU 或真实 vLLM 引擎。
docs: CPU-first development guide and CONTRIBUTING updatedocs/dev-cpu.md(新建)+ CONTRIBUTING.md纯文档 PR,不涉及代码逻辑;基于你自己踩坑的真实经验,风险为零,且能立刻帮助其他无 GPU 的贡献者。
test(rollout): add test for rollout dump→replay token-exact paritytests/unit/test_dump_replay_parity.py(新建,可先只测 router 与 experience_maker 的数据通路)用 mock 或 CPU tensor 验证 dump/replay 的数据通路(token ids / logprobs / rewards 的 round-trip),不依赖真实 vLLM;与 README 已有的 --train.rollout_dump_dir / --rollout_replay_dir 功能绑定,不假设任何 bug。

怎么知道自己站住了

风险与对策
  • 仓库处于快速迭代期(v0.1.8→0.1.10 三周三连发),你的 PR 可能因上游重构被 force-push 冲掉。:前 90 天的 PR 全部限定在 tests/unit/、docs/、examples/ 三个目录,这些目录在 commit 热点里虽有改动但幅度小;每次 rebase 前先 fetch upstream/main。
  • AutoModel 上游 commit 8f73178ca 是 git-pinned,在 macOS 上可能无法 import(依赖 CUDA 或 TransformerEngine)。:优先用 MOLT_AUTOMODEL=slim 路径(slim 分支裁掉了 GPU-only 代码);如果 slim 也失败,在 tests/unit/conftest.py 里加 nemo_automodel mock fixture,让 agent/vlm 测试不依赖真实 AutoModel import。
  • vLLM 0.21.0 在 macOS 无 wheel,pip install -e ".[vllm]" 会失败,阻塞整个开发环境。:按 runbook 跳过 [vllm] extra,只装 pip install -e .;在 molt/trainer/vllm/ 的 import 路径上加 lazy import 或 try/except,让 molt.cli.train_rl_ray 在缺少 vLLM 时报清晰错误而非 cryptic ImportError。
  • 你的 GPU 经验(CUDA/Triton/CuTe)在 Molt 的 agent/vlm 薄层里用不上,前期贡献可能感觉「太浅」。:把 agent 层的「token 对齐」当作 kernel 正确性来审(TITO、image placeholder、compaction),用你熟悉的「bit-exact + boundary case」思维写测试;阶段 90 后通过 slim parity 脚本进入模型后端,那里 FSDP2/TP/EP 才是你的主场。
  • 社区响应慢:NVIDIA-NeMo 团队是集体维护,PR 可能几天没人 review。:前 30 天主动在 Discord/Slack(如果有)或 GitHub Discussion 里露面,把 PR 链接发过去;优先提「测试/文档」类 PR,这类 PR 审查成本低、合入速度快;在 PR 描述里写清「已在 MacBook Air CPU 上跑过,不影响 GPU CI」。
  • Apple Silicon 16GB 内存有限,跑全量 tests/unit 可能 OOM。:用 pytest -k 'test_agents or test_vlm or test_chat' 限定范围;在 conftm 里加 pytest --memray 或简单 resource 监控;避免一次性 import 所有模型权重。
  • AutoModel-Slim 分支的维护规则不透明(README 说「model and parallel-stack changes go to that branch as PRs」),你提交的 slim 相关 PR 可能被 redirect。:阶段 90 之前不主动向 slim 分支提 PR;先在主仓库的 issue 里问清楚 slim 的 review 流程(找 hijkzzz 或 NVIDIA-NeMo 团队),确认后再动手。
  • README 明确说 PyPI 包「not a supported install path right now」,你写的 CPU-first 文档可能很快过时。:在 docs/dev-cpu.md 顶部加一行「Last verified: v0.1.10, 2026-10」;每次 release 后跑一次 smoke test 并更新;把「CPU-first」作为长期 issue 挂着,而非一次性 PR。

六、怎么介入这个项目

建议顺序

成为长期维护者的路径
  • molt/agents/ + molt/utils/vlm_utils.py + tests/unit/agent* 与 vlm* 测试簇
  • 长期负责「agent contract + 多模态 token 对齐」这条 CPU 可验证薄层

七、任务卡

任务 1优先 · medium · Mac · 2–3 个晚上

test(agents): CPU-only conftest fixtures + mark GPU-only agent tests

无人认领3 条评论更新 2026-07-30

用到的专长:测试基础设施与 Python 调度逻辑,CPU 可验证。

目标:在 tests/unit/conftest.py 新增 cpu-only / gpu-only fixture 与 marker,把现有 agent 测试中依赖 CUDA/vLLM 的用 skipif 隔离,确保 Mac 上 pytest tests/unit -m cpu_only 全绿。

为什么值得长期做:agents 是 Molt agentic-first 定位的门面,commit 热点 #185/#186/#191 都在修 event-loop 阻塞。CPU/GPU 测试分离是所有后续 agent 测试的基础设施。

怎么介入:Issue #51 是社区贡献意愿确认,无 assignee、无 open PR;借其「start small (docs, tests)」语境切入测试基建是得体的。
第一个 PR 的边界:仅限 tests/unit/conftest.py(新增)与现有 agent 测试加 marker,不动 molt/ 源码。
第一步:调查 tests/unit/conftest.py 是否存在、现有 agent 测试文件(test_agents_base.py、test_chat_agent.py、test_chat_server.py)里哪些 import 或 fixture 触发 CUDA。
本机怎么复现 / 验证:在 Mac 上 pip install -e ".[vllm]" 后 pytest tests/unit -m cpu_only --collect-only 看 marker 是否生效;pytest tests/unit/test_agents_base.py 验证 agent 测试可跑。
认领留言(英文,可直接贴到 Issue)
Hi — I'd like to pick up the CPU-first test infra from the 'start small (docs, tests)' spirit in this issue. Plan: add tests/unit/conftest.py with cpu_only/gpu_only markers, mark CUDA/vLLM-dependent agent tests with skipif, and add a smoke test that imports molt.agents on CPU. No changes to molt/ source. Does cpu_only/gpu_only marker naming look good, or do you prefer requires_cuda? I'll have a PR up within a couple of evenings.
大致实施方案
  • 在 tests/unit/conftest.py(新增)里定义 cpu_only / gpu_only marker 与 is_cuda_available 检查
  • 在现有 agent 测试中给依赖 vLLM/CUDA 的测试函数加 @pytest.mark.gpu_only + skipif(not is_cuda_available)
  • 在 tests/unit 下新增 test_import_agent_cpu.py 验证 molt.agents.base / molt.agents.chat_agent 可在 CPU import
  • 本地跑 pytest tests/unit -m cpu_only --collect-only 与 pytest tests/unit -m cpu_only 确认
  • 提交 PR,scope 仅限 tests/unit 与 conftest,不动 molt/ 源码
可能涉及的目录或文件
  • tests/unit/conftest.py(新建)
  • tests/unit/test_agents_base.py
  • tests/unit/test_chat_agent.py
  • tests/unit/test_chat_server.py
验收方式
  • pytest tests/unit -m cpu_only 在 Mac 上全绿
  • pytest tests/unit -m gpu_only 在 Mac 上全 skip、不报错
  • CI 中现有 GPU 测试不受影响(marker 不改变其行为)
开工前问题与风险

向维护者确认

  • 是否偏好 cpu_only / gpu_only 命名,还是沿用 requires_cuda 之类?
  • conftest.py 是否应放在 tests/unit/ 还是根 tests/?

风险

  • 若
  • 误
  • 把
  • 非
  • G
  • P
  • U
  • 测
  • 试
  • 标
  • 为
  • g
  • p
  • u
  • _
  • o
  • n
  • l
  • y
  • 会
  • 降
  • 低
  • 覆
  • 盖
  • 率
  • ;
  • 需
  • 逐
  • 文
  • 件
  • 确
  • 认
  • i
  • m
  • p
  • o
  • r
  • t
  • 链
  • 。
任务 2可选 · medium · Mac · 2–3 个晚上

test(vlm): unit tests for vlm_utils image placeholder expansion

无人认领0 条评论更新 2026-09-07

用到的专长:多模态 token 对齐是训练性能工程师熟悉领域,纯函数测试 CPU 可验证。

目标:新建 tests/unit/test_vlm_utils.py(新增),用 PIL.Image.new 或 torch.zeros 构造假图片,覆盖 process_prompt_with_images 与 estimate_vllm_input_expansion_delta 的纯函数逻辑。

为什么值得长期做:VLM 是 README 主打卖点之一(multi-turn/VLM/tool-call 共享格式),vlm_utils.py 是 token 对齐关键函数,但 tests/unit/ 下无对应测试。

怎么介入:Issue #104 本身与 OrcaRouter 相关,但 vlm_utils 测试是其「OpenAI-compatible provider」无关的独立缺口;在 Issue 下简短评论说明认领的是测试子任务即可。
第一个 PR 的边界:仅新增 tests/unit/test_vlm_utils.py,不动 molt/ 源码。
第一步:阅读 molt/utils/vlm_utils.py 与 molt/agents/base.py 中 _tokenize_observation 的调用方式,确定函数签名与期望输出。
本机怎么复现 / 验证:在 Mac 上 pytest tests/unit/test_vlm_utils.py -v 运行新增测试;若无该文件则先确认 molt/utils/vlm_utils.py 在 CPU 上可 import。
认领留言(英文,可直接贴到 Issue)
I'd like to add unit tests for molt/utils/vlm_utils.py — it's currently untested and is on the VLM token-alignment path the README highlights. Plan: create tests/unit/test_vlm_utils.py covering process_prompt_with_images and estimate_vllm_input_expansion_delta with fake images (PIL/torch.zeros), all CPU-runnable. No changes to molt/ source. Any implicit assumptions on image shape/format I should encode? PR ready in a couple of evenings.
大致实施方案
  • 在 tests/unit/test_vlm_utils.py(新增)中构造 fake image tensor / PIL image
  • 测试 process_prompt_with_images 在不同 placeholder 模式下的 token 展开
  • 测试 estimate_vllm_input_expansion_delta 在空/非空 image list 下的返回值
  • 本地跑 pytest tests/unit/test_vlm_utils.py -v 确认全绿
  • 提交 PR,scope 仅限新增测试文件
可能涉及的目录或文件
  • tests/unit/test_vlm_utils.py(新建)
  • molt/utils/vlm_utils.py(只读)
验收方式
  • pytest tests/unit/test_vlm_utils.py 在 Mac 上全绿
  • 覆盖 placeholder 展开与 delta 估算两个函数的主要分支
开工前问题与风险

向维护者确认

  • process_prompt_with_images 是否对 image 尺寸/格式有隐含假设需要在测试里显式约束?

风险

  • 若
  • 函
  • 数
  • 内
  • 部
  • 隐
  • 式
  • 依
  • 赖
  • C
  • U
  • D
  • A
  • t
  • e
  • n
  • s
  • o
  • r
  • ,
  • 需
  • 确
  • 认
  • 其
  • 在
  • C
  • P
  • U
  • 上
  • 可
  • 跑
  • ;
  • 否
  • 则
  • 调
  • 整
  • 测
  • 试
  • 输
  • 入
  • 类
  • 型
  • 。
任务 3可选 · medium · Mac · 2–3 个晚上

test(agents): DistillationEnv / chat_minimal env 单元测试

已有 PR #960 条评论更新 2026-08-24

用到的专长:agent contract 测试是纯 Python 逻辑,CPU 可验证。

目标:新建 tests/unit/test_chat_minimal.py(新增)与 tests/unit/test_distill_agent.py(新增),覆盖 Result 形状、terminated 默认值、reward=0.0 placeholder 等纯 Python 逻辑。

为什么值得长期做:examples/python/agents/ 下 chat_minimal.py / distill_agent.py 无对应 unit test,是 agent 层测试覆盖缺口;与 #51 的「start small (tests)」一致。

怎么介入:Issue #95 已有 open PR #96 处理 prepare_math 脚本,但测试覆盖是独立缺口;在 #95 下简短评论说明认领的是 agent 测试子任务即可。
第一个 PR 的边界:仅新增 tests/unit/test_chat_minimal.py 与 tests/unit/test_distill_agent.py,不动 molt/ 或 examples/ 源码。
第一步:阅读 examples/python/agents/chat_minimal.py、molt/agents/distill_agent.py,确定 Env 接口与 Result 字段。
本机怎么复现 / 验证:在 Mac 上 pytest tests/unit/test_chat_minimal.py tests/unit/test_distill_agent.py -v 运行新增测试;若文件不存在则先确认 examples/python/agents/chat_minimal.py 在 CPU 上可 import。
认领留言(英文,可直接贴到 Issue)
I'd like to add unit tests for the example agents that currently lack coverage — chat_minimal.py and DistillationEnv. Plan: create tests/unit/test_chat_minimal.py and tests/unit/test_distill_agent.py covering Result shape, terminated defaults, and reward placeholders. All CPU-runnable, no changes to molt/ source. Do these envs have any hidden external LLM dependencies I should mock? PR ready in a couple of evenings.
大致实施方案
  • 在 tests/unit/test_chat_minimal.py(新增)中实例化 env、调用 step、断言 Result 字段类型与 terminated 默认值
  • 在 tests/unit/test_distill_agent.py(新增)中覆盖 DistillationEnv 的基本轨迹生成
  • 本地跑 pytest tests/unit/test_chat_minimal.py tests/unit/test_distill_agent.py -v
  • 提交 PR,scope 仅限新增测试文件
可能涉及的目录或文件
  • tests/unit/test_chat_minimal.py(新建)
  • tests/unit/test_distill_agent.py(新建)
  • examples/python/agents/chat_minimal.py(只读)
  • molt/agents/distill_agent.py(只读)
验收方式
  • pytest tests/unit/test_chat_minimal.py tests/unit/test_distill_agent.py 在 Mac 上全绿
  • 覆盖 Result 形状、terminated 默认、reward placeholder
开工前问题与风险

向维护者确认

  • chat_minimal env 是否需要 mock 外部 LLM 调用?若是,确认是否用 unittest.mock 即可在 CPU 上跑。

风险

  • 若
  • e
  • n
  • v
  • 内
  • 部
  • 隐
  • 式
  • 依
  • 赖
  • v
  • L
  • L
  • M
  • 实
  • 例
  • 化
  • ,
  • 需
  • 确
  • 认
  • 测
  • 试
  • 路
  • 径
  • 可
  • 跳
  • 过
  • 该
  • 依
  • 赖
  • 。
任务 4可选 · medium · Mac · 3–4 个晚上

test(rollout): rollout dump→replay token-exact parity 测试

已有 PR #1322 条评论更新 2026-07-31

用到的专长:rollout 数据通路是训练性能工程师熟悉领域,纯逻辑测试 CPU 可验证。

目标:新建 tests/unit/test_dump_replay_parity.py(新增),用 mock 或 CPU tensor 验证 dump→replay 的 token ids / logprobs / rewards round-trip 一致性。

为什么值得长期做:README 已暴露 --train.rollout_dump_dir / --rollout_replay_dir 标志,但无端到端验证脚本;router/experience_maker 数据通路是 CPU 可测的纯逻辑。

怎么介入:Issue #10 有 open PR #132 处理 Qwen-vLLM parity,但 dump/replay 测试是独立缺口;在 #10 下简短评论说明认领的是测试子任务即可。
第一个 PR 的边界:仅新增 tests/unit/test_dump_replay_parity.py,不动 molt/ 源码。
第一步:阅读 molt/trainer/rollout/router.py、experience_maker.py 与 tests/unit/test_routing_replay.py,确定 dump/replay 数据结构与序列化路径。
本机怎么复现 / 验证:在 Mac 上 pytest tests/unit/test_dump_replay_parity.py -v 运行新增测试;若文件不存在则先确认 molt/trainer/rollout/experience_maker.py 在 CPU 上可 import。
认领留言(英文,可直接贴到 Issue)
I'd like to add a dump→replay parity test for the rollout path — README exposes --train.rollout_dump_dir / --rollout_replay_dir but there's no end-to-end verification. Plan: create tests/unit/test_dump_replay_parity.py that constructs fake Experience (token ids/logprobs/rewards), runs dump then replay, and asserts bit-exact round-trip. All CPU-runnable with mock tensors. Does the dump path assume GPU tensors or a specific filesystem I should accommodate? PR ready in a couple of evenings.
大致实施方案
  • 在 tests/unit/test_dump_replay_parity.py(新增)中构造 fake Experience(token ids / logprobs / rewards)
  • 调用 dump 路径序列化到临时目录,再走 replay 路径反序列化
  • 断言 round-trip 后 token ids / logprobs / rewards 完全一致
  • 本地跑 pytest tests/unit/test_dump_replay_parity.py -v
  • 提交 PR,scope 仅限新增测试文件
可能涉及的目录或文件
  • tests/unit/test_dump_replay_parity.py(新建)
  • molt/trainer/rollout/router.py(只读)
  • molt/trainer/rollout/experience_maker.py(只读)
验收方式
  • pytest tests/unit/test_dump_replay_parity.py 在 Mac 上全绿
  • round-trip 后 token ids / logprobs / rewards 完全一致
开工前问题与风险

向维护者确认

  • dump/replay 是否依赖特定文件系统或 GPU tensor?若是,确认是否可用 CPU tensor + tempfile 替代。

风险

  • 若
  • d
  • u
  • m
  • p
  • 路
  • 径
  • 隐
  • 式
  • 依
  • 赖
  • C
  • U
  • D
  • A
  • t
  • e
  • n
  • s
  • o
  • r
  • ,
  • 需
  • 调
  • 整
  • 测
  • 试
  • 输
  • 入
  • 为
  • C
  • P
  • U
  • t
  • e
  • n
  • s
  • o
  • r
  • 。
任务 5可选 · easy · Mac · 1–2 个晚上

docs: CPU-first 开发指南 + CONTRIBUTING 更新

无人认领3 条评论更新 2026-07-30

用到的专长:文档与贡献指南是低风险高可见度贡献。

目标:新建 docs/dev-cpu.md(新增)并在 CONTRIBUTING.md 加「CPU-only 贡献」指引,说明哪些 marker 是 CPU-safe、如何在 Mac 上跑测试。

为什么值得长期做:README 安装章节只给 container 与 pip install -e '.[vllm]' 两条 GPU 路径,无 Apple Silicon / CPU-only 文档;CONTRIBUTING.md 只提 sign-off + pre-commit,没说无 GPU 怎么跑测试。

怎么介入:Issue #51 是社区贡献意愿确认,无 assignee、无 open PR;借其「start small (docs, tests)」语境切入文档是得体的。
第一个 PR 的边界:仅新增 docs/dev-cpu.md 与 CONTRIBUTING.md 追加,不动代码。
第一步:确认 docs/ 目录结构与 CONTRIBUTING.md 当前内容,结合前几张测试卡的经验整理 CPU-first 流程。
本机怎么复现 / 验证:在 Mac 上 pre-commit run --all-files 确认格式;cat docs/dev-cpu.md 检查内容。
认领留言(英文,可直接贴到 Issue)
Following the 'start small (docs, tests)' spirit in this issue, I'd like to add a CPU-first development guide. Plan: create docs/dev-cpu.md documenting how to run tests on Mac (cpu_only marker, install steps), and add a 'CPU-only contributions' section to CONTRIBUTING.md referencing the marker convention. Pure docs, no code changes. Any preferred doc format (md vs rst)? PR ready in an evening or two.
大致实施方案
  • 在 docs/dev-cpu.md(新增)中写明 Mac 上 pip install -e ".[vllm]" 后的测试命令、cpu_only marker 用法
  • 在 CONTRIBUTING.md 加一节「CPU-only contributions」,引用前几张测试卡建立的 marker 约定
  • 本地 pre-commit run --all-files 确认格式合规
  • 提交 PR,scope 仅限 docs/ 与 CONTRIBUTING.md
可能涉及的目录或文件
  • docs/dev-cpu.md(新建)
  • CONTRIBUTING.md(追加)
验收方式
  • pre-commit run --all-files 通过
  • 文档中命令在 Mac 上可复现
开工前问题与风险

向维护者确认

  • docs/ 目录是否偏好特定格式(如 markdown 还是 rst)?

风险

  • 纯
  • 文
  • 档
  • P
  • R
  • ,
  • 风
  • 险
  • 为
  • 零
  • 。