编程智能体基准测试应与真实用户任务流相匹配
[LOADING...]
左图:SWE-Bench Pro,每个任务都是一条用户消息,几乎总是新功能或 bug 修复。右图:软件工程师在 JetBrains IDE 中工作的会话里前五条开发者消息,仅统计至少包含三条消息的会话。每一列是一个消息位置,彩色块表示请求类型,色带宽度表示某一类型紧随另一类型的频率。
本文总结了我们的论文 《观点:编码智能体基准应匹配其用户的任务流》,该论文被 NeurIPS 2026 的 Evaluation of Interactive Agents 研讨会接收。
在 JetBrains Research,我们最近分析了 4,782 个软件工程师在 JetBrains IDE 中工作的智能体会话,并将它们与三个公开的智能体对话集合进行了比较。在我们考察的开发者会话中,修复 bug 和添加功能合计不到开发者要求编码智能体所做事情的一半。其余包括关于代码库的问题、规划、代码审查、重构和命令执行。另一方面,在 SWE-Bench Pro 中,93.8% 的任务是功能开发和 bug 修复,而且每个任务都以一条完整消息到达。差异相当大。
这一差距正是本文的主题。我们的分析结论是:不存在普遍现实的编码智能体基准:基准应根据对特定用户群体的测量进行校准。 SWE-TaskFlow 是我们为此做出的贡献,可应用于任何源自 issue 的基准;在本文中,我们将其应用于 SWE-Bench Pro。
基于 issue 的基准衡量什么
SWE-bench 及其后继者(SWE-Bench Pro、SWE-rebench、DeepSWE)从 GitHub issue 构建任务。智能体获得仓库检出和 issue 文本,探索代码、编辑代码并提交补丁。测试决定补丁是否解决该 issue;已解决 issue 的比例就是解决率。
这些任务背后的基础设施构建成本很高:例如,处于正确提交的仓库、代码可运行的环境,以及验证更改的测试。然而,其上的交互层是固定的。完整规格以一条完整且措辞精炼的消息到达,最终只对一个最终补丁评分。
尽管交互层固定,IDE 中的开发者只有部分时间是这样工作的。也就是说,我们看到的会话中有一半是单条消息。在其余会话中,需求分批到来:在一次变更请求与下一次请求之间,开发者会要求智能体解释项目某部分如何工作、规划下一次变更或审查已完成的工作,而先前需求仍需贯穿其中。
开发者实际如何使用智能体
这 4,782 个会话(我们称为 Production Sessions,即生产会话)中的每一个,都是开发者与 IDE 内编码智能体之间的一次对话;它们合计包含约 14,000 条开发者消息。我们只看开发者一侧,下图展示了 Production Sessions 中消息的分布。
[LOADING...]
按开发者消息数量划分的 4,782 个会话(图中称为 prompt)。一条开发者消息可触发多个智能体动作。
一半会话(50.9%)是单条消息;约 15% 超过五条。由于我们的主题是交互式智能体,后续分析聚焦于 至少包含三条开发者消息的 33% 会话,即长会话,如下所述。
一个开放权重 LLM(Gemma 4-31B)为每条消息标注了 16 种请求类型之一,或称为意图:bug 修复、新功能、解释、规划、代码审查、执行等(全部 16 种定义见论文)。同一个分类器、同一提示词标注了公开集合和 SWE-Bench Pro 的 issue,因此本文中的每个分布都是在同一口径下测得的。
在所有会话中,bug 修复占已标注消息的 26%,新功能占 19%。在长会话中,对项目自身代码的解释占消息的 6%,一般编程问题另占 10%;规划、代码审查、重构、调试和执行构成其余大部分。以同样方式标注的 SWE-Bench Pro 包括 55% 新功能、39% bug 修复、6% 重构,别无其他。
会话长度和意图构成是**任务流(Task Flow)**三个组成部分中的两个;第三个是意图彼此跟随的顺序。一个以功能请求开始的会话,常常会继续提出关于现有行为的问题、一个规划步骤和一个审查请求。
公开集合如何比较
我们的 Production Sessions 对应一个用户群体。为了观察图景在多大程度上取决于用户群体,我们对以下每个公开集合中的 1,000 个会话运行了分类器,并保留长会话。下面我们为每个集合附上桑基图。本文中的桑基图就是任务流:每一列是一个消息位置,列与列之间的色带就是这些转移。
SpecStory 由公开的 IDE 会话导出组成,即 Programming by Chat 中分析的数据。其 1,000 个会话中有 521 个是长会话。在三个集合中,它最接近我们的会话,规划占比更大。
[LOADING...]
DataClaw 收集社区分享的编码智能体会话。1,000 个中有 585 个是长会话。它以执行请求和简短的操作性消息为主。
[LOADING...]
SWE-chat 是在聊天环境中收集的真实用户编码智能体对话集合。1,000 个中有 698 个是长会话。执行和规划是它最大的意图。
[LOADING...]
这些语料来自不同产品、不同用户和不同收集方法,因此我们不对它们做定量比较。不过,校准到其中任何一个的基准,其任务和转移的混合比例都会与校准到另一个的基准不同。它们都不是基准真相,我们的 Production Sessions 也不是;目标必须被选择并明确说明。
在我们的试点中,目标是长 Production Sessions。按频率校准有一个副作用:目标中罕见的任何内容都会被推向零。罕见但后果重大的行为,例如破坏性 shell 命令或与安全相关的审查,应改为在单独的压力测试切片中评估,并拥有各自的任务数量。
SWE-TaskFlow 如何适配现有任务
为每个目标构建新的交互式基准会丢弃基于 issue 的基准已有的东西。相反,我们提出 SWE-TaskFlow,它转换现有基准:保留仓库、环境、测试和原始需求,仅重新生成用户消息。
将 issue 拆分为多个请求
LLM 将每个 issue 改写为三个有序请求;我们称它们为 issue 请求,因为其中的所有内容都来自原始 issue。智能体在看到第二个请求之前先处理第一个。拆分必须保留每一条原始需求,且不添加任何需求;标识符和代码片段逐字保留;每个请求必须在先前请求留下的仓库状态下可执行。第二遍模型检查结果的完整性。731 个公开 SWE-Bench Pro issue 中有 31 个未通过这些拆分和评估检查,被排除在外,剩下 700 个任务。
以下是一个 qutebrowser issue 的示例,标题为 “由于旧版 QtWebEngine 缺少 Array.prototype.at 支持,LinkedIn 加载失败”。原始 issue 是一条约 1,000 字符的消息。拆分后,它变成:
- 请修复 macOS 上 QtWebEngine 5.15.2 中 qutebrowser 的 LinkedIn 兼容性问题。LinkedIn 的前端 JavaScript 使用了 Array.prototype.at,而该旧版引擎缺少这一方法,因此 JavaScript 执行失败,LinkedIn 页面会卡住或无响应。添加所需的 qutebrowser JavaScript 兼容支持,使 LinkedIn 能够正常加载和运行,使用 polyfill 透明地解决该问题。
- 当原生不支持 Array.prototype.at 时,兼容支持应在 6.3 之前的 QtWebEngine 版本上提供该方法,并且必须在 LinkedIn 域页面和 qutebrowser 测试域中处于启用且可工作的状态。对于数组实例,正整数索引应返回指定索引处的元素,而负索引从末尾向前计数,其中 -1 指最后一个元素。
- 完善该行为,使超出数组边界的索引对于正整数和负整数索引都返回 undefined。只有当 JavaScript 环境中尚未提供原生 Array.prototype.at 方法时,才应注入该 polyfill。
第一个请求足以开始工作;边界情况稍后到达。
添加关于仓库的问题
对项目自身代码的解释在 Production Sessions 中很常见,而在基于 issue 的基准中缺失,因此我们生成这类问题。一个模型读取仓库以及先前解决该 issue 的智能体轨迹,并提出一到三个问题。每个问题必须仅凭仓库即可回答,在修复前后都保持有效,并且不能泄露解决方案。
每个问题都附带参考答案和一个可执行的证明脚本(proof script),该脚本从仓库中收集答案的证据。在数据集创建时,我们在干净检出中运行脚本,只有当脚本通过、生成证据且不改变仓库时,才保留该问题。这在构造上排除了答案无法在代码中观察到的问题(“为什么这样设计?”)。在评估时,智能体以文本回答,另一个 LLM 根据隐藏的参考答案及其证据评判答案。
在发布的配置中,上面的 qutebrowser 任务获得一个问题,放在第一个和第二个 issue 请求之间:
简明答案:追踪相关的样式表配置更改如何同时更新未来的 QtWebEngine 文档和已加载的文档,包括 CSS 组装、脚本替换、执行世界(execution world)、子框架行为,以及无关选项的空操作路径。
参考答案指出了触发此路径的两个配置选项,并逐一说明五个文件。证明脚本针对真实代码执行样式表配置更改,检查生成的脚本注册和对活动页面的调用,并确认无关选项不会产生任何效果。该问题与 Array.prototype.at 无关:它来自解决智能体沿途阅读的代码,而不是来自修复本身。
选择与目标匹配的序列
问题可以放在 issue 请求之前、之间或之后,因此每个任务都有多个候选序列。我们为每个任务选择一个序列,使基准整体上类似于长 Production Sessions,并以**任务流对齐分数(TaskFlow Alignment Score,TFAS)**衡量。TFAS 使用 Jensen-Shannon 散度比较目标与基准之间的三个分布(会话长度、意图、转移),并将它们合成为一个 0 到 100 的分数。纯拆分相对于我们的目标得分为 59.6。在固定位置添加问题可将分数提高到 75.6 到 77.1;让优化器选择每个任务保留多少问题以及放在哪里,可提高到 77.8。结果是 700 个任务中的 255 个共包含 454 个问题(113 个任务有一个问题,85 个有两个,57 个有三个),其中 67 个任务仅将问题放在 issue 请求之前,86 个仅放在之后,102 个交错放置。其余 445 个任务保留其三个 issue 请求。
[LOADING...]
SWE-Bench Pro(左)与 TFAS 优化选择(右,TFAS 77.8)的任务流。每个 issue 的一条用户提示变成最多六条不同类型的顺序提示。仓库、请求的更改和最终测试保持不变。
在右图中,issue 请求带有 issue 中本就存在的任务类型:bug 修复、新功能和一些重构,这与左图中构成整个 SWE-Bench Pro 的三种类型相同。一旦拆分 issue,较小的意图也会显现:调试、转换、测试、规划以及其他一些意图。这些并非新增内容,而是原始 issue 的一部分;当分类器将 issue 视为一条消息时,会把它们归入主导意图(例如,一个还要求回归测试的 bug 修复 issue),而拆分后它们作为单独消息变得可见。唯一来自 issue 外部的意图是解释,由仓库问题承载。
试点结果:四个模型,三种设置
为了评估 SWE-TaskFlow,我们让 GPT-5.6 Luna、GPT-5.6 Terra、GPT-5.4 Mini 和 Gemini 3.7 Flash 通过 mini-swe-agent 在相同的 700 个任务上运行,每种设置运行三次:
- Single(单条): 原始 issue 作为一条消息。
- Split(拆分): 三个请求在单个对话中依次交付。
- Split+QA(拆分+问答): 采用 TFAS 选出的序列并加入仓库问题。
[LOADING...]
三次运行的均值;须线为观测到的最小值到最大值。颜色表示模型,形状表示设置。
将 issue 拆分为三条消息,使每个模型每任务的成本增加 2.0 到 2.6 倍。 由于仓库、测试和需求都没有变化,额外成本衡量的是当需求分批到达时智能体需要多付出多少努力。解决率变化较小:GPT-5.6 Terra 保持不变,其他三个平均下降 4 到 5 个百分点,这与同一设置单次运行之间的差异相当。每种设置三次运行,这些结果并不能对模型进行排名;它们表明,渐进式披露会可靠地改变投入,但只微弱地改变结果。
LLM 改写本身,而非排序,也可能让任务变得更难。一个对照条件 Concat 将同样三个改写部分粘贴为一条消息交付。对于三个 GPT 模型,各运行一次,它在成本和解决率上都接近 Single,因此 Split 的额外成本来自顺序交付,而不是来自重新措辞。
添加仓库问题会在 Split 之上再增加 4% 到 24% 的成本,具体取决于模型。在带有问题的 255 个任务上,评判器判定正确的答案比例(回答准确率)从 69.8%(GPT-5.4 Mini)到 83.0%(GPT-5.6 Terra) 不等。
[LOADING...]
实心圆:回答准确率。空心圆:同样 255 个任务上的解决率,因此这些解决率数值与上图不同。
拆分后的轨迹也允许中间验证。在每个 issue 请求之后,我们可以对仓库做快照并重新运行测试,仅根据目前揭示的需求评分。在一项 64 个任务的消融实验中,解决率和测试通过率都随着每个 issue 轮次增长,而问题的位置不会移动曲线。一个任务产生多个已验证检查点,而不是单一最终分数。这对诊断有用,也可能对训练有用;我们尚未尝试后者。
SWE-TaskFlow 尚未覆盖的内容
SWE-TaskFlow 目前生成两类消息:issue 请求和仓库问题。真实会话任务流中的其他所有内容(一般编程问题、规划、代码审查、超出 issue 已有内容的重构、执行、无修复的调试)仍需要各自的生成器和验证器,而且对于其中大多数内容,如何自动检查响应尚不清楚。测得的任务流至少告诉我们缺少哪些增强以及大致比例。
所有消息也在运行前固定。这提供了精确的可重放性和配对比较,并衡量了渐进式披露、记忆和适应,但不衡量智能体如何处理反馈:“用户”无法对智能体的行为作出反应。带有模拟用户的反应式基准能以轨迹方差为代价覆盖这一点;完整的评估套件应将校准后的静态核心与有针对性的反应式切片结合起来。除此之外,分类器没有人工标注的准确率集合;有些 issue 无法拆分,问题难度取决于编写问题的模型,而且试点每种设置只有三次运行。
Hugging Face 上的 SWE-TaskFlow-SWE-Bench-Pro 数据集 有 12 个配置,分别作为独立拆分:原始提示、拆分提示、Split+QA 变体以及仅 QA 会话。每个问题都附带其参考答案和证明脚本。仓库、金标准补丁和测试仍随原始 SWE-Bench Pro 发布版 提供。