![]()
你有没有想过一个问题:教一个学生做题,最怕的不是题目太难,也不是题目太简单,而是你根本不知道这道题对他来说是难是易。
如果题目他闭着眼睛都能秒杀,那这道题练了也是白练。如果题目超出他的能力范围一大截,他做十次错十次,那这道题也教不会他任何东西。真正有用的练习,是那种他努力一下能做对、放松一下就会错的题。教育学里管这个叫"最近发展区"。
现在把这个问题搬到AI训练上。研究者们想让大语言模型学会在电脑终端里干活,修bug、写脚本、处理数据、管理文件系统,这些统称为"终端任务"。要教会AI这些技能,第一步是给它准备练习题。可这些练习题从哪来?总不能全靠人工一条条编写,那样成本高得离谱,速度也跟不上。于是大家开始琢磨,能不能让AI自己给自己出题、自己检验答案对不对。
这本身没问题,过去几年已经有不少团队在做这件事,而且做得挺像样。但这篇论文的作者们发现了一个被忽略的漏洞:一道题"能被解出来"和一道题"适合用来训练"完全是两件事。
能解出来,不代表值得练
先说清楚这个漏洞到底在哪。
现有的terminal-task合成系统,大致流程是这样的:先让一个AI(我们叫它"出题人")去写一个任务,包括任务说明、需要的软件环境、以及用来判断任务是否完成的自动化测试脚本。然后系统会做结构检查,确保这个任务的文件齐全、环境能跑起来,再让出题人自己尝试解一遍,如果它自己都能解开,这道题就算"验证通过",可以进入训练题库了。
**问题就出在这个"自己解一遍"上。**
出题人自己能解开这道题,只能证明这道题在技术上是可行的,不是一个逻辑上根本无解的坑。但这跟"这道题难度合适"完全是两码事。可能这道题简单到随便一个AI都能顺手做对,那训练价值就是零,因为学生根本不需要费脑子。也可能这道题里藏着一个隐蔽的坏味道,比如测试脚本写错了、任务描述里藏着矛盾的要求、或者环境配置有隐患,导致表面上"能解开"其实是走了个巧,而不是真正解决了问题本身。
用现实中的场景类比一下:一个老师自己批改自己出的卷子,自己做一遍觉得没问题,就直接拿去给全班学生考试。可老师是出题人,他知道所有的坑在哪、知道正确答案是什么,这种"自我验证"跟真正让一个不知情的学生去做题完全不是一回事。如果不引入外部的、不知道答案的解题者去实际试一试,这份卷子到底是太简单、太难、还是压根有印刷错误,老师根本发现不了。这不是装饰性的比喻,而是这篇论文最核心的痛点:**自我验证只能证明"可行",不能证明"合适"**。
论文里给这套流程起了一个名字,叫做验证有效性
> 验证有效性*:指任务经过结构检查和自我求解后,确认在技术上是可执行、可完成的,但这不代表任务的难度对训练来说是恰当的。
作者们的破局思路是,不能只让出题人自己判断,得引入真正的"外部解题者"去试,而且要把这些解题者的表现,当成修改任务的反馈信号,反复打磨,直到这道题落在一个"刚好合适"的难度区间里。
CalibForge:把出题变成一场持续的拉锯战
这篇论文提出的系统叫CalibForge
> CalibForge*:一套自主运行的终端任务合成系统,核心创新是用"解题者的实际表现"来反复校准任务难度,而不是只做一次性验证。
CalibForge的整个流程可以理解成三段。
第一段是调研和起草。系统会拿到一个"线索"(比如"数据处理与ETL"这个大方向),然后像一个真正做技术调研的人那样,去搜官方文档、GitHub上的issue讨论、Stack Overflow上的问答,找那些真实存在的技术坑,比如版本冲突、依赖问题、边界情况处理不当。论文附录里给了一个具体的例子:出题人围绕"数据处理"这个线索,搜了24次,考察了六个方向,包括表格数据修复、数据库恢复、压缩文件修复、媒体格式解析、老旧格式处理、二进制传感器日志恢复,最后选定了"二进制传感器日志恢复"这个方向,因为它足够复杂,不是一条命令就能搞定,同时又能明确验证对错。
第二段是搭建候选任务并做结构验证。出题人把选定的方向,具体写成任务说明、执行环境(用Dockerfile定义)、还有一套自动化验证测试。这一步会先做两阶段检查:结构验证确认所有必要文件齐全、环境能构建起来、测试在初始状态下全部失败(这个很关键,如果测试在什么都没做的情况下就通过了,说明这道题本身就有问题);然后是自我求解,出题人在一个隔离的沙盒里真的动手试着解一遍,确认解法确实可执行。
第三段才是这篇论文真正的重头戏,叫对抗式解题者校准
> 对抗式解题者校准*:让真正的解题AI(不是出题人自己)去实际尝试这道候选任务,根据它们的成功或失败情况,判断这道题是不是落在合适的难度区间里,如果不合适就返回去修改任务本身,反复迭代直到达标或者放弃。
这里的"对抗"二字很值得琢磨。出题人和解题者之间形成了一种角力:解题者拼尽全力想解开题目,出题人则根据解题者的表现不断调整题目的难度和表述,直到落进一个理想的区间。这跟传统的"一次性生成、一次性验证"完全不同,更像是一场持续的拉锯战。
CalibForge设计了两种具体的校准策略,分别叫多解题者校准和对比式解题者校准。
策略一:让多个AI互相拆台,专挑它们意见不合的题
第一种策略叫多解题者校准
> 多解题者校准*:同时派出多个不同的AI模型去尝试解同一道候选任务,只有当至少一个成功、至少一个失败时,才把这道题保留下来。
具体到论文的实验设置,CalibForge派出了三个不同的模型作为解题者:DeepSeek-V4-Flash、GLM-5、Kimi K2.5,让它们各自独立尝试同一道候选任务。
这里的判定逻辑写成公式是这样的:如果K个解题者的结果全部一致(全部通过,或全部失败),这道题就被判定为"不在学习区间内",要打回去修改;只有当结果出现分歧,一部分通过一部分失败,才说明这道题恰好落在了"有些模型能解开、有些模型解不开"的临界地带,值得保留。
为什么全部通过或全部失败都要打回去?逻辑其实很直白。如果三个模型全都解开了,这道题可能太简单,存在一条谁都能找到的捷径,练了也没有增量价值。如果三个模型全都失败,这道题可能难度爆表,或者压根就是任务本身有毛病,比如测试脚本写错了、任务描述里藏着矛盾。这两种情况,训练价值都接近于零。
论文附录里有一个很生动的案例。有一道任务是要求对比两份客户数据库导出文件,找出差异。第一轮测试里,三个解题者GLM-5、Kimi-K2.5、DeepSeek-V4-Flash全部失败了。但出题人仔细看了三份失败的解题记录后发现,三个模型犯的是同一个错误:它们都把"某一份文件里多出来的字段"误判成了"该条记录被修改了"。这不是随机的技术失误,而是任务说明本身写得含糊,导致所有AI理解偏了。出题人把任务说明里"如何界定记录是否被修改"这句话重新写清楚之后,再测一次,结果变成两个通过、一个失败,恰好达到了"有分歧"的目标状态,这道题被保留了下来。
这个例子特别能说明"全部失败"这个信号的价值:它不是在说"这题太难了",而是在提示"这题的表述可能出了系统性的问题"。三个不同厂商、不同架构的模型犯了完全相同的错误,这种一致性本身就是线索。
打个类比,如果你出的一道考题,班里学习最好的学生和垫底的学生都写错了同一个知识点,而且错误方式惊人地一致,你大概不会怀疑这些学生笨,你会怀疑题目本身有歧义。如果只依赖单个学生的对错去判断题目质量,你根本发现不了这种系统性的表述问题,因为一个人犯错可能只是他自己粗心,只有多个独立的人犯了同样的错,才能排除"个体偶然性"这个干扰项。这正是多解题者校准比单一解题者反馈更有效的核心原因。
策略二:一强一弱两个AI掰手腕,专挑刚好卡在中间的题
第二种策略叫对比式解题者校准
> 对比式解题者校准*:指定一个"更强"的解题者和一个"更弱"的解题者,只有当强的那个成功、弱的那个失败时,才保留这道题。
论文中具体的设置是,DeepSeek-V4-Pro扮演"更强的解题者",DeepSeek-V4-Flash扮演"更弱的解题者"。这两个是同一家公司出的模型,一个能力更强一些,一个相对弱一些。
这个策略的逻辑跟前一种略有不同,它不是找"分歧",而是找一个精确的能力区间。弱模型失败说明这道题超出了弱模型的能力范围;强模型成功说明这道题在强模型的能力范围之内。两者叠加起来,恰好把这道题的难度框定在"弱模型够不到、强模型够得到"这个夹层里。
如果两个模型都成功了,说明这道题可能有捷径,难度不够;如果两个都失败了,出题人就要去检查这道题是不是本身有问题;如果反过来,弱模型成功了强模型却失败了,这种"倒挂"现象往往说明任务本身有漏洞,比如信息泄露、结果不确定、或者表述有误导性。
附录里的第三个案例特别有意思,讲的是一道"修复老旧密码保管库的加密漏洞"的任务,第一轮测试出现了倒挂:强模型DeepSeek-V4-Pro失败了,弱模型DeepSeek-V4-Flash却通过了。出题人调查后发现,强模型采用了一种技术上完全合理但和验证脚本预期不一致的加密布局,它把密码、备注等敏感字段打包成一条记录整体加密,而验证脚本却死板地要求每个字段必须单独加密存储。强模型不是能力不够,而是验证脚本本身写得太死板,把一种合理的替代方案错误地判定为失败。出题人把验证逻辑改成了不限定具体存储结构,只检查加密是否达到安全标准这个更本质的要求,重新测试后,强模型通过、弱模型失败,恢复了正常的期望关系,这道题才被保留。
这个案例揭示了一个很重要的洞察:所谓"倒挂",往往不是解题者错了,而是裁判(验证脚本)错了。**如果没有引入强弱两个解题者做对比,这种验证脚本本身的漏洞几乎不可能被发现**,因为出题人自己测试的时候只关注"我的标准答案能不能通过",根本不会去想有没有其他同样合理的解法被误判。
拿体育比赛来类比,如果裁判定的规则本身有漏洞,比如某种合理的战术动作被判成违规,那么水平高的运动员反而更容易触发这个漏洞被误判(因为他们更有能力尝试非常规解法),水平一般的运动员因为只会按套路来,反而侥幸"合规"。这种时候,你看到的比赛结果是"强的输了,弱的赢了",第一反应不该是怀疑强者的能力,而是该去查规则本身是不是有问题。
实验数据说话:光加反馈没用,得看反馈"怎么用"
光讲原理容易显得像空谈,论文里做了一组对照实验,专门验证这两种校准策略到底比"随便加个反馈"强在哪。
实验设置了四个版本进行对比:完全不引入解题者反馈("无解题者"版本)、引入一个单独的解题者子代理但不做多模型对比或强弱对比("单解题者"版本)、多解题者校准、对比式解题者校准。四个版本都在同样的任务数量(1300个)、同样的蒸馏训练流程下进行比较,确保差异只来自校准策略本身。
结果是这样的:
| 校准模式 | 收集任务数 | 训练轨迹数 | Terminal-Bench 2.0准确率 | 相比无解题者的提升 |
| 无解题者 | 1300 | 2466 | 22.47% | – |
| 单解题者 | 1300 | 2493 | 24.34% | +1.87 |
| 多解题者校准 | 1300 | 2425 | 29.21% | +6.74 |
| 对比式解题者校准 | 1300 | 2561 | **31.09%** | **+8.62** |
这组数字里最耐人寻味的一点是,多解题者校准产生的训练轨迹数量(2425)反而比"无解题者"版本(2466)还少一点,但准确率却高出6.74个百分点。这说明**提升不是来自"数据量更多",而是来自"数据质量更精准"**。单纯给出题人加一个反馈渠道,只带来1.87个百分点的提升,远远不如真正引入"跨模型分歧"或"强弱对比"这种结构化的判断标准。
这个对比很直观地说明了一件事,给学生反馈这个动作本身没有那么值钱,关键是这个反馈是怎么设计出来的。一个老师只是简单告诉学生"你这道题做错了",效果远不如"三个不同班的学生都在同一个地方犯了同样的错误,这说明题目本身出的方式有问题"这样结构化的诊断。前者是单点反馈,后者是有对比基准的诊断信号,信息密度完全不同。
从19%到96%:校准到底改变了多少任务的命运
如果说前面的对照实验证明了这两种策略"有用",接下来这组数据要回答一个更深的问题:这种校准过程到底在多大程度上改变了任务的样貌?
论文追踪了所有进入对比式校准流程的候选任务,从它们第一次被解题者测试的结果,到最终是否被保留的结果。
第一次测试的结果分布是这样的:只有19%的候选任务一上来就恰好符合"强模型通过、弱模型失败"这个目标关系;16%的任务两个模型全部失败;高达61%的任务两个模型全部通过;还有4%出现了前面说的"倒挂"现象。
也就是说,**即便这些任务已经通过了结构检查和自我求解验证,真正一上来就"难度刚好"的比例只有19%,剩下81%全都需要经过后续的反馈和修改才能达标**。这跟前面提到的核心矛盾完全呼应,验证有效性确实存在,但离"适合训练"还差得很远。
经过反复的反馈、修改、再测试,累计通过率被拉升到了96%,只有4%的任务被最终放弃。
而这个校准过程需要跑多少轮才能完成,论文也给了具体的分布数据:15%的任务只需要一次探测就达标,53%在五次探测以内完成,93%在二十次探测以内完成。这个分布形态很像很多现实中的问题解决场景,大部分容易矫正的偏差可以很快修正,剩下一小部分顽固的问题需要持续投入更多轮次去打磨。
这组数据回答了一个可能会让人产生的疑问,是不是校准这个环节本质上只是在做"过滤",把不合格的任务筛掉,合格的留下?数据给出的答案是否定的。**如果只是过滤,那么最终留存率应该等于初始合格率,也就是19%左右,但实际留存率是96%,说明绝大多数任务不是被筛掉了,而是被修改、被救活了**。校准的核心动作不是筛选,是"诊断加治疗"。
这就像医生看病,如果医生只会说"你这个病治不了",然后把病人劝退,那治愈率永远等于第一次就诊时能确诊治愈的比例。但如果医生擅长根据检查结果反复调整治疗方案,大部分原本"看起来治不了"的病人最终都能被治好,那真正决定治愈率的不是初诊的准确度,而是后续调整的能力。CalibForge的价值主要体现在后者。
拿真实的基准测试打分,CalibForge到底强在哪
说了这么多设计原理,最终还是要看训练出来的模型表现如何。
论文用CalibForge构建了5431个校准过的终端任务(1263个来自多解题者校准,4168个来自对比式校准),用这些任务蒸馏出训练数据,分别微调了两个基座模型:Qwen3-30B-A3B-Instruct和Qwen3.5-35B-A3B。对比的基线方法包括Endless Terminals、CLI-Gym、SETA-Env、TermiGen、TerminalTraj这几个公开的终端任务合成系统。
主要评测在Terminal-Bench 2.0
> Terminal-Bench 2.0*:一个用来评测终端智能体解决真实、复杂命令行任务能力的公开基准测试。
同时为了检验训练效果是不是只在"原题型"上有效,论文还额外测了两个完全不同类型的基准:SWE-bench Pro(检验能不能在真实代码仓库里解决复杂的软件工程问题)和Doc2Repo(检验能不能根据自然语言需求从零生成一整个代码仓库)。这两个都属于领域外评测
> 领域外评测*:指训练数据的来源领域和评测任务的领域不完全一致,用来检验模型学到的能力是不是"真本事"而不是死记硬背特定题型。
结果如下:
| 训练数据 | Terminal-Bench 2.0准确率 | SWE-bench Pro解决率 | Doc2Repo通过率 |
| Qwen3-30B-A3B-Instruct(基座) | 7.87% | 3.26% | 5.94% |
| Endless Terminals | 19.48% | 21.84% | 18.26% |
| CLI-Gym | 23.22% | 28.81% | 29.91% |
| SETA-Env | 23.22% | 29.91% | 24.91% |
| TermiGen | 23.60% | 27.77% | 34.11% |
| TerminalTraj | 26.22% | 26.28% | 24.36% |
| **CalibForge** | **32.58%** | **30.94%** | **35.98%** |
| Qwen3.5-35B-A3B(基座) | 39.10% | 41.29% | 44.92% |
| TermiGen | 40.07% | 43.37% | 44.54% |
| TerminalTraj | 40.82% | 43.91% | 47.20% |
| **CalibForge** | **47.57%** | **44.32%** | **48.77%** |
数字背后的信息量很大。在30B模型上,基座模型只有7.87%的准确率,用CalibForge训练之后跳到32.58%,足足提升了24.71个百分点,相当于原来10次任务能做对不到1次,现在10次能做对3次多。在35B模型上,同样是CalibForge数据训练出来的效果最好,47.57%,超过第二名(TerminalTraj训练的版本)将近7个百分点。
更值得留意的是领域外的成绩。在SWE-bench Pro(修真实软件仓库的bug)这个和训练数据领域完全不搭边的任务上,30B模型的提升幅度是27.68个百分点,从几乎不会到能解决三成的问题。这说明CalibForge训练出来的不是一套针对特定题型的"应试技巧",而是一种更通用的问题解决能力,能迁移到没见过的任务类型上。
5431道题都长什么样
除了训练效果,论文还花了大篇幅去分析这批合成出来的任务本身的特点,这部分内容其实很值得细看,因为它回答了一个更基础的问题:一个"好"的训练数据集,应该长什么样?
首先是领域覆盖。作者们用一套16类的领域分类法,对比了CalibForge和几个现有数据集的构成。结果很明显,很多现有数据集存在严重的领域偏斜:SETA-Env里74.6%都是系统管理类任务,CLI-Gym里67.0%是调试类任务,Endless-Terminals里40.6%是文件操作类任务。相比之下,CalibForge最大的类别是软件工程,占25.5%,但没有一个类别占比过高,系统管理、科学计算、安全、文件操作、数据科学、调试、数据处理都有相当的比例。
这个差异很像营养搭配。如果一个人天天只吃某一种食物,即使这种食物本身很有营养,长期下来身体也会出现某种短板。训练数据如果长期集中在某一类任务上,模型练出来的能力也会出现类似的偏科,擅长处理某类问题,遇到别的类型就露怯。
除了大类领域,论文还统计了更细粒度的能力标签
> 能力标签*:描述一个任务具体涉及哪些工具、技巧、问题解决方式的标记,比方说涉及"二进制解析"还是"网络配置"。
结果显示CalibForge的任务集里出现了3885个不同的能力标签,中位数是每个任务包含5个标签。这个分布呈现出很长的尾部,51.6%的标签只出现在一个任务里,82.2%的标签出现次数不超过5次。这说明这批任务不是靠少数几种能力反复排列组合出来的,而是覆盖了大量高度专精的细分技能。
再往下看任务的复杂程度指标。论文统计了每个任务初始文件数量、涉及的文件类型数、环境依赖包数量、验证测试函数数量,中位数分别是2个文件、1种文件类型、2个依赖包、7个测试函数,90分位数则分别是8、4、7、15。这些数字说明整个数据集不光是话题多样,连"任务的复杂程度"本身也有丰富的梯度分布,有轻量的小任务,也有需要处理很多环境状态和验证逻辑的重量级任务。
最后是轨迹特征的对比,论文测量了每个任务对应的解题轨迹的交互步数和"思考token数"
> 思考token数*:指大模型在给出实际操作之前进行内部推理时产生的文本量,可以粗略理解为模型"思考"花了多少功夫。
CLI-Gym的任务(它是通过把现有Python项目的正常环境"倒推"出一个损坏版本来构造任务的)产生的交互轨迹最长,中位数28步,但CalibForge的中位数只有21步。有意思的是,思考token数的排序反过来了,CalibForge的中位数是5300个,反而是所有对比对象里最高的,CLI-Gym只有4000个。
这组数据揭示了一个容易被忽略的事实:**交互步数多,不代表推理深度大**。CLI-Gym的任务因为需要反复执行命令、调试、验证,天然会拉长交互次数,但每一步可能只是简单的试错。CalibForge的任务用更少的步骤完成,但每一步之前模型思考得更充分。这就像考试时,一个学生埋头写了十页草稿纸但每一步推理都很浅,另一个学生只用两页纸但每一步都想得很深,谁的解题能力更强,不能只看纸用了多少。
模型练完了,它到底还会在哪里栽跟头
论文最后有一部分内容特别真诚,专门去挖掘训练出来的模型在实际测试中失败的具体案例,而不是止步于一个总分。这部分内容对理解"AI在终端里到底难在哪"特别有价值。
第一个案例叫"regex-log",任务要求写一个正则表达式,从日志里提取出每一行包含合法IPv4地址的最后一个有效日期,存到指定文件里。30B模型的三次测试全部失败,35B模型三次全部成功。检查失败轨迹发现,30B模型其实花了不少功夫在琢磨正确的正则表达式,反复写脚本测试,但最终都没有把选定的表达式真正写入要求的文件,时间就用完了。这是**"想明白了,但没做完"**的典型案例,推理过程本身没问题,但没能把中间成果转化成最终要交付的东西。
第二个案例是密码恢复任务,要求从残缺证据里拼出一个23字符长度、开头是8XD、结尾是W54的密码。30B模型的两次运行都把答案拼错了,原因是它误把某个前缀标签(比如PASSWORD=)算进了23个字符的长度里。35B模型则正确地把两段分散的证据碎片拼接起来,并且专门检查了拼出来的密码长度、前缀、后缀是否都符合要求。这暴露的问题是**过早地相信了一个看起来说得过去的局部证据,却没有拿全局的约束条件去反复核对**。
第三个案例是数据库WAL日志恢复任务,要求修复一个加密的SQLite写前日志,恢复出全部11条记录(基础数据库里只有5条)。这次两个模型全部失败了。追查原因发现,所有六次运行,不管是30B还是35B,都在还没有备份或解密WAL文件之前,就先用SQLite直接打开了主数据库,而SQLite这个操作本身会把无法读取的WAL文件自动删除或合并掉,导致那6条额外的记录彻底丢失,后面再怎么努力都恢复不回来了。
这第三个案例特别值得琢磨。它揭示的不是"模型不够聪明",而是**"第一步操作本身就是不可逆的"**这种更本质的风险。这跟法医取证的道理很像,如果在没有先拍照、封存现场的情况下,直接用手去翻动一个犯罪现场,哪怕后续侦查手段再高明,原始证据可能已经被破坏了,案子再也破不了。这种"操作顺序错了就万劫不复"的坑,是靠模型变聪明也无法弥补的,必须靠训练它养成"先备份,再操作"这种谨慎的行为习惯。
三个案例合起来,勾勒出终端任务里三种截然不同的失败方式:推理充分但没有落地成交付物,过早相信局部证据而忽略全局约束,以及在不知情的情况下执行了破坏性的不可逆操作。这些细节比一个总分数字有价值得多,因为它们指向的是具体可以改进的方向。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.