跳到正文
Tessl Blog· Justin Cormack·· 22 天前精选AI 评分62

AI 智能体评估始于证据:用 35 万行 Rust 对象存储的实践复盘

AI Agent Evaluation Starts With Evidence

AI 导读

Tessl 博客刊出 Justin Cormack 在 AI Native DevCon 的演讲复盘,他借助 AI 构建 S3 兼容对象存储,代码规模约 35 万行 Rust,并写了约 1500 个针对 S3 的测试作为行为预言机。

推荐理由

作者用 35 万行 Rust 对象存储的实践复盘,说明测试预言机、边缘用例与可观测性如何构成智能体评估的证据闭环。

正文 · AI 翻译

我喜欢测试。我一直都喜欢测试,而 AI 让我对测试有了更多思考。如果 AI 要帮助我们编写生产代码,重要的问题不是它能否快速生成大量代码。重要的问题是,我们能否构建一个反馈循环,告诉我们什么才是真正有效的。

这就是我演讲《当测试说谎:用可观测性让 AI 保持诚实》的原因。我想了解,当你把 AI 用在比玩具项目大得多的东西上时会发生什么。小工具很有趣。你可以用半天时间写出来,对它们进行密集测试,并对结果感觉相当不错。但你能用 AI 构建一个大型、复杂的基础设施系统吗?

我决定用兼容 S3 的对象存储来尝试。对象存储是我最喜欢的云服务,而我看过的大多数实现至少花了两年时间才写出来。有些花了十年。我知道这将会庞大而复杂。在演讲时,代码库大约有 35 万行 Rust,我并不打算假装自己读过每一行。

这是实验的一部分。我想要高质量的代码。我有架构上的主张。我关心安全性、性能和分布式系统行为。我也希望保持人在循环中,因为我想知道哪里出了问题,而不是从一开始就把一切自动化掉。

把这次演讲用作智能体上下文

Tessl 已经把我的 AI Native DevCon 演讲变成了一个你的智能体可以用作上下文的技能。你也可以观看完整录像。

DevCon NYC
注册以获取早鸟折扣

为什么我要针对 S3 本身进行测试?

复制一个现有系统的一大好处是,你得到了一个测试预言机。就我而言,我可以针对 S3 运行测试,观察真实行为,然后告诉 AI,我们的实现必须表现得完全一样。

这改变了工作的质量。我最终有了大约 1,500 个针对 S3 运行并锁定行为的测试。对智能体来说,这比模糊的指令要好得多。它给模型提供了一个有依据的基线,也在我决定是否信任实现时给了我证据。

我现在认为,如果你要编写一个复杂系统,一个好的起步动作是先构建一个非常简单的版本。它不必是最终架构。它可以只是行为的一个简单模型。但如果你能针对那个简单版本构建一套测试,你就可以在构建更复杂版本时把它用作预言机。

这并不完美。S3 在某些地方是最终一致的,尤其是在授权行为方面,所以测试有时需要重试,才能正确反映真实行为。预言机并不完全等同于规范。你仍然必须解释你所看到的东西。

另一个发现是,文档还不够。S3 有大量文档,但当你深入细节时,文档往往是粗略的、过时的,或者根本没有描述你实际观察到的行为。或者干脆就是错的!文档可以给你关于要测试什么的提示。测试告诉你真正发生了什么。

为什么 100% 覆盖率是错误的目​​标

我最初尝试追求 100% 测试覆盖率,因为这似乎是个好主意。我测量了不同种类的覆盖率,包括来自集成测试的覆盖率。它并没有像人们有时假设的那样有帮助。

当我让一个 AI 智能体去实现 100% 覆盖率时,它写了一些琐碎的测试。其中一些在技术上提高了数字,但并没有提升我的信心。如果正确的行为只是返回错误或 panic,我不需要为每一条随机数生成器失败路径都写测试。那不是最有用的证据所在。

我仍然有很多测试。大多数文件的覆盖率在 75% 到 100% 之间。重点不是说覆盖率不好,而是 100% 的语句覆盖率并不能替代思考。

测试是发现工具,不是魔法答案。你要在不确定的地方、怀疑的地方、以及认为系统可能隐藏错误的地方添加测试。如果代码让你担心,你就花更多时间去试图破坏它。

这就是我希望在 AI 辅助开发中保持的心态。智能体可以生成测试,但我仍然需要决定我要暴露的是什么风险。

边缘情况是测试套件赢得信任的地方

让我获得信心的时刻之一,是 AI 在 S3 中发现了一个可复现的 500 错误。它正在针对 S3 的一个边缘情况编写测试,并发现了看起来像真实 bug 的行为。后来它又发现了另一个可复现的 500 错误。

这很令人兴奋,因为这意味着测试套件不只是在检查显而易见的路径。它探索了足够多的行为空间,从而发现了奇怪的情况。当你构建一个复杂系统时,你会花大量时间在“一切都糟透了,这永远不会成功”和“实际上,它又能工作了”之间来回摇摆。好的测试能帮助你重新走向信心。

有趣的是,在从文档中寻找一些边缘情况方面,我比 AI 做得更好。我会阅读 AWS 文档,想“这是真的吗?”,然后让 AI 编写测试,接着发现行为只是近似等于文档所述。当我直接把文档指给 AI,让它直接寻找边缘情况时,它并不擅长。

