别 教 智能 体 怎么 做 TDD, 告诉 它 该 跑 哪些 测试
编码智能体的榜单几乎只看有没有修好。TDAD 在改代码之前用代码和测试的依赖图指出该核验的测试。在 100 条 SWE-bench Verified 上,测试级回归率从 6.08% 降到 1.82%。只加测试驱动的流程说明、不指出具体测试,回归率反而升到 9.94%。

本文目录
本文是 arXiv 论文 TDAD: Test-Driven Agentic Development – Reducing Code Regressions in AI Coding Agents via Graph-Based Impact Analysis(arXiv:2603.17973)正文第 1 节至第 8 节的中文译文,由智测团队翻译。参考文献未逐条展开。正文保留了两阶段实验表、影响分析权重和自动改进循环里的数字。
1 引言
基于大语言模型的编码智能体,已经能解决相当一部分真实软件问题。在 SWE-bench Verified 上,前沿智能体能解决流行开源仓库里超过 70% 的 GitHub Issue。评测几乎只看解决率:智能体补丁通过该 Issue 专用测试的比例。一个互补的问题很少被注意:这份补丁弄坏了多少原先通过的测试?近期证据表明,回归和持续集成失败,是智能体提交的拉取请求被拒绝的主要原因之一。
没有依赖意识,回归很难防。智能体要么跑全部测试,对大代码库太慢;要么只跑改动文件附近的测试,漏掉间接依赖。这和经典的回归测试选择类似,但智能体场景多了新要求:改动是程序生成的,智能体的上下文窗口有限,而且验证必须发生在提交之前,而不是事后的持续集成流水线里。在基线实验中,一个不加额外信息的智能体在 100 条实例上造成 562 次由通过变为失败的测试,平均每个生成的补丁弄坏 6.5 个测试。
SWE-bench 的评测框架其实已经收集了测回归所需的数据。PASS_TO_PASS 记录黄金补丁之前就通过、之后仍应通过的测试。这些数据没有出现在榜单排名里。METR 发现,大约一半在 SWE-bench 上通过的补丁,真实维护者不会合并。Ehsani 等人表明,持续集成失败是智能体拉取请求被拒的主要原因。回归率应当和解决率一样,成为一等指标。
本文提出 TDAD(Test-Driven Agentic Development)。它是一个开源工具,在人工智能编码智能体改代码之前做影响分析。TDAD 建立源码和测试之间的依赖图,使智能体在提交补丁前知道该核验哪些测试,并能自行改正。图 1 是这条工作流。关键看法是:不必教智能体怎么做测试驱动开发,要告诉它该检查哪些测试。运行时智能体只需要 grep 和 pytest,不需要图数据库、MCP 服务或接口调用。
评测在 SWE-bench Verified 上分两阶段:先用一个模型在 100 条实例上做受控比较,再用另一个模型和另一个智能体框架做泛化。四条发现如下。
第一,回归减少约 70%。阶段 1 用 Qwen3-Coder 30B、单智能体、100 条实例。TDAD 把测试级回归率从 6.08% 降到 1.82%,由通过变失败的次数从 562 降到 155。
第二,测试驱动提示的悖论。同一阶段里,消融实验只加测试驱动的流程说明(先写测试再实现),却不告诉智能体该查哪些具体测试。回归率升到 9.94%,比不加任何说明更差。没有对准上下文的流程说明,会起反作用。
第三,作为智能体技能时,解决率上升。阶段 2 用另一个模型 Qwen3.5-35B-A3B 加 OpenCode,25 条实例。TDAD 把解决率从 24% 提到 32%,生成率从 40% 提到 68%。
第四,自主自我改进。在 10 条实例的子集上,自动改进循环迭代修改 TDAD 自己的配置,把解决率从 12% 提到 60%,回归率为 0%。
贡献有五条。开源的、基于图的测试影响分析工具,安装命令是 pip install tdad。一套把回归率提升为一等指标的基准方法。跨两个模型和智能体框架的经验证据。一个用于迭代改进工具的自主循环。全部代码、数据和 28 次实验以 MIT 许可发布。
2 相关工作
2.1 人工智能编码智能体与基准
SWE-bench 在 12 个流行 Python 仓库的 GitHub Issue 上评智能体,是编码智能体的主要基准。Verified 子集为 500 条实例提供人工核验过的地面真值。SWE-Agent 用面向仓库导航的智能体–计算机接口。AutoCodeRover 把代码搜索和基于频谱的故障定位合在一起。OpenHands 提供跨多个基准开发和评测编码智能体的统一平台。
生态还在变。SWE-smith 从任意 Python 代码库自动合成任务,产出 5 万条实例,训练出的开源模型在 SWE-bench Verified 上达到 40.2%。SWE-Bench++ 扩到 11 种语言、1.1 万条实例。SWE-CI 把焦点从一次性修缺陷转到长期代码库维护,要求智能体处理跨越数月的提交序列。
这些工作主要看解决率。回归行为即便被报告,也只是附带。SWE-bench 框架确实会执行由通过变失败的测试,但结果不上榜。Ehsani 等人研究 GitHub 上 3.3 万个由智能体撰写的拉取请求,发现持续集成失败和回归是最常见的拒绝原因。只看解决率不够。本文认为这种省略造成一种扭曲激励:奖励激进打补丁,不管副作用。
2.2 回归测试
回归测试选择和优先级排序在软件工程里历史很长。Elbaum 等人综述持续集成环境里改进回归测试的技术,指出即便简单的选择策略也能大幅减少执行时间。Legunsen 等人大规模评估静态回归测试选择,发现类级依赖跟踪的精确率不错。Gligoric 等人用文件系统监视做动态的文件级依赖跟踪。Chianti 用调用图差分,对 Java 程序做方法级变更影响分析。
TDAD 把这些经典想法用到人工智能编码智能体上。差别有三点。时机:传统方法在变更提交之后选择要跑的测试,以节省持续集成时间;TDAD 在智能体提交之前运作,使它能自行改正,而不是事后才发现。消费者:传统方法的输出喂给测试运行器或流水线;TDAD 的输出是一份静态文本,供大模型智能体用 grep 读取,以尊重上下文窗口。目标:传统方法在固定测试套件上尽量少花执行时间;TDAD 要减少回归,办法是指出智能体该核验哪些测试,而不只是指出该跑哪些测试。
2.3 基于图的代码分析
代码属性图把抽象语法树、控制流图和程序依赖图合在一起,用于漏洞检测。GraphRAG 表明,对复杂推理,图结构检索胜过扁平的向量搜索。GRACE 为仓库感知的代码补全构造多层代码图,包括文件结构、抽象语法树、调用图和类层次,比先前的基于图的检索增强基线提高 8%。TDAD 用类似的「图优先」原则,但任务不同:不是代码补全,而是遍历显式的代码–测试依赖图,以较高精确率找出受影响的测试。
2.4 测试驱动开发与人工智能智能体
测试驱动开发规定先写测试再写实现,用紧的反馈回路及早抓住回归。TDAD 借用它的核心看法,也就是提交前先验证,但把「写测试、变红、变绿、重构」这套程序,换成上下文指导:不吩咐智能体按步骤做,而告诉它哪些具体测试有风险。这个区分直接引出第 5.2 节的悖论:没有上下文的流程说明反而增加回归。Cui 提出一个测试驱动基准,测试用例既是提示也是验证。他发现,对测试驱动的成功,遵循指令和上下文学习比一般编码能力更重要,而且指令变长时成绩下降。这与本文一致:较小的模型从简短、对准的上下文里受益,多于从冗长的流程说明里受益。
Rehan 独立提出另一个「测试驱动的人工智能智能体定义」框架,通过迭代的测试–精炼循环,把行为规格编译成智能体提示,达到 97.2% 的回归安全。两者共享测试驱动的看法,缩写甚至都是 TDAD,但问题不同。Rehan 验证的是智能体行为是否符合规格。本文验证的是智能体生成的代码补丁。
3 系统设计
3.1 总体结构
图 2 是流水线。阶段 1 是索引:解析 Python 仓库,建立代码–测试依赖图。阶段 2 是影响分析:找出受改动文件影响的测试,导出静态文件 test_map.txt。智能体收到这个文件,外加一份 20 行的技能定义。运行时不需要 MCP 服务、接口调用或图数据库。智能体对测试地图做 grep,找出要核验的测试。
3.2 图模式
图有四种节点、五种边,见表 1。节点是结构单元,边来自抽象语法树分析的静态关系。
| 种类 | 实体 | 主要属性 |
|---|---|---|
| 节点 File | Python 源文件 | 路径、内容哈希 |
| 节点 Function | 顶层函数 | 名称、文件、行、签名 |
| 节点 Class | 类定义 | 名称、文件、基类 |
| 节点 Test | 测试函数或方法 | 名称、文件、是否为测试 |
| 边 CONTAINS | 文件指向函数或类 | 结构包含 |
| 边 CALLS | 函数指向函数 | 静态调用解析 |
| 边 IMPORTS | 文件指向文件 | 导入跟踪 |
| 边 TESTS | 测试指向函数或类 | 测试与代码的连接 |
| 边 INHERITS | 类指向类 | 基类关系 |
3.3 索引流水线
索引器有三部分。
抽象语法树解析器用标准库 ast 解析每个 Python 文件。抽出函数定义及其签名、行范围和文档字符串;类定义及其基类和方法;导入语句;函数体内的调用目标。递归访问者同时处理简单名和属性链。测试文件按命名约定识别:文件名是 test_.py 或 _test.py,函数名是 test_,类名是 Test。
图构建器填充节点和边。每个文件产生一个 File 节点,以及通过 CONTAINS 连上的 Function 或 Class 子节点。调用目标用模块范围的名字解析,产生 CALLS。导入产生 IMPORTS。类继承产生 INHERITS。
测试连接器建立 TESTS 边,把测试节点连到它们演练的代码。这是最关键的部分,因为 Python 项目组织测试的约定很多。三种策略按优先级:(1)命名约定,例如 test_foo.py 对应 foo.py,包括科学计算 Python 里常见的下划线前缀变体;(2)前缀匹配,逐步截短测试文件词干,找最吻合的源文件;(3)目录邻近,当一个词干匹配多个源文件时用来消歧。对单体测试模块,例如 Django 的 tests.py,用专门的邻近算法,映射到最近的非测试祖先目录里的源文件。
3.4 影响分析
给定改动文件,四种策略并行运行,再合并分数。见表 2。分数公式是:
score = (1 − c_w) × 策略权重 + c_w × 置信度
置信度权重 c_w 取 0.3。置信度在 0 到 1 之间,反映链接强度:直接 TESTS 边为 1.0,传递调用链为 0.56,覆盖为 0.5,导入为 0.45。一个测试经多种策略出现时,只保留最高分。测试分三档:高(不低于 0.8)、中(0.5 到 0.8)、低(低于 0.5),直到可配置上限,默认 50。三种权重画像:保守(偏精确率)、平衡(默认)、激进(偏召回)。
常数的理由。c_w = 0.3 把 70% 的分数给策略权重,30% 给链接质量,使关系类型占主导,同时仍奖励更强的证据。1.0、0.56、0.5、0.45 单调下降:直接 TESTS 边是地面真值式的关联,传递调用链随跳数衰减,文件级覆盖更粗,导入是最弱信号。这些值先按图结构启发式设定,再由第 5.5 节的自动改进循环精炼。三种画像让使用者不必改公式就能适配不同代码库。
表 2 是平衡画像下的策略和基础权重。
| 策略 | 权重 | 含义 |
|---|---|---|
| 直接 | 0.95 | 直接测试被改的代码 |
| 传递 | 0.70 | 经 1 到 3 跳调用链到达被改代码 |
| 覆盖 | 0.80 | 文件级依赖 |
| 导入 | 0.50 | 导入了被改的文件 |
3.5 作为技能接入智能体
TDAD 用两份静态产物接入。test_map.txt 把源文件映射到测试文件,一行一条,可以用 grep。SKILL.md 只有 20 行:(1)修缺陷;(2)在 test_map.txt 里 grep 相关测试;(3)跑这些测试并修失败。简短被证明很关键。自动改进循环里,把 SKILL.md 从 107 行减到 20 行,单独就把解决率从 12% 翻到 50%,也就是四倍。
3.6 后端
TDAD 最初用 Neo4j 加 Docker 存图。迭代之后,默认改成 NetworkX 内存后端,去掉 Docker。安装是 pip install tdad,运行时不再依赖外部服务。图用 pickle 存在 .tdad/graph.pkl。大规模部署仍可用环境变量 TDAD_BACKEND=neo4j。两种后端暴露同一套 GraphDB 接口。
4 实验设置
4.1 基准
评测用 SWE-bench Verified,500 条经人工核验的 GitHub Issue,来自 12 个流行 Python 仓库,包括 Django、scikit-learn、sympy、matplotlib、astropy、Flask、pytest 等。每条实例有 Issue 描述、Issue 创建时的仓库快照、黄金补丁所修复的 FAIL_TO_PASS 测试,以及应保持通过的 PASS_TO_PASS 测试。阶段 1 用规范顺序的前 100 条。阶段 2 用为多样性选出的 25 条。
4.2 模型与智能体
阶段 1 用 Qwen3-Coder 30B,Q4_K_M 四比特量化,经 llama.cpp 在消费级硬件上服务。上下文窗口 3.2 万词元,温度 0,以求确定输出。每条实例最多 15 分钟生成补丁。这一阶段在三种提示配置上评回归减少。选较小的本地模型有三个理由:说明 TDAD 的好处不依赖前沿规模的模型;实验可复现且没有接口费用;在每一个上下文词元都要紧的条件下加压测试。
阶段 2 用 Qwen3.5-35B-A3B,四比特量化,混合专家、激活参数 30 亿,经 MLX 在 Apple Silicon 上服务,智能体是 OpenCode v1.2.24。这一阶段把 TDAD 作为可复用技能、配 NetworkX 后端来评,模型、量化框架和智能体都与阶段 1 不同,用来看方法能否泛化。
作为参照,Qwen3-Coder 30B 在功能完整的脚手架(SWE-Agent,100 轮以上)上,SWE-bench Verified 大约 52%。Qwen 报告 Qwen3.5-35B-A3B 为 69.2%。本文基线更低(31% 和 24%),反映的是四比特量化、消费级硬件、更短的上下文和更简单的脚手架。这些条件是故意用来在资源受限下加压测试 TDAD。
表 3 是两种阶段的配置。
| 阶段 | 配置 | 说明 |
|---|---|---|
| 1 | 原样 | 默认提示,没有测试驱动说明,也没有图 |
| 1 | 测试驱动提示 | 只加测试驱动的工作流说明 |
| 1 | 图加测试驱动 | 测试驱动说明,加上 SKILL.md 和 test_map.txt |
| 2 | 基线 | OpenCode,没有 TDAD 技能 |
| 2 | TDAD 技能 | OpenCode 加上 TDAD 技能和 NetworkX |
4.3 评测协议
补丁用 SWE-bench 的 Docker 框架评测。对每条实例:检出 Issue 基线提交上的仓库;应用智能体补丁;跑由失败变通过的测试,看是否解决;跑由通过应保持通过的测试,看回归。每条实例在隔离容器里评。空补丁不计入由通过变失败的评测。
四个指标。解决率:全部由失败变通过的测试都通过的实例比例。生成率:产出非空补丁的比例。测试级回归率:全部由通过变失败的次数,除以全部此类测试数。这是主要回归指标,因为它区分弄坏 1 个测试和弄坏 100 个。实例级回归率:生成的补丁里,至少有 1 次由通过变失败的比例。
5 结果与分析
5.1 阶段 1:减少回归(100 条)
表 4 是 Qwen3-Coder 30B 在 100 条上的结果。向下箭头表示越低越好。灾难性回归指该实例上全部应由通过保持通过的测试都失败了。
| 指标 | 原样 | 仅测试驱动提示 | 图加测试驱动 |
|---|---|---|---|
| 解决率 | 31% | 31% | 29% |
| 生成率 | 86% | 75% | 74% |
| 应保持通过的测试总数 | 9,245 | 8,040 | 8,536 |
| 由通过变失败的次数 | 562 | 799 | 155 |
| 测试级回归率 | 6.08% | 9.94% | 1.82% |
| 实例级回归率 | 30.2% | 33.3% | 33.3% |
| 灾难性回归次数 | 3 | 5 | 1 |
图加测试驱动把由通过变失败的次数减少 72%(562 到 155),把回归率减少 70%(6.08% 到 1.82%)。相对只加测试驱动提示,失败次数少 81%(799 到 155)。灾难性回归从原样的 3 次、只加提示的 5 次,降到 1 次。
解决率略降 2 个百分点,原因是空补丁更多(26% 对 14%)。测试地图指出风险时,智能体更常放弃。在真正生成出来的补丁里,图加测试驱动解决 Issue 的可能性并不更低。
分母说明。三种配置的非空补丁数不同,分别是 86、75 和 74,因此应保持通过的测试池也不同。实例级回归率 30.2%、33.3%、33.3% 看起来和测试级结果矛盾。绝对数上,图加测试驱动的回归实例更少:74 个补丁里 25 个,原样是 86 个里 26 个。比例更高,是生成率更低造成的分母效应。两个指标都报,但以测试级回归率为主,因为它抓住严重程度:弄坏 322 个测试和弄坏 1 个,性质不同。
表 5 是若干严重回归实例。数字是失败数除以该实例应保持通过的测试总数。破折号表示空补丁,未评测。
| 实例 | 原样 | 仅测试驱动提示 | 图加测试驱动 |
|---|---|---|---|
| astropy-13977(322) | 322/322 | 4/322 | 12/322 |
| astropy-8872(80) | 80/80 | 80/80 | — |
| django-13089(352) | 4/352 | 352/352 | — |
| django-11532(148) | — | 148/148 | — |
| django-11299(103) | — | 103/103 | — |
在 astropy-13977 上,原样 322 个全失败,图加测试驱动只失败 12 个。在 django-13089 上,只加测试驱动提示造成全部失败(352/352),原样只失败 4 个。没有定位的测试驱动提示,可以比什么都不做更糟。
5.2 测试驱动提示的悖论
没有图上下文的测试驱动提示,把回归率从 6.08% 升到 9.94%,由通过变失败的次数比原样多 42%。两个因素。
冗长提示伤害小模型。测试驱动提示用流程说明占掉上下文词元,把 30B 模型做准确修改所需的仓库上下文挤出去。
有野心但没有定位。被提示的智能体尝试更野心的修复,碰到更多文件。没有图告诉它该核验哪些测试,这种野心造成附带损伤。只加提示时有 5 次灾难性回归,原样是 3 次。图加测试驱动同时对付这两点:20 行的 SKILL.md 腾出上下文,测试地图把注意力集中到有风险的测试上。
消融。先前实验把两部分拆开。没有图上下文时,把提示从 119 行缩短到 49 行,解决率从 30% 降到 20%。说明单靠提示变短,解释不了图加测试驱动的改进。反过来,没有图上下文时把提示加长(49 行的原样对 119 行的测试驱动),解决率都是 31%。额外的流程文字单独既无帮助也无伤害。改进需要从图来的上下文:短提示加上测试地图。
实际含义:对较小的模型,上下文(该查哪些测试)胜过程序(怎么做测试驱动开发)。
5.3 解决率与回归的权衡
解决率从 31% 降到 29%,这 2 个百分点是有意的保守偏向。测试地图指出高回归风险时,图加测试驱动产生更多空补丁(26% 对 14%)。智能体「知道自己不知道」,于是放弃。
实验里没有任何一种配置产生既解决了问题、又带回归的补丁。三种配置的「已解决且有回归」都是 0。对这个模型,正确修复和回归大体是分开的失败模式:补丁要么干净地解决问题,要么造成损坏,很少两者同时。这对智能体设计有含义:像 TDAD 这种压掉有害补丁的机制,对解决质量的代价很小。
5.4 阶段 2:作为智能体技能(25 条)
阶段 1 和自动改进循环之后,TDAD 被包装成可复用技能,后端是 NetworkX,没有 Docker,并用不同的模型和智能体框架评测。表 6 是结果。
| 指标 | 基线 | TDAD 技能 | 差值 |
|---|---|---|---|
| 已解决 | 6/25(24%) | 8/25(32%) | +8 个百分点 |
| 已生成 | 10/25(40%) | 17/25(68%) | +28 个百分点 |
| 已生成中的解决 | 6/10(60%) | 8/13(62%) | +2 个百分点 |
| 空补丁 | 15 | 8 | −7 |
| 回归率 | 0% | 0% | 0 |
表 6 里「已生成」是 17/25,而「已生成中的解决」的分母写成 13。8/13 约为 62%。两列分母不一致,按原文照录,没有改成同一个数。
作为技能,TDAD 把解决率提高 8 个百分点(24% 到 32%),生成率提高 28 个百分点(40% 到 68%)。四个原先为空的实例在有技能时被解决。两个基线里已解决的实例因模型非确定性丢失。
改进机制和阶段 1 不同。这个较小的实例集上两边回归率都是 0%,测试地图不是靠减回归起作用,而是提供结构上下文,帮助智能体生成更多补丁。代码–测试图有两个用途:指出该核验的测试(阶段 1 里减少回归),以及画出代码库结构(阶段 2 里改善导航和生成)。
5.5 自动改进循环
受 Karpathy 的 autoresearch 启发,作者做了一个外层循环,由智能体迭代修改并评测,自主改进 TDAD 的组件。仓库是 https://github.com/karpathy/autoresearch 。
每一轮:(1)一个 Claude Code 智能体拿到全部实验历史,对 TDAD 源文件做一处集中修改,例如 SKILL.md、impact.py、ast_parser.py;(2)单元测试做门禁,失败就立刻回滚;(3)用 5 到 25 条 SWE-bench 实例测生成率和解决率;(4)与已知最好分数比较。变好就更新最好快照,变差就回滚,解决率相同的横向移动保留,以便探索。完整性防护防止钻空子:评测脚本做 SHA-256 校验并设为只读;连续 5 次回滚就强制恢复到最好快照。
表 7 是 15 轮、每轮 10 条实例的评测。只列出被接受的轮次,11 轮被回滚。
| 轮次 | 改动 | 生成率 | 解决率 | 关键改动 |
|---|---|---|---|---|
| 1 | SKILL.md | 50% | 50% | 从 107 行简化到 20 行 |
| 5 | impact.py | 70% | 60% | 导出静态测试地图 |
| 12 | impact.py | 70% | 60% | 路径邻近打分 |
| 13 | impact.py | 80% | 60% | 基于导入的映射 |
| 循环前 | — | 28% | 12% | — |
| 循环后最好 | — | 80% | 60% | — |
| 原样基线 | — | 40% | 24% | — |
15 轮里接受 4 处改动,接受率 27%。生成率从 28% 升到 80%,解决率从 12% 升到 60%,所有轮次回归率都是 0%。
影响最大的单次改动是第 1 轮:把 SKILL.md 从 107 行、分 9 个阶段的详细测试驱动说明,收成 20 行:修复、grep、核验。仅此就把解决率从 12% 提到 50%,四倍。确认激活参数只有 30 亿的小模型用不了冗长工作流。随后几轮改进测试映射启发式:第 5 轮加上静态 test_map.txt 导出,第 12 轮加上目录邻近消歧,第 13 轮加上基于导入的回退匹配。
11 次被拒同样有信息:扩大抽象语法树解析器、重组图构建器,或把 SKILL.md 写得更规定性,都会降低解决率。循环在第 5 轮左右收敛,之后收益递减。
6 讨论
6.1 上下文胜过程序
给人工智能编码智能体做工具时,主流做法是写带分步指令的详细提示。对较小的模型,这可能适得其反。TDAD 的成功说明,露出正确信息(哪些测试有风险、哪些文件相关)比规定工作流(先写测试、再实现、再重构)更重要。
这与检索增强生成里的观察一致:上下文质量是输出质量的主要决定因素。给智能体做工具,应优先信息密度,而不是程序完备:塞进紧上下文窗口的短而实的上下文,胜过把有用信息挤出去的冗长指令。
6.2 回归作为一等指标
当前人工智能编码基准造成扭曲激励:只要解决了就给奖励,不管附带损坏。实践里,解决一个问题却引入三处回归的补丁,价值是负的。METR 把这个缺口说具体了:scikit-learn、Sphinx 和 pytest 的维护者审阅 296 个在 SWE-bench 上通过的补丁,大约一半不会被合并,回归和代码质量是主要拒绝原因。作者主张把回归率和解决率一起作为标准报告。数据 SWE-bench 的 Docker 框架已经在收,只是需要出现在评测报告和榜单上。
一个简单的复合指标可以同时抓住两维:净分数等于解决率减去 α 乘以回归率,其中 α 大于 1,反映回归相对于漏修的不对称代价。
6.3 局限
规模和统计功效。阶段 1 是 100 条,阶段 2 是 25 条,没有正式的显著性检验。阶段 1 的效应大(失败次数减少 72%,562 对 155),说明有实践意义,但在这个样本量上,较小的效应可能是噪声。100 条的范围来自硬件和时间:实验都在消费级硬件、本地模型上跑,每条要几分钟推理;每种配置跑满 500 条要好多天。资源允许时应在全部 500 条上确认。
只有两个模型。都是较小的本地模型。前沿模型未必表现出同样的测试驱动提示悖论。
只有 Python。扩到其他语言需要语言专用的解析。Tree-sitter 可以统一这件事。
静态分析。抓不住动态分派、猴子补丁或运行时生成的代码。
自动循环的规模。每轮只在 10 条实例上评。
6.4 效度威胁
内部效度。配置是顺序跑的,不是交错跑的,与时间有关的因素可能系统性地偏向较早的运行。温度 0 和 Docker 隔离用来缓解。自动改进循环固定用 10 条实例,有过拟合风险。被接受的改动是结构性的(测试连接启发式、提示简化),并且泛化到了不重叠的 25 条阶段 2 集合。
外部效度。SWE-bench Verified 只来自维护良好、测试很多的 Python 仓库。测试套件稀疏、非 Python,或单体仓库,对基于图的影响分析反应可能不同。两个模型都是较小的本地模型。上下文更长的前沿模型未必表现出同样的悖论,因为冗长指令占可用上下文的比例更小。
构念效度。测试级回归率对所有由通过变失败一视同仁,不管测试重要性或业务影响。工具函数的单元测试失败,和关键接口的集成测试失败,计成一样。实例级回归率把任何回归当成二值,部分缓解这一点,但两个指标都不抓住严重程度。另外,应保持通过的测试集由 SWE-bench 框架定义,未必覆盖补丁影响到的全部代码路径。
7 结论
TDAD 是一个开源工具和方法,用基于图的测试影响分析减少人工智能编码智能体的回归。在 SWE-bench Verified 上、跨两个模型和智能体框架,阶段 1 把测试级回归减少 70%,阶段 2 作为技能把解决率提高 8 个百分点。实验揭示测试驱动提示的悖论:流程说明增加较小模型的回归,而从图来的上下文减少回归。自动改进循环把解决率从 12% 提到 60%,回归率为 0%。
未来工作包括用 Tree-sitter 扩到多种语言,接入动态覆盖以提高影响分析的精确率,并用前沿模型(例如 Claude Opus 4.6、GPT-5.4)看这个悖论在更大规模上是否还在。作者主张社区采用同时抓住解决和回归的复合指标,使智能体按净贡献被评测。
8 数据
代码、补丁、评测日志和 28 次实验记录在 https://github.com/pepealonso95/TDAD ,MIT 许可。安装命令是 pip install tdad。生成式人工智能被用来协助写实现代码、整理实验日志、概括实现细节和改进文稿措辞。实验设计、工作实施、结果解释和最终内容的核验由作者完成。致谢中,Sergio Yovine 部分由乌拉圭 ANII 资助,编号 FMV_1_2023_1_175864。
觉得有用,转给同事
微信扫码
用微信扫一扫,在手机上打开后即可转发。