Environment Evolution:让终端环境持续变难,怎样避免把任务改坏?

一个值得追问的问题:给 Agent 准备训练环境时,怎样区分“任务增加了能力要求”和“任务变得更含糊、更脆弱”?Environment Evolution 提供了一个研究入口:沿着环境谱系设计难度变化,再控制模型接触这些环境的顺序。本文先列出论文的关键证据,随后用原创数值例子分析难度建模、课程调度与验证盲区,并讨论无需训练 GPU 就能开展的实验。

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\)。

这只是组内相对奖励的教学解释,不表示全失败样本对任何训练算法都完全无用。过程奖励、其他辅助目标或跨组比较可能改变结论。

值得研究的对象因此变成:在给定策略、工具和预算下,哪些环境能持续产生可区分的结果? 这里的“难度”至少有三个层面:

  1. 任务本身需要什么能力;
  2. 某个模型掌握这些能力的程度;
  3. 执行器、上下文和资源预算是否允许它发挥能力。

把这三层混在一起,就容易把依赖安装失败当作推理失败,把更长输出当作更强能力。

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
parent: orders_v0
intent: require_refund_aggregation
new_requirements:
- deduct each refund exactly once
- retain original orders
unchanged_requirements:
- aggregate by user_id
artifacts_to_change:
- task.md
- seed.sql
- reference.py
- tests/test_result.py
expected_failure_modes:
- ignore_refunds
- duplicate_join

审查时首先检查逻辑,而不是让 Agent 先花钱跑:字段是否定义充分?退款金额是否可以超过订单金额?是否允许部分退款?重复退款记录代表重试事件还是两次真实退款?

如果问题没有确定答案,应先补任务约束。否则参考解和 verifier 可能共享一个未写明的假设,把另一种合理答案判错。

4.2 第二层循环:用执行证据验收改动

在独立沙箱中创建数据库,执行参考解,运行检查,再销毁环境。参考解成功只能证明“至少这条路径被测试接受”,还要构造负例。

现在给订单 A 加一笔 20 的退款,正确净消费应为

\[ 100+50-20=130. \]

验收矩阵可以这样写:

候选行为 预期结果 为什么需要它
正确扣除退款,得到 130 通过 基本可解性
什么也不做 拒绝 防止初始状态已满足或测试空转
忽略退款,得到 150 拒绝 新要求确实被检查
重复扣除退款,得到 110 拒绝 检查关联或去重错误
得到 130,但删除原始订单 拒绝 检查状态保护要求
用不同 SQL 或 Python 算法得到合法结果 通过 避免绑定参考实现

空操作失败是最低限度的检查,不是验证器可靠性的充分条件。 它抓不到“做了一半就被判成功”,也抓不到“正确答案被拒绝”。

一个有价值的开源扩展是把错误解生成系统化:每新增一项需求,就必须增加一种针对该需求的错误行为,并要求测试能够区分它。代价是需要维护错误变换;风险则是过度拟合已有错误类型,所以应当留出未参与开发的变换。

5. EL 调度:生成顺序和学习顺序是两回事

环境可以提前准备,但接触环境的时机仍然取决于当前模型。用一个教学谱系演示前述严格阈值:

1
2
3
第 1 代:E1a → E1b
第 2 代:E2a → E2b
第 3 代:E3a
当前环境 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
2
3
4
5
6
7
8
orders_refund_g1/
task.md # 给求解者的完整要求
seed.sql # 可重建的初始状态
reference.py # 独立参考实现,不对求解者暴露
tests/ # 验收逻辑,与执行沙箱隔离
mutations/ # 故意错误的候选解
lineage.json # 父环境、修改意图、随机种子
audit.json # 验收证据、成本、失败原因

把“修改了哪些文件”与“增加了哪些能力要求”分别记录。文件改得多,不自动代表技能变化大。

8.2 三条对照流程

  1. 直接让生成器把任务变难。
  2. 结构化计划加基本可执行验证。
  3. 相同生成器与预算,加错误解测试和随机实例验证。

首先在同一批种子上成对比较。报告每个种子的结果,按种子家族划分开发与留出部分,不能把同一父任务的孩子分别放进调参集与测试集后当成独立泛化。

建议至少测量:环境重建率、合法解误拒率、错误解误接受率、每个合格环境的成本,以及跨运行的一致性。有少量 API 预算时,再补充固定 agent 和预算下的难度变化。

一个原创的试跑预算例子:5 个种子、3 条流程,每条流程产出一个后代;使用 2 个模型,每个环境运行 2 次,则后代评测需要

\[ 5\times3\times2\times2=60 \]

次 rollout。另给 5 个种子做同样的模型评测,需要 20 次,总计 80 次。这个数字不含生成、修复和失败重试,也不能把一次 rollout 等同于一次模型调用。

先做这轮试跑,记录真实 token、容器时间和失败比例,再决定规模。完全没有 API 预算时,也可以先发布程序化任务生成器与验证器压力测试,明确保留“对真实 Agent 的难度变化”这一待验证项。

8.3 结论边界就是项目质量的一部分

离线验证能够支持“环境可重建”“测试能区分某类错误”“在固定预算下更难”等结论。要进一步说“更适合学习”,仍需在相同训练资源下比较训练结果。

因此,一个扎实的阶段成果可以是:找到一类反复出现的验证漏洞,给出独立错误样例,证明修复没有增加合法解误拒,并发布可复现的环境谱系。等到有训练资源,再检验这些改进是否转化为学习收益。

读完这篇论文,我更关注的不是一共造出多少任务,而是三项能落到证据上的问题:改了什么,怎样知道改对了,以及模型什么时候适合学习它。


Environment Evolution:让终端环境持续变难,怎样避免把任务改坏?
https://kissshhot.github.io/2026/09/18/environment-evolution-terminal-agents/
作者
丁一帆
发布于
2026年9月18日
许可协议

点赞与评论

喜欢这篇文章?点个赞,或留下你的想法。登录 GitHub 后即可参与。

如果评论无法加载,请检查网络连接后刷新页面。