Aioga
AI资讯 / 行业动态
返回 AI资讯

代理在多大程度上运用了测试/验证技术?

Hacker News 热门(buzzing.cc 中文翻译)Aioga 编辑团队2026-09-08T11:34:04.000Z热度 58

文章探讨了AI智能体在多大程度上实际运用测试与验证技术。作者基于自身观察与经验,分析了当前智能体在代码生成等任务中对测试环节的利用程度,指出其表现与理想状态存在差距。文章属于技...

行业动态Hacker News 热门(buzzing.cc 中文翻译)

今日 AI 情报摘要

文章探讨了AI智能体在多大程度上实际运用测试与验证技术。

作者基于自身观察与经验,分析了当前智能体在代码生成等任务中对测试环节的利用程度,指出其表现与理想状态存在差距。 文章属于技术评论与分析,未提供具体模型名称、版本号或量化评测数据。

中文正文 · AI 翻译

我们之前提到,虽然让编码代理使用有效的测试技术比以往任何时候都更容易达到特定的质量标准,但软件质量似乎在下降:/ai-coding/,这表明开发者使用的默认设置可能并不太有效。在这里,我们测试简单地指导代理使用特定技术或库是否能提高实现的正确性,作为一种测试,看看当由没有测试经验但可能听说过应该应用某些技术或使用特定库的人指导时,代理的效果如何。

我们将重新使用在这篇关于代理程序语言效果比较中讨论的 Zstd 实现评估:/pl-tokens/,而是比较在给代理提供实现 Zstd 的提示时,不同测试技术和测试库的表现,以及不同附加说明,如“使用测试驱动开发”、“使用 Lean 4”、“使用 QuickCheck”、“使用基于属性的测试”等。我还运行了一些其他评估,例如 IMAP RFC 的评估,这里会简要讨论。

我事先登记了一些关于各条件表现的猜测:

