Files
Mujoco_WASM/plans/reward-auto-tuning-agent.md
T
chenlin deead17a9a
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
feat(training): release V0.8 自调参 Agent
2026-09-02 13:49:34 +08:00

17 KiB
Raw Blame History

奖励函数自调参 Agent 实施计划

Context

当前项目已有完整的本地训练链路:React/Vite 前端通过 LocalTrainingClient 调用仅监听 loopback 的 Python training_server,服务再启动内置 training_server/rl 中的 Go2 + mjlab/RSL-RL 训练器,并产出 policy.onnx。现有请求只包含环境数、迭代数、随机种子、设备和 W&B 模式;奖励项与权重固定在任务配置中,服务主要从标准输出解析迭代进度,尚未向前端提供结构化奖励曲线或自动调参循环。

第一版范围已确定为 Unitree-Go2-Flat,优化优先级依次为:速度跟踪、动作平滑、姿态稳定、减少跌倒、足端滑移、能耗。Agent 可以调整现有奖励权重、启停白名单奖励项以及修改获准的阈值/核宽等参数,但不能生成或执行任意 Python 奖励代码。系统同时提供全自动与逐轮审批模式,在本地 RTX 5080 上串行训练,通过云端 API 调用 Agent;独立打开一个参考 Isaac/TensorBoard 交互方式的监控网页,展示曲线、trial 对比、参数 diff 与最佳策略。

目标是在现有安全边界内增加一个可审计、可暂停、可恢复、可回退的调参闭环。云端只接收裁剪后的数值配置、曲线摘要和评估指标,不接收机器人资产、checkpoint、源代码、训练服务访问令牌或本地路径。已确认使用 DeepSeek 官方 OpenAI-compatible APIBase URL https://api.deepseek.com)和精确模型标识 deepseek-v4-flash;API key 仅从训练服务环境变量读取。目标占比采用 35/20/15/15/10/5,逐轮审批时基线自动运行、之后每个建议等待批准。最佳结果保存为命名 preset 并可用于后续训练,不覆盖仓库内 Python 默认值。

Approach

