Lex:让模型修改文档这件事听起来很有趣,以后我们就可以让 agent 去执行一系列任务,第二天再来看这个 Agent 同事都完成了哪些工作。
Aman:我们可能会设计不同的运行版本。有些任务比较简单,比如用户在编程时,有些操作模型几分钟就可以帮用户完成,这种时候可以让代码在用户的本地机器上运行。但有些任务更复杂,需要更长时间来完成更大的更改,可能更适合在远程沙盒环境中执行。这就带来了一个问题:如何精确地复制或最大程度复制用户的本地环境,确保远程沙盒与用户本地环境中运行代码的效果一致。
Lex:我觉得 Agent 应用范围不应该局限于 coding。比如说我们现在正在录的这期播客就涉及视频剪辑、上传视频、翻译和配音等,我可能会希望 Agent 可以帮助我们把很多和视频编辑不直接相关的任务自动化。在 coding 上,我比较期待 agent 能帮忙找 bug,特别是逻辑错误,以及帮助确定大方向等等。
Aman:有一个很有意思的现象是,如果用户给出的 prompt 是找 bug,那么模型的准确率其实很低,在这类任务上即便是最聪明的模型表现也很差,甚至是 o1 这样的模型。
Lex:怎么解释这个现象?
Aman:模型是 pre-train 数据分布的一个强映射,随着 loss 越来越低,模型的泛化能力也会不断提升,但目前 loss 还没有低到能让模型在代码领域完全实现泛化。我们目前使用到的最新一代的模型很擅长代码生成和问答,这是因为在 pre-train 阶段这类数据特别多,GitHub 上有几万亿个 token,Stack Overflow 上也有海量的问答内容。
但是如果我们想让模型做一些网上很少见的任务,比如 Cursor Tab 要做的根据已完成的编辑预测下一处编辑,这些模型在这类任务和场景上的弱点就会暴露出来。漏洞检测(bug detection)也是一个很好的例子能说明模型的这个短板。互联网上真实的 bug 检测和修复的完整案例其实很少,并不像代码问答那样数据丰富,所以模型在这类任务上就表现得很吃力。
不过我认为这是模型能力迁移的问题。就像我们已经看到的,我们可以把模型在 pre-tarin 阶段获得的通用的代码理解能力迁移到 Cursor Tab 的任务上。如果一个通用模型在代码方面很强,也应该能通过类似的方式把它的能力迁移到 bug 检测任务上,只是需要一些适当的引导和调整。
Sualeh:需要说清楚的一点是,这些头部模型其实对代码的理解是很到位的。在 pre-train 阶段,在构建内部 representation 时 ,我们几乎可以确定,在处理流程的某个环节,模型能够感知到代码中可能存在一些问题,但是仅仅是感知到“不对劲”是不够的,最关键的问题在于,人类对于哪些bug真正重要有着准确的判断力,比如有的 bug 无关紧要,有的却会导致服务器宕机。
人类工程师之所以能做到这一点一部分也是行业经验和文化的积累。为什么资深工程师很厉害,是因为他们知道 3 年前有人写了一段有问题的代码导致了服务器宕机,相比之下,如果只是在做实验性质的代码,有一些 bug 也没关系,因为主要目的是尝试和体验。所以如果在写实验代码时,模型过分较真,不停地给出提示,反而会很烦人。
但如果是在写生产环境的代码,比如写一个数据库,在 Postgres 或 Linux 这样的系统写代码,或者假如我们是 Linus Torvalds 这样的人(注:Linux 的创始人),那就必须做到万无一失,任何 edge case 的 bug 都不能有,这就要求模型能准确理解开发者对代码质量的要求程度。
Aman:但即使作为开发者我们把对模型代码任务的质量要求调到最高,模型还是不能完全理解到这些微妙的差异。
Lex:但其实人类工程师要真正做到准确判断不同 bug 的重要性也很难。比如你们也有一个原则是,如果某一段代码可能会带来不可控的影响,应该给它特别注释去说明“This line of code is dangerous.”,甚至还会用到大写标记来突出。
Arvid:是的,我觉得这个原则对今天的 AI 模型同样适用。如果每一行代码上都有专门的标注,那么模型就会更关注这一部分,也更有可能发现这一部分的bug。但这个做法本身也也存在争议。一些人会觉得这种做法不太美观,比如 Sualeh 就不喜欢。
除非我们可以做到所有代码都能通过严格的数学方法来证明其正确性,到那个时候就可以随意写代码了,因为只要验证通过,我们就能确定这里没有引入到任何 bug。
Sualeh:虽然从代码审美角度来看我并不喜欢这种做法,但我认为它确实对模型和人类都有用,因为人类经常会忘记很多事情,而且很容易犯一些小错误,从而导致服务器崩溃。就算我们进行了大量的测试,但在这方面我们还是要格外谨慎。
Aman:是的,就拿普通的文档注释来说,人们在修改代码时往往只是匆匆扫一眼,想着“哦,我知道怎么做”,但实际上我们还需要更加明确地提醒他们注意某些细节,否则很容易就疏忽了。
Arvid:我认为未来人们不会再手写测试代码了。当 coding 的同时,AI 模型会自动为这段代码生成一个规范说明(spec),开发者只需要审核这个规范是否符合预期。同时,推理模型会通过计算来验证代码实现是否完全符合这个规范。我觉得这种方式将适用于大多数代码功能的测试。
Michael:这件事是不是又会涉及到我们在前面提到的,人们在开发软件时可能很难很清楚地描述自己的目标和意图,而有时候之所以难以证明代码实现符合预期,也可能正是因为我们很难准确地描述出我们想要什么。
即便模型给出了一个 spec ,我们还是要面对一个问题:我们真的能做到 formal verification 吗?这在技术上是否可行?我觉得这里面还有很多需要深入探讨的地方。又比如 spec 是用自然语言编写的还是用公式来表达?即便是 spec 也还有很多细节很难被清晰界定。所以只是考虑 formal verification 还不够。
Lex:你在前面提到模型在处理 bug findings 这类任务时通常表现不是很好,长远来看你的预期是什么样的?
Sualeh:我觉得模型首先应该能帮助我们解决那些简单的小错误,它应该能快速检查并及时发现“差一错误(off by one error)”这种简单的 bug,因为这类问题非常常见。在这个时候模型就应该给出对应提示,但长远来看,它肯定还需要能够捕捉到更难发现的bug。
Michael:我觉得很重要的一点是,找 bug 能力是让 AI 完成更多 coding 任务的必要条件。当我们想要让 AI 帮我们构建越来越多的系统时,就不仅需要它帮助做代码生成,还需要能验证代码的正确性,如果没有这种验证能力,我们前面聊到的这些模型在代码任务上的问题就很难解决,让 AI 拥有找 bug 的能力不仅仅是为了找出人类写代码时产生的 bug,更关键的是能够验证和检查 AI 生成的代码。
Arvid:关于如何实现让 AI 更好地找到 bug 我们也有过很多次讨论,比如如何训练一个 bug 检测模型,还有一个更受欢迎的想法是:“制造 bug 比找 bug 更简单”,所以对应的思路是,我们可以先训练一个模型,让它学会在现有的正确代码中注入各种类型的 bug,基于这种方式我们会得到大量带有已知 bug 的训练数据,然后,就可以用这些合成数据来训练另一个模型,专门用于发现和检测代码中的 bug。这只是众多可能方法中的一个例子,还有很多其他的训练思路可以尝试。
Michael:还可以有其他思路来完成。我们可以先想象有一个 access 范围足够宽的模型,这个模型可以接触到包括代码在内的各种信息,因为只盯着一个文件来找 bug 其实是很难的,对人类来说也很难,所以通常情况下我们的做法是运行代码、查看traces、通过调试器逐步检查。这是另一个完全不同的方向。
所以这里有两种不同的产品形态。一种是有一个非常专业且运行速度很快的模型在后台运行,一直去寻找 bug,另一种情况就是开发者已经很明确有一个 bug 需要解决,在这种情况下,人们可能会投入大量的计算资源来做这件事。
Lex:你们考虑过代码生成、编辑和 debugging 环节里引入付费的可能性吗?如果能帮助发现 bug,或者生成让用户非常满意的代码,用户愿意为之付费或者打赏,而除了获得收入之外,付费也是比“接受代码”更强的信号来帮助优化产品和模型。
Arvid:这个思路很有意思但也很有争议,并且还涉及到我们对于用户心理的把握,也涉及到算力成本和定价之间的平衡。但整体上我们会觉得引入这个机制可能会让产品变得不那么有趣,可能通过订阅的方式,每月支付一定费用后享受所有这些功能更符合开发者的需求,而不是将 debugging 等功能点单独付费,即便是打赏机制也会有影响。
Lex:在具体的代码任务和代码终端结果之间有更好的信息交互?比如是否存在一个类似于 code -> terminal -> output -> analysis -> code suggestions 这样的循环和反馈机制?
Aman:用户在使用 command+K 功能的时候会利用到终端上下文信息,但我们目前还没有实现循环反馈的部分,但我们觉得这样的功能应该很有价值,问题在于这个功能是在前台执行,还是像我们之前讨论的那样在后台执行。
Lex:前面提到基准测试并不能真实反应模型代码任务的能力?这二者之间有什么区别?如果要评估模型,我们看到的基础测试有什么不足?
Sualeh:基准测试和现实中的代码任务中间有一个非常重要且关键的细节差异,那就是现实中的代码任务并不是“编程面试题”。在现实的工作中,人们有时会用不标准的英语来表达任务需求,或者会给出“照我之前那样做”、“添加这个,然后帮我做那个,再做一个 UI 元素” 之类的指令。很多任务都是依赖于具体场景的。
所以对于模型和产品来说,真正需要的是理解用户意图并完成他们想要的事情,真实的人类需求往往是模糊的、不那么明确的,而不是“面试题”那样具有非常明确、详细规范说明的任务。
Michael:除了 Sualeh 和 Aman 提到的问题外,基准测试还存在一个问题是,实际可以建模的内容与真实的编程之间存在一定的偏差,这种偏差很难概括,因为真实的编程是很混杂的,有些时候很难去明确解释什么是对的,什么是不对的。
而且,由于测试集是公开数据集的原因,这件事会变得更难。有两方面的原因,首先,公开的基准测试有时会被进行针对性地“爬坡优化”(hill climbing),另一方面,要从模型中剔除掉这些公开基准测试的数据也非常难。
举个例子,SWE-Bench 是目前最受欢迎的 Agent 基准测试之一,但它的测试数据也是 Foundation Model 的训练数据的一部分。所以如果我们给到 Foundation Model 一个 SWE-Bench 问题,即使没有提供代码库的上下文,模型还是可以“编造”出一个正确的文件路径和函数名。