SlopCodeBench:编码智能体在长周期迭代任务中性能退化的基准测试 SlopCodeBench: Benchmarking How Coding Agents Degrade Over Long-Horizon Iterative Tasks
首个评估编码智能体迭代代码质量退化的基准,揭示代码腐化与冗余问题
前置知识
编码智能体(Coding Agent)
基于大语言模型的自动化编程系统,能够接收自然语言需求描述并生成、修改代码。典型代表包括 GitHub Copilot、Cursor、Claude Code 等工具。这些智能体通过多轮交互与用户协作,在迭代过程中逐步构建和扩展代码库。与传统的单次代码生成不同,编码智能体需要在已有代码基础上进行增量式修改,这要求它们不仅要写出正确代码,还要做出合理的架构设计决策。
SlopCodeBench 的核心研究对象就是这些编码智能体,理解它们的工作方式是理解本文评测框架的前提。本文发现这些智能体在迭代扩展代码时会产生显著的质量退化问题。
圈复杂度(Cyclomatic Complexity)
由 Thomas McCabe 于 1976 年提出的软件度量指标,用于衡量程序中独立执行路径的数量。计算公式为 $CC = E - N + 2P$,其中 $E$ 是边数、$N$ 是节点数、$P$ 是连通分量数。在实际应用中,每个 if、while、for、case 等分支语句都会增加圈复杂度。Radon 等代码分析工具通常将 $CC > 10$ 视为高复杂度阈值。本文用圈复杂度来量化函数的控制流复杂程度,是计算结构腐化指标的核心组件。
本文定义的结构腐化(structural erosion)指标直接依赖圈复杂度来识别高复杂度函数,理解这一概念是理解论文核心质量度量的关键。
AST-Grep 模式匹配
一种基于抽象语法树(Abstract Syntax Tree)的代码模式匹配工具,可以识别特定的代码结构模式而不仅仅是文本匹配。本文利用 137 条精心构造的 AST-Grep 规则来检测代码中的冗余模式,例如不必要的中间变量赋值、可以用内置函数简化的循环、重复的条件检查等。相比简单的正则匹配,AST-Grep 能够捕获语义级别的代码冗余。
AST-Grep 规则是本文计算冗余度(verbosity)指标的重要组成部分,用于自动识别智能体生成代码中的低质量模式。
结构克隆(Structural Duplication)
代码克隆检测的一种形式,用于识别代码库中结构相似或完全重复的代码片段。本文使用克隆行数除以总代码行数(LOC)来量化结构性重复。常见的克隆类型包括:完全相同的代码复制(Type-1)、仅有变量名差异的代码(Type-2)、以及功能相似但实现略有不同的代码(Type-3)。智能体在迭代过程中经常通过复制粘贴来添加新功能,导致大量结构性克隆。
结构性克隆是计算冗余度指标的另一个重要组成部分,与 AST-Grep 规则共同构成完整的冗余度度量体系。
迭代式软件开发
一种软件开发范式,开发者需要在已有代码基础上反复添加新功能、修改现有功能。每次迭代都基于之前版本的代码,早期的设计决策会直接影响后续扩展的难度。例如,如果开发者在第一版中硬编码了语言特定的逻辑,那么后续添加新语言支持时就需要大规模重构。这种范式与单次(one-shot)开发形成对比,后者每次任务都是从零开始。
本文的核心创新就是将编码智能体的评估从单次范式转向迭代范式,这更贴近真实的软件开发场景,也揭示了单次评估无法发现的质量退化问题。
研究动机
现有的编码智能体基准测试存在一个根本性的设计缺陷:它们采用单次评估(single-shot evaluation)的范式,即智能体只需针对一个完整的任务规格生成一次代码。这种设置系统性地掩盖了设计决策问题——智能体可以选择任何架构,因为它们不需要考虑未来的扩展需求。例如,SWE-bench、HumanEval 等主流基准都采用这种单次评估方式,它们只能测量智能体是否能为当前规格生成正确代码,而无法评估这些代码在面对未来变更时是否仍然可扩展。更具体地说,如果一个智能体在实现搜索功能时使用正则表达式硬编码了模式匹配逻辑,当后续任务要求支持结构化模式匹配(如 AST 匹配)时,整个架构都需要重写。但单次评估基准永远不会暴露这类问题。虽然近期出现了一些多轮或长周期编码基准(如 EvoCodeBench),但它们通过分解单体解决方案为依赖有序的子问题来构造迭代任务,或者从成熟开源仓库的提交历史中提取任务,这些做法都无法真正测试迭代编码——因为智能体从未为其早期设计决策付出代价。
本文的目标是本文的具体目标是创建一个全新的基准测试框架 SlopCodeBench(SCBench),专门用于测量编码智能体在反复扩展自身代码时的代码质量演变。该基准需要满足三个核心目标:第一,迫使智能体做出真实的架构设计决策,这些决策会直接影响后续扩展的难度;第二,除了正确性之外,还要引入可量化的代码质量指标来捕捉智能体代码的退化模式;第三,通过与人类代码库的对比校准,建立智能体代码质量的合理参照系。最终,作者希望通过这个基准回答一个关键问题:编码智能体能否在迭代开发中保持代码质量和可扩展性?
与已有工作不同的是,本文的独特切入角度在于三个方面。首先,与现有迭代基准不同,SCBench 要求智能体在自己的代码上构建,而不是在人类编写的代码上修改——这使得智能体必须为其早期设计决策承担后果。其次,SCBench 采用黑盒、语言无关的问题设计:所有问题只指定 CLI 或 API 边界上的可观察行为,不规定内部接口,也不暴露测试套件。这迫使智能体自行做出架构决策,同时确保评估不依赖特定语言的生态系统。第三,本文引入了两个全新的轨迹级质量指标——结构腐化(structural erosion)和冗余度(verbosity),它们独立于正确性测量,能够捕捉到通过率无法暴露的代码退化。这种多维度评估框架是前所未有的,它揭示了一个关键现象:智能体可以通过检查点同时产生越来越腐化和冗余的代码。
核心方法
SlopCodeBench 的方法论可以分为三个层次来理解。在最高层次,它是一个迭代评估框架,其中每个问题由一系列有序检查点组成,智能体在每个检查点接收新的规格说明并在之前的工作空间上扩展代码。直觉上,这就像真实的软件开发过程——你今天的架构决策会影响明天添加新功能的难度。在技术层面,SCBench 的 36 个问题横跨 196 个检查点,每个问题包含 3 到 8 个检查点。每个检查点只指定 CLI 或 API 边界上的可观察行为,不规定内部结构,测试套件完全对智能体隐藏。在质量评估层面,本文定义了两个独立的代码质量指标:结构腐化测量高复杂度函数中集中了多少复杂性质量,冗余度测量代码中的重复和冗余模式。这两个指标与正确性一起,共同构成对智能体代码的三维评估。
SCBench 的核心创新在于其「自食其果」的评估范式。与之前所有迭代基准不同,SCBench 要求智能体在自己的先前代码上构建,而不是在参考解决方案或人类编写的代码上修改。这意味着智能体在检查点 $i$ 做出的架构选择会直接影响检查点 $i+1$ 的扩展难度。用论文中的形式化表示:$y_i = \pi_\theta(x_i, y_{i-1})$,其中 $y_i$ 是检查点 $i$ 的工作空间,$x_i$ 是新规格,$\pi_\theta$ 是智能体。如果参考解决方案在回合之间替换了智能体的代码,从早期决策到后期退化的因果链就会被切断——这正是其他基准的根本问题。另一个核心创新是「质量高于正确性」的评估哲学:通过率可以保持稳定,即使底层代码变得越来越难以扩展,因此需要专门的质量指标来捕捉这种隐性退化。
方法步骤详情
SlopCodeBench 的评估流程包括以下步骤。第一,问题构建:36 个问题由论文作者手工编写,每个问题包含有序的检查点序列。问题要么是全新设计,要么受流行代码仓库启发。每个问题都经过两阶段审查——提案阶段确保问题有意义地测试设计决策,验证阶段通过实际运行智能体来识别和修正模糊或不充分的测试用例。第二,检查点执行:每个检查点在全新的 Docker 容器中运行,以非 root 用户执行,只有工作目录在检查点之间持久化。智能体只能看到当前规格和之前的工作空间,看不到之前的对话上下文。这确保了智能体必须基于代码的当前结构来推理变更。第三,解决方案评估:每个检查点的测试通过子进程或 API 与解决方案交互,测试输出经过标准化处理。测试分为四类:核心测试(Core)、错误测试(Error)、功能测试(Functionality)和回归测试(Regression,包含所有先前检查点的测试)。第四,质量度量:结构腐化通过公式 $Erosion = \frac{\sum_{f \in F} I[CC(f) > 10] \cdot mass(f)}{\sum_{f \in F} mass(f)}$ 计算,其中 $mass(f) = CC(f) \times \sqrt{SLOC(f)}$。冗余度通过 $Verbosity = \frac{|AST\text{-}Grep\ 标记行 \cup 克隆行|}{LOC}$ 计算。第五,与人类代码校准:收集 473 个 Python 仓库(从不到 100 星的业余项目到超过 10k 星的主流框架),对每个仓库随机采样最多 30 个修改源代码的提交,共 13667 个提交作为参照系。
技术新颖性
SCBench 的技术新颖性体现在多个层面。首先,在基准设计层面,它是第一个真正实现「自食其果」迭代评估的基准。之前的迭代基准要么重置智能体的工作空间、要么在人类代码上修改、要么提供测试反馈——这些做法都切断了早期决策与后期退化之间的因果链。SCBench 的设计确保了这个因果链的完整性。其次,在质量度量层面,结构腐化和冗余度是两个全新的轨迹级指标。结构腐化创新性地将圈复杂度与代码行数结合为「复杂性质量」$mass(f) = CC(f) \times \sqrt{SLOC(f)}$,其中平方根压缩了大小因子,使复杂度占主导地位。冗余度则结合了 AST-Grep 模式匹配和结构克隆检测,前者基于 137 条针对常见冗余模式的规则,后者使用克隆行数标准化。这两个指标测量不同的失败模式——代码可以在不集中复杂度的情况下变得更冗余,复杂度也可以在不显著增长的情况下集中在某些函数中。第三,在问题设计层面,语言无关的黑盒合约设计是独特的:所有问题只描述 CLI 和 API 行为,不规定内部结构,这使得评估可以扩展到任何实现语言。
实验结果
本文的实验结果揭示了编码智能体在迭代开发中的严重质量退化问题。在核心发现方面,没有任何智能体能够端到端地完全解决任何问题。GPT 5.5 达到了最高的严格通过率 14.8% 和隔离通过率 28.1%,Opus 4.5 达到了最高的核心通过率 67.3%。关键的是,随着问题的推进,核心通过率和隔离通过率之间的差距从 2.5 倍扩大到 5.4 倍,核心通过率从 64.6% 下降到 35.5%。在质量退化方面,结构腐化在 77% 的轨迹中增加,冗余度在 75.5% 的轨迹中增加。圈复杂度至少为 10 的函数平均数量从 3.6 增加到 23.7,最大圈复杂度从 27.5 增加到 69.0。Opus 4.7 在 forge 问题上的 main() 函数在 8 个检查点中圈复杂度增长了 7 倍,从 38 行增长到 240 行。与人类代码的对比校准显示,智能体代码的冗余度是人类代码的 2.3 倍,结构腐化是人类代码的 2.0 倍。智能体的冗余度每检查点增长 0.0144,结构腐化增长 0.0264;人类的中位数分别是 0.0022 和 0.0053——智能体积累冗余的速度大约是人类的 7 倍,结构腐化的速度大约是 5 倍。在提示策略研究方面,anti-slop 提示可以将初始冗余度降低最多 35.6%(GPT 5.5)、结构腐化降低最多 57.6%(GPT 5.5),但无法阻止迭代退化。质量感知提示还导致每次检查点的成本平均增加 12.1%,正确性下降 2.3 个百分点。
查看结构化数据
| 任务 | 指标 | 本文 | 基线 | 提升 |
|---|---|---|---|---|
| SlopCodeBench 严格通过率(36个问题,196个检查点) | Strict Solve Rate (%) | GPT 5.5: 14.8%, GPT 5.3 Codex: 11.2%, GPT 5.4: 10.7% | Opus 4.5: 9.2%, Opus 4.6: 9.7%, Sonnet 4.6: 7.1% | GPT 5.5 达到最高严格通过率 14.8%,但没有任何智能体能完全解决任何问题 |
| SlopCodeBench 隔离通过率 | Isolated Solve Rate (%) | GPT 5.5: 28.1%, GPT 5.3 Codex: 26.0%, GPT 5.4: 23.5% | Opus 4.7: 20.9%, Opus 4.6: 20.9%, Kimi K2.6: 18.9% | GPT 5.5 达到最高隔离通过率 28.1%,核心与隔离通过率差距从2.5倍扩大到5.4倍 |
| 与473个人类Python仓库的冗余度对比 | Verbosity | 智能体检查点: 0.44 +/- 0.18 | 人类仓库(全部): 0.19 +/- 0.11 | 智能体代码冗余度是人类的2.3倍,增长速度快约7倍 |
| 与473个人类Python仓库的结构腐化对比 | Erosion | 智能体检查点: 0.68 +/- 0.20 | 人类仓库(全部): 0.34 +/- 0.22 | 智能体代码结构腐化是人类的2.0倍,增长速度快约5倍 |
| Anti-slop提示策略对GPT 5.4的影响 | Erosion / Verbosity / Strict Solve Rate | Erosion: 0.28, Verbosity: 0.24, Strict: 9.2% | Just-Solve: Erosion 0.51, Verbosity 0.33, Strict 10.7% | Erosion降低45.1%, Verbosity降低27.5%, 但Strict通过率下降1.5pp,成本增加25% |
局限与改进
SlopCodeBench 存在若干值得关注的局限性。首先,尽管问题设计为语言无关,但由于成本限制,本文只评估了 Python 轨道。不同编程语言的生态系统差异可能导致不同的退化模式,例如静态类型语言可能通过编译器检查抑制某些形式的代码腐化。其次,36 个问题和 196 个检查点的规模虽然比许多现有基准更大,但仍然可能无法全面代表所有类型的软件开发任务——特别是缺乏涉及数据库交互、网络通信、并发处理等真实场景的复杂问题。第三,评估框架假设智能体在每个检查点之间完全失去上下文(只能看到代码,不能看到之前的对话),这与真实的工具使用场景有所不同——大多数现代编码工具(如 Cursor、Claude Code)会保留对话历史。第四,结构腐化和冗余度指标虽然有理论基础,但其阈值选择(如 $CC > 10$)具有一定的人为性,不同的阈值可能导致不同的结论。第五,与人类代码的校准比较存在方法论上的挑战——人类仓库的提交历史包含了大量不同类型的变更(bug 修复、文档更新、重构等),而智能体的检查点专注于功能扩展,这种不对称性可能影响比较的公平性。最后,评估成本非常高昂——GPT 5.5 的完整评估花费约 295.59 美元,Kimi K2.6 的评估时间长达每检查点 26.9 分钟,这限制了基准的可重复性和广泛使用。
独立分析的弱点
本文存在几个值得深入分析的弱点。第一,上下文隔离假设过于理想:每个检查点在全新的 Docker 容器中运行,智能体只能看到当前代码和新规格,无法访问之前的对话历史。这与真实的编码助手使用场景差异很大——开发者通常在连续对话中工作,助手可以引用之前的讨论。这种隔离可能放大了退化效果,因为智能体无法从设计意图的上下文中受益。改进方向是设计保留有限上下文的变体评估,例如允许智能体访问前一个检查点的对话摘要。第二,质量指标的计算依赖于 Python 特定的工具链(Radon 用于圈复杂度、ast-grep 用于模式匹配),这使得扩展到其他语言需要重新实现整个度量管道。改进方向是开发语言无关的中间表示(如基于 LLVM IR 或 Tree-sitter AST 的通用度量)。第三,提示策略研究只测试了两种简单的提示变体(anti-slop 和 plan-first),而实际的智能体系统通常包含复杂的多步提示链、代码审查循环和自我修正机制。改进方向是评估更复杂的提示工程方法和工具增强策略。第四,问题构造完全由论文作者手工完成,虽然有审查流程,但可能存在作者偏见——他们可能倾向于设计能突出退化现象的问题。改进方向是引入社区众包的问题构造流程。
未来方向
本文为多个有前景的研究方向奠定了基础。作者明确提出的方向包括:扩展到更多编程语言(特别是静态类型语言如 TypeScript、Rust),以及测试更复杂的提示策略来缓解退化。基于本文成果可延伸的方向包括:第一,开发「退化感知」的编码智能体,能够在迭代过程中主动监控自身代码质量,并在检测到腐化趋势时触发重构。第二,研究架构恢复技术——当智能体代码已经严重腐化时,如何自动重构以恢复可扩展性。第三,将质量指标整合到智能体的训练目标中,通过强化学习或直接偏好优化来激励高质量代码生成。第四,探索混合评估模式,结合迭代扩展和维护任务(如 bug 修复、性能优化),以更全面地评估智能体的软件工程能力。第五,研究不同智能体架构(如多智能体协作、代码审查智能体)对退化率的影响——多智能体系统可能通过专门化分工来缓解单个智能体的退化倾向。第六,开发实时的「代码健康度」监控系统,将本文的结构腐化和冗余度指标整合到 IDE 中,为开发者提供即时反馈。
复现评估
SlopCodeBench 在可复现性方面做出了较好的努力。论文明确指出完整的问题和代码可在 scbench.ai 获取,这为社区复现提供了基础。数据层面,36 个问题和 196 个检查点都是手工编写的,测试套件包含公开部分(规格说明和示例)和隐藏部分(完整测试),这种设计在保证评估公平性的同时也允许研究者理解问题结构。然而,复现面临几个实际挑战:第一,成本高昂——使用商业 API 评估 15 个模型的完整运行需要数百美元(GPT 5.5 约 295.59 美元,Opus 4.6 约 620.80 美元),这对独立研究者或资源有限的团队构成障碍。第二,时间消耗大——某些模型(如 GLM 5.1、Kimi K2.6)的每检查点平均耗时超过 25 分钟,完整评估一个模型可能需要数十小时。第三,由于评估依赖商业 API,模型版本更新可能导致结果不可复现——同一模型名称在不同时间点可能对应不同的底层实现。第四,473 个人类 Python 仓库的校准数据集虽然描述了收集方法(随机采样最多 30 个提交),但没有提供具体的仓库列表,这使得精确复现校准结果有一定难度。总体而言,论文在开源和方法透明度方面做得不错,但高成本和 API 依赖是主要的复现障碍。
论文图表