Skip to content

roadmap: eval 模式化——缺后端 owner 配置时的跨后端 sim2sim 回放 #1472

Description

@TATP-233

背景与目标

uv run eval 的目标语义是:任务即使没有目标后端的 owner YAML,也能回放任意后端训练出的 checkpoint(train 仍必须显式配置 owner YAML)。PR #1469 已解决第一层(CLI owner YAML 缺失时回退到同任务同 profile 的兄弟 owner + training.sim_backend override),但实测 uv run eval --algo ppo --task microduck_velocity_flat --sim motrix --render-mode interactive --load-run <mjwarp run> 仍被后两层挡住:

  1. Registry 层registry.makesrc/unilab/base/registry.py:270)要求 env 为目标后端注册了 factory。MicroduckVelocityFlat 只注册了 mujoco/mjwarp(src/unilab/tasks/locomotion/microduck/__init__.py:19-28),报 does not support simulation backend 'motrix'
  2. 后端能力层:就算注册,motrix 不支持 base.yaml 中 randomize_armature event 需要的 dof_armature reset payload,env 构建期 NotImplementedErrorsrc/unilab/base/reset_state.py:768)。仓库现有惯例是后端 owner YAML 显式 events.<term>: null 禁用不支持的 term(如 go2_joystick_flat/motrix.yamlgo2_footstand/drake.yaml)——这又回到"每后端一份 yaml"的前提,与本 roadmap 目标矛盾。

目标:把 eval 提升为一等模式——策略 I/O 契约(sim2sim DENYLIST)严格校验不变,物理保真项(DR、scene 等 ALLOWLIST 字段)在目标后端能力不足时可降级,从而缺配置也能 sim2sim 回放。

参考:mjlab 的做法(~/ws/simulator/mjlab)

mjlab 只有一个物理后端,但其 play 机制可借鉴:

  • 注册表为每个任务同时持有 env_cfgplay_env_cfg,play 裁剪(关 obs 噪声、pop 扰动 event、清 curriculum)是注册时的一等公民(src/mjlab/tasks/registry.py:10-15tasks/velocity/config/go1/env_cfgs.py:237-257);startup 型 DR 在 play 中保留。
  • checkpoint 只载 actor 权重(load_cfg={"actor": True}, strict=True),环境配置永远由代码 factory 重建;训练 dump 的 params yaml 仅供审计,play 不读。
  • 能力不匹配在 env 构建期 fail-fast(@requires_model_fields + expand_model_fields),无运行时降级。
  • deploy 方向:部署元数据(joint 顺序、obs scale、action_scale)内嵌进 ONNX metadata,部署侧完全免训练配置。

UniLab 已有的对应物:play_profile(owner YAML 内 play 覆写,config_adapter.py:50-115,目前仅视觉覆写)、sim2sim ALLOWLIST 已含 env.domain_rand / env.scene(即仓库已认定 DR/scene 差异不影响策略 I/O 契约)、后端能力检查本身是冷路径声明式的(_capability_error)。

交付边界(候选方案,按长期成本排序)

  • 方案 A:eval 模式的能力感知裁剪。仅 play_only 路径:EventManager 绑定到目标后端不支持的 reset payload term 时 warning + 跳过该项;train 保持 NotImplementedError fail-closed。契约依据:DR 已在 sim2sim ALLOWLIST,DENYLIST(obs/actions/action_scale/网络结构)不受影响。效果等价于自动生成那份不存在的后端 owner YAML 中的 events.<term>: null
  • 方案 B:registry 的 eval 语义放宽。ManagerBased 任务的 factory 本是后端无关的 generic factory(如 make_microduck_velocity_env 仅包一层资产解析);eval 模式可允许"已注册 config 的 ManagerBased 任务"在目标后端直接用 generic factory 建 env,不再要求 per-task 逐后端枚举注册。注意:这会改变 support 声明语义(support matrix 由 registry 扫描生成),属于 support 等级的长期责任变更。
  • 方案 C(独立、长期):一键部署 bundle。训练/导出时把策略 I/O 元数据物化进导出物(mjlab ONNX metadata 做法),deploy 场景彻底免配置。与 A/B 正交,可另立 roadmap。

A+B 组合即可让上述实测命令跑通,且都只作用于 eval/play 路径,train 语义不变。

预计规模

  • 方案 A:EventManager/reset_state 的 play 模式降级分支 + 测试,约 2-4 个文件,~150-300 LOC(含测试)。
  • 方案 B:registry eval 路径 + support matrix 生成逻辑/文档同步,约 3-5 个文件,~200-400 LOC(含测试与 support matrix 重生成)。
  • 方案 C:导出管线 + artifact 元数据 schema,规模另估,建议独立 roadmap。

永久维护成本

  • 方案 A:新增"play 模式降级"语义,需长期保持与 sim2sim DENYLIST/ALLOWLIST 的一致性;降级项变化时需更新文档与审计脚本(scripts/audit_sim2sim_contracts.py)。
  • 方案 B:support 声明从 per-task 枚举变为 runtime 能力声明,support matrix 语义与文档需长期同步;维护者需明确"注册即支持"的新含义。
  • 方案 C:新增 artifact 元数据 schema 的版本化责任。

现状

暂不实施,保持现状。PR #1469(CLI 层 owner YAML 回退)已独立交付,是后续任何方案的前提。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions