打开网易新闻 查看精彩图片

2014 年,语音识别领域有一件让所有人挠头的事:训练一个能听懂人说话的模型,需要成千上万小时的标注音频。可标注音频这东西,贵、慢、还容易出错。十年后,AI 编程智能体(就是那种能在命令行里帮你写代码、修 bug、跑测试的 AI)遇到了一个几乎一模一样的麻烦。

这些智能体每天都在产生海量的操作记录,读了哪个文件、改了哪行代码、跑了什么命令,全都留下了痕迹。这些记录堆积如山,但它们几乎没法直接拿来训练更强的模型。

这篇来自阿里巴巴通义千问团队和清华大学的论文,就是在解决这个看似简单实则棘手的问题。

**为什么记录不能直接拿来用**

先说清楚一件事:智能体的"操作记录"和"能反复使用的练习场",根本不是一回事。

打个比方,你请了一位维修师傅上门修水管,全程录了像。这段录像很有用,你能看到师傅拧了哪个阀门、换了哪个零件。但如果你想让另一个学徒练手,光看这段录像是不够的:管道已经修好了,水已经不漏了,学徒没法在这套水管上重新练习"如何修漏水"这件事,因为问题已经不存在了。

论文里管这种一次性记录叫"轨迹"(trajectory),意思是一条走过就消失的路径,只能看,不能重走。

轨迹*:AI 智能体执行任务时留下的完整操作记录,包括它读了什么、写了什么、运行了什么命令,本质上是一次性的历史快照。

这就是问题所在:轨迹的质量完全取决于当初执行任务的那个模型有多强,而且你根本没法验证它当时改的代码到底对不对。相比之下,一个能反复使用的"环境"(environment)就完全不同了,你可以让更强的模型重新解决一遍这个任务,可以用自己的测试来验证结果,还可以在同一个工作场景上出更难的题。

对于训练下一代 AI 智能体来说,环境才是真正稀缺又值钱的资源。

那能不能人工搭建这些环境呢?行业里确实有先例,比如 Terminal-Bench 这个基准测试,每道题都配了定制的容器、任务说明和自动评分脚本,质量非常高。但这种做法完全靠人工一点点搭,产出速度慢得让人绝望,根本没法满足训练所需要的海量数据规模。

**从旧轨迹里"考古"出新环境**

研究团队的思路是,与其从零开始造环境,不如反过来想:轨迹里其实已经藏着环境的全部线索。

智能体在执行任务时调用的每一个工具,读文件、写文件、编辑文件,都会暴露出它当时所在的那个工作空间长什么样。既然线索都在,为什么不把它倒推回去,把整个环境给"复原"出来?

这就是这篇论文提出的核心框架,叫 Terminal-Universe。它做的事情,用一句话概括就是把死的轨迹变成活的、可以反复练习的编程环境。

这个复原过程分成两步走。

第一步叫确定性回放(deterministic replay)。系统会按时间顺序把轨迹里所有的读、写、编辑操作重新过一遍,找出每个文件在智能体动手改之前的原始样子。这里有个细节很关键:智能体自己新建的文件,还有它做出的所有改动,全部被排除在外。为什么要这么做?因为你要复原的是"任务开始前"的状态,如果把智能体的答案也一起复原进去,那这个环境就没法再拿来出题了,答案已经写在黑板上了,还练什么。

这一步的结果只是一个"部分工作空间",因为轨迹只暴露了智能体碰过的文件,没碰过的东西自然无从得知。

第二步叫智能体补全(agentic completion)。这一步派出一个专门的补全智能体,去把第一步留下的空白填上,创建缺失的文件、补全残缺的代码、恢复项目需要的依赖库。但有一条铁律:补全智能体绝对不能顺手把任务给解决了,也不能暴露解决方案应该改在哪里。

这就好比你请了两位不同的师傅。第一位负责把损坏的水管恢复到"漏水前"的原始状态,他只做这一件事,绝不多手去把漏洞焊死。第二位师傅负责把整套水管系统周围该有的配件都装齐,阀门、接头、说明书,让这套系统看起来是个完整能用的房子,但绝对不能把那个漏水点顺手补上。如果第一位师傅手滑把漏洞焊了,或者第二位师傅心急把漏洞也堵了,那这套系统就废了,没法再拿来给学徒练手了。

数据证明了这两步分工的必要性。仅靠第一步回放,能达到"任务可用"标准的工作空间只有 40.2%(针对终端类轨迹)和 20.1%(针对软件工程类轨迹)。加上第二步补全之后,这个比例跳到了 93.5% 和 77.1%。补全前后的对比也很直观:终端类工作空间的平均文件数从 2.9 个暴涨到 22.4 个,涨了 7.7 倍。

补全之后,系统还会用一个专门的"充分性判断"智能体去检查每个工作空间,判断它是否真的具备足够的项目背景信息可以支撑一个任务。只有通过这一关的环境才会被留下来用于后续生成任务。整个流程最终从 35.9 万条原始轨迹里,筛选出了 3.73 万个"任务充分"的可用环境。

