Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,20 @@ Python 方法,由 manager 运行时契约定义(`wiki/design/manager/runtime

### 测试规范

- `tests/` 下的测试应面向通用功能、公共接口、行为契约和不变量,确保实现变化不会破坏框架能力。
- 根目录及各 package 的长期测试应面向通用功能、公共接口、行为契约和不变量,确保实现变化不会破坏框架能力。长期测试保护长期契约,一次性验收证明本次改动,不要混淆两者。
- 新增测试前,明确它保护的契约、能够发现的真实错误,以及是否能用更小、更稳定的测试覆盖同样风险。不要为了覆盖率或证明某次配置搬迁而机械新增测试。
- 优先测试可观察的输入输出、状态转换和错误处理,不绑定内部函数调用顺序或实现结构,除非它们本身就是公共契约。修复可复现缺陷时,优先保留最小回归测试,不复制整套任务或运行环境。
- 不要在测试中重复抄写实现或配置作为唯一的正确性依据。版本、内部依赖等跨文件一致性规则可以测试,但应断言关系或不变量,而不是固定当前版本号。

#### 测试分层与成本

- 单元测试应快速、确定、范围小,不依赖网络、真实 GPU 或外部服务。模块协作、插件和 CLI 行为归入集成测试;依赖解析、包构建与安装闭包归入安装/发布验收;实际 GPU 运行、训练和性能验证使用专门环境。
- 优先用较低成本的测试保护行为。联网解析、创建临时 Git 仓库、调用包管理器、解析第三方 CLI 输出或搭建完整环境的验证,若只服务于本次依赖调整或迁移,应作为一次性验收,不保留为长期测试。
- 只有当高成本验证保护明确、持续支持的跨系统契约,且轻量测试不足时,才保留为长期集成/安装测试;明确执行入口、所需环境和维护归属,与默认单元测试分开。默认跳过或增加 opt-in 开关不能单独构成保留理由。
- 在 PR 中记录实际执行的验收命令和结果,并区分依赖解析、安装计划、实际安装及硬件运行;不要用 dry-run 或元数据检查声称运行时兼容。

#### 配置与迁移验收

- 不应针对具体任务配置中的固定数值编写测试,例如 reward scale、默认姿态、训练超参数或其他可能随调参变化的值。
- 不应为纯配置的缺失状态编写负向单元测试,例如断言某个环境注册名、配置字段、preset 或兼容 alias 不存在。删除这类配置时,
应通过引用扫描、静态检查和现存功能的正向行为测试完成验收。
Expand Down
51 changes: 51 additions & 0 deletions motrix_rl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,57 @@ extras. The workspace root requires `motrix-rl-builtin` and `motrix-rl-skrl`, en
for the built-in demos. The root `skrl-jax` extra adds the JAX backend; `rslrl` adds the optional RSLRL plugin.
Runtime installation does not force other optional workspace packages.

## GPU installation profiles

`motrix-rl[cuda]` and `motrix-rl[rocm]` define the tested NVIDIA and AMD Torch dependency profiles. Without either extra,
Torch uses the default package index; this does not imply a CPU-only build. The workspace forwards its `cuda`/`rocm` extras
to this package, so `sh install.sh --gpu cuda` and `sh install.sh --gpu rocm` remain unchanged.

For an external **uv project consuming Git sources**, select one profile and pin the source revision:

```toml
[project]
dependencies = ["motrix-rl[cuda]"] # or motrix-rl[rocm]

[tool.uv.sources]
motrix-rl = { git = "https://github.com/Motphys/MotrixLab", rev = "<commit>", subdirectory = "motrix_rl" }
```

uv reads this source package's extra-gated PyTorch index routing and resolves its internal workspace dependencies
(`motrix-env-core` and `motrix-deploy`) from the same Git revision. No consumer-side Torch version pins, PyTorch index
mappings, or sibling-package source mappings are needed.

If the consuming project exposes **both** profiles as optional extras, declare both the forwarding and package-qualified
conflict pairs at the consuming root. Workspace resolution collects member-local conflicts, but external Git consumers
need the explicit package-qualified pair for the index-specific source split:

```toml
[project.optional-dependencies]
cuda = ["motrix-rl[cuda]"]
rocm = ["motrix-rl[rocm]"]

[tool.uv]
conflicts = [
[{ extra = "cuda" }, { extra = "rocm" }],
[{ package = "motrix-rl", extra = "cuda" }, { package = "motrix-rl", extra = "rocm" }],
]
```

Select one with `uv sync --extra cuda` or `uv sync --extra rocm`. CUDA routing applies on Linux/Windows; ROCm routing is
Linux x86_64 only. On other platforms these profile-specific requirements are inactive and the base Torch dependency
uses the default index. Universal lockfiles that combine GPU profiles and macOS may also need explicit platform splits,
as in the workspace root's `tool.uv.environments`.

Use `uv sync` for profile installation. In uv 0.9.8 and 0.9.14, `uv export` does not correctly preserve GPU selection
through forwarding extras; do not use its exported requirements to install these GPU profiles.

**Wheel/PyPI and pip installations:** extras retain their version requirements, but wheel metadata does not carry
`tool.uv.sources` or index definitions, and pip does not interpret them even for Git sources. Configure the appropriate
[PyTorch wheel index](https://pytorch.org/get-started/locally/) in the consuming installer/project explicitly. In particular,
a `rocm` extra's Torch version alone does not guarantee a ROCm build. GPU selection is explicit, not hardware auto-detection.

## Workspace training

Environment-specific training presets live under `configs/task/`, while shared provider defaults live under
`configs/algo_base/`. From the workspace root, select a preset with Hydra's `task=<env-id>/<method>` syntax (run from the
activated workspace environment, `source .venv/bin/activate`):
Expand Down
47 changes: 44 additions & 3 deletions motrix_rl/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,53 @@ dependencies = [
# ONNX export of trained policies; onnxruntime (for the parity check and
# deployment inference) comes in via motrix-deploy.
"onnx==1.20.1",
# Default training backend; also required by scripts/view.py. The exact
# version and wheel index are chosen by the workspace root `cuda`/`rocm`
# extras (see the root pyproject.toml tool.uv.sources).
# Default training backend; GPU profiles below optionally pin its version
# and, when consumed from source with uv, its wheel index.
"torch>=2.7,<3",
]

[project.optional-dependencies]
cuda = [
"torch==2.7.0; sys_platform == 'linux' or sys_platform == 'win32'",
"torchvision==0.22.0; sys_platform == 'linux' or sys_platform == 'win32'",
"torchaudio==2.7.0; sys_platform == 'linux' or sys_platform == 'win32'",
]
# ROCm wheels are available only for Linux x86_64.
rocm = [
"amdsmi; sys_platform == 'linux' and platform_machine == 'x86_64'",
"torch==2.11.0; sys_platform == 'linux' and platform_machine == 'x86_64'",
"triton-rocm==3.6.0; sys_platform == 'linux' and platform_machine == 'x86_64'",
]

[tool.uv]
conflicts = [[{ extra = "cuda" }, { extra = "rocm" }]]

[[tool.uv.index]]
name = "pytorch-cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = true

[[tool.uv.index]]
name = "pytorch-rocm72"
url = "https://download.pytorch.org/whl/rocm7.2"
explicit = true

[tool.uv.sources]
# Keep default installs on PyPI; only explicit GPU extras select these indexes.
torch = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux' or sys_platform == 'win32'", extra = "cuda" },
{ index = "pytorch-rocm72", marker = "sys_platform == 'linux' and platform_machine == 'x86_64'", extra = "rocm" },
]
torchvision = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux' or sys_platform == 'win32'", extra = "cuda" },
]
torchaudio = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux' or sys_platform == 'win32'", extra = "cuda" },
]
triton-rocm = [
{ index = "pytorch-rocm72", marker = "sys_platform == 'linux' and platform_machine == 'x86_64'", extra = "rocm" },
]

[project.urls]
Homepage = "https://github.com/Motphys/MotrixLab"
Repository = "https://github.com/Motphys/MotrixLab"
Expand Down
61 changes: 7 additions & 54 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,16 @@ docs = [
"sphinx-design",
"tensorboard==2.20.0",
]
# Mutually exclusive GPU wheel profiles: `cuda` pulls the NVIDIA wheels from
# the pytorch-cu128 index, `rocm` the AMD wheels from the pytorch-rocm72
# index. Select exactly one with `uv sync --extra cuda` or
# `uv sync --extra rocm`; the extras are declared conflicting so uv keeps
# both branches in the single uv.lock. Without any extra, torch resolves
# from the default index (PyPI).
cuda = [
"torch==2.7.0; sys_platform == 'linux' or sys_platform == 'win32'",
"torchvision==0.22.0; sys_platform == 'linux' or sys_platform == 'win32'",
"torchaudio==2.7.0; sys_platform == 'linux' or sys_platform == 'win32'",
]
# GPU profiles are owned by the installable RL package. Keep the workspace
# installation entry points without duplicating versions or index routing.
cuda = ["motrix-rl[cuda]==0.4.0b1"]
# TBB threading layer for numba parallel manager kernels on many-core
# machines (see motrix-env-core's tbb extra); optional, combines with any
# GPU profile.
tbb = [
"motrix-env-core[tbb]==0.4.0b1",
]
# ROCm wheels only exist for Linux x86_64; the markers keep other platforms
# from resolving these requirements against the default (PyPI) index.
rocm = [
"amdsmi; sys_platform == 'linux' and platform_machine == 'x86_64'",
"torch==2.11.0; sys_platform == 'linux' and platform_machine == 'x86_64'",
"triton-rocm==3.6.0; sys_platform == 'linux' and platform_machine == 'x86_64'",
]
rocm = ["motrix-rl[rocm]==0.4.0b1"]

[dependency-groups]
dev = [
Expand Down Expand Up @@ -98,25 +84,9 @@ members = [
environments = ["sys_platform == 'darwin'", "sys_platform != 'darwin'"]
package = false
prerelease = "if-necessary-or-explicit"
# `cuda` and `rocm` resolve torch from different indexes and can never be
# installed together; declaring them conflicting lets uv keep both branches
# (as separate forks) in the same uv.lock.
conflicts = [
[
{ extra = "cuda" },
{ extra = "rocm" },
],
]

[[tool.uv.index]]
name = "pytorch-cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = true

[[tool.uv.index]]
name = "pytorch-rocm72"
url = "https://download.pytorch.org/whl/rocm7.2"
explicit = true
# The forwarding extras are mutually exclusive. uv also collects motrix-rl's
# member-local conflicts when resolving this workspace.
conflicts = [[{ extra = "cuda" }, { extra = "rocm" }]]

[[tool.uv.index]]
name = "pypi"
Expand All @@ -137,23 +107,6 @@ motrix-rl = { workspace = true }
motrix-rl-builtin = { workspace = true }
motrix-rl-skrl = { workspace = true }
motrix-rl-rslrl = { workspace = true }
# The `extra = "rocm"` entry routes torch requirements declared in the rocm
# extra to the ROCm index; the `extra = "cuda"` entry does the same for the
# cuda extra. Requirements outside both extras (bare sync) fall back to the
# default index.
torch = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux' or sys_platform == 'win32'", extra = "cuda" },
{ index = "pytorch-rocm72", marker = "sys_platform == 'linux' and platform_machine == 'x86_64'", extra = "rocm" },
]
torchvision = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
torchaudio = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
triton-rocm = [
{ index = "pytorch-rocm72", marker = "sys_platform == 'linux' and platform_machine == 'x86_64'" },
]

[tool.commitizen]
name = "cz_conventional_commits"
Expand Down
Loading
Loading