在做智能体训练的时候,环境往往是最容易被低估的一环。很多项目里,训练环境是提前写死的:固定的地图、固定的任务、固定的奖励规则。模型在这样一套静态环境里刷了很多轮,成功率看着不错,但换一个场景立刻掉链子。Google AI 推出的 EnvHarness,核心思路就是把静态环境变成一个可以由程序动态调整的自适应训练世界,中间通过一层“可编程层”来控制环境怎么变化、什么时候变、变化幅度有多大。如果你也在做强化学习、多智能体训练或者 Agent 评测,这篇文章值得先花几分钟看完。
我先把话说明白:EnvHarness 并不是一个传统意义上“训练一次跑完一个环境”的工具,而是一套环境侧的抽象框架。它解决的问题不是“模型怎么学”,而是“环境怎么给”。同样是训练一个导航智能体,普通做法是把它丢进固定地图;EnvHarness 的定位是让你能编写一套环境规则,让导航地图在训练过程中自行演化,难度从简单到复杂,场景从单一到多样。下面按实际落地顺序拆一遍。
1. 静态环境最值得警惕的三个问题
1.1 模型记住了路径,而不是学会了策略
这是固定环境训练最典型的翻车现场。训练循环跑到中后期,智能体的累计回报看着越来越高,但打开评测结果会发现,它只是在当前环境里找到了一条反复能走的“套路”。把初始位置换一下,成功率瞬间下降;把障碍物位置挪一点,整套行为全部失效。
原因很好理解。环境一旦固定,存在大量可以被模型利用的静态线索。位置坐标、物体排列、奖励出现的地点,都变成了隐式的“作弊笔记”。模型不需要真正理解环境结构,只需要记住哪条路能拿到分数。这种问题在迷宫导航、表格操作、游戏 AI 里特别明显。
如果只做一轮固定环境的 Demo,这个问题很难暴露。因为训练和测试用的都是同一张地图,模型只要死记硬背也能拿到不错的分数。但一旦进入真实场景,或者换一个评测集,过拟合的问题会被迅速放大。这也是为什么越来越多训练方案开始强调环境多样性。
1.2 训练和评测环境不一致,成绩虚高
还有一种更隐蔽的情况:训练环境和评测环境虽然看起来是同一套代码,但初始化随机种子、障碍物生成规律、难度分布并不一样。训练时模型见过的是固定难度分布,评测时突然换成高难度场景,或者出现训练阶段从未见过的布局,结果自然不理想。
这不能完全怪模型。静态环境决定了模型只能从有限的样本里学规律。如果环境本身不提供足够多样的交互空间,再强的算法也没有办法凭空泛化。就像一个人只练过固定路线,突然让他走一条全新路线,他大概率会迷路,不是因为方向感差,而是因为练习内容太单一。
评测环境如果是人工构造的,还容易出现另一个问题:评测集本身不够大。人工写几十个场景很容易,但要覆盖真实世界长短尾分布就很难。环境侧需要一种机制,让场景能够按规则生成,而不是靠人肉枚举。
1.3 环境规则一旦写死,扩展成本很高
从工程角度来说,固定环境的维护成本也很高。每次想增加一个难度档位,就要修改环境代码;每换一种任务目标,就要重写一套状态转移逻辑。环境逻辑和任务逻辑纠缠在一起,后面做实验的人往往只能小步改动,不敢大改。
更麻烦的是,环境逻辑一旦写死,训练流程就跟着定型了。你很难在不改动训练框架的情况下,临时插入一条“当模型成功率超过阈值时,把地图扩大一圈”的规则。每次试验都要改代码、重新跑、再验证,实验周期被拉得很长。
自适应训练想解决的问题,正是先把环境的“规则层”抽出来。环境不再是训练循环里的一个常量,而是一个可以被程序持续更新的变量。
2. EnvHarness 的可编程层到底“可编程”在哪里
2.1 可编程层在训练架构里的位置
要理解 EnvHarness,先看它在整个训练流程里的位置。常规的智能体训练循环是:智能体在环境里执行动作,环境返回状态和奖励,智能体更新策略,然后继续下一轮。环境在循环里是一个固定的交互对象。
EnvHarness 的思路是在环境和训练器之间插入一个可编程层。这一层能读取智能体的训练反馈,比如回合奖励、成功率、任务完成时间,也能根据这些反馈去修改环境配置。环境不再是“训练脚本外面包了一层封装接口”,而是变成“一个可以按规则演化的动态对象”。
从工程上看,这就是环境侧从“类”变成了“生成器”。固定环境下,你拿到的是一个实例;可编程环境下,你拿到的是一个会根据输入输出不断生成新实例的流程。训练循环仍然可以和环境正常交互,但环境本身的生成逻辑已经交给上层规则控制。
2.2 环境动态化的三要素:状态、任务、奖励
可编程层具体控制哪些东西?我习惯归纳成三个要素:状态、任务、奖励。
状态控制的是环境的物理或逻辑布局。对导航任务来说,是地图大小、障碍物位置、起点和终点。对文本任务来说,是输入文本的句式结构、长度、领域。对机器人任务来说,是初始关节角度、目标位置、干扰大小。状态变了,智能体观察到的内容就会变,它必须学会在新状态下决策。
任务控制的是智能体需要完成的目标类型。同一个环境框架可以承载多种任务:从走到一个点,变成依次经过多个点,再到在规定时间内完成路线规划。任务变了,智能体学到的能力也会跟着变。固定环境下,任务目标通常写死在奖励函数里;自适应环境下,任务本身可以成为被调整的对象。
奖励控制的是反馈信号的设计。固定环境下,奖励公式通常写死在环境代码里;可编程环境下,奖励公式可以随训练阶段调整。比如前期更强调成功到达,后期更强调路径效率。奖励函数的调整直接影响策略优化的方向,也是环境可编程层里最需要小心设计的部分。
这三个要素组合起来,就形成了“环境空间”。EnvHarness 这类框架的价值不是帮你把某个具体环境调好,而是帮你建立一套能够在环境空间里自动移动的控制机制。
2.3 一个便于理解的类比:从固定考场到自适应考试系统
可以把传统训练环境理解成一场固定难度的线下考试。所有考生拿到同一套试卷,考完之后按分数排名。问题在于,这套试卷可能整体偏简单,也可能整体偏难,无法准确区分考生真实水平。
EnvHarness 的定位更像是一套自适应在线考试系统。系统先给你几道基础题,答对了加大难度,答错了降低难度。最后评估的不是某一次绝对分数,而是你能够达到的最高难度层级。训练过程也类似:模型先学会简单任务,环境根据表现逐步加压,直到模型暴露出能力边界。
这个类比不一定完全精确,但对理解核心思路很有帮助:环境的作用不是一成不变地提供交互,而是像一位有经验的教练,跟着学员水平调整训练内容。教练不会一上来就让初学者跑马拉松,也不会一直让老手练基础动作,而是根据实时反馈调节训练强度。
3. 自适应训练世界的运行机制
3.1 训练初期:环境不能上来就拉满难度
第一次接触自适应环境的时候,很多人最容易犯的错是把难度曲线设计得太陡。环境演进速度太快,模型还没来得及掌握当前难度下的基础策略,下一个场景又换成了新规则。训练曲线会出现明显波动,甚至从一开始就学不进去。
更稳妥的做法是先把“简单环境”跑稳。让智能体在固定且足够简单的地图里完成基本探索,确认动作空间、奖励信号、状态表示都没有问题,再把环境变化开关打开。这个过程不能跳。一个连基础任务都学不好的模型,放进自适应环境里只会让问题更复杂。
我刚接触这类框架时也走过弯路。第一次搭建闭环,我直接把地图大小、障碍物密度、任务数量三个维度同时打开,希望环境能自己演化得丰富一点。结果训练了两万步,成功率一直贴着地面,日志里环境配置每几百步就跳一次。后来把变化维度收敛到只有“地图大小”一项,训练才开始正常。
3.2 自适应不是随机变化,要有反馈闭环
环境变化必须有一个反馈闭环,否则它只是一个“随机环境生成器”。闭环大致是这样:智能体与环境交互一个批次,训练器更新策略,评估器计算当前指标,然后环境调节器读取指标,决定下一步环境怎么变。
这个闭环里最关键的是“调节信号”。它可以是回合平均奖励,可以是成功率,可以是任务完成时间,也可以是多个指标的加权组合。信号选择不同,环境演化的方向就会完全不同。如果只看奖励,模型可能找到一个环境漏洞;如果只看成功率,又可能忽略效率指标。
我建议在早期实验里至少保留两个信号:一个是任务成功率,一个是回合平均步数或耗时。前者看出不出结果,后者看效率是否同步提升。两个信号一起看,才能判断环境难度的上调是否真的带来了能力提升。
信号指标本身也要做平滑处理。单回合波动太大,直接用当前回合的成功率决定是否升级环境,容易误判。更常见的做法是取最近 N 个回合的平均值,或者用滑动窗口统计,让调节信号更稳定。
3.3 环境变化的节奏比幅度更重要
环境变化可以分成两个维度:变化幅度和变化频率。幅度管的是每次改动多大,频率管的是每隔多久改一次。我自己的经验是,幅度可以逐步加大,频率一开始一定要保守。
原因很简单:策略网络的参数更新需要一定数量的数据。环境改动太频繁,模型始终在追赶一个新目标,永远处于“还没学完就换题”的状态。比较合理的起点是每训练几百到上千个回合再评估一次环境是否要变,而不是每几十个回合就切场景。
在资源有限的情况下,宁可让环境变化慢一点,也要保证每次变化之后都能看到训练曲线重新稳定下来。判断“稳定”的方法也很直接:连续若干个评估窗口内,成功率不再大幅下降,平均步数不再异常拉长,就可以认为模型基本适应了当前环境配置。
4. 本地搭建一个最小自适应训练闭环
4.1 环境准备:系统、依赖、硬件
EnvHarness 属于环境侧框架,落地时通常跑在 Python 生态里,和常见的强化学习库配合使用。系统层面,Linux 服务器是最常见的运行环境,Windows 和 macOS 也能跑,但要注意路径和底层依赖的差异。
硬件方面,如果只是验证闭环逻辑,CPU 环境可以先跑小规模经典控制任务;如果要训练图像输入或者大规模并行环境,至少准备一张支持 CUDA 的显卡,显存大小取决于输入分辨率和并行环境数量。原始资料没有给出明确的官方最低配置,所以更实际的做法是先看框架依赖的深度学习库要求,再结合自己的任务设定。
如果你只有一台普通笔记本,不用着急。先把任务规模压缩到最小:小地图、低分辨率、短步数、少量并行环境。确认闭环逻辑正确之后,再上更大规模的机器。低配机器能跑通不代表适合批量训练,但至少能帮你验证核心设计。
4.2 最小样例:先让固定环境跑通
不管用什么框架,第一步都不应该直接跳到自适应逻辑。先写一个最简单的固定环境,跑通完整的“交互—学习—评估”循环。比如二维网格寻路,智能体从起点出发,走到终点,每成功一次计为正奖励,碰到障碍物或超出步数计为负奖励。
这一步验证的是最底层的东西:环境能不能被正确创建,动作能不能被环境接受,状态能不能返回,奖励信号能不能被训练器读取。这些如果出问题,后面所有环境自适应逻辑都没有意义。
固定环境跑通之后,还要顺手确认输出目录、日志格式、随机种子这些细节都能对齐。很多项目在固定环境阶段一切正常,一加入环境自适应就显得“不稳定”,其实问题出在日志格式混乱、随机种子没有隔离、输出目录互相覆盖这类工程细节上。
4.3 加入可编程层:让环境根据指标变化
固定环境跑通之后,再加环境变化逻辑。可以先写一个非常轻量的环境调节器:
if success_rate > threshold and avg_steps < limit: env_params["map_size"] += 1 env_params["obstacle_density"] += 0.1 reset_env(env_params)这段代码不是某个框架的官方 API,而是为了说明可编程层的基本形态:根据智能体的表现指标,修改环境配置,然后重置环境。真正的 EnvHarness 实现会把这种逻辑抽象成更通用的配置器和控制接口,但核心思路一致。
注意,这里不需要把环境设计得多么复杂。先控制一个维度,比如地图大小。等这个维度的自适应流程稳定之后,再增加障碍物密度、任务类型、奖励权重这些变化维度。
4.4 验证闭环是否正常工作
自适应闭环跑起来之后,最需要验证的不是“最终分数高不高”,而是环境确实在随指标变化。打开环境配置日志,检查训练步数到达哪个位置时地图开始变复杂,成功率是否在那个位置出现过拐点。
如果环境配置一直在变,但训练曲线没有任何变化,多半说明环境变化没有真正影响智能体的观察或奖励信号。这时候不要急着调策略网络,先确认模型能不能感知到环境状态的变化。检查状态编码里是否包含地图尺寸、障碍物位置、任务目标这些关键信息,再确认奖励函数是否真的随环境配置发生了改变。
还有一种容易忽略的情况:环境确实变了,但变化不够显著。地图从 5×5 变成 6×6,对模型来说几乎没有任何挑战提升。这种时候不是框架有问题,而是调节幅度设置得太小。
5. 关键参数和判断标准
5.1 环境变化频率
环境变化频率是最先要定的参数。频率太高,模型来不及适应;频率太低,环境长期不变,退化成静态训练。
建议起点:先以“评估窗口”代替固定回合数。收集最近 500 个回合的指标,达到阈值再改环境。这样环境变化速度会跟着模型水平自动调节,而不是机械地每隔固定步数切任务。
这里不要一上来就追求“动态评估窗口”。对所有指标先做固定窗口统计,跑通之后再考虑按模型水平动态调整窗口大小。复杂度是逐步加上去的,不是一开始就全部铺开。
5.2 难度调节规则
难度调节需要明确两个问题:哪些维度可以调,每次调多少。可以直接用表格列出来:
| 维度 | 起点设置 | 上调方式 | 下调方式 | 影响 |
|---|---|---|---|---|
| 地图尺寸 | 5x5 | 每次加 1 | 每次减 1 | 探索难度增大 |
| 障碍物密度 | 0.1 | 每次加 0.05 | 每次减 0.05 | 路径规划难度增大 |
| 任务目标数 | 1 个 | 同时要求经过 2 个点 | 回到 1 个点 | 任务组合复杂度增加 |
| 时间限制 | 充足 | 缩短到 80% | 恢复到原来值 | 策略效率要求提高 |
表格里的数据仅作为示例。实际参数要根据环境类型、模型容量、训练预算来定。关键是,每个维度都要能单独调节,并且调节之后重置环境不会把之前的训练优势全部清零。
如果环境重置会清空某些缓存或记忆,需要在设计时额外处理。比如导航任务里,环境地图换了之后,智能体之前的路径规划结果已经失效,必须从头探索。
5.3 成功阈值
判断“该不该升级难度”需要成功阈值。这个阈值不要拍脑袋定。先观察模型在静态环境下的表现上限,把阈值设在稳定表现之下一点点。比如静态环境下模型成功率能到 90%,那么阈值设在 85% 比较合理。这样既确认模型学会了当前难度,又不至于等太久。
阈值太低会导致模型还没掌握就升难;阈值太高会导致训练长时间停在同一难度。对新手来说,宁可先定低一点,让环境动起来,再逐步校准。
还有一个容易踩的坑:模型成功率可能是周期性波动的,前面几个窗口高,后面几个窗口低。如果阈值刚好卡在波动区间里,环境会在“上升—下降—再上升”之间反复切换。这种时候把窗口拉长一些,或者要求连续多个窗口都达到阈值,再触发难度升级。
5.4 资源占用和训练时长的判断标准
环境自适应不是零成本。每次环境变化之后,模型都需要重新适应,训练总时长通常比固定环境更长。这不是框架的问题,而是能力边界探索本身就要付出更多采样成本。
判断资源占用是否合理,主要看三条标准:第一,训练吞吐量是否稳定,环境重置和生成新配置不要让 CPU 占用成为瓶颈;第二,单次难度切换后训练曲线是否能在合理步数内恢复上升;第三,显存和内存占用不随环境复杂度无限增长,如果内存一直涨,优先怀疑环境实例没有正确释放。
如果训练时间超出预期,不要立刻怀疑环境自适应逻辑。先对比同任务在固定环境下的训练时长,看看差距。如果差距在 1.5 倍以内,属于合理范围;如果拉到 3 倍以上,就要检查是不是环境切换太频繁,或者每次切换后模型都在重新学习旧技能。
6. 批量实验时如何组织配置、日志和任务队列
6.1 配置先行:把环境变化规则抽成配置文件
单个任务跑通不算完,做研究或工程落地还要跑批量实验。批量实验最容易出问题的是配置管理。不要在每个实验脚本里写死环境参数,把环境变化的初始设置、变化维度、阈值、频率全部抽到配置文件里。
一份 YAML 配置可以长这样:
env: initial_map_size: 5 obstacle_density: 0.1 max_steps: 200 adaptive: enabled: true metrics: ["success_rate", "avg_steps"] success_threshold: 0.85 difficulty_change_interval: 500这段配置同样只是示例,但思路值得参考:环境初始状态、自适应规则、切换条件分开管理。换实验时只改配置文件,不碰代码逻辑,批量实验的复现性会好很多。
配置文件的另一个好处是方便做版本管理。每次实验跑完,把配置文件连同结果一起归档。后面复盘时,只要看配置 diff,就能知道两组实验之间到底改了哪些环境参数。这比翻代码提交记录要直观得多。
6.2 日志记录:环境快照和智能体指标一起存
自适应环境的训练日志比静态环境复杂,因为环境本身是随时间变化的。只看训练曲线,会出现“某一轮成功率突然下降”的现象,但如果没有环境变化的日志,你就很难判断这是模型问题还是环境难度提升导致的。
建议把环境快照和智能体指标写入同一条日志。每条日志至少包含:当前训练步数、环境配置版本、地图尺寸、障碍物密度、任务数量、本轮平均奖励、成功率、平均步数。后面排查问题时,只要把环境配置版本对齐,就能知道成功率下降到底发生在哪次难度升级之后。
日志本身也要定期做持久化。不要只在终端打印几条信息,要写到按时间戳命名的文件里。训练跑崩了,终端输出可能已经滚屏丢失,但文件日志还在,排查问题就有据可查。
6.3 任务调度:先单进程,再并发,最后上训练平台
批量实验的调度顺序也有讲究。先确认单个进程能稳定跑完一次完整实验,再开多进程并发。并发时要注意随机种子隔离、输出目录隔离、日志文件隔离,否则多个实验写同一个文件,日志会互相覆盖。
如果实验规模更大,可以考虑接入任务队列或训练平台。这时候并不需要自己写一套分布式框架,先把一次实验做成可复用的命令行入口,输入参数是配置文件路径,输出是日志目录和结果文件。只要做到这一步,后面接调度工具会非常顺。
并发数量也要控制。不是并发越高越好,环境自适应逻辑里通常包含大量环境生成和重置操作,这些操作在 Python 里往往受 GIL 限制,多进程并行比多线程并行更有效。我建议先开 4 个并发做一组压测,看 CPU 和内存占用是否稳定翻倍,再决定是否继续加大。
7. 常见问题、误判和排查顺序
7.1 训练曲线一直不涨
训练曲线不涨,最常见的不是模型不行,而是环境变化节奏和模型学习节奏错位。先看日志:环境配置是不是在频繁变化?如果每隔几百步就改一次地图,模型每次都在适应新场景,曲线自然很难平滑上升。
解决办法是降低难度变化频率,或者把难度阈值调高一点。先让模型在一个难度档位上充分收敛,再放行下一档。如果已经频繁切换很久,可以先暂停自适应逻辑,把当前环境固定下来训练一段时间,看曲线能不能恢复。
还有一种情况是环境配置变化速度正常,但模型状态表示没有包含环境变化的信息。模型根本不知道地图变大变小,自然无法针对新环境调整策略。这种时候问题不在训练逻辑,而在状态编码。
7.2 环境切换后训练崩溃
这里说的崩溃不是程序崩溃,而是训练指标出现断崖式下跌。如果环境每切换一次,成功率就掉到接近零,说明难度变化幅度太大。模型在旧环境学到的策略,在新环境里完全不通用。
可以把变化幅度减小,或者给环境切换加一个“过渡期”。过渡期内环境不直接切到全新配置,而是保留一部分旧环境特征,让模型慢慢适应。比如新地图尺寸更大,但障碍物密度保持和旧环境一致,让模型先适应较大的探索空间,再逐步增加障碍物复杂度。
另一个思路是环境升级之后,允许一定次数的“探索回放”。把旧环境的一些样本重新放进训练集,让模型在适应新环境的同时,不彻底忘记旧策略。这样即使新环境反弹,模型也有缓冲空间。
7.3 改了环境参数却没有效果
环境参数修改后,训练曲线没有任何变化,这种问题的排查优先级要高于策略调参。先确认环境参数是否真的传到了环境实例里,再确认模型观察里是否包含环境变化的信息。
如果模型根本看不到地图尺寸或障碍物位置,环境再怎么变,模型都不会有反应。很多这类问题都出在状态编码和参数传递上,而不是策略算法本身。检查路径:环境配置修改了没有,重置逻辑是否读取了新配置,状态生成是否使用了新配置,奖励计算是否依赖新配置。链路里任何一环断掉,环境变化都不会生效。
我遇到过最隐蔽的一种情况:环境配置确实更新了,但环境的缓冲区和缓存没有清空,模型仍然在观察旧场景的图像。表面看地图已经变了,实际返回给模型的状态还是上一轮的残留数据。
7.4 通用排查顺序
我把常用的排查顺序整理成四步:第一步看现象,确认是训练指标不涨、训练崩溃还是环境不生效;第二步看输入,检查环境配置、状态编码、任务定义是否正确;第三步看资源,确认 CPU、内存、显存没有达到瓶颈;第四步看参数,再调难度阈值和变化频率。这个顺序能覆盖大多数问题,不用一上来就怀疑模型算法。
排查过程中最好保持每次只改一个变量。很多人遇到曲线异常,同时把成功率阈值、环境变化频率、地图尺寸步进值全改一遍,结果验证的时候根本分不清是哪个改动起了作用。环境自适应本来变量就多,更要控制单次实验的改动范围。
8. 落地建议:一次只加一个变化维度
8.1 不是所有训练任务都需要环境自适应
先泼一盆冷水:环境自适应不是银弹。如果任务模式单一、数据分布稳定、当前静态环境已经能满足需求,不必为了“自适应”而自适应。它更适合目标开放、难度层次多、几乎不可能提前枚举所有场景的任务,比如通用导航、网页操作、具身智能、多智能体协作。
判断标准很简单:如果你能提前枚举出训练需要的所有难度档位,并且不觉得维护成本高,那就继续用静态环境,把精力放在策略模型上。只有当场景数量大、变化维度多、人工设计环境已经跟不上需求时,EnvHarness 这类方案才真正值得投入。
8.2 分阶段推进的三个里程碑
第一个里程碑:固定环境能跑。这个阶段目标是确认环境定义、动作空间、奖励函数、训练循环全部正确。至少跑三轮实验,确保结果稳定可复现,再进入下一步。
第二个里程碑:一个维度能自适应。只打开一个环境变化维度,比如地图大小,跑完一次完整训练。确认环境确实随着指标变化、训练曲线逐步上升、日志能够回溯到每一次环境切换。
第三个里程碑:环境配置、日志、参数全部外部化。配置文件统一管理,日志完整记录,参数可以通过命令行覆盖。这时再增加任务类型、奖励权重、多智能体机制这些复杂功能。
三个里程碑之间不要跳。每次跳级都会引入新的变量,一旦出现问题,很难判断是环境自适应逻辑的问题,还是新功能引入的问题。
8.3 遇到瓶颈时先承认环境,别总怀疑模型
做强化学习训练,遇到曲线不涨,第一反应通常是“模型是不是不够强”“学习率是不是不对”。但在自适应环境里,这类问题经常会转嫁成环境问题。环境切换太快、难度提升太猛、反馈信号不稳定,都可能让一个本来正常的模型持续表现不佳。
排查时不要执着于调模型。先看环境,再看数据,最后看参数。我曾经花了一整天调策略网络结构,最后发现环境配置版本号在日志里根本没对齐,两次实验用的根本不是同一套环境逻辑。那种时候就意识到,工程上的小疏漏比算法问题更隐蔽。
8.4 最终检验:换一批新鲜环境配置看泛化
训练结束后,一定不要只用最后一轮环境配置做评测。要准备一批训练过程中从未出现过的环境配置,把环境初始状态、障碍物生成规则、任务目标都换掉,看模型在新环境上的表现。
如果模型在全新环境配置下也能保持较高的成功率,说明自适应训练真的让它学到了泛化能力,而不是又记住了某几套特定地图。如果只是训练时见过的那几套配置表现好,换环境就崩,那就要回头检查环境空间的覆盖度是不是还不够。
EnvHarness 这类方案的真正价值,不是让环境变复杂,而是让环境变化这件事变得可控制、可观测、可复现。把它当成一个环境侧的实验平台来用,比把它当成一个“自动生成无限任务的黑盒”要靠谱得多。你先用最小的环境变化跑通一次完整训练,后面的路会顺很多。