**光有环境不够,还得会出题**

有了可复用的环境,接下来的问题是:怎么在这些环境里出题,而且出得像真实的软件开发场景?

论文提出了四种"再提问"(re-querying)方式,覆盖了从最简单到最复杂的场景。

第一种叫意图恢复(Intent Recovery),说白了就是把原始轨迹里用户真正想要什么给还原出来,整理成一个独立完整的任务描述。这一步的价值在于,它能作为一个干净的对照组:如果直接拿原始轨迹去训练模型,效果是 36.7 分;但如果用意图恢复出来的任务,让一个更强的老师模型重新解决一遍再拿去训练,效果直接跳到 52.1 分,涨了 15 个百分点。

这个差距说明了什么?说明单纯模仿一段旧轨迹里那个(可能能力有限的)智能体的行为,价值远不如让一个更强的模型在同一个场景里重新做一遍。这也印证了本文标题里那句话的分量:轨迹是死的,环境是活的。

第二种是单工作空间任务合成(Single-WS),一个探索型智能体会去逛这个复原出来的工作空间,自己发现里面可以出的题,比如某个配置文件有打包问题、某个函数缺少边界检查。

第三种是跨工作空间合成(Cross-WS),这是这篇论文比较有巧思的一个设计。真实世界里的程序员经常需要参考别的项目来写代码,比如看看另一个仓库是怎么实现某个功能的,然后把这个能力搬到自己的项目里。论文用 TF-IDF(一种衡量文本相似度的经典算法)先粗筛出可能相关的项目对,再用一个大模型去判断这两个项目之间是不是存在"依赖关系",也就是一个项目缺的能力,另一个项目正好有。

举个论文里的真实例子:有两个用 C 语言写的 RSA 加密工具包,其中一个只有密钥生成、加密和签名功能,唯独少了解密程序;另一个工具包却把完整的加解密流程都实现了。系统就据此生成了一个任务,要求在缺解密功能的那个仓库里新建一个解密程序,同时明确规定只能参考另一个仓库的挂载路径,不能直接把具体的实现细节告诉解题的模型,逼着它自己去读代码、理解、再动手实现。

这种跨仓库任务比单一仓库任务难得多。数据显示,跨工作空间任务的平均对话轮数是单工作空间任务的 1.6 倍,工具调用次数是 1.9 倍,而老师模型的一次通过率从 72.3% 直接掉到 49.2%。这不是任务变复杂的偶然结果,而是"必须读两个仓库、还要在两者之间做协调"这个要求本身带来的难度。

如果不做跨仓库这道题,只在单一仓库里出题会怎样?论文的对比实验给出了答案:单独用跨工作空间数据训练,终端基准测试成绩是 55.4 分;把它和单工作空间数据混合训练,成绩涨到 58.4 分。而且分类别看,"模型训练"类任务涨了 15 分,"调试"类任务涨了 10 分,这些恰恰是最需要"跨项目类比迁移"能力的场景。

第四种是多轮用户查询(Multi-Round),这一种在我看来是最贴近真实工作状态的设计。现实里几乎没有人会一次性把需求说清楚,往往是先提一个初步要求,等看到结果之后再补充、再纠正、甚至改主意。

论文为此设计了一个"用户智能体",在编程智能体完成第一轮任务之后接着扮演用户,根据当前的执行结果继续提要求。这个用户智能体背后维护着一份需求清单,会记录哪些要求已经满足、哪些还在等待、哪些被更新了。每一轮结束后,系统会用一个自动化的验证器去跑测试,检验这一轮的结果对不对。

这里有个设计我觉得特别巧妙:编程智能体本身是看不到测试代码和报错细节的,它只能通过用户智能体转述的"自然语言抱怨"来了解哪里出了问题。这就非常接近真实场景,普通用户报 bug 的时候,说的从来不是"第 47 行断言失败",而是"这个功能好像坏了,能不能修一下"。

论文里有个具体案例很能说明这套机制怎么运作。一个传感器数据处理任务,第一轮是让智能体支持自定义输入输出路径。第二轮用户要求增加"断点续传"式的增量处理能力,不用每次都从头处理全部数据。第三轮实现之后系统检测出聚合结果不稳定(原来是引入了未固定随机种子的缩放逻辑),用户智能体没有暴露"测试失败"这种技术细节,而是转述成"这个平均值算出来不对,而且每次跑结果还不一样",让智能体自己去定位问题、修正。后面几轮又陆续加了阈值告警、把告警从"每次覆盖"改成"追加历史记录"、加报表功能、最后加上"试运行"式的自动修复能力。

这一整套需求演变,从路径配置到断点续传,从告警到历史追溯,再到自动修复,几乎就是一个真实项目从雏形长成生产系统的缩影。

数据上看,加入多轮数据之后,衡量"能连续完成多少轮需求"的指标 MT@4 从 18.4 分涨到 21.0 分;如果去掉每轮的验证反馈机制,这个数字反而掉到 18.8 分,比不加多轮数据时还低。这说明单纯堆更多轮对话没有意义,关键是每一轮都要有"确实做对了"这个反馈信号在支撑,不然智能体只是在瞎猜用户接下来会说什么。