下面,我们有一张非常杂乱的图,显示了测试条件的结果(codex 配合 GPT-5.6 Sol,使用 medium 和 xhigh 努力)。在查看数据时,我倾向于偏好比大多数人更加密集和杂乱的图,例如这里的第一张图:/android-updates/。因为大多数人会觉得这种图杂乱到难以阅读,所以我在向他人展示信息时,倾向于将信息拆分成一系列图表,每张图显示较少信息。出于下面讨论的原因,我在这里不会这样做,仅仅展示这张极其杂乱的图,其中 x 轴为成本,y 轴为通过 100%(隐藏)测试的运行比例,取每个条件和努力下 80 次运行的平均值(鼠标悬停在项目上显示 bootstrap 协方差,50% 不确定性:https://statmodeling.stat.columbia.edu/2016/11/05/why-i-prefer-50-to-95-intervals/,并尝试让相似的事物颜色相近,例如正式方法用蓝色调,基于属性的测试用绿色调等):

我们可以看到的一点是,没有任何一种方法表现特别出众。然而,默认(没有额外指令)表现明显高于平均水平。看看xhigh,平均来看,与形式化方法相比,模糊测试和基于PBT的条件表现略好,而在中等水平时情况则更加混合。测试相关技能codex推荐我们尝试的方法表现欠佳,尽管我们的快速自定义技能表现尚可(一个主要区别在于我们的技能旨在引导远离默认行为,朝更有效的行为发展,而其他技能更像是教程)。TDD表现不佳,如预期(有一项技能还建议代理使用TDD,而在代理尝试遵循指令的情况下,该技能也表现不佳)。

如果我们仔细看看代理所做的事情,很快就会发现,通常来说,代理并不擅长使用这些工具或技术。正如我们在这里所指出的:/ai-coding/,以及所有我交流过的人也指出的那样,代理在测试方面表现非常差,而且似乎默认情况下并不理解如何合理地进行测试。例如,这是Gary Bernhardt的评论:https://x.com/garybernhardt/status/2067002665427775613:

AI代理对测试的做法,大致如下:

采用十五年前某人反对mock的病态案例,而这个人实际上从未真正使用过mock。天真地梦想过度使用mock。

将这些病态情况作为测试策略的骨干。

在xhigh上,代理通常能够让它们编写的测试通过,但它们写的测试质量很差(例如,它们会向一个使用四个比特流的功能测试提交四个相同的比特流,并因此错过由于比特流顺序错置而产生的任何错误)。正如我们之前在Zstd评测中关于语言方面所指出的:/pl-tokens/#appendix-medium-in-a-loop-vs-ultra,使用低强度在一个简单循环中运行会得到更差的结果(代理会做更多这种操作,并且正确性下降时容易停滞)。

下面我们将按条件查看代理的操作情况,从正确率最差到最好排列,但我建议任何人都不要根据这个顺序得出任何强有力的结论。

这里的许多失败似乎类似于我们在研究编程语言对令牌使用和正确性的影响时看到的失败:/pl-tokens/,因为这些失败通常是特殊情况。例如,在编程语言方面,我们发现代理在 Clojure 中对字节转换语义的理解错误率相当高,但在 Java 中却不如此,尽管代理“应该”(也可能某种程度上确实知道)通过使用 unchecked-byte 而不是 byte 可以获得 Java 字节转换语义。

Verus:https://github.com/verus-lang/verus 使用 SMT 求解器和各种类型的推理来证明代码符合规范。

虽然 Verus 可以证明代码符合规范,但代理没有这样做。相反,他们对与 Zstd 相关的各种抽象属性进行了证明。我自己没用过像 Verus 这样的工具,所以无法说明专家甚至初学者通常会做什么,但从阅读教程来看,我觉得奇怪的是代理没有尝试使用 Verus 来验证任何实际代码,而只是用它进行抽象推理,因为它似乎旨在使证明实际代码属性变得容易。

此外,如果我们看看所证明的属性,通常证明的属性很少,并且所证明的属性并不有趣。例如,代理会证明诸如“在给定有效的光标/索引/距离的情况下,结果操作保持在边界内”,这类证明并不坏,但实际上并不是错误的来源。此外,代理经常编写空洞的证明,实际上是 A => A。一个实际的 Verus 证明的例子是:

在代理实际上证明某些东西的情况下,他们通常证明相对简单的内容,并避免证明那些可能有错误的部分的属性(例如,代理经常未能反转 encode 和 decode 的比特流顺序,并且会编写无法检测此问题的测试,因为测试是回文的;也许在这里进行某种反转的证明可能会让代理以不同的方式“思考”这个问题)。

当仅提供 Verus 和 Verus 文档时,似乎代理并没有从 Verus 中获得价值。

如果我们看结果,总体来说 xhigh Verus 的结果还可以(正确率略低于平均值,但成本要低得多)。medium 的结果成本一般,但正确运行的百分比最低,平均正确测试数量也最低。由于代理实际上并没有从 Verus 中获得价值,它们为正确性所做的工作主要是传统测试(内置 Rust #[test] 函数的单元测试)。从 medium 提升到 xhigh 时,代理在传统测试上花了更多的精力,而在使用 Verus 上只增加了一点点努力,这使得 xhigh 的结果还可以。

看实际测试,对于两个 Verus 代理表现较差的功能之一(四流跳表:https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md),Verus 代理在 160 个案例中写了 89 个测试,巧合的是,与 Default 代理数量完全相同,但 Verus 代理更容易写出糟糕的测试。他们更可能在测试中编码错误结果,以及制作容易通过但覆盖不充分的测试,例如让四条流完全相同。我所说的失败是特异性的,就是指这种情况。Verus 本身并不必然导致在不使用 Verus 时写出糟糕的测试,我们通常也不会期望使用 Verus 的人写出不好的单元测试,就像我们不会期望使用 Clojure 的人在字节转换上犯更多错误一样,但出于某种原因(可能是巧合)这里发生了这种情况。

我不知道 AI 实验室内部的人是否能得到关于事情为什么发生的更好信息,但在外部,一般很难判断这种情况的发生原因(即使我们对语言问题提出了一个合理假设,也需要运行很多语言的不同样本,而我们参考的研究同一问题的论文没有观察到语言流行度与代理有效性之间的相关性,因为它们要么研究的语言太少,难以推断这种微弱相关性,要么研究的问题过小、过于简单)。

Alloy 通常被称为有界模型检查器。对于 Alloy 6 来说,这种说法可能不完全正确,因为它引入了一些额外的功能,但这超出了我的专业知识范围。我的理解是,使用 Alloy 时,你通常是证明模型的性质(而不是证明你的代码能够正常工作)。

Alloy 的正确性得分是第二差,并且与往常不同,它在中等和极高复杂度上的表现普遍较差。虽然未显示(因为似乎没有增加任何信息),总体来看,最大复杂度和极高复杂度的结果高度相关,而它们与中等复杂度的结果有较大差异。

正如我们在 Verus 中看到的,使用 Alloy 的代理几乎完全依赖标准的 Rust #[test] 来验证正确性,并且大部分时间都在摆弄 Alloy。再次强调,糟糕地使用形式化工具并没有帮助提高正确性。

有个别 Alloy 使用案例接近发现问题或风险,但即便如此,数量也很少。在一个案例中,Alloy 找到了一个反例,这促使代理实现了 Rust 版本,并对潜在 bug 进行了缓解。不幸的是,这个反例依赖于 8 位溢出,而实际实现使用的是 64 位 usize,对于给定输入不可能发生溢出,因此它只是增加了代码的复杂性,而并未防止实际的 bug。

在另一个案例中,Alloy 规范不正确,相关测试失败。测试失败后,代理修正了 Alloy 规范。如果规范本身是正确的,也许代理就会在没有失败的情况下编写正确的代码。有一些情况可能发生了这一良性过程,但不清楚是否真正避免了潜在的 bug。

Alloy 代理确实对与 Zstd 算法更紧密相关的对象进行了建模,而不同于 Verus 代理(后者主要检查算术等内容),但这仍然是错误的建模。

差异测试是一种技术,你将相同的输入提供给多个实现,然后比较结果以发现问题。从原理上讲,这似乎是对大型语言模型尝试的一种合理方法,因为我们通常会从不同的尝试中得到不同的结果,正如我们在这里指出的:/pl-tokens/#appendix-medium-in-a-loop-vs-ultra,让一个代理更多地迭代某个实现(可能只是整个程序的一部分,甚至可能只是某个函数的一部分)通常不如让代理从头开始重新启动。

但这给我们带来了第三差的结果。在这种情况下,我们在 xhigh 上的结果略高于平均水平,而在 medium 上的结果远低于平均水平。没有代理创建两个完整的实现进行比较。在 160 次运行中,有 135 次可以算作做了差异测试,但像我们看到的其他情况一样,这些测试通常很简单,实际上没有什么用处。而且,在差异测试可能捕捉到漏洞的情况下,代理并没有以独立的方式实现功能,而只是做同样的事情两次,并在两个版本中编码了相同的漏洞。

我有时会告诉代理独立地执行任务,并让它们在不同的上下文中启动,但这种方法在差异测试中没有有效执行,代理通常只是写了两次相同的东西。

讨论官方 Hegel 技能如何改变 Hegel 的行为是有意义的,但按正确性逆序排列时,Hegel 技能似乎排在 Hegel 之上,因为结果在正确性上更差。有关该技能的讨论,请参见下面的 Hegel 部分。

Lean 4 可以描述为一种交互式定理证明器:https://en.wikipedia.org/wiki/Proof_assistant。

虽然我没有对 Lean 提出预注册的猜测,但如果我预先注册了关于哪些形式化工具表现良好的猜测,我会把 Lean 放在我预期表现良好的列表中,因为它相对热门/流行,因此由于 RL 环境中的合成数据,它看起来相对可能具有良好的性能。

Lean 代理确实证明了属性,例如 Verus 条件,代理大多数进行的是算术证明,这些证明没有触及容易出错或有风险的领域。

像其他形式化条件一样,Lean 代理在很大程度上依赖标准的 Rust 测试。正如迄今为止的形式化条件那样,做一些不重要的证明并不能提高正确性。

QuickCheck 是一个基于属性的测试库:https://en.wikipedia.org/wiki/Property_testing,可能长期以来是最知名的此类库,尽管 Hypothesis 目前可能占据这一地位。

不幸的是,代理在使用基于属性的测试时的效果与他们使用迄今为止看到的形式化工具一样有限。在使用 QuickCheck 时,代理主要编写非常简单的“冒烟测试”,几乎没有进行检查。他们还使用随机输入,而当完全随机时,对于测试像 Zstd 这样的东西效果很差(因为它们只是进入几条失败/拒绝代码路径之一)。

此外,被检查的属性相对较少。虽然所有代理都使用了 QuickCheck,但在 160 次运行中有 63 次仅检查了单一属性。代理再次主要依赖传统测试,尽管技术上他们确实使用了 QuickCheck。出于某种原因,代理实际上编写了比默认条件或大多数其他条件下更多的传统测试,但进行了更少的测试-修复迭代(这使得该条件的成本低于平均水平)。

TDD 在此处的表现不如人意,就像在 IMAP RFC 评估中一样。

TDD 提示似乎导致代理行为发生了巨大变化。代理生成了两倍数量的测试,并采用更迭代的测试-代码-测试-代码等工作流程,尽管 TDD 拥护者可能会说代理实际上并没有使用 TDD。只有少数情况下,代理进行了一些细粒度的迭代 TDD。

总体而言,代理事先编写了更多测试;例如,在进行实质性(非存根)实现之前,在 160 个案例中有 67 个案例中代理有一个或多个失败的测试,而默认条件下是 0 个案例。

对于广泛的测试类别,TDD 有更多各种类型的测试。有更多的小型、琐碎的测试,同时也有更多的集成测试和端到端测试。任何明显的高层次“代理做了太多或太少的 X”似乎都不符合数据。如果我们查看具体的失败以及它们是如何被测试遗漏的,可以观察到 TDD 条件下也存在这些情况。例如,当有四个哈夫曼流时,Zstd 使用了一种称为跳转表的东西。

虽然 TDD 代理写了更多覆盖一般情况的测试,但他们更有可能在此类情况下未通过 eval 测试。由于某些原因,TDD 代理更有可能编写不覆盖难处理情况的测试(例如,使四个流完全相同然后也使它们很简单,就像我们在 Verus 中看到的那样)。这是另一个让我好奇的问题,即 AI 实验室的人能看到什么样的情况,因为从外部来看,为什么用 TDD 训练代理会让他们写出更差的测试和实现并不明显。

如果我们只有 TDD 和一些测试条件可用,一个假设可能是,TDD 编写的代码通常似乎有很多不太好的小测试,因此也许用 TDD 训练代理会导致他们编写更多这类无效测试。但为什么在 Verus 中也会看到相同的模式则不明确。如果我们在一个开放模型上重新运行实验,并检查模型内部实际发生的情况,或许可以判断 TDD 是否存在相同的问题,或者是否存在 Verus(或其他)行为的共同原因?

还有两项技能也导致代理采取更迭代的方法,也许理论上认为更频繁地执行会得到更好的结果,而这两项技能的表现也不佳。一般来说,在所有条件下,代理能够让他们编写的测试在 xhigh 和 max 上通过(未显示,但 max 的正确率略高于 xhigh,而且成本明显更低)。更迭代地使自己的测试通过往往会导致代理编写更多不正确的测试,这些测试会强制执行错误的行为。

Yossi Kreinin 对于为什么 TDD 可能导致测试更差有这样的想法:

仅供参考,我认为如果你在写代码之前先写测试,会更难测试那些难的情况,因为你对什么会困难了解得少。即使你进行随机测试——我认为“tdd”并不与之相关——你也不太可能将测试分布引导到有漏洞的方向。如果你写了代码或者至少可以查看它,你就会知道哪些看起来显然是正确的,哪些可能行也可能不行,因为它的工作原理不容易理解。换句话说,TDD 会将你引向黑箱测试,而对于复杂的机制来说,在我看来,黑箱测试效果似乎不如白箱测试;我相当确定人类是这样,但不太确定对于智能体是否也是如此。

我猜 TDD 表现不佳的推测是正确的吗?严格从结果上看,答案是肯定的。从我的推理来看(虽然没有明确以书面形式预注册,但我确实知道当时的思考过程),答案并不清楚。我的思路大概是这样的,正如我们最近在各种语境中讨论过的那样,要让智能体真正做正确的事情而不是仅仅过拟合,是实现智能体良好性能或正确性的关键。就整体方法论而言,而不仅仅是这条指令如何改变了智能体的行为,TDD 似乎容易导致过拟合。

智能体确实写出了较差的测试,有时还使用了一种相对昂贵且低效的迭代工作流程,但我不认为我原本预期的人类使用TDD并指导智能体实现那个失败模式是这里的真正问题,而那正是我的直觉来源。我会给这里的推理评分为“可能正确,也可能不正确”;我认为需要更多评估和调查来决定这一点,我猜更多数据的结果可能会显示我最初的推理是错的。

现在我们进入结果接近平均水平的范围。Spin 在中等和极高难度上表现稍低于平均水平,但成本低于平均水平。正如我们在其他正式工具中看到的,Spin 的使用总体上效果不理想。在本例中,使用 Spin 对某类行为建模与通过或未通过覆盖该行为的隐藏测试之间没有相关性。使用 Spin 是表面的,不具生产力。

Hegel 是一个基于属性的测试库,基于 Hypothesis:https://github.com/hypothesisWorks/hypothesis/。

正如我们现在可能预料的那样,代理并未有效使用 Hegel。在他们使用它的程度上,使用得非常表面化,而且通常是在大量依赖普通测试之后才使用它。由于单纯指出代理实际上并没有真正做这件事会显得重复,我会让这些部分简短,只突出特定的好奇点。

代理实际使用的工作流程通常是

如上所述,Hegel 技能并没有改善正确性。正确性反而更差(尽管差距很小,也可能是随机的)。更引人注目的是成本更高(中等增加 26%,极高增加 41%),原因似乎具有因果关系。

该技能导致代理生成更多的测试。额外的测试主要是检查畸形输入不会引发 panic 以及往返测试。前者是代理已经倾向于在所有基于属性和模糊测试条件下过度执行的操作,因此在这里的额外努力并没有用处。后者似乎并不是一个本质上糟糕的想法(我甚至经常明确指导代理创建往返测试,而且这些测试似乎对于检查特定属性很有用),但它并没有在最易出错的区域执行。如果没有额外指示,代理倾向于为相对简单且已经可能正确的属性创建往返测试。

至于成本,有多个原因。一是该技能相当大(技能本身 34k 字符,同时还加载了一个 45k 字符的 Rust 专用参考,最终超过 20k 个 token)。这些内容在运行开始时加载,并在之后的许多操作中反复读取。这导致中等情况下平均额外成本增加 16%,极高情况下增加 18%(按原始 token 计算,中等平均增加 90 万,极高增加 180 万;尽管这些缓存命中率很高,初次读取后的命中率为 99.85%,但由于仍有多次重读,所以这仍然占总成本的相当一部分)。

一个乘法成本(这个乘数已包含在前面的数字中)是该技能还指定了一组结构化的操作,这会导致更多的工作量。这些工作并没有提高正确性,因此增加了成本而没有相应的益处。

需要注意的一点是,该技能在160个案例中“仅”使用了157次。正如使用大型语言模型(LLM)时通常的情况一样,操作和结果是随机的。如果你有一个认为代理在特定任务中应该使用的技能,它可能会使用,也可能不会使用,这取决于一些对 AI 实验室外的人来说似乎不透明的因素。

在这种情况下,160 次运行中只有 108 次实际上打开了技能:https://github.com/trailofbits/skills/blob/d3323cefbcf645678b8dc481de204b02ad3d02dc/plugins/property-based-testing/skills/property-based-testing/SKILL.md 来阅读它。该技能建议在 Rust 中使用 proptest,但技能建议添加依赖需要批准,而这些都是单次自动运行,因此没有执行。

与到目前为止看到的其他属性测试案例一样,属性测试是初步的,并且没有以有用的方式进行。

Rstest 是基于测试夹具的:https://en.wikipedia.org/wiki/Test_fixture#Software_test_library.

情报判断

Aioga 编辑摘要

文章以代码智能体实现 Zstd 的评测为例,比较在提示中加入测试驱动开发、Lean 4、QuickCheck、基于属性的测试等要求后的结果。作者称,各条件没有出现明显的压倒性优势,未附加指令的默认条件表现高于平均水平。

背景分析

作者指出,尽管让编码智能体采用有效测试技术更容易达到特定质量门槛,但软件质量似乎仍在下降。文中以不同提示附加项进行比较,并提到还做过 IMAP RFC 等其他评测;所示图表以成本及通过全部隐藏测试的运行占比呈现结果。

Aioga 观点

Aioga 判断:这份材料更适合被视为对“如何引导智能体使用测试方法”的一次具体实验与技术评论,而不足以证明某类测试技术对所有模型、代码任务或开发环境都具有稳定优势。默认条件较好也值得关注。

影响与后续

影响分析:团队可能需要把测试提示、测试工具使用方式和最终验证分开评估,而不应仅凭加入某个方法名称就假定正确性会提升。文中结果不足以替代独立复现、任务覆盖度检查及面向实际代码库的验证。 后续观察:可关注来源后续是否披露各条件的更细结果、评测设置与其他任务表现,并比较不同努力档位下模糊测试、基于属性的测试及形式化方法的差异。现有摘录不代表这些结果可直接外推。

来源与版权说明

本页正文由公开来源页面提取并按原有信息整理,同时保留来源、发布时间和原文入口。版权归原作者及来源网站所有,请通过原文链接核验和阅读来源版本。

抓取通道: 摘要聚合 · 原始域名: danluu.com

来源: Hacker News 热门(buzzing.cc 中文翻译)

原文链接: 打开原始来源

Aioga 归档: 查看情报页

Content record: source-page · Updated: 2026-09-08T11:34:04.000Z

API 中转站
API RELAY · DEVELOPER INFRASTRUCTURE

API 中转站

统一接入主流 AI 模型 API,为开发、测试与生产环境提供稳定调用入口。

立即访问 api.w173.com
AIOGA SHARE POSTER

分享这篇 AI 情报

文章探讨了AI智能体在多大程度上实际运用测试与验证技术。作者基于自身观察与经验,分析了当前智能体在代码生成等任务中对测试环节的利用程度,指出其表现与理想状态存在差距。文章属于技...

Hacker News 热门(buzzing.cc 中文翻译)2026-09-08T11:34:04.000Z
扫码打开文章详情扫码直达文章详情

Aioga 自动聚合全球 AI 动态,并保留来源信息用于核验与引用。