
OpenAI工程师Predrag Gruevski分享用AI提升Rust代码正确性的方法
来源标题:How to Use AI for Rust Development: Lessons From an OpenAI Engineer
OpenAI前沿系统工程师Predrag Gruevski分享了他以AI辅助Rust开发的实践:不追求写更多代码,而是让代码更正确。他在RustRover直播中建议,交给AI前先按出错代价给代码排序,并非每行代码同等重要。
以下正文由 AI 翻译自 JetBrains Blog(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
“有人用 AI 写更多代码。我用 AI 让我的代码更正确。”Predrag Gruevski 的置顶帖概括了他用 AI 做 Rust 开发的方式。Predrag 在 OpenAI 从事前沿系统的工作,他创建了 cargo-semver-checks 和 Trustfall。在他的工作里,几乎没有犯错的空间。尽管如此,他的大部分工程工作仍然让 AI 参与其中,而他的质量门槛反而提高了。但这是怎么做到的?
我们想知道这在实践中是什么样子,于是邀请他参加了一场 RustRover 直播。他的演讲是我们与 Rust Foundation 联合推出的 AI & Rust 直播系列的一部分,该系列关注 Rust 与 AI 交汇处的真实用例、成功经验和失败教训。本文聚焦于 Predrag 最实用的建议:该审查什么、如何给 AI 编码 agent 写提示词、如何验证它们的工作,以及当它们出错时该怎么办。
你可以在这里观看完整的直播录像 👇
使用 AI 时,哪些 Rust 代码最值得关注?
在把任何东西交给 AI agent 之前,先按“出错代价”给工作排序。并非每一行代码都同等重要。有些行值得你投入比其它行多 1000 倍的注意力。当你亲手敲下每一行时,10 行 unsafe Rust 和 10 行普通代码写起来花的时间差不多。现在普通代码交给 AI 了,你就可以把那部分时间挪到出错代价高昂的行上。
把你的代码想象成一条风险标尺。一端是错误很容易发现和修复;另一端是错误可能隐藏数月并造成真正的损害。以下是这条标尺上的三个点:
低风险代码。GitHub Actions workflow 就是个好例子。你知道它该做什么,agent 也读过文档,那就让它写这个 workflow 并测试它。如果某个 CI bash 脚本坏了,且不涉及任何安全相关的东西,就让 agent 去修。
别人依赖的逻辑。cargo-semver-checks 能在破坏性变更发布前捕获它们,它现在运行在 Rust 自己的 CI 里。在它被加入之前的五年里,它本可以捕获 Rust 发布中大约六起意外破坏性变更——这些变更曾迫使官方进行 backport。另一方面,如果它的逻辑错了,把并非破坏性的变更误报为破坏性,那就是非常严重的问题。所以在为 Rust 的 CI 做准备时,Predrag 让 AI 构造一些会触发误报的标准库新增内容。这种审查发现了也可能影响普通库的误报。这样的代码值得你投入多得多的时间。
Unsafe 代码。这里的一个错误可能意味着内存不安全、安全问题,或者一个十亿次才出现一次的 Heisenbug。这听起来很罕见,直到你在数据中心里运行它。在那里,0.0000001% 的概率损坏数据意味着它一直在发生。在一个真实案例中,这类问题仅仅由 unsafe 块里的 20 行代码引起。这才是值得逐行阅读、甚至手动编写的代码。为 100 行 unsafe 代码花四个小时是合理的代价。
如何给 AI 编码 agent 写提示词,让它写出可靠的 Rust?
描述你想要什么、你希望它怎么完成,以及“足够好”意味着什么。不要满足于“请给我这十行代码”。一个任务可能消耗数十亿 token,产出的代码远超你所能阅读的量,所以工程工作必须发生在提示词里。要写出好的提示词,你需要做三件事:
勾勒设计
像给一位技术高超、非常勤勉但缺乏你上下文的同事交代任务那样,向 agent 交代清楚。在白板前,你会画一些方框和箭头。你会解释类型如何工作、你需要哪些函数和字段、数据流向哪里。这些是承重的部分。把它们放进提示词,让 agent 在此基础上展开。
测试也一样。测试用例内部的变量名远不如测试结构重要。测试是否覆盖了所有主要情况?正确的事情是否在正确的时间点发生?在提示词里描述这个结构。
说明哪些假设可以接受
如果你告诉模型要彻底、要测试一切,你会得到针对停电期间陨石撞击的测试。对于飞行器软件,这种谨慎程度是对的。对大多数代码来说,这是白费力气。告诉 agent 哪些假设没问题,并让它检查某个场景是否真有可能发生。
要精确
Rust 的问题往往有条件性答案。问某个改动是否是破坏性的,准确的回答可能是“是,但有六个前提”。这取决于该 trait 是否已经存在、它是否实现在一个已存在的类型上、该 trait 是否被封存(sealed),等等。你的提示词也需要同等程度的精确,说明你想要什么、不想要什么。
所有这些都要花时间,但会有回报。为了在 Rust 编译器和标准库里寻找加速点,Predrag 花了 45 分钟为 Codex 写一条提示词。它告诉 agent 去哪里找:那些很久没人优化过的热点代码。它说明偏好哪些改动:复用项目其它地方已经奏效的思路的小改动。它还说明了如何做基准测试:交错运行,几何平均值至少提升 1%。
在一个 PR 中,Predrag 删掉了新 trait solver 里的一行。这行重新计算了代码 40 行之前已经算过的东西。删掉它让新 trait solver 快了最多 7.5%。一旦有人指出来,所有人都会同意这行该删,但找到它需要大量的工程工作和思考。
“人们很容易把 AI 想成一匹更快的马。这是一个它并非更快的马的例子。原则上,这些工作我们本可以全部手动完成。只是要花五年才能找到这些优化。” Predrag Gruevski OpenAI 前沿系统软件工程师
如何验证 AI 生成的 Rust 代码?
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。