**规模化之后,效果到底怎样**

把这套流程铺开之后,团队总共产出了 3.73 万个任务充分的环境,最终筛选出 3.2 万条可用于训练的完整对话记录,涵盖了大约 14.2 亿个训练 token。

用这批数据对 Qwen3.5-27B 模型做微调之后,在单轮编程测试 Terminal-Bench 2.1 上的表现从 46.2 分涨到 58.1 分,提升了 11.9 个百分点;在多轮迭代式编程测试 EvoCode-Bench v2 上,MT@4 指标从 6.3 分涨到 20.1 分,提升了 13.8 个百分点。

更有意思的是一个"预算怎么花最划算"的实验。研究者固定了训练数据的总规模,然后分别尝试三种扩充方式:增加更多不同的环境、给同一个环境出更多道题、给同一道题生成更多个解法。结果只有"增加环境数量"这一种方式带来了实打实的提升(从 53.2 分涨到 56.0 分),另外两种方式几乎原地踏步。

这个结果其实回应了整篇论文最初的立论:稀缺的从来不是"题目"或者"答案",而是不同的、真实的执行场景本身。就像一个学生刷题,把同一道题做十遍,收获远不如做十道不同的题。环境的多样性,才是真正决定训练效果的那个变量。

论文还测试了这套方法能不能跨领域迁移。他们把这套流程用在软件工程类的轨迹上(而不是终端操作类的),结果同样能给终端基准测试带来提升,从 47.0 分涨到 50.0 分。这说明这套"从轨迹里复原环境"的思路本身具备一定的通用性,不是只能在某一个特定领域里生效的窄招数。

当然,这套方法也不是万能的。论文自己也坦承了几个局限:所有复原出来的工作空间都跑在标准的 Ubuntu 24.04 容器里,而不是针对每个项目单独定制的专属环境,这在遇到需要特殊系统依赖或者复杂编译步骤的边缘情况时,可能会打些折扣。另外,复原出来的环境在语言、领域、工具链上的分布,天然受限于收集到的原始轨迹本身有什么,巧妇难为无米之炊。还有一点是,整个流程里出题、写答案、写验证脚本,用的都是同一个"老师模型",如果这个模型本身有能力盲区,那这些盲区很可能会被系统性地遗漏。

写在后面

读完这篇论文,我印象最深的其实不是那些漂亮的分数提升,而是那个看似朴素的洞察:被丢弃的东西,往往比被精心制作的东西更值钱。

这些散落在各处的智能体操作日志,原本大家可能觉得它们的使命已经完成了,任务跑完了,日志存档了,事情就结束了。但这篇论文告诉我们,日志里藏着的不是"过去发生了什么",而是"当时那个世界长什么样"。这两者的区别,恰恰是历史学家和考古学家工作方式的区别:前者读文献里写了什么,后者从残片里重建整个文明的样貌。

还有一处细节让我反复琢磨:补全智能体被明确要求"不能顺手把任务解决了"。这条规则听起来简单,但它其实在提防一种很隐蔽的数据污染,就像监考老师明明知道某道题的答案,却必须忍住不能在改卷子的时候顺手把答案写在草稿纸上留给下一个学生。AI 系统里的这种"知道答案但要装作不知道"的克制,本身就是一件挺反直觉的事情,因为大部分时候我们训练 AI 都是希望它尽可能展示自己知道的东西,而不是刻意隐藏。

论文里那个跨仓库合成 RSA 解密程序的例子,我觉得比任何抽象论述都更能说明"跨项目学习"这件事的价值:一个模型如果只在单一项目的边界里打转,永远学不会"读别人的代码、理解别人的设计、再把这套逻辑迁移到自己的项目里"这种真实程序员每天都在做的事。而这恰恰是当前很多训练数据集里缺失的一环。

这套方法目前测试的方向是从软件工程类轨迹迁移到终端操作类任务上,效果不错。那反过来呢?用海量的终端操作日志去反哺更复杂的软件工程任务,会不会同样有效?论文里没有做这个实验,留了个悬念。

Q&A

Q1:Terminal-Universe是什么?

A:Terminal-Universe是阿里巴巴通义千问团队和清华大学联合提出的一个框架,它能把AI编程智能体已经跑过的操作记录(轨迹),重新复原成可以反复使用、能验证结果的编程练习环境。

Q2:为什么不能直接用智能体的操作记录来训练模型?

A:因为操作记录是一次性的死档案,质量完全取决于当初执行任务那个模型的水平,而且没法验证改动是否真的正确。而复原出来的环境可以让更强的模型重新解答,还能用测试来验证结果,价值完全不同。

Q3:这套方法训练出来的模型效果提升有多少?

A:用这套方法产出的数据微调Qwen3.5-27B模型后,单轮编程测试Terminal-Bench 2.1提升了11.9个百分点,多轮迭代编程测试EvoCode-Bench v2的MT@4指标提升了13.8个百分点。