Environment Evolution:让终端环境持续变难,怎样避免把任务改坏?
一个值得追问的问题:给 Agent 准备训练环境时,怎样区分“任务增加了能力要求”和“任务变得更含糊、更脆弱”?Environment Evolution 提供了一个研究入口:沿着环境谱系设计难度变化,再控制模型接触这些环境的顺序。本文先列出论文的关键证据,随后用原创数值例子分析难度建模、课程调度与验证盲区,并讨论无需训练 GPU 就能开展的实验。
- 论文:Environment Evolution for Terminal Agents
- 作者:Zhiyuan Fan 等,Tencent Hunyuan Team
- 阅读版本:2026-09-03,arXiv v1
- 全文:HTML · PDF
1. 方法与主要结果
方法按场景新颖性、技能稀有性、执行长度演化环境;先循环审查计划,再循环修改和验收环境。验收包含参考解、空操作负例与质量规则。EL(Evolution-Lineage)调度器沿谱系推进:每组 8 次 rollout,成功率须严格超过 6/8。生成无需目标策略的在线失败轨迹,但仍调用强模型。§3–4
实验采用 RFT 后的模型、GRPO、200 步 RL、Claude Code harness 和 Terminal-Bench 2.1 Verified。Figure 7 报告的是沿训练过程选出的峰值;摘要对应提升为 14.4、18.0 个百分点。§5
| 模型 | Environment Evolution 峰值 | Co-evolution 峰值 | Ensemble 峰值 |
|---|---|---|---|
| Qwen3.6-27B | 71.5% | 62.9% | 60.0% |
| Qwen3.6-35B-A3B | 64.9% | 55.1% | 52.8% |
另外,Table 1 的 length 单步演化使成功率平均下降 7.1 个百分点。v1 附录仅说明未来会补充细节,不能据此补出 GPU 总预算。Table 1 · 版本说明
下面的任务、概率、代码草图和改进方案均为教学构造或我的分析,不是论文实验的复现数据。
2. Motivation:为什么要关心环境的“学习窗口”
假设一个二值奖励任务,每次采样 8 条轨迹。有三种很不一样的局面:
| 成功轨迹数 | 可以直接观察到什么 | 下一步值得检查什么 |
|---|---|---|
| 8 | 当前模型在这组采样中全部成功 | 是否需要更具区分度的任务 |
| 4 | 同题下存在成功与失败 | 哪些决策造成结果差异 |
| 0 | 当前预算下全部失败 | 能力不足、预算不足,还是环境有问题 |
把环境数量翻倍,未必能增加第二类样本。大量简单任务可能继续全对;机械拼接任务又可能让模型全部失败。
以最简化的组内标准化为例,忽略其他正则项,令
\[ A_i=\frac{r_i-\bar r}{\operatorname{std}(r)+\epsilon}. \]
当 8 个奖励均为 0 或均为 1 时,所有分子都是 0,这一组的终局奖励无法区分轨迹优劣。若 4 条成功、4 条失败,按总体标准差计算,均值为 0.5、标准差为 0.5;忽略很小的 \(\epsilon\),成功轨迹得到 \(+1\),失败轨迹得到 \(-1\)。
这只是组内相对奖励的教学解释,不表示全失败样本对任何训练算法都完全无用。过程奖励、其他辅助目标或跨组比较可能改变结论。
值得研究的对象因此变成:在给定策略、工具和预算下,哪些环境能持续产生可区分的结果? 这里的“难度”至少有三个层面:
- 任务本身需要什么能力;
- 某个模型掌握这些能力的程度;
- 执行器、上下文和资源预算是否允许它发挥能力。
把这三层混在一起,就容易把依赖安装失败当作推理失败,把更长输出当作更强能力。
3. 难度建模:有启发性的分解,不是普遍定理
理解论文的三个方向,可以先构造一个简化的参考分布模型。设任务目标为 \(g\),高层执行分成 \(L\) 个阶段。第 \(t\) 个阶段具有场景 \(\sigma_t\),要求技能 \(\kappa_t\)。用我们人为指定的参考频率 \(q\) 定义一个分数:
\[ S(\xi)=\sum_{t=1}^{L} \left[-\log q(\sigma_t\mid g) -\log q(\kappa_t\mid\sigma_t,g)\right]. \]
这个教学分数与论文的建模思路对应:少见场景、少见技能和更多阶段都可能提高分数。但这里没有假装知道真实的世界知识概率,也没有把它直接称作模型失败概率。
3.1 一次可以手算的变化
设原任务只有两个阶段,每个阶段的场景频率为 0.5,条件技能频率也为 0.5。采用自然对数,单位为 nat:
\[ S_0=2[-\log0.5-\log0.5] =2\log4\approx2.773. \]
三个独立修改分别得到:
| 教学修改 | 其余条件 | 新分数 | 相对原分数 |
|---|---|---|---|
| 一个场景频率从 0.5 改为 0.25 | 技能、长度不变 | 3.466 | +0.693 |
| 一个技能频率从 0.5 改为 0.25 | 场景、长度不变 | 3.466 | +0.693 |
| 加入一个频率均为 0.5 的阶段 | 原两个阶段不变 | 4.159 | +1.386 |
这个例子解释了三种操作为何可以放进同一分数框架,却还不能证明“第一种操作必然让真实模型更难”。
例如,新场景虽然少见,但技能恰好更简单;又例如,模型可以用一个 SQL 查询合并完成原本写成三步的计划。若评估者仍按旧的阶段数计分,就会高估新任务的难度。
3.2 为什么不能把概率分解当作严格推导的终点
对一般的高层事件序列 \(z_1,\ldots,z_L\),链式法则给出的是
\[ p(z_1,\ldots,z_L\mid g) =\prod_{t=1}^{L}p(z_t\mid z_{<t},g). \]
把历史条件压缩为“当前场景与目标”,需要额外的表示充分性或独立性假设。若前一步是否保存备份,会影响后一步能否恢复数据库,历史显然不能随意删除。
另一个问题是:低概率不必然等于难。 一个随机文件名极少出现,但读取这个文件未必需要新技能;一种罕见的等价 SQL 写法概率低,也不意味着任务只有这条解法。
因此,我更愿意把这种分解看成组织环境编辑的启发式坐标。要声称它衡量了难度,还应检验:
- 不同估计者给出的排序是否一致;
- 分数能否预测未见模型上的成功率;
- 控制运行预算后,关系是否仍然存在;
- 同一任务存在更短合法解时,分数是否仍然有效。
这些问题不需要先跑一次大规模 RL 才能研究。
4. 用一个数据库任务解释“演化”应该改什么
以下是原创任务,不来自论文数据集。
种子环境包含一个 SQLite 数据库,有一张订单表:
| order_id | user_id | amount |
|---|---|---|
| A | U1 | 100 |
| B | U1 | 50 |
目标是生成用户消费汇总,U1 的正确结果为 150。任务要求保留原始订单表。
可以设计三条分支:
| 分支 | 对任务的修改 | 真正增加的要求 |
|---|---|---|
| 场景分支 | 输入改为数据库和 JSON 混合来源,提供完整格式说明 | 在新的数据布局中完成原有汇总 |
| 技能分支 | 加入分期退款记录,计算净消费 | 正确处理关联与聚合粒度 |
| 长度分支 | 汇总前先恢复损坏索引、验证来源,再写入结果并做幂等检查 | 管理跨步骤依赖和状态变化 |
这三个分支只是设计意图。混合来源可能顺带增加解析技能;退款任务可能顺带增加步骤数。因此实验中还要记录实际变化,不能仅凭生成 prompt 的标签就声称控制住了变量。
4.1 第一层循环:先评审一个可检查的计划
我会把计划写成下面的结构,而不是一句“增加复杂度”:
1 | |
审查时首先检查逻辑,而不是让 Agent 先花钱跑:字段是否定义充分?退款金额是否可以超过订单金额?是否允许部分退款?重复退款记录代表重试事件还是两次真实退款?
如果问题没有确定答案,应先补任务约束。否则参考解和 verifier 可能共享一个未写明的假设,把另一种合理答案判错。
4.2 第二层循环:用执行证据验收改动
在独立沙箱中创建数据库,执行参考解,运行检查,再销毁环境。参考解成功只能证明“至少这条路径被测试接受”,还要构造负例。
现在给订单 A 加一笔 20 的退款,正确净消费应为
\[ 100+50-20=130. \]
验收矩阵可以这样写:
| 候选行为 | 预期结果 | 为什么需要它 |
|---|---|---|
| 正确扣除退款,得到 130 | 通过 | 基本可解性 |
| 什么也不做 | 拒绝 | 防止初始状态已满足或测试空转 |
| 忽略退款,得到 150 | 拒绝 | 新要求确实被检查 |
| 重复扣除退款,得到 110 | 拒绝 | 检查关联或去重错误 |
| 得到 130,但删除原始订单 | 拒绝 | 检查状态保护要求 |
| 用不同 SQL 或 Python 算法得到合法结果 | 通过 | 避免绑定参考实现 |
空操作失败是最低限度的检查,不是验证器可靠性的充分条件。 它抓不到“做了一半就被判成功”,也抓不到“正确答案被拒绝”。
一个有价值的开源扩展是把错误解生成系统化:每新增一项需求,就必须增加一种针对该需求的错误行为,并要求测试能够区分它。代价是需要维护错误变换;风险则是过度拟合已有错误类型,所以应当留出未参与开发的变换。
5. EL 调度:生成顺序和学习顺序是两回事
环境可以提前准备,但接触环境的时机仍然取决于当前模型。用一个教学谱系演示前述严格阈值:
1 | |
| 当前环境 | 8 次采样的成功数 | 下一步 |
|---|---|---|
| E1a | 4 | 留在 E1a |
| E1a | 6 | 仍留在 E1a:0.75 没有严格超过 0.75 |
| E1a | 7 | 进入同代 E1b |
| E1b | 8 | 本代结束,进入 E2a |
| E2a | 0 | 留在 E2a;值得检查是否跨度过大 |
这里的演示忽略了多条谱系之间的全局采样,也没有擅自补出论文未给定的回退实现。
5.1 八次采样会不会让晋级过于偶然?
以下是我的统计分析。假设同一任务每次尝试独立、真实成功率为 \(p\)。一次检查至少成功 7 次的概率为
\[ P(\text{晋级})={8\choose7}p^7(1-p)+p^8. \]
当 \(p=0.75\) 时,
\[ P(\text{晋级}) =8(0.75)^7(0.25)+(0.75)^8 \approx0.3671. \]
也就是说,真实成功率恰好 75% 的模型,在某一次检查中也有约 36.7% 的概率达到晋级条件。这不是程序错误,而是有限样本阈值的自然结果。
但实际 rollout 可能因共享缓存、同一故障或相似采样路径而相关,不能机械套用独立假设。可研究的改进包括滑动窗口、连续两次达标、置信下界以及失败后的短暂回访。它们可能减少偶然晋级,也可能让课程反应变慢、增加推理开销。
验证时应比较相同 rollout 或 token 预算下的训练效果与课程推进速度,不能只比较相同更新步数。更贵的调度器很容易在“步数相同”时暗中使用更多计算。
6. 实验结果支持到哪里
开头的结果给出了这套系统在所报告训练设置下的正向证据。但阅读时还要分别回答几个问题。
第一,峰值不是末步成绩。 每隔一段时间挑 checkpoint,峰值受评测次数和选择规则影响。复现实验应同时报告末步、选定 checkpoint 的规则,以及多个训练随机种子的变化。
第二,模型成绩上升不等于任意环境修改都有用。 应区分完整系统的贡献和某个模块的贡献。若要研究计划审查,就固定调度器;若要研究调度器,就固定环境池。
第三,成功率下降只是“变难”的一种观测。 前面的数据库任务如果因为磁盘满而失败,成功率也会下降。把错误归为策略错误、依赖错误、超时、验证器错误和任务歧义,才能解释难度的来源。
第四,轨迹更长的含义需要拆开。 更长可能来自新增依赖、合理检查、无效重试,也可能来自更啰嗦的文字。建议分别记录完成的有效子目标、失败工具调用、重复动作与恢复步骤,而不是只统计 token 和 turn。
也不要把这里的分数直接与另一篇 SETA 精读横向排序。不同 benchmark 版本、基础模型、harness 和预算组合,没有形成可以直接比较的方法实验。
7. 最值得借鉴的贡献,以及还缺的证据
在我看来,最有价值的是把“增加难度”变成一个可以审核的研究对象:明确编辑意图,保留父子环境关系,验证编辑结果,再研究何时使用这些环境。 环境谱系使失败不再只是一个孤立数字,而能追问到“哪次修改改变了什么”。
还要注意方法适用范围:论文的种子筛选仍使用 Claude Opus 5 的成功率和交互轮数,所称 off-policy 主要针对后续演化无需目标策略失败轨迹,并非整条数据生产链与模型无关。§5.1
我的分析是,一个生成器偏好某类工具,参考解采用某种实现,质量评审习惯某种任务表达,都可能塑造最终分布。
下面是值得继续验证的具体问题:
| 问题 | 可以做的改进 | 新的代价或风险 | 验证方式 |
|---|---|---|---|
| 演化分支越来越同质 | 对技能图和状态变化做去重 | 去重规则可能误删有价值变体 | 留出模型上的覆盖与成功率 |
| Oracle 与 verifier 共享错误假设 | 分离实现者并加入随机实例 | 更多开发与执行成本 | 人工审查和留出错误类型 |
| 难度跳跃造成全失败 | 限制单次新增依赖,生成中间节点 | 谱系更长,维护量增加 | 首次可解率、部分成功组比例 |
| 低成功率来自执行故障 | 将基础设施失败单独标注 | 分类器自身可能不准 | 抽样人工复核与重跑一致性 |
| 有限采样导致课程不稳定 | 使用置信区间或重复检查 | 调度变慢、推理成本更高 | 同预算下的效果与晋级方差 |
这些是由方法引出的研究提案,尚不能当成已经获得训练收益的结论。
8. 没有训练 GPU,怎样做一个有说服力的项目
可以把目标收窄为:在固定生成预算下,产出更多有效、可区分且可复现的演化环境。 第一个版本只做 SQLite、JSON 或文件处理,不需要复刻整个终端 benchmark。
8.1 最小产物
每个环境发布一个版本化包:
1 | |
把“修改了哪些文件”与“增加了哪些能力要求”分别记录。文件改得多,不自动代表技能变化大。
8.2 三条对照流程
- 直接让生成器把任务变难。
- 结构化计划加基本可执行验证。
- 相同生成器与预算,加错误解测试和随机实例验证。
首先在同一批种子上成对比较。报告每个种子的结果,按种子家族划分开发与留出部分,不能把同一父任务的孩子分别放进调参集与测试集后当成独立泛化。
建议至少测量:环境重建率、合法解误拒率、错误解误接受率、每个合格环境的成本,以及跨运行的一致性。有少量 API 预算时,再补充固定 agent 和预算下的难度变化。
一个原创的试跑预算例子:5 个种子、3 条流程,每条流程产出一个后代;使用 2 个模型,每个环境运行 2 次,则后代评测需要
\[ 5\times3\times2\times2=60 \]
次 rollout。另给 5 个种子做同样的模型评测,需要 20 次,总计 80 次。这个数字不含生成、修复和失败重试,也不能把一次 rollout 等同于一次模型调用。
先做这轮试跑,记录真实 token、容器时间和失败比例,再决定规模。完全没有 API 预算时,也可以先发布程序化任务生成器与验证器压力测试,明确保留“对真实 Agent 的难度变化”这一待验证项。
8.3 结论边界就是项目质量的一部分
离线验证能够支持“环境可重建”“测试能区分某类错误”“在固定预算下更难”等结论。要进一步说“更适合学习”,仍需在相同训练资源下比较训练结果。
因此,一个扎实的阶段成果可以是:找到一类反复出现的验证漏洞,给出独立错误样例,证明修复没有增加合法解误拒,并发布可复现的环境谱系。等到有训练资源,再检验这些改进是否转化为学习收益。
读完这篇论文,我更关注的不是一共造出多少任务,而是三项能落到证据上的问题:改了什么,怎样知道改对了,以及模型什么时候适合学习它。
点赞与评论
喜欢这篇文章?点个赞,或留下你的想法。登录 GitHub 后即可参与。
如果评论无法加载,请检查网络连接后刷新页面。