采用“确定性试验编排 + 独立评估 + 云端 Agent 建议”的分层方案,而不是让 LLM 直接改源码或决定 trial 是否有效:

  1. 白名单参数空间:为每个 reward term 定义固定符号、默认值、上下界、是否允许置零及单轮最大变化;开放权重,以及 stdcommand_thresholdtarget_height、步态 period/threshold、姿态分段容差等少量参数。保留当前 15 个奖励项,并新增默认关闭(权重为 0)的 electrical_power,以覆盖能耗目标。track_linear_velocitytrack_angular_velocitybody_orientation_l2is_terminatedjoint_pos_limitsaction_rate_l2 不允许关闭;其余白名单项可置零。每个 proposal 最多改 4 个标量,非零权重幅值单轮限制在前值的 0.5×–2×(同时受绝对上下界约束),符号不可翻转,Go2 trot 的足序 offset 不开放。Agent 只能返回结构化 patch,服务端合并并二次校验。
  2. 权重无关的质量指标:现有 Episode_Reward/* 已由 mjlab RewardManager 自动记录,但它随权重变化,不能直接作为优化目标。新增固定定义的速度误差、动作加速度、姿态误差、跌倒率、接触足滑移速度和正向机械功率指标;训练曲线用于诊断,最终排名采用固定命令集与固定评估种子得到的这些指标,避免通过放大奖励权重“刷高总奖励”。
  3. 指标与产物管线:调参 trial 强制使用本地 TensorBoard writer;训练脚本接受服务端生成的明确输出目录与奖励配置文件,保存 env.yaml、Agent patch、checkpoint、ONNX 和评估结果。服务通过 TensorBoard EventAccumulator 增量读取 scalar 并写入 SQLite,曲线 API 按 LTTB/桶聚合降采样;不依赖脆弱的控制台正则解析指标。
  4. 独立评估与评分:增加无探索噪声的评估入口,使用同一组站立、前进/侧移、转向和组合速度命令,对每个 rung 的 checkpoint 运行相同场景。速度目标内部按线速度/角速度误差 80/20 合并;六个顶层目标按已确认的 35% / 20% / 15% / 15% / 10% / 5% 聚合。对所有“越低越好”的原始指标使用创建 session 时冻结的基线尺度 scale=max(abs(baseline), physical_floor),计算并裁剪相对改善 (baseline-current)/scale;跌倒率不得高于基线 +2%,速度误差不得恶化超过 5%,否则该 trial 不可晋级。输出原始指标、各目标改善、总分和 3-seed 均值/离散度,确保后续新增 trial 不会改变旧 trial 的分数。
  5. DeepSeek Agent 与数值搜索协作:采用 PydanticAI 的 OpenAI-compatible provider 连接 deepseek-v4-flash,以严格类型的 RewardProposal 返回最多 4 项参数 patch、依据、预期影响和置信度;优先使用模型 JSON/structured-output 能力,能力探测失败时退回 PydanticAI 的 prompted JSON + 本地 Pydantic 校验,不授予 Agent 任何 shell、文件或网络工具。Optuna study 记录完整参数/分数并执行 successive-halvingAgent proposal 作为 enqueue/fixed trial 进入 study,只有显式启用 fallback 时才由 Optuna sampler 代提候选。模型使用低温度、60 秒超时和最多 2 次结构化修复;每次仅发送最多 12 个 trial 摘要、每条曲线最多 64 个降采样点,并记录脱敏 prompt hash、模型名、token usage、批准操作与最终 patch。服务对输出执行有限数值、符号、边界、最大步长、重复配置和高风险组合校验,校验失败要求 Agent 修正,不能静默执行。
  6. session 状态机:基线自动运行 → 短预算 trial → 固定评估 → Agent 建议 →(自动批准或进入 awaiting_approval)→ 下一 trial → successive-halving 晋级 → 最佳配置复核。逐轮审批支持接受、拒绝并附反馈、手动修改后接受;暂停不杀死已完成数据,停止会终止当前进程组。完成后把最佳 reward patch 保存为不可变命名 preset,并提供“从 preset 新建普通训练/新 tuning session”、导出 JSON、下载/导入 ONNX;不写回 velocity_env_cfg.py
  7. 默认 RTX 5080 预算:12 个唯一配置(含基线)、4096 个并行环境、GPU 0;所有配置先训练 300 iterations,前 4 名从自身 checkpoint 续训到 900,前 2 名续训到 2000,总量约等于 4.1 次完整 2000-iteration 训练。连续 4 个建议无显著提升时提前停止;trial 数、环境数和各 rung 可在 4–20 / 合法服务范围内调整。搜索期固定训练 seed 控制方差,晋级候选使用 3 个固定评估 seed 复核。
  8. 独立监控网页:新增 Vite 多页面入口 tuning.html,从现有训练面板用新标签页打开。页面采用 TensorBoard 风格的 run 选择、平滑、缩放、悬浮值、标签过滤和多 trial 叠加图,并增加 Agent 决策时间线、API 连通性测试、审批卡片、参数 diff、排行榜、暂停/恢复/停止、preset 导出及最佳 ONNX 下载/导入。新标签页 URL 只携带 session ID;训练服务 token 通过同源、校验 origin 的一次性 postMessage 交接并仅存于新标签页 sessionStorage,失败时回退到手工输入,绝不放入 query/hash。“导入最佳策略”由 dashboard 向仍打开的 workbench 发送同源消息,workbench 使用自身 client 下载并调用现有 onPolicyReady;无 opener 时回退为文件下载。图表使用轻量 uPlot,不启动或 iframe 嵌入第二个 TensorBoard 服务。
  9. API 与落盘边界:新增 capabilities/Agent 测试、session 创建与详情、trial/metrics 查询、proposal 批准/拒绝、pause/resume/cancel、preset 列表/导出和最佳 artifact 下载接口;继续沿用现有 Bearer Token、Host/Origin 校验与 32 KiB 请求限制。SQLite 使用 WAL 和每线程连接,默认位于已忽略的 training_server/rl/logs/auto_tuning/tuning.sqlite3,trial 产物位于同目录的 session 子目录;API 永远只接受 ID,不接受客户端文件路径。启动时把遗留 training/evaluating 状态标记为 interrupted,从最后完整 checkpoint 显式恢复,不尝试盲目重连旧 PID。
  10. DeepSeek 配置:使用 DEEPSEEK_API_KEYMUJOCO_TUNING_AGENT_BASE_URL(默认 https://api.deepseek.com)和 MUJOCO_TUNING_AGENT_MODEL(默认 deepseek-v4-flash);可配置 timeout,但 API key 不提供 CLI 参数,避免进入 shell history。健康接口仅返回 configured/model/baseUrl,连接测试返回能力与脱敏错误,不返回 key 或完整供应商响应。未配置云端 key 时普通训练保持可用,tuning capability 明确显示不可用;自动模式不静默退回 Optuna,只有用户在 session 中显式勾选 fallback 才允许。

初始权重白名单如下;负项只能保持负号,正项只能保持正号。绝对边界与单轮 0.5×–2× 限制同时生效,实际启用前用基线 smoke test 校验量纲:

Reward term 当前值 允许范围 可关闭
track_linear_velocity 1.0 0.53.0
track_angular_velocity 1.0 0.252.0
body_orientation_l2 -1.0 -3.0-0.1
pose 1.0 02.5
body_ang_vel -0.05 -0.20
angular_momentum -0.025 -0.10
is_terminated -200 -400-50
joint_acc_l2 -2.5e-7 -2e-60
joint_pos_limits -10 -30-2
action_rate_l2 -0.05 -0.2-0.005
foot_gait 0.5 01.5
foot_clearance -1.0 -3.00
foot_slip -0.25 -1.00
soft_landing -1e-3 -5e-30
stand_still -1.0 -3.00
electrical_power(新增) 0 -5e-30

参数白名单限制为:线速度 std=0.251.0、角速度 std=0.351.2pose 三档 std 使用当前 Go2 数组的 0.5×–2× 缩放因子,walking/running threshold 分别为 0.050.5 / 1.02.5 且保持有序;foot_gait.period=0.40.8threshold=0.450.65foot_clearance.target_height=0.060.16;各运动相关 command_threshold=0.020.30。结构对象、函数名、传感器名、asset selector、步态 offset 和终止角度不开放。

Files to modify

关键修改与新增路径:

  • training_server/rl/src/tasks/velocity/velocity_env_cfg.py:挂载固定质量指标与可选能耗奖励项。
  • training_server/rl/src/tasks/velocity/config/go2/env_cfgs.py:Go2 参数默认值及白名单配置应用入口。
  • training_server/rl/src/tasks/velocity/mdp/metrics.py(新增)与 mdp/__init__.py:权重无关的六类质量指标。
  • training_server/rl/src/tasks/velocity/mdp/rewards.py:仅在现有函数无法覆盖白名单参数时补充实现;优先复用 mjlab 内置项。
  • training_server/rl/scripts/train.py:显式 run 目录、奖励 patch、checkpoint 续训和 TensorBoard 配置。
  • training_server/rl/scripts/evaluate.py(新增):固定命令/seed 的 checkpoint 评估与 JSON 结果。
  • training_server/rl/src/tasks/velocity/rl/runner.py:保持 checkpoint/ONNX 对应关系,必要时暴露最终 checkpoint 元数据。
  • training_server/tuning/(新增):schema/目标函数、SQLite storage、TensorBoard ingest、PydanticAI advisor、Optuna sampler 与 session orchestrator,避免继续膨胀单文件服务。
  • training_server/server.py:组合现有训练 manager 与 tuning manager,增加 /api/tuning/* 路由和启动配置。
  • training_server/tests/test_server.py 及新增 training_server/tests/test_tuning_*.py:API、状态机、存储、Agent 校验与 fake trainer 集成测试。
  • training_server/requirements.txt(新增)与 requirements-dev.txt:加入并固定经 Python 3.12 实测的 pydantic-ai-slim[openai]、Optuna 和 TensorBoard;保留 training_server/rl/requirements.txt 只承载 mjlab 训练栈,避免职责混杂。
  • web_platform/tuning.htmlweb_platform/src/tuning/(新增):独立监控入口、dashboard、uPlot 曲线、审批/参数 diff/排行榜。
  • web_platform/src/training/types.tsLocalTrainingClient.ts:调参 API 类型与方法;必要时按职责拆出 TuningClient.ts
  • web_platform/src/training/LocalTrainingPanel.tsx:创建 session 的基础入口及“在新网页打开”按钮。
  • web_platform/vite.config.ts:多页面构建入口;package.json / lockfile 增加 uplot
  • .gitignoreREADME.mdtraining_server/README.mdweb_platform/README.md:忽略本地状态/产物并记录安装、安全和使用流程。

Reuse

  • 复用 training_server/server.py 的 Bearer Token、loopback/CORS 限制、无 shell 参数数组、训练任务互斥、进程组取消和 ONNX 下载机制;tuning 与普通训练共享同一个 GPU 活动锁。
  • 复用 training_server/rl/scripts/train.py 的 tyro/dataclass 配置和现有 checkpoint resume 流程,新增 patch 应用层而不是改写源文件。
  • 复用 mjlab RewardManager 自动产生的 Episode_Reward/<term>MetricsManagerEpisode_Metrics/<term>TerminationManagerEpisode_Termination/<term>,以及 RSL-RL TensorBoard scalar writer。
  • 复用当前 mean_action_accfeet_slipbody_orientation_l2 等计算;能耗优先复用 mjlab 的 electrical_power_cost,不重复实现扭矩功率算法。
  • 复用 VelocityOnPolicyRunner.save() 的 checkpoint + policy.onnx 同步导出和元数据附加;晋级 trial 从自己的 checkpoint 恢复。
  • 参考已安装 mjlab 的 scripts/play.py / tracking evaluate 结构实现仓库内最小速度任务评估入口。
  • 复用 LocalTrainingClient 的鉴权/错误处理、LocalTrainingPanel 的连接信息与取消/策略下载交互,以及共享 ButtonBadgeTabsProgressBar 等 UI。
  • 当前前端没有路由器或图表库,故使用 Vite MPA 而非引入整套路由;图表仅新增面向大量 scalar 的 uPlot

Steps

  • 固化 Unitree-Go2-Flat 的 15 个现有 reward term schema:当前值、符号、上下界、启停规则、可调参数、每次最多 4 项、0.5×–2× 变化率和跨参数约束,并为能耗加入默认关闭项。
  • 增加权重无关的六类训练/评估指标,定义归一化方向、目标阈值、默认 35/20/15/15/10/5 聚合权重、失败/NaN/过早跌倒惩罚。
  • 扩展训练入口以接收服务生成的 patch 文件与明确 run 目录,支持同配置 checkpoint 晋级续训,并强制保存完整配置快照。
  • 实现固定命令集、固定 seed、无探索噪声的独立评估入口,产生可验证 JSON 与 TensorBoard scalars。
  • 实现 TensorBoard scalar 增量采集、SQLite schema/migration、曲线降采样及 session/trial/proposal/audit 持久化。
  • 实现 tuning orchestrator、successive-halving、共享 GPU 互斥、提前停止、崩溃恢复、暂停/取消和最佳产物选择。
  • 通过 PydanticAI OpenAI-compatible provider 接入官方 deepseek-v4-flash 和 Optuna study,实现环境变量密钥、连接/能力测试、脱敏上下文、结构化输出、重试/修复、超时、usage 审计与显式 Agent 不可用状态。
  • 实现自动批准与 awaiting_approval 两条状态路径,包括接受、拒绝反馈、手动修订后接受及完整审计记录。
  • 扩展 /api/tuning/*、健康信息、指标查询和最佳 ONNX 下载,并补齐 TypeScript 类型/客户端。
  • 新增 tuning.html TensorBoard 风格 dashboard 与现有面板的新标签页入口,完成曲线、筛选/平滑/缩放、trial 对比、Agent 时间线、审批、diff、排行榜和控制操作。
  • 添加 Python/TypeScript/组件/E2E 测试,更新依赖锁、忽略规则、安全说明和安装/使用文档。

Verification

  • 单元测试:参数 schema 与边界、目标分数、建议约束、状态转换、失败/取消/恢复、最佳 trial 选择、API 鉴权。
  • 集成测试:使用轻量 fake trainer 产生确定性 TensorBoard events/评估 JSON,并用 fake PydanticAI model 返回合法、越界、重复和畸形 proposal,完整跑通多 trial 调参而不依赖 GPU 或真实云端 API。
  • 前端测试:表单校验、轮询、曲线渲染、参数 diff、自动/审批分支、跨标签页无 URL 密钥交接、停止、preset 与最佳结果操作。
  • 真实训练 smoke test:在本地 RTX 5080 / GPU 0 上先用 256512 environments、1020 iterations 跑基线与 2 个 trial,验证 TensorBoard 指标、评估 JSON、checkpoint、ONNX、参数快照和数据库记录一一对应;再单独确认 4096 environments 不 OOM 后启用默认预算。
  • 确定性检查:相同 checkpoint + 相同命令/seed 的评估分数在容差内一致;改变 reward 权重不会直接改变固定质量指标的定义或归一化。
  • 恢复检查:分别在训练、评估、等待审批时重启服务;确认 session 从 SQLite 恢复且不会重复启动 trial,活动子进程能被停止。
  • 回归:npm run typechecknpm run lintnpm run testnpm run test:training-servernpm run buildnpm run test:e2e;具备依赖时执行 npm run lint:python
  • 安全检查:非法奖励名、符号翻转、越界/NaN/Inf、超大 patch、路径注入、重复 proposal、并发普通训练/session、伪造 artifact 路径和 Agent 超时均被拒绝或进入明确状态;API key 不出现在响应、日志、SQLite 或浏览器存储中。