这说明了一些关于人类角色的重要事情。我仍然必须像测试人员一样思考。我必须询问零长度、一长度、10001 长度,以及系统容易出问题的那些奇怪角落。智能体可以帮助把这种怀疑转化为可执行的测试,但怀疑本身仍然重要。

永远不要忽视不稳定的测试

不稳定的测试是这个项目中最有趣的部分之一。AWS 会随时间收敛到真相,这浪费了大量时间。但我的硬性规则很简单:绝不允许 AI 产生不稳定的测试。立即修复它们。

原因是智能体可能会从围绕不稳定测试的文化中学到错误的教训。有时感觉训练数据告诉模型,开发者不修复不稳定的测试,所以它应该忽略它们。我不得不提醒它,在这个代码库中我们会修复不稳定的测试,而且这写在智能体指令里。

危险是显而易见的。如果一个测试间歇性失败,智能体可能会认为外部系统变了,或者这个测试不值得信任,或者实现应该继续改变以匹配噪声。这恰恰是反的。先修复测试。

快速的测试使这成为可能。在演讲时,我大约有 5,000 个测试在约两分钟内运行。两分钟大约是我可接受的极限。当测试运行得很快时,你可以频繁运行它们,也能更早发现不稳定测试。对于罕见情况,我还在多台机器上进行了整夜的重复测试运行。

这正是 AI 真正有用的地方之一。如果你把修复不稳定的测试作为任务,并且拒绝让这种不稳定性变成常态,它就擅长处理这件事。

测试无法告诉你什么?

测试至关重要,但它们并不能告诉你一切。它们有时能发现竞态条件,尤其是在测试运行得快且频繁的情况下。它们能帮助验证许多形式的行为。模糊测试和基于属性的测试为我发现过问题。在出现 bug 之后,问 AI 我们本应有哪些测试,往往能产生有用的新测试思路。AI 在不同类型的测试方面有大量背景知识。

但测试不会自动发现安全问题。它们不会判断你的架构是否良好。它们不会告诉你哪些东西你没有度量。如果你无法观察某样东西,你就无法真正测试它。

这让我更深入地思考可测试性。任何能从黑盒中给你信号的东西都是有用的。如果有信号,就捕获它。如果公共 API 暴露得不够,就构建管理、报告或后端接口,让你更好地理解系统。

我后悔的一件事是没有更早地构建更多这类管理和报告接口。我过于专注于公共 API,因为那是我试图复刻的东西,也是我拥有有用参照的地方。但内部行为同样重要,你能暴露的结构化信号越多,测试和调试就越容易。

为什么可观测性如此重要?

追踪变得极其有用。我让 AI 构建了一个手工维护的追踪框架,即便只是这样,也足以改变调试工作流。它不需要集成到生产可观测性系统中就已经很有价值。

原因很简单:当你给 AI 一个没有复现步骤的罕见 bug 时,它可能会浪费大量时间。它可能无法复现问题,猜测修复方案,或者做出一个看似合理但实际上并未解决问题的改动。

当我能给它一份来自整夜运行的追踪记录,并说“这发生了,我们需要修复它”时,工作就变了。追踪给了它具体的东西去推理。它可以尝试复现相同的条件,比较行为,缩小真正问题的范围,而不是靠猜。AI 猜测的修复往往并不准确,但有了复现,它就能写出正确的修复。

性能优化工作也有类似的教训。AI 的行为很像人类做性能工程。它会尝试一些看起来应该有帮助的东西,然后这个改动要么毫无效果,要么让情况更糟。如果你把这项工作视为廉价且可丢弃的,那就没问题。如果它没有提升性能,就扔掉它,再试别的。

我还发现有些地方正确的答案不是更多追踪或更多测试,而是更好的类型系统。我在权限检查以及检查时/使用时(TOCTOU)行为方面遇到过问题。最终我告诉智能体在类型中建模授权边界,这样需要已授权请求的函数只能接收已授权的请求。一旦类型系统强制了这一属性,你就不需要为这类错误写那么多测试了。如果错误在编译时就被捕获,它们就不会进入生产环境!

人类是反馈回路的一部分

我把 AI 安全审查作为另一个信号来源。我把发现的问题提交到仓库,并让 AI 来审查它们。其中很大一部分是有效的,即使并非每个发现都是直接的安全问题。更重要的是,它们带来了有用的审查会议:我们本该如何避免这个问题,什么样的测试或设计变更能更早地发现它?

这就是我如何看待自己在系统中的角色。我是反馈回路的一部分。我有自己的观点。我想理解哪里出了问题。我不想过度自动化,以至于不再看到失败模式。

AI 可以写大量代码。它也能帮助生成测试、追踪、重构和审查。但质量仍然由我负责。我在意代码是否优秀、架构是否自洽、系统是否真的在朝着更好的方向收敛。

最后的教训是,重构也是反馈回路的一部分。我有几周经历了非常大的行数变更,包括一个必须重构的 43,000 行文件。你不需要一次性完成整个系统。你是逐步收敛的。你取得进展,然后问还有什么可以更好。

这就是为什么我不把 AI 智能体评估看作单一分数。它是一个证据回路:测试预言、边缘情况发现、不稳定测试纪律、追踪、性能检查、安全审查、类型系统约束,以及人类判断。当我们要求测试独立存在时,它们可能会说谎。当它们只是一个旨在让智能体保持诚实的系统中的信号之一时,它们就变得有用得多。

这一论点的完整版本已在 AI Native DevCon London 上展示。要深入了解,请观看完整录像。

来源:Tessl Blog · tessl.io