「Lex Fridman 访谈 - 447」Cursor 团队谈论 AI 与编程的未来
内容介绍
本篇内容整理自 Lex Fridman 播客第 447 期,访谈嘉宾为 AI 辅助编程工具 Cursor 的四位创始成员:Aman Sanger, Arvid Lunnemark, Michael Truell 和 Sualeh Asif。Cursor 是一款基于 VS Code 构建、深度集成 AI 功能的代码编辑器,在开发者社区引发了广泛关注。
此次对话深入探讨了 AI 技术在现代软件开发中的角色与影响。内容从代码编辑器的基本概念出发,回顾了开发者工具的演进,特别是 GitHub Copilot 的出现及其意义。随后,对话聚焦于 Cursor 的诞生背景、核心功能(如创新的 Cursor Tab 自动补全与编辑、Diff 可视化界面)以及其背后的技术实现,包括定制化的机器学习模型、性能优化策略(如缓存、推测执行)、提示工程方法(如受 React 启发的 Preempt 系统)和面临的基础设施扩展挑战。
除了对 Cursor 工具本身的细致剖析,本次访谈还将视野扩展至更宏观的层面,讨论了 AI 代理(Agents)在编程中的潜力与局限、大语言模型(如 GPT、Claude、Sonnet、o1)在编码任务上的比较与评估、基准测试的有效性、合成数据的应用、强化学习方法(RLHF/RLAIF)以及对 AI Scaling Laws 的当前理解。最后,对话展望了编程的未来,探讨了 AI 将如何重塑编程技能、开发流程乃至人机协作模式,以及这对现有和未来的程序员意味着什么。
内容纲要
├── 一、 引言与代码编辑器的基础
│ ├── 访谈嘉宾与 Cursor 简介
│ ├── 访谈主题:AI 在编程中的作用及未来
│ ├── 代码编辑器的作用与演变
│ └── 代码编辑器的重要特质:有趣与快速
├── 二、 从 Vim 到 VS Code 与 GitHub Copilot
│ ├── 团队成员的编辑器使用历程 (Vim -> VS Code)
│ ├── GitHub Copilot 的功能与体验
│ └── Copilot 的重要性:首个 AI 消费级产品与 LLM 杀手级应用
├── 三、 Cursor 的诞生:动机与愿景
│ ├── 起源动力:Scaling Laws, Copilot 体验, GPT-4
│ ├── 从具体工具到整体环境的转变
│ └── 为何选择构建编辑器而非插件
├── 四、 Cursor 的竞争优势与开发理念
│ ├── 如何与 VS Code + Copilot 竞争:创新速度
│ ├── 开发优势:自用驱动、一体化开发
│ └── 使用 Cursor 开发 Cursor
├── 五、 Cursor 核心功能:Cursor Tab
│ ├── Cursor 的两大核心能力:预测下一步与指令转代码
│ ├── Cursor Tab 的目标:超越字符补全,预测编辑与跳转,消除低熵操作
│ ├── Tab 的能力范围:生成、编辑、文件内/外跳转、下一动作预测
│ └── 终极愿景:快速完成可预测的编程任务
├── 六、 用户体验:Diff 界面与代码验证
│ ├── Diff 界面的重要性与设计
│ ├── Diff 界面设计的迭代过程
│ ├── 验证难题及其解决方案探索 (AI 辅助审查)
│ └── 多文件 Diff 的改进:超越传统 Code Review
├── 七、 交互模型:自然语言及其他
│ ├── 自然语言在编程交互中的角色与局限
│ └── 多样化交互方式:示例、可视化操作、未来接口
├── 八、 底层机器学习技术
│ ├── 核心技术:定制模型与前沿大模型集成
│ ├── 定制模型应用:Cursor Tab (MoE, 推测编辑), Apply 功能
│ └── 性能优化 - 使 Tab 快速:推测性编辑原理与优势
├── 九、 大语言模型(LLM)比较与评估
│ ├── 编程最佳 LLM 的权衡 (Sonnet vs o1)
│ ├── 基准测试的局限性:与真实编程差异、数据污染
│ ├── 替代评估方法:人类定性反馈 (“Vibe Check”)
│ └── 模型表现波动的可能原因
├── 十、 提示工程(Prompt Engineering)与上下文管理
│ ├── 提示的重要性与挑战
│ ├── Cursor 的 “Preempt” 系统:类 React/JSX 的声明式提示构建
│ ├── 用户交互目标:自然输入,系统智能检索
│ └── 处理模糊性:模型提问、提供选项、建议上下文
├── 十一、 AI 代理(Agents)在编程中的应用
│ ├── AI Agents 现状:潜力巨大但实用性待发展
│ ├── 潜在应用场景:委托任务、自动化设置、后台协作
│ └── 局限性与混合模式应用
├── 十二、 性能优化策略
│ ├── 关键技术:缓存预热、KV 缓存原理与应用
│ ├── 高级缓存/推测技巧
│ ├── RL 优化提高小模型性能
│ └── 高效 Attention 机制 (MQA/GQA/MLA) 与内存带宽优化
├── 十三、 后台处理与影子工作区(Shadow Workspace)
│ ├── 目标:利用后台计算处理更长远的任务
│ ├── 反馈机制:利用 LSP 获取信息
│ ├── 影子工作区概念与实现
│ └── 挑战与方案探索:环境复制、文件系统/数据库交互
├── 十四、 调试、代码验证与潜在商业模式
│ ├── AI 调试能力现状与原因分析
│ ├── 提升 Bug 检测能力的途径 (合成数据, 专用模型)
│ ├── 验证的重要性
│ └── 付费模式思考:打赏、悬赏与荣誉系统问题
├── 十五、 高级概念:分支与基础设施
│ ├── 终端集成与未来潜力
│ ├── 万物皆可分支 (数据库, 文件系统) 及其在 AI 测试中的应用
│ ├── 基础设施选择 (AWS) 与扩展挑战
│ ├── 代码索引实现:嵌入、向量存储、Merkle 树状态同步、缓存复用
│ └── 本地 vs. 云端:性能、部署、隐私考量 (同态加密)
├── 十六、 上下文、检索与模型训练
│ ├── 自动上下文的挑战与权衡
│ ├── 改进上下文检索的方法
│ └── 模型直接理解代码库:无限上下文、权重内学习 (后训练, 合成数据)
├── 十七、 OpenAI o1 与测试时计算
│ ├── o1 特点:扩展测试时计算,缓解数据瓶颈
│ ├── 优势与挑战:动态分配计算,内部机制未知
│ ├── 过程奖励模型的作用与研究现状
│ ├── 隐藏 o1 思维链的可能原因
│ └── o1 在 Cursor 中的应用现状与未来潜力
├── 十八、 合成数据分类
│ ├── 定义与类型一:蒸馏 (Distillation)
│ ├── 类型二:正向易/反向难问题 (如 Bug 检测)
│ └── 类型三:生成+验证 (Generation + Verification)
├── 十九、 强化学习:RLHF vs. RLAIF
│ ├── RLHF 定义与依赖
│ ├── RLAIF 定义与可行性假设
│ └── Cursor 的混合实践方法
├── 二十、 AI 与科学/数学突破
│ ├── 验证 vs. 生成的直观比较 (P vs NP 类比)
│ └── AI 获奖预测:数学 (菲尔兹奖) 可能先于其他领域
├── 二十一、 规模法则(Scaling Laws)再思考
│ ├── 发展历程与当前实践的转变
│ ├── 多维度考量对架构选择的影响
│ ├── “越大越好”的适用性与蒸馏的作用
│ └── 瓶颈:计算 vs. 想法 vs. 工程能力
└── 二十二、 编程的未来
├── Cursor 的愿景:程序员主导,强调速度、自主、控制
├── 人机混合的未来工程师形态
├── 未来交互界面的可能性 (抽象层级控制)
├── 对程序员技能和工作内容的影响
├── 编程的乐趣与学习建议
└── 对编程热爱者的意义:更高带宽的意图表达
Lex Fridman 播客 -447:Cursor 团队谈论 AI 与编程的未来
访谈者: Lex Fridman 受访者: Cursor 团队 (Michael Truell, Sualeh Asif, Arvid Lunnemark, Aman Sanger)
一、 引言与代码编辑器的基础
Lex Fridman: 接下来的对话是与 Cursor 团队的创始成员进行的,他们是 Michael Truell, Sualeh Asif, Arvid Lunnemark 和 Aman Sanger。Cursor 是一款基于 VS Code 的代码编辑器,它增加了许多强大的 AI 辅助编码功能。它吸引了编程和 AI 社区的广泛关注和兴奋。所以我想,这是一个深入探讨 AI 在编程中作用的绝佳机会。这是一次超级技术性的对话,其意义不仅仅在于一个代码编辑器。它关乎编程的未来,以及更广泛的人类与 AI 在设计和工程化复杂强大系统方面协作的未来。这是“Lex Fridman 播客”。若要支持,请查看描述中的赞助商链接。现在,亲爱的朋友们,让我们欢迎 Michael, Sualeh, Arvid 和 Aman。
Lex Fridman: 好的,这太棒了。我们请到了 Cursor 团队的 Michael, Aman, Sualeh, Arvid。首先,一个大而有点傻的问题。代码编辑器的意义何在?
Cursor 团队: 代码编辑器很大程度上是你构建软件的地方。如今或者说很长一段时间以来,这意味着你用它来编辑形式化的编程语言文本。对于非程序员来说,可以把代码编辑器想象成一个为程序员量身定做的、功能极其强大的文字处理器。之所以说它功能强大,是因为代码具有很多结构。因此,这个所谓的“文字处理器”,也就是代码编辑器,能为你做很多事情,而写作领域的文字处理器还无法为编辑文本的人做到这些。这包括从给你代码中实际标记(token)的视觉区分以便快速浏览,到让你像浏览互联网超链接一样在代码库中导航(跳转到你使用的东西的定义),再到错误检查以捕捉基本 bug。传统上,这就是代码编辑器的含义。我认为,未来十年,代码编辑器的内涵将发生巨大变化,因为构建软件的方式本身可能会变得有所不同。
Cursor 团队: 我觉得代码编辑器也应该很有趣。
Cursor 团队: 是的,这一点非常重要,非常重要。这其实是我们决定构建什么时一个被低估的方面。我们构建的很多东西,尝试过后,会做个实验,然后如果它们不好玩,我们实际上会放弃它们。所以,很多时候,有趣很大程度上意味着快速。“快即是乐”。
Lex Fridman: 是啊,快就是...(笑)对,这应该印在 T 恤上。(众人笑)
Cursor 团队: 从根本上说,我认为吸引很多人在计算机上创造事物的原因之一,就是这种惊人的迭代速度。在其他学科,你可能会受到资源或能力的限制。甚至仅仅是召集一大群人一起工作的能力。而编码是一件很神奇的事情,只有你和计算机,仅凭此,你就能非常快地构建出非常酷的东西。
二、 从 Vim 到 VS Code 与 GitHub Copilot
Lex Fridman: 对于不了解的人来说,Cursor 是这款超酷的新编辑器,它是 VS Code 的一个分支。听你们解释一下你们自己的编辑器使用历程会很有趣。我想你们都是 VS Code 加 Copilot 的忠实粉丝。你们是如何最终选择 VS Code 的?这又如何引导你们走向 Cursor 的旅程?
Cursor 团队: 是的,我想我们很多人,嗯,我们所有人最初都是 Vim 用户。
Cursor 团队: 纯 Vim。
Cursor 团队: 纯 Vim,是的。不是 Neovim,就是纯 Vim 和一个终端。至少对我自己而言,大概是在 Copilot 刚出来的时候,也就是 2021 年,我非常想尝试一下。于是,我转向了 VS Code,当时它是唯一提供 Copilot 的代码编辑器。尽管我非常享受使用 Vim,但 Copilot 搭配 VS Code 的体验足以说服我转换。所以,那基本上就成了默认选择,直到我们开始开发 Cursor。
Lex Fridman: 也许我们应该解释一下 Copilot 的作用。它是一个非常好的自动补全工具。当你开始写东西时,它会建议一两行或三行来帮你完成。这其中有一种有趣的体验。你知道就像你有一个亲密的朋友,他能接上你的话茬吗?(众人笑)当它做得好时,会有一种亲密的感觉。可能有比“亲密”更好的词,但会有一种很酷的感觉,就像“天哪,它懂我”。(众人笑)然后,当它不懂你的时候,就会有一种不愉快的感觉。所以,存在这种摩擦。但我认为对很多人来说,“它懂我”的感觉盖过了它不懂的时候。
Cursor 团队: 而且,我认为 Github Copilot 一个被低估的方面是,即使它错了,虽然有点烦人,但也没那么糟糕,因为你只需多输入一个字符,也许它就能懂你了,或者再多输入一个字符,它就懂了。所以即使它错了,也不是什么大问题。
Lex Fridman: 是的,你可以迭代并修正它。我的意思是,Copilot 对我来说另一个被低估的部分是,它就是第一个真正的 AI 产品。也就是第一个语言模型的消费级产品。
Cursor 团队: 所以,Copilot 就像是 LLM 的第一个杀手级应用。
Cursor 团队: 是的。
Cursor 团队: 是的,它的 Beta 版在 2021 年就出来了。
Lex Fridman: 对,好的。
三、 Cursor 的诞生:动机与愿景
Lex Fridman: 那么,Cursor 的起源故事是怎样的?
Cursor 团队: 大约在 2020 年,OpenAI 发表了关于 Scaling Laws 的论文,那是一个标志性时刻,感觉这个领域有了清晰、可预测的进展方向。即使我们没有更多新想法,似乎只要有更多的计算和数据,就能让这些模型变得更好。
Lex Fridman: 顺便说一句,我们可能会就 Scaling Laws 这个话题聊上三四个小时。(众人笑)但简单总结一下,这是一篇论文、一系列论文和一系列想法,它们指出在机器学习领域,更大的模型尺寸和数据量可能会更好。
Cursor 团队: 不仅是更大更好,而且是可预测地更好。
Lex Fridman: 好的,这是另一个话题。
Cursor 团队: 是的。
Cursor 团队: 是的。大约在那个时候,我们中的一些人进行了很多概念性的讨论:这将会是什么样子?对于所有这些不同的知识工作领域,随着这项技术越来越好,它们将如何被改进?然后,我认为有几个时刻,那篇论文中预测的理论收益开始变得非常具体,感觉就像是如果你想在 AI 领域做有用的工作,真的可以不用去读博士了。感觉当时立刻就能构建出一整套非常有用的系统。我认为第一个时刻我们已经稍微谈到过,那就是玩 Copilot 的早期 Beta 版,那真是太棒了,太神奇了。我认为下一个重要的、让一切豁然开朗的时刻,实际上是获得了 GPT-4 的早期访问权限。大概是在 2022 年底,我们开始摆弄那个模型,能力的提升感觉是巨大的。在此之前,我们一直在做一些不同的项目。因为 Copilot,因为 Scaling Laws ,因为我们之前对这项技术的兴趣,我们一直在尝试为程序员开发工具,但都是非常具体的。比如,我们为需要在 Jupyter Notebook 中工作的金融专业人士构建工具,或者尝试用这些模型做静态分析。然后,GPT-4 的能力提升感觉就像是,看,这确实具体化了我们之前预测的理论收益。感觉在那一刻,你可以立刻构建出更多的东西。而且,如果我们保持一致的逻辑,这真的感觉不仅仅是一个点解决方案。感觉所有的编程都将通过这些模型进行。这似乎需要一种不同类型的编程环境,一种不同类型的编程。所以,大约在那个时候,我们开始着手构建那个更大的愿景。
Cursor 团队: 我清楚地记得一件事。我的室友是 IMO(国际数学奥林匹克竞赛)金牌得主,美国有一个叫做 PUTNAM 的竞赛,相当于大学生的 IMO,也是一个数学竞赛。他非常非常厉害。我记得,大概是 2022 年 6 月,申通(音译)和 Aman 打了个赌,赌 2024 年 6 月或 7 月,模型是否能赢得 IMO 金牌。
Lex Fridman: IMO 是国际数学奥林匹克竞赛。
Cursor 团队: 是的,IMO 是国际数学奥林匹克竞赛。Arvid 和我也都参加过。所以,这对我们来说有点私人感情。(众人笑)我记得当时想,“老天,这不可能发生。”尽管我某种程度上相信进步,但我认为 IMO 金牌,Aman 是在妄想。老实说,我当时确实,很明显,大错特错。但这也许是团队里最有先见之明的赌注了。
Lex Fridman: 所以 DeepMind 的新成果证明你是对的。
Cursor 团队: (众人议论)[Arvid] 技术上讲不是。
Cursor 团队: 技术上不正确,但差一点。
Cursor 团队: Aman 当时对这些东西非常热情。之前,Aman 有一件印着 Scaling Laws 的 T 恤,上面有图表和公式,他会穿着到处走。
Lex Fridman: 所以你感受到了 AGI 或者说你感受到了 Scaling Laws 。
Cursor 团队: 是的,我清楚地记得有一次和 Michael 的对话,在那之前我还没有非常深入和批判性地思考过 Scaling Laws 。他提出了一个问题:为什么 Scaling ($...Scaling...$
) 不是你所需要的一切,或者为什么 Scaling ($...Scaling...$
) 不会导致巨大的收益和进步?我想我经历了悲伤的几个阶段。有愤怒、否认,最后思考过后,是接受。我想从那时起,我对进步一直相当充满希望和乐观。我想补充一点的是,我认为这也取决于你将在哪些领域看到进步。数学是一个很好的领域,尤其是形式化定理证明,因为你能得到一个非常好的信号,可以实际验证结果是否正确。这意味着像强化学习(RL)这样的东西可以做得非常好,我认为你可能会有在数学上远超人类的系统,但技术上讲仍然没有达到 AGI。
Lex Fridman: 好的,那么我们能一路谈到 Cursor 吗?
四、 Cursor 的竞争优势与开发理念
Lex Fridman: Cursor 是什么?它是 VS Code 的一个分支,而 VS Code 是很长一段时间以来最受欢迎的编辑器之一。每个人都爱上了它。每个人都离开了 Vim,我为此离开了 DMAX。抱歉。(众人大笑)所以,它在某种根本方式上统一了开发者社区。然后,你审视了整个局面,看到了 Scaling Laws ,AI 变得越来越神奇。你决定,好吧,仅仅通过 VS Code 写一个扩展是不够的,因为那样限制太多了。如果 AI 会持续变得越来越好,我们需要真正重新思考 AI 如何成为编辑过程的一部分。于是,你决定 fork VS Code,并开始构建许多我们将要讨论的惊人功能。但做那个决定是怎样的?因为有很多 VS Code 的扩展,包括 Copilot,都在做类似 AI 的事情。决定直接 fork VS Code 是怎样的?
Cursor 团队: 至少对我们想要做和实现的目标来说,做一个编辑器的决定似乎是不言自明的。因为当我们开始做编辑器时,想法是这些模型会变得越来越好,它们的能力会提升,这将完全改变你构建软件的方式,既会带来巨大的生产力提升,也会彻底改变构建软件的行为本身。如果你只是一个现有编码环境的插件,你对代码编辑器的控制就非常有限,我们不想被这些限制束缚。我们只想能够构建最有用的东西。
Lex Fridman: 好的。那么,自然的问题就是,VS Code 加上 Copilot 算是竞争对手,那么你们怎么赢?基本上就是靠功能的速度和质量吗?
Cursor 团队: 是的,我的意思是,我认为这是一个非常有趣,也许相当独特的领域。如果你回顾之前的技术浪潮,可能只是发生了一件主要的事情,然后解锁了一波新公司。但现在,每一年,每一次模型能力的提升或飞跃,都会解锁新一波的功能,新可能的事物,尤其是在编程领域。所以,我认为,在 AI 编程领域,哪怕只领先几个月,更不用说一年,都会让你的产品变得有用得多得多得多。我认为一年后的 Cursor 需要让今天的 Cursor 看起来过时。我认为微软做了很多很棒的事情,但我不认为他们处于一个能够像初创公司那样真正持续创新和推动这个领域的位置。
Lex Fridman: 只是快速实现功能。
Cursor 团队: 是的,并且进行必要的研究实验来真正突破上限。
Cursor 团队: 我不确定我是否将其视为“功能”,而更多地是看作程序员的“能力”。随着新的 o1 模型问世,我相信还会有更多不同类型的模型,比如更长上下文、也许更快,你可以尝试各种疯狂的想法,希望其中 10% 的疯狂想法能变成某种酷炫有用的东西,我们希望人们能更早地拥有它。
Cursor 团队: 换句话说,一个被低估的事实是:我们是为自己做的。当我们开始做 Cursor 时,你真的能感受到那种挫败感,你能看到模型在变好,但 Copilot 的体验却没有改变。就好像是,“天花板在升高,他们为什么不创造新东西?他们应该创造新东西。那些 alpha 功能在哪里?根本没有 alpha 功能。” 我相信它卖得很好。我相信它是个好生意,但我是那种非常想尝试和使用新事物的人,而很长一段时间都没有新东西出现。
Lex Fridman: 是的,这很有趣。我不知道该怎么用语言表达,但当你比较 Cursor 和 Copilot 时,Copilot 不知为何很快就开始让人感觉陈旧。
Cursor 团队: 是的,我认为有一点对我们有帮助,那就是我们是一体化进行的。我们在开发 UX 和你与模型交互方式的同时,也在开发我们如何实际让模型给出更好的答案。比如,如何构建提示,或者如何找到上下文,对于 Cursor Tab,如何训练模型?所以,我认为让同一群人端到端地负责整个体验对我们是有帮助的。
Cursor 团队: 是的,就像做 UI 的人和训练模型的人就坐在 18 英尺远的地方。
Cursor 团队: [Aman] 甚至常常是同一个人。
Cursor 团队: 是的,常常甚至是同一个人。你可以创造出那种如果你不交流、不实验就无法实现的东西。
Lex Fridman: 而且你们,就像你说的,用 Cursor 来写 Cursor?
Cursor 团队: 当然。
Cursor 团队: 哦,是的。
Cursor 团队: 是的。
五、 Cursor 核心功能:Cursor Tab
Lex Fridman: 好,让我们谈谈其中的一些功能。让我们谈谈那个全知全能、值得赞美的 Tab,(众人笑)基本上是打了激素的自动补全。Tab 是如何工作的?Tab 是什么?
Cursor 团队: 高层次地概括一下,我认为 Cursor 目前有两件事做得相当不错。它还有其他功能,但主要在两方面帮助程序员。一是这种“在你身后看着”的想法,扮演一个反应极快的同事,他能抢在你前面,打字,并预测你接下来要做什么。这是好的自动补全背后的核心思想——预测你接下来要做什么,但你可以让这个概念更有野心,不仅仅是预测你光标后的字符,而是预测你将要做的下一个完整的更改,下一个 diff,下一个你要跳转到的地方。第二件 Cursor 目前也做得不错的事情是,有时帮助你抢在 AI 前面,告诉它该做什么,从指令到代码。在这两方面,我们都做了很多工作,让这些事情的编辑体验符合人体工程学,并且让它们变得智能和快速。
Cursor 团队: 我们真正想要的一件事是,我们希望模型能为我们编辑代码。这有点像一个愿望,在我们拥有一个能为你编辑代码的好模型之前,我们尝试了很多次。然后,在我们有了一个好模型之后,我认为我们花了很多力气来让推理变得足够快以获得良好体验。我们已经开始融入,我的意思是,Michael 提到了这种跳转到不同地方的能力,我认为这种跳转能力源于一种感觉:一旦你接受了一个编辑,就好像,“天哪,下一步去哪里应该是非常明显的。” 比如,“我做了这个改动,模型就应该知道下一个该去的地方是下面 18 行。” 如果你是 Vim 用户,你可以按 18JJ 之类的,但我在做什么呢?模型就应该知道。所以想法就是你只需按 Tab,它就会跳到 18 行下,然后向你展示下一个编辑,你再按 Tab,如此循环,只要你能一直按 Tab。所以内部的竞赛就是,我们能让用户连续按多少次 Tab?一旦你有了这个想法,更抽象地看,需要思考的是编辑如何能做到“零熵”(zero entropy)?当你完成你的想法不需要任何新的信息比特,但你仍然需要输入一些字符让计算机理解你真正在想什么时,也许模型就应该直接读懂你的心思,所有这些零熵的比特都应该通过按 Tab 来完成。这大概是抽象的版本。
Cursor 团队: 有一个有趣的现象,如果你看语言模型在不同领域上的损失(loss),我相信代码的每字节比特数(bits per byte),这是一种字符归一化的损失度量,比自然语言要低。这意味着,总的来说,代码中有很多标记(token)是极其可预测的,很多字符是极其可预测的。我认为,当你不仅仅是试图自动补全代码,而是预测用户接下来在编辑现有代码时要做什么时,这一点甚至更加明显。所以,Cursor Tab 的目标是:让我们消除你在编辑器中采取的所有低熵(low entropy)行为。当意图基本确定时,让我们直接帮你快进时间,跳过这些步骤。
Lex Fridman: 预测下一个光标位置的直觉和技术细节是什么?那种跳转,对人们来说可能不那么直观。
Cursor 团队: 是的。我可以谈谈让这些功能实现的一些细节。它们需要极低的延迟,所以你需要针对这个任务训练小模型。特别是,它们非常需要大量的预填充(pre-fill)标记。这意味着它们有非常非常长的提示,需要看到你大量的代码,但实际上生成的标记并不多。对此最完美的匹配是使用稀疏模型(sparse model),也就是 MoE(Mixture of Experts)模型。这是我们取得的一个突破,显著提高了它在更长上下文中的性能。另一个突破是我们开发的一种称为“推测性编辑”(speculative edits)的推测解码(speculative decoding)变体。我认为这两点是使其质量高且速度快的重要组成部分。
Lex Fridman: 好的,所以 MoE,专家混合模型,输入巨大,输出很小。
Cursor 团队: 是的。
Lex Fridman: 好的。缓存(caching)在这里起作用吗?
Cursor 团队: 哦,缓存起了巨大的作用。因为你要处理这么多输入标记,如果在给定行中你输入的每一个按键都必须让模型重新运行所有传入的标记,那你首先会显著降低延迟,其次你的 GPU 负载会爆炸。所以,你需要设计用于模型的实际提示,使其具有缓存意识(caching aware)。然后是的,你需要在请求之间重用 KV 缓存,这样你就能花费更少的工作量,更少的计算。
Lex Fridman: 再说一次,在短期内,Tab 应该能做哪些事情,让我们稍微停留一下?生成代码,填充空白,还有跨多行编辑代码,然后在同一文件内跳转到不同位置,然后...
Cursor 团队: 希望也能跳转到不同的文件。所以如果你在一个文件中做了编辑,也许你需要去另一个文件来完成你的想法,它也应该能跳转到第二个文件。
Cursor 团队: 完全的泛化是“下一个动作预测”(next action prediction)。有时,你需要在终端运行一个命令,它也应该能根据你写的代码建议这个命令。
Cursor 团队: 它建议了某样东西,但你很难知道它是否正确,因为你实际上需要更多信息来学习。你需要知道类型才能验证它是否正确。所以也许它实际上应该带你到一个东西的定义处,然后再带你回来,这样你就拥有了所有必要的知识来接受下一个补全。
Lex Fridman: 所以是为人类提供知识。
Cursor 团队: [Arvid] 是的。
Lex Fridman: 对。
Cursor 团队: 嗯哼,是的。
Lex Fridman: 我刚认识一个叫 Primeagen 的家伙。你可以通过 SSH 点咖啡。
Cursor 团队: (笑)哦,是的。
Cursor 团队: 我们做过那个。
Cursor 团队: 我们做过那个。
Lex Fridman: 所以,模型也能做到那个并为你提供咖啡因吗?好的,那是大致的框架。
Cursor 团队: 是的。编程是一个奇怪的学科,有时你接下来五分钟要做的事情,并非总是如此,但有时,确实可以从你最近做的事情中预测出来。所以,你能否达到这样一个世界:那接下来的五分钟要么是你放手让它带你完成?或者可能更多的是你看到它下一步要做什么,你说,“好的,这很好,这很好,这很好,这很好,”然后你就可以通过按 Tab 键完成这些大的改动。
六、 用户体验:Diff 界面与代码验证
Lex Fridman: 当我们讨论这个的时候,我应该提到 Cursor 一个非常酷且引人注目的地方是,它有这整套 diff 界面处理。模型用红色和绿色来建议我们将如何修改代码,在聊天窗口你可以应用它,它会向你展示 diff,你可以接受这个 diff。所以,也许你能谈谈这方面的任何方向?
Cursor 团队: 我们大概有四五种不同的 diff。我们为自动补全优化了 diff,所以它的 diff 界面与你审查较大代码块时的界面不同。然后我们正在尝试为处理多个不同文件的情况优化另一种 diff 界面。总的来说,区别在于,当你进行自动补全时,它应该非常非常快就能读懂。实际上,所有情况下都应该非常快就能读懂,但在自动补全时,你的眼睛聚焦在一个区域。人类无法同时看太多不同的地方。
Lex Fridman: 所以,你是在谈论界面方面?
Cursor 团队: 在界面方面。所以它目前在旁边有一个框。我们有当前的框,它试图在某个地方删除代码,并试图添加其他代码,它试图在旁边给你显示一个框。
Lex Fridman: 如果我们打开 cursor.com,也许可以展示一下。这就是我们谈论的。
Cursor 团队: 那个框...
Lex Fridman: 正是这里。
Cursor 團隊: 大概经过了三四次尝试才让这东西奏效。第一次尝试是蓝色的删除线。在侧边框出现之前,它曾经通过像谷歌文档那样的方式向你展示要删除的代码,你会看到一条线穿过它,然后看到新的代码。那太让人分心了。有删除,有尝试用红色高亮。然后下一个迭代,有点好笑,你需要按住 Mac 上的 Option 键。它会高亮一个代码区域,提示你可能有东西要来。比如在这个例子里,input
和 value
都会变蓝。蓝色是为了高亮 AI 有一个建议给你。所以,它不是直接向你展示东西,而是暗示 AI 有建议,如果你真的想看,你就按住 Option 键,然后你会看到新的建议。如果你松开 Option 键,你就会看到你原来的代码。
Lex Fridman: 嗯哼,顺便说一句,那挺好的,但你得知道要去按 Option 键。
Cursor 团队: 是的。
Lex Fridman: 顺便说一句,我不是 Mac 用户,但我明白了,Option。我想是你们这些人有的一个按钮。
Cursor 团队: 再说一次,它就是不直观。我认为这才是关键。
Cursor 团队: 而且这也有可能不是最终版本。
Cursor 团队: 我个人非常期待在这个领域做出很多改进。我们经常称之为“验证问题”(verification problem)。这些 diff 对于小的编辑来说很棒。对于大的编辑或者涉及多个文件时,审查这些 diff 实际上有点令人望而却步。所以,这里有几个不同的想法。我们有一个想法是,好吧,diff 的某些部分很重要,它们包含大量信息。而 diff 的另一些部分熵非常低,只是同样的东西一遍又一遍重复。所以也许你可以高亮重要的部分,然后淡化不那么重要的部分。或者也许你可以有一个模型来查看 diff,发现“哦,这里可能有一个 bug”,然后用红色小波浪线标记出来,说“你应该重点审查 diff 的这一部分”。我认为这个方向的想法很令人兴奋。
Lex Fridman: 是的,这是一个非常迷人的 UX 设计工程领域。所以你,基本上,是试图引导人类程序员阅读所有他们需要阅读的内容,不多不少,达到最优。
Cursor 团队: 是的,而且你想要一个智能模型来做这件事。目前,diff 算法,它们就像普通的算法一样。没有智能。设计算法时有智能投入,但它不关心这个东西或那个东西的含义,而你希望模型来做这件事。
Cursor 团队: 所以,普遍的问题是,天哪,这些模型会变得越来越聪明。随着模型变得越来越聪明,它们能够提出的改动会大得多。所以随着改动变得越来越大,人类必须做越来越多的验证工作。你需要帮助他们。我不想把所有时间都花在审查代码上。
Lex Fridman: 你能多谈谈跨多文件的 diff 吗?
Cursor 团队: 是的,我的意思是,GitHub 试图解决这个问题,对吧,通过代码审查(code review)。当你进行代码审查时,你正在审查跨多个文件的多个 diff。但正如 Arvid 之前说的,我认为你可以做得比代码审查好得多。代码审查有点糟糕。你花费大量时间试图理解那些通常对你来说相当陌生的代码,而且它通常甚至抓不到多少 bug。我认为你可以使用语言模型显著改善这种审查体验,例如,使用 Arvid 描述的那种技巧,比如将你引向真正重要的区域。我认为,如果代码是由这些语言模型产生的,而不是由其他人产生的。代码审查体验是为审查者和代码产生者双方设计的。在代码产生者是语言模型的情况下,你不太需要关心它们的体验,你可以围绕审查者设计整个过程,让审查者的工作尽可能有趣、轻松、高效。我觉得这正是仅仅简单地试图让这些东西看起来像代码审查的问题所在。我认为你可以更有创造力,突破可能性的界限。
Cursor 团队: 这里有一个想法是,我认为顺序很重要。通常,当你审查一个 PR(Pull Request)时,你会看到一个文件列表,然后从上到下审查它们,但你实际上可能想先理解这部分,因为它在逻辑上是先发生的,然后你想理解下一部分。你不想自己去搞清楚这个顺序。你想要一个模型来引导你完成整个过程。
Lex Fridman: 创造的步骤会越来越多地是自然语言吗?目标是这样,而不是实际编写代码?
Cursor 团队: 我认为有时会是。我不认为所有编程都会变成自然语言。原因是,如果我和 Sualeh 结对编程,Sualeh 在电脑和键盘前,有时如果我主导,我想对 Sualeh 说,“嘿,实现这个函数,”这行得通。但有时向 Sualeh 解释我想要他做什么实在太烦人了,所以我实际上会接管键盘,向他展示。我写一部分示例,然后他就明白了,这是最简单的沟通方式。所以,我认为对于 AI 也是如此。有时与 AI 沟通最简单的方式是展示一个示例,然后它去其他所有地方做同样的事情。或者有时如果你在做一个网站,例如,向 AI 展示你想要什么的最简单方式不是告诉它做什么,而是拖拽东西或画图。也许最终,我们会发展到脑机接口之类的,你可以理解你在想什么。所以,我认为自然语言会有一席之地。但我绝对认为它不会是大多数人大多数时候编程的方式。
七、 交互模型:自然语言及其他
(内容已在上一节融合讨论)
八、 底层机器学习技术
Lex Fridman: 我真的能从这个编辑器感受到 AGI。(众人笑)感觉底层有很多机器学习在进行。告诉我一些让这一切运转起来的 ML 东西吧?
Cursor 团队: Cursor 真正的工作方式是通过一个我们训练的定制模型与前沿模型(frontier models)的集成系统(ensemble)。前沿模型在需要强推理的任务上非常出色。例如,Cursor Tab 就是一个很好的例子,通过专门化训练,这个模型在它被设定的任务上的评估(evals)结果甚至比前沿模型更好。另一个领域,虽然令人惊讶它需要定制模型,但确实必要且效果很好,那就是“应用”(Apply)功能。前沿模型很擅长勾勒代码计划和生成更改的粗略草图,但实际上,创建 diff 对前沿模型来说相当困难,对你训练的模型来说也是。你用 Sonnet、用 o1、用任何前沿模型尝试做这个,它都会在一些愚蠢的事情上出错,比如计算行号,尤其是在非常非常大的文件中。所以我们为了缓解这个问题所做的是,我们让模型勾勒出这个粗略的代码块,表明将要做什么更改,然后我们训练一个模型来将这个更改“应用”到文件中。
Lex Fridman: 我们应该说一下,“Apply”是指模型看了你的代码,给出了一个非常好的关于下一步做什么的建议。而对于人类来说看似微不足道的将两者结合起来的步骤,你却说并不那么简单。
Cursor 团队: 与普遍看法相反,它不是一个确定性算法(deterministic algorithm)。
Cursor 团队: 是的,你在其他地方看到过 Apply 的浅层复制品,它们大多数时候都会坏掉,因为你以为可以尝试做一些确定性的匹配,结果至少有 40% 的时间会失败,这导致了糟糕的产品体验。我认为总的来说,在这个模型越来越智能的时代。Apply 让你做的另一件事是,它让你能用最智能的模型使用更少的 token。这在生成所有这些 token 的延迟和成本方面都很昂贵。所以,你可以给出这个非常非常粗略的草图,然后让你的模型去实现它,因为实现这个非常非常粗略的代码是一个容易得多的任务。我认为这个模式会持续下去,你可以用越来越智能的模型来做规划,然后也许实现细节可以由不那么智能的模型来处理。也许你会用 o1,也许是能力更强的模型给出一个更高层次的计划,然后由 Sonnet 递归地应用,最后由 Apply 模型执行。
Cursor 团队: 也许我们可以谈谈如何让它变快,如果你愿意的话。快总是一个有趣的细节。
Cursor 团队: [Arvid] 快是好的。
Lex Fridman: 是的,你们是怎么让它变快的?
Cursor 团队: 是的,所以让它变快的一个重要组成部分是“推测性编辑”(Speculative Edits)。推测性编辑是推测解码(speculative decoding)的一种变体,也许简单描述一下推测解码会有帮助。通过推测解码,你可以利用这样一个事实:大多数时候,并且我要加上一个前提条件,即当你在语言模型生成中受内存限制(memory bound)时,一次处理多个 token 比一次生成一个 token 要快。这就是为什么如果你看提示 token(prompt tokens)与生成 token(generated tokens)的每秒 token 数,提示 token 要快得多得多。所以我们做的是,不使用推测解码通常做的那样,即用一个非常小的模型来预测“草稿” token,然后让你的大模型去验证。对于代码编辑,我们有一个非常强的关于现有代码会是什么样子的先验(prior),这个先验就是字面意义上的完全相同的代码。所以你可以做的是,你只需将原始代码块反馈给模型,然后模型大多数时候会基本同意,“好吧,我就把这段代码吐出来。”这样你就可以并行处理所有这些行,你只需要对足够多的代码块这样做。最终,你会到达一个分歧点,模型会预测出与原始代码不同的文本。它会生成那些 token,然后在足够多的 token 匹配原始代码后,我们会决定重新开始以代码块的形式进行推测。这实际上的效果看起来就像是普通编辑代码的一个快得多的版本。所以,它看起来就像是模型重写所有代码的一个快得多的版本。因此,我们可以使用与 diff 完全相同的界面,但它会以快得多的速度流式输出。
Cursor 团队: 然后优点是,当它在流式输出时,你也可以在它完成之前就开始审查代码,所以没有大的加载屏幕。也许这是优势的一部分。
Lex Fridman: 所以,人类可以在事情完成之前就开始阅读。
Cursor 团队: 我认为这里有趣的发挥点在于,我觉得推测(speculation)如今是一个相当普遍的想法。不仅仅是在语言模型中。很明显 CPU 中有推测,数据库也有推测,推测无处不在。
九、 大语言模型(LLM)比较与评估
Lex Fridman: 好,让我问个有点离谱的问题:哪个 LLM 更擅长编码?GPT、Claude,在编程的背景下谁赢?我相信答案会更细致,因为听起来这其中的每个部分都涉及不同的模型。
Cursor 团队: 是的,我认为没有哪个模型能在所有方面都帕累托占优(Pareto dominate),也就是说,在所有我们认为重要的类别中都更好。这些类别包括速度、编辑代码的能力、处理大量代码的能力、长上下文、以及其他一些因素和编码能力。我认为目前综合来看最好的(net best)是 Sonnet。我觉得这是共识。O1 非常有趣,它在推理方面确实很强。所以如果你给它非常难的编程面试风格的问题或 LeetCode 问题,它能做得相当好,但感觉它不像 Sonnet 那样能理解你大概的意图。如果你看其他很多前沿模型,我有一个疑虑是,感觉它们不一定是过度拟合,我不是说它们针对基准测试进行训练,但它们在基准测试上的表现相对于中间的所有东西来说都非常好。所以如果你在所有这些基准测试以及与它们评估的基准测试分布一致的事物上尝试它们,它们会做得非常好。但是当你把它们稍微推到那个范围之外时,我认为 Sonnet 是在保持相同能力方面做得最好的那个。它在基准测试中的能力与你尝试指示它用代码做任何事情时的能力是相同的。
Lex Fridman: 另一个有点离谱的问题是,正常的编程体验与基准测试所代表的有什么不同?当我们评估这些模型时,你认为基准测试在哪些方面存在不足?
Cursor 团队: 顺便说一句,这是一个非常非常困难、极其重要的细节:基准测试与真实编码有多大不同。真实编码不是面试风格的编码。人类有时说的是半通不通的英语,有时你说,“哦,照我之前做的来。”有时你说,“去加上这个东西,然后帮我做那个,然后做这个 UI 元素。”然后,很多事情都依赖于上下文。你真正需要的是理解人类,然后做人类想做的事,而不是像面试问题那样,可能抽象地说,面试问题是非常良构的(well specified)。它们非常依赖于规范,而人类的东西则不那么规范。
Cursor 团队: 是的。我认为这个基准测试问题既因为 Sualeh 刚才提到的而变得复杂,也因为 Aman 深入探讨的而变得复杂。存在一个问题,即你能在基准测试中实际建模的东西与真实编程之间的偏差,这有时很难概括,因为真实编程非常混乱,有时事情并没有明确规定什么是正确的或不正确的。但由于公开基准测试的问题,它也变得加倍困难。这既因为公开基准测试有时会被过度优化(hill climbed on),也因为很难将公开基准测试的数据从模型中去除。例如,最流行的 Agent 基准测试之一,SWE-Bench,在这些基础模型的训练数据中受到了非常非常严重的污染。所以如果你让这些基础模型去做一个 SWE-Bench 问题,但你实际上不给它们代码库的上下文,它们可以幻化出正确的文件路径,幻化出正确的函数名。所以,这些东西的公开性本身也很棘手。
Cursor 团队: 是的,在这种情况下,它可能是在字面意义上的 issue 或 pull request 本身上训练的,也许实验室会开始做得更好,或者他们已经做得很好,来清理这些东西,但他们不会省略仓库本身的实际训练数据。这些都是一些最流行的 Python 仓库。SimPy 是一个例子。我不认为他们会为了在这些基准测试中获得真实的评估分数而牺牲他们的模型在 SimPy 和所有这些流行的 Python 仓库上的能力。
Cursor 团队: 我认为,考虑到基准测试的混乱,构建使用这些模型的系统或构建这些模型本身的地方,已经采用了一些有趣的权宜之计,来判断它们是否走在正确的方向上。在很多地方,人们实际上会让人类去玩这些东西,并给出定性反馈。一两个基础模型公司,他们有专门的人员负责这个。在内部,我们也定性评估这些模型,并且除了我们拥有的私有评估(private evals)之外,也非常依赖这一点。
Cursor 团队: [Arvid] 这就像是“感觉”(vibe)。
Cursor 团队: “感觉”,是的,“感觉”。
Cursor 团队: 这就像是“感觉”。
Lex Fridman: “感觉”基准测试,人类基准测试,人类。你拉来人类做个“感觉”检查。
Cursor 团队: 是的。(笑)
Lex Fridman: 好的。我就是这么做的,只是阅读在线论坛、Reddit 和 X。嗯,我不知道如何正确地加载人们的意见,因为他们会说,“我感觉 Claude 或 GPT 变笨了,”之类的话。他们会说,“我感觉。”然后我有时也会有这种感觉,但我不知道这是模型的问题还是我的问题。
Cursor 团队: 对于 Claude,我听过一个有趣的说法,我认为 AWS 有不同的芯片,我怀疑它们的数值计算(numerics)与 Nvidia GPU 略有不同,有人推测 Claude 性能下降可能与使用了 AWS Bedrock 上存在的量化(quantized)版本有关,而不是在 Anthropic 自己的 GPU 上运行的版本。
Lex Fridman: 我采访过一些有阴谋论的人,所以我很高兴你谈到了这个阴谋论。
Cursor 团队: 嗯,这与其说是阴谋论,不如说是人类。人类就是人类,存在这些细节。
Lex Fridman: [Lex] 是的。
Cursor 团队: 你在做这种令人不安数量的浮点运算(flops),芯片是复杂的,天哪,你就是会遇到 bug。避免 bug 的难度怎么强调都不为过。
十、 提示工程(Prompt Engineering)与上下文管理
Lex Fridman: 在这一切中,一个好的提示(prompt)扮演着什么角色?我们提到基准测试有结构化、形式良好的提示。人类应该怎么做才能最大化成功率?人类的重要性是什么,你写了一篇博客文章,称之为“提示设计”(Prompt Design)。
Cursor 团队: 是的,我认为这取决于你使用的是哪个模型,它们都略有不同,对不同的提示反应也不同,但我认为最初的 GPT-4 和去年的原始(indistinct)模型对提示相当敏感,而且它们的上下文窗口(context window)非常小。所以,我们有所有这些关于代码库的信息片段,它们可能在提示中是相关的。你有文档,你有你添加的文件,你有对话历史,然后就有一个问题:你如何决定实际在提示中放什么,以及当你空间有限时?即使对于今天的模型,即使你有长上下文,填满整个上下文窗口也意味着它更慢。这意味着有时模型实际上会感到困惑,有些模型比其他模型更容易困惑。我们在内部有一个系统,我们称之为 Preempt,它在这方面帮助了我们一点。我认为它是为我们拥有 8000 token 上下文窗口之前的时代构建的。这有点类似于当你制作一个网站时。你希望它在移动设备上工作,你希望它在桌面屏幕上工作,你有这种动态信息,而你没有。例如,如果你在设计一本印刷杂志,你确切地知道你可以在哪里放东西。但是当你有一个网站或者一个提示时,你有这些输入,然后你需要格式化它们以使其始终有效,即使输入非常大,你也可能需要削减一些东西。所以想法是,好吧,让我们借鉴一些灵感。设计网站的最佳方式是什么?嗯,我们真正喜欢的是 React 和声明式方法,即你在 JavaScript 中使用 JSX,然后你声明,“这是我想要的,我认为这个优先级更高,或者这个 Z-index 比其他东西高。”然后,在网页设计中你有这个渲染引擎,比如 Chrome,而在我们的案例中它是一个 Preempt 渲染器,它然后将所有东西适配到页面上。正如你声明的那样,决定你想要什么,然后它弄清楚你想要什么。所以,我们发现这相当有帮助,我认为它的作用随着时间的推移发生了变化,最初是为了适应那些小的上下文窗口。现在,它非常有用,因为它帮助我们将进入提示的数据和实际的渲染分离开来。因此,调试更容易,因为你可以更改提示的渲染方式,然后在旧的提示上尝试,因为你拥有进入提示的原始数据,然后你可以看到,“我的更改是否真的对这个整个评估集有所改进?”
Lex Fridman: 所以,你们真的用 JSX 来写提示吗?
Cursor 团队: 是的,是的。
Cursor 团队: 是的。
Cursor 团队: 所以它看起来像 React,有组件。我们有一个文件组件,它接收光标位置。通常,你的文件中有一行是光标所在的位置,那可能是最重要的一行,因为那是你正在看的一行。然后,你可以给出优先级,所以那一行有最高优先级,然后对于距离更远的每一行,你减去 1。最后,当它被渲染时,它会计算出实际能容纳多少行,并围绕那个重要的东西居中。
Lex Fridman: 太神奇了。
Cursor 团队: 是的。你还可以做其他花哨的事情,比如如果你有来自整个代码库的大量代码块,你可以使用检索(retrieval)以及像嵌入(embedding)和重排(re-ranking)分数这样的东西,通过这些组件为你添加优先级。
Lex Fridman: 那么人类在提问时,也应该尝试使用类似的方法吗?在问题中写 JSX 会有好处吗,还是说整个想法就是这应该是松散和混乱的?
Cursor 团队: 我认为我们的目标是,你应该只做对你来说最自然的事情,然后我们的工作是弄清楚我们如何实际检索相关的东西,以便你的想法真正有意义?
Lex Fridman: 这是我和 Perplexity 的 Aravind 讨论过的话题,他的整个想法是你应该让用户想多懒就多懒。
Cursor 团队: 是的。
Cursor 团队: 嗯哼。
Lex Fridman: 是的,那是一件美好的事情,但我觉得你被允许对程序员要求更多,对吧?
Cursor 团队: 是的。
Lex Fridman: 所以如果你说,“只做你想做的,”我的意思是,人类是懒惰的。在仅仅懒惰和提供更多信息作为提示之间存在一种张力,几乎就像系统在给你压力或激励你表达得更清楚。不是指句子的语法,而是指你在提示中传达的思想深度。
Cursor 团队: 我认为即使系统接近某种完美水平,当你向模型请求某样东西时,通常传达的意图不足以让它知道该做什么。有几种方法可以解决这种意图不明的问题。一种是简单的方法,让模型直接问你,“根据你目前的查询,我不确定如何处理这些部分。你能澄清一下吗?” 我认为另一种可能是,也许如果有五六种可能的生成结果,“鉴于你目前查询中存在的不确定性,为什么我们不直接把所有这些都展示给你,让你来选择呢?”
Lex Fridman: 模型选择反问有多难?这很难,如何处理不确定性。我是否应该选择请求更多信息来减少歧义?
Cursor 团队: 所以,我的意思是,我们做的一件事,是最近增加的功能,就是尝试建议你可以添加的文件。当你正在输入时,可以猜测不确定性在哪里,也许可以建议你正在编写你的 API,我们可以使用你之前在同一文件中所做的提交来猜测客户端和服务器非常有用,并且存在一个棘手的技术问题,即如何在所有提交中解决这个问题?考虑到你当前的提示,哪些文件最重要?我们仍在初步版本推出阶段,我相信我们可以让它更准确。这非常实验性,但想法是我们向你展示,你是否只想添加这个文件、这个文件、这个文件,也告诉模型为你编辑那些文件?因为也许如果你在做 API,你也应该编辑使用该 API 的客户端和服务器以及解析该 API 的另一端。所以这会很酷,因为在你编写提示的阶段。甚至在你点击“Enter”之前,也许我们就能帮助解决一些不确定性。
十一、 AI 代理(Agents)在编程中的应用
Lex Fridman: 你们在多大程度上使用代理(agentic)方法?代理有多大用处?
Cursor 团队: 我们认为代理非常非常酷。
Lex Fridman: (笑)好的。
Cursor 团队: 我觉得代理,它就像是像一个人。你能感觉到你正在接近 AGI,因为你看到一个演示,它的行为像人一样,这真的非常非常酷。我认为代理目前在很多事情上还不是特别有用。我认为我们正在接近它们将真正变得有用的时刻。所以,我认为对于某些类型的任务,拥有一个代理会非常好。我很想拥有一个代理。例如,如果我们有一个 bug,有时你无法在我们的聊天输入框中 Command+C 和 Command+V,这是一个定义非常明确的任务。我只想用两句话说,“这个不行,请修复它。”然后我很希望能有一个代理,它自己去处理,完成它,然后一天后,我回来审查结果。
Lex Fridman: 你是说它去找到正确的文件?
Cursor 团队: 是的,它找到正确的文件,尝试重现 bug,修复 bug,然后验证它是正确的。这可能是一个需要很长时间的过程。所以,我认为我很想拥有那个。然后我认为对于很多编程任务,常常有一种信念,认为代理将接管所有编程。我不认为我们认为会是这样,因为很多编程,很多价值在于迭代,或者你实际上不想预先指定某些东西,因为在你看到初始版本之前,你并不真正知道你想要什么,然后你想在此基础上迭代,然后你提供更多信息。所以,对于很多编程任务,我认为你实际上想要一个即时的系统,它能立即给你一个初始版本,然后你可以非常非常快地迭代。
Lex Fridman: 像最近出现的 replica agent 那样的东西怎么样?它还能设置开发环境、解决软件包问题、配置所有东西、配置数据库,并实际部署应用程序。那也在你梦想的事情之列吗?
Cursor 团队: 我认为是。我认为那会非常酷。对于某些类型的编程来说,那会非常酷。
Lex Fridman: 那在 Cursor 的范围内吗?
Cursor 团队: 是的,我们目前没有在积极地做这件事。我们想让程序员的生活更轻松、更有趣,有些事情就是非常繁琐,你需要经历一系列步骤,你想把这些委托给一个代理。然后有些事情,你实际上可以在工作时让一个代理在后台运行。假设你有一个 PR 同时涉及后端和前端,你正在处理前端部分,然后你可以让一个后台代理去工作,弄清楚你在做什么。然后,当你处理 PR 的后端部分时,你就有了一些可以迭代的初始代码。所以那也会非常酷。
十二、 性能优化策略
Lex Fridman: 我们已经谈到了速度,但我想知道我们是否可以就此再多停留一会儿,讨论涉及的技术细节,让这东西变得真正快。Cursor 的方方面面,大部分方面都感觉非常快。就像我提到的,Apply 可能是最慢的事情。抱歉,看到 Arvid 脸上痛苦的表情。(Arvid 和 Lex 笑)
Cursor 团队: 我知道。这很痛苦,这是我们感受到的痛苦,我们正在努力修复它。(Arvid 和 Lex 笑)
Lex Fridman: 是的,这说明了一些感觉,我不知道是什么,像一秒或两秒,感觉很慢。这实际上表明其他一切都真的非常非常快。那么,有没有一些技术细节是关于如何让这些模型变快,如何让聊天变快,如何让 diff 变快?有什么是立刻想到的吗?
Cursor 团队: 是的。我们可以过一遍我们使用的很多策略。一个有趣的事情是缓存预热(cache warming)。你很可能会使用某段上下文,并且在用户完成输入之前你就能知道这一点。所以正如我们之前讨论的,重用 KV 缓存可以降低延迟、降低跨请求的成本。因此,当用户开始输入时,你可以立即用比如说当前文件的内容来预热缓存,然后当他们按下 Enter 键时,实际需要预填充(pre-fill)和计算的 token 就非常少了,然后就可以开始生成了。这将显著降低 TTFT(Time To First Token,首个 token 时间)。
Lex Fridman: 你能解释一下 KV 缓存是如何工作的吗?
Cursor 团队: [Aman] 是的,所以 Transformer 的工作方式是。(众人笑)
Lex Fridman: 我喜欢这个开头。
Cursor 团队: (众人笑)允许 Transformer 不仅仅独立地看待每个 token,而是看到先前 token 的机制是 Attention 中的键(keys)和值(values)。通常,Attention 的工作方式是,在你当前的 token 处,你有一个查询(query),然后你有所有先前 token 的键和值,这是模型内部存储的所有先前提示 token 的某种表示。默认情况下,当你进行聊天时,模型必须为每一个 token 在整个模型中进行一次前向传播(forward pass)。这涉及大量的矩阵乘法,非常非常慢。相反,如果你已经做完了这些,并且存储了键和值,并将其保存在 GPU 中,比如说我必须为最后 N 个 token 排序。如果我现在想计算第 N+1 个 token 的输出 token,我不需要让前 N 个 token 通过整个模型,因为我已经有了所有那些键和值。所以,你只需要对最后一个 token 进行前向传播。然后当你进行 Attention 时,你正在重用那些已经计算出来的键和值,这是 Transformer 中唯一有点顺序(sequential)或顺序依赖(sequentially dependent)的部分。
Lex Fridman: 是否有更高级别的缓存,比如提示的缓存的缓存,或者类似的东西能有所帮助?
Cursor 团队: 我明白了。是的,你可以做其他类型的缓存。一个有趣的事情是,对于 Cursor Tab,你基本上可以提前预测,就好像用户会接受建议一样,然后触发另一个请求。这样你就缓存了,你做了推测性的。这是推测和缓存的混合,对吧?因为你在推测如果他们接受了会发生什么。然后你就有了这个缓存的值,这个建议。然后当他们按下 Tab 键时,下一个建议会立刻等着他们。这是一个聪明的启发式方法/技巧,使用了更高级别的缓存。它让人感觉很快,尽管模型本身实际上没有任何改变。
Cursor 团队: 如果你能让 KV 缓存更小,你得到的一个好处是,也许你可以进行更多的推测。也许你可以猜测,“这里有 10 件可能有用的事情,预测接下来的 10 件”,然后用户命中这 10 件之一的可能性就存在了。这比用户命中你展示给他们的那一个的确切概率要高得多。也许他们输入另一个字符,然后命中了缓存中的其他东西。这里的普遍现象是,我认为这对强化学习(RL)也非常有用,也许模型的单个样本不是很好,但如果你预测 10 个不同的东西,结果发现这 10 个中有一个是正确的概率要高得多。存在这些 Passive K 曲线,而 RL 的一部分作用是,你可以利用这种 Passive K 现象来进行许多不同的预测。思考这个问题的一种方式是,模型内部知道它对哪个关键点是正确的,或者人类想要哪个关键点,存在一定的不确定性。当我们对 Cursor Tab 模型进行 RL 时,我们做的一件事是,我们预测模型产生的 100 个不同建议中,哪一个更受人类欢迎?哪一个人类比其他更喜欢?也许有的建议模型可以预测得很远,有的只能预测一点点,有的在中间。然后你可以给人类更喜欢的建议奖励,惩罚他们不喜欢的,然后训练模型输出人类更喜欢的建议。你有这些非常有用的 RL 循环,它们利用了这些 Passive K 曲线。Aman,也许可以更详细地介绍。
Cursor 团队: 是的,这与速度有点不同,但技术上讲,你可以把它联系起来,因为如果你对你的小模型进行 RL,并且它达到了与大模型相同的性能,你就可以用更小的模型。所以,当我提到关于 KV、关于减小 KV 缓存大小的事情时,还有其他技术在那里也对速度非常有帮助。所以,回到过去,一直到两年前,人们主要使用多头注意力(Multi-Head Attention, MHA),我认为已经有向更高效的注意力方案迁移的趋势,比如分组查询注意力(Grouped-Query Attention, GQA)或多查询注意力(Multi-Query Attention, MQA),这对于在更大批量大小(batch sizes)下更快地生成 token 非常有帮助。有趣的是,这现在对那个首个 token 时间(TTFT)的预填充速度没有影响。它影响的是现在生成 token 的速度。为什么呢?因为当你生成 token 时,你不再受限于在所有 token 上进行那些超级可并行的矩阵乘法,而是受限于,对于长上下文和大批量大小,你能多快地读取那些缓存的键和值。这就是内存带宽(memory bandwidth),我们如何让它更快?我们可以尝试压缩这些键和值的大小。多查询注意力是其中最激进的。通常在多头注意力中,你有一定数量的所谓的“注意力头”(attention heads),以及一定数量的查询头(query heads)。多查询只保留查询头,去掉所有键值头(key value heads)。所以只有一种键值头,但保留了所有剩余的查询头。而分组查询则保留所有查询头。键和值的头数量减少了,但没有减少到只有一个。但无论如何,这里的重点就是你在减小你的 KV 缓存的大小。
Lex Fridman: 然后还有 MLA。
Cursor 团队: 是的,多潜伏(Multi-Latent Attention)。那个稍微复杂一点。它的工作方式是,它有点像把你所有头(heads)的全部键和值变成一个单一的潜伏向量(latent vector),然后在需要的时候再将其“扩展”出来。
Cursor 团队: 但是 MLA 来自这家叫做 DeepSeek 的公司。这是一个非常有趣的算法。也许关键思想在于,无论是在 MQA 还是其他地方,你所做的都是减少 KV 头的数量。你从中得到的好处是它们的数量变少了。你希望每个键和值实际上是不同的。所以,一种减小大小的方法是你为所有键和值保留一个大的共享向量,然后为每个 token 保留更小的向量。这样你就可以只存储那个更小的东西,作为某种低秩(low-rank)的缩减。最终,当你最终想要计算最终结果时,记住你的内存带宽,这意味着你仍然有一些计算能力可以用于这些事情。如果你能将潜伏向量扩展回来,并且某种程度上这效率高得多,因为你减少了,例如,也许你减少了 32 倍的向量大小。
Cursor 团队: 是的,拥有一组成对匹配的独立的键、值和查询可能比将它们全部压缩成一个并在交互中损失掉一些东西要更丰富一些。
Lex Fridman: 好的,所有这些都是为了应对内存带宽受限的问题。
Cursor 团队: 是的。
Lex Fridman: 我的意思是,最终,这如何映射到用户体验?试图让...
Cursor 团队: 是的,它映射到的两件事是,你现在可以让你的缓存大得多,因为你为 KV 缓存分配的空间更少了。你可以更积极地缓存更多的东西,所以你会得到更多的缓存命中,这有助于减少首个 token 的时间,原因之前已经描述过了。然后第二点是,当你开始用越来越多的请求和越来越大的批量大小进行推理时,你在生成 token 的速度方面不会看到太大的减速。
Lex Fridman: 嗯,它也允许你在某些情况下让你的提示更大...
Cursor 团队: 是的,是的。所以,你的 KV 缓存的大小是你所有提示的大小乘以并行处理的提示数量。所以你可以增加这两个维度中的任何一个,对吧?批量大小或者你提示的大小,而不会降低生成 token 的延迟。
十三、 后台处理与影子工作区(Shadow Workspace)
Lex Fridman: Arvid,你写了一篇博客文章,“影子工作区:在后台迭代代码”(Shadow Workspace: Iterating on Code in the Background)。那么,发生了什么?
Cursor 团队: 所以,需要明确的是,我们希望有很多东西在后台发生,我们正在试验很多东西。目前,除了缓存预热或找出进入你的 Command+K 提示的正确上下文之外,我们没有太多后台操作。但想法是,如果你真的能在后台花费计算资源,那么你可以帮助用户,也许在一个比仅仅预测你将要做的下几行代码更长的时间尺度上。而是在接下来的 10 分钟里,你将要做什么?通过在后台进行,你可以花费更多的计算来做这件事。所以我们实现的“影子工作区”(Shadow Workspace)的想法,我们在内部用它做实验,是这样的:为了真正利用在后台做事情的优势,你需要某种反馈信号反馈给模型,否则,你也可以通过让模型思考更长时间来获得更高的性能,o1 就是一个很好的例子。但是另一种提高性能的方式是让模型迭代并获得反馈。所以,当你是程序员时,一个非常重要的反馈是语言服务器(language server),这个东西,它对大多数不同的语言都存在,每种语言都有一个单独的语言服务器。它可以告诉你,“你在这里使用了错误的类型,”然后给你一个错误,或者它可以让你跳转到定义,并理解你的代码结构。有 TypeScript 语言服务器,由 TypeScript 的人开发;有 Rust 语言服务器,由 Rust 的人开发,然后它们都通过语言服务器协议(Language Server Protocol, LSP)与 VS Code 进行交互。这样 VS Code 就不需要将所有不同的语言都内置到 VS Code 中,而是可以使用现有的编译器基础设施。
Lex Fridman: 用于 linting 的目的,什么...
Cursor 团队: 是用于 linting。用于跳转到定义,以及查看你正在使用的正确类型。
Lex Fridman: 所以它也做类型检查?
Cursor 团队: 是的,类型检查和跳转到引用(go to references)。这就像当你在一个大项目中工作时,你有点需要这个。如果你没有这个,在一个大项目中编码真的很难。
Lex Fridman: 你能再说一遍,在 Cursor 内部是如何使用这个,语言服务器协议通信这东西的吗?
Cursor 团队: 所以它在 Cursor 中被用来向程序员展示信息,就像在 VS Code 中一样,但想法是你想把同样的信息展示给模型,即 IM 模型(注:应指 AI 模型),并且你希望以一种不影响用户的方式来做这件事,因为你希望在后台进行。所以“影子工作区”背后的想法是,好吧,一种方法是我们可以启动一个独立的、隐藏的 Cursor 窗口,你可以设置这个标志,让它隐藏起来。有一个窗口但你实际上看不到它。在这个窗口内部,AI 代理可以随意修改代码,只要它们不保存,因为它仍然是同一个文件夹,然后可以从 linter 获取反馈,跳转到定义,并在它们的(内存中的)代码上进行迭代。
Lex Fridman: 所以字面上是在后台运行一切,对吧,甚至可能运行代码。
Cursor 团队: 这就是最终的版本,也是你想要的。博客文章的很多内容实际上是关于如何实现这一点,因为它有点棘手。你希望它在用户的机器上运行,这样它就能精确地镜像用户的环境。然后在 Linux 上,你可以做一个很酷的事情,你可以实际镜像文件系统,让 AI 对文件进行更改,它以为它是在文件层面上操作,但实际上,那是存储在内存中的,你可以创建一个类似内核扩展的东西来让它工作。而在 Mac 和 Windows 上,这有点困难,但这是一个有趣的技术问题,所以这就是原因。
Cursor 团队: 一个可能有点 hacky 但有趣的想法是持有保存锁(holding a lock on saving)。这样基本上,你可以让语言模型持有保存到磁盘的锁,然后你不是在操作保存到磁盘的真实文件版本,而是在操作之前是“影子工作区”的那些东西,那些只存在于内存中但你仍然可以得到 linter 错误并且可以在其中编码的未保存的东西。然后当你尝试比如运行代码时,它只是会有一个小警告说有一个锁,然后如果你试图并发地做事情,你就会从语言服务器那里拿回锁,或者如果你试图并发地做事情,就从影子工作区那里拿回锁。
十四、 调试、代码验证与潜在商业模式
Lex Fridman: 顺便说一句,那真是个令人兴奋的未来。有点跑题,但是允许模型更改文件,对人们来说很可怕,但这真的很酷,能够让代理完成一系列任务,你第二天回来观察,就像它是一个同事一样。
Cursor 团队: 我认为对于那些你在几分钟内代表用户进行的简单事情,当他们编程时,让一些东西在他们的本地机器上工作是有意义的。我认为对于更激进的事情,即你进行更大规模的更改,需要更长时间,你可能想在某个沙盒化的远程环境中进行,这是另一个极其棘手的问题:如何精确地复制,或者说在运行代码方面基本复制到等效的程度,用户的环境与这个远程沙盒。
Lex Fridman: 我很好奇你想要什么样的代理来编码?你希望它们找到 bug 吗?你希望它们实现新功能吗?你想要什么样的代理?
Lex Fridman: 顺便说一句,当我想到代理时,我不仅仅想到编码。我想,对于这个特定的播客,有视频编辑,如果你看 Adobe,背后有代码。文档写得很差的代码,但你可以用代码与 Premiere 交互,例如,基本上所有上传,我在 YouTube 上做的所有事情,你能想象到的一切,我都是通过代码完成的,包括翻译和配音,所有这些。所以,我设想的是所有这些类型的任务。自动化许多与编辑本身不直接相关的任务,就是那个。好的,这就是我在想的。但在编码方面,我基本上会考虑 bug 发现,很多层次的 bug 发现,也包括发现逻辑 bug,不是那种精神层面的逻辑 bug。(众人笑)那种实现的大方向上的问题,诸如此类。
Cursor 团队: 神奇的(听不清)和 bug 发现。
Lex Fridman: 是的,我的意思是,这些模型在仅仅被提示去查找 bug 时,表现如此之差,这真的很有趣。它们的校准(calibrated)极其糟糕。
Cursor 团队: 即使是最聪明的模型。
Lex Fridman: 完全正确,即使是 o1。
Lex Fridman: 你怎么解释这个?有什么好的直觉吗?
Cursor 团队: 我认为这些模型是预训练(pre-training)分布的强烈反映,我确实认为随着损失(loss)越来越低,它们会泛化,但我认为损失还不够低,以至于它们在代码上真正完全泛化。我们使用这些东西,那些前沿模型擅长的事情,主要是代码生成和问答。这些东西在预训练中大量存在,所有 GitHub 上的代码规模达到数万亿 token,以及像 Stack Overflow 和 GitHub issues 上的问答。所以,当你尝试推动一些在网上不怎么存在的东西时,例如 Cursor Tab 的目标:根据到目前为止所做的编辑预测下一个编辑,脆弱性就显现出来了。然后 bug 检测是另一个很好的例子,实际上并没有那么多检测真实 bug 然后提出修复方案的例子,模型在这方面确实很挣扎。但我认为这是一个迁移(transferring)模型的问题,就像你从仅仅在通用代码上预训练的模型获得了到 Cursor Tab 目标的奇妙迁移一样。你会看到一个非常非常类似的事情发生在通用模型(它们非常擅长代码)到 bug 检测上。它只是需要一点点朝那个方向的“轻推”。
Cursor 团队: 看,需要明确的是,我认为,它们确实很好地理解了代码。当它们被预训练时,建立起来的表示(representation)几乎肯定,比如在流的某个地方,模型知道也许有什么可疑的事情正在发生。部分原因在于人类对于哪些 bug 真正重要有很好的校准。不仅仅是实际说有什么可疑。而是这个可疑是微不足道的,还是这个可疑会导致服务器宕机。部分原因也许是文化知识,为什么一个资深工程师(staff engineer)很厉害?因为他们知道三年前有人写了一段非常可疑的代码导致服务器宕机了。(众人笑)这个东西是一个实验。所以,有几个 bug 没关系,你只是想尝试一下,感受一下。所以如果模型在你写实验代码时变得非常烦人,那就很糟糕。但如果你在写一些用于超级生产环境的东西,你在写一个数据库。你在写 Postgres 或 Linux 或其他什么里面的代码。你是 Linus Torvalds。即使是一个边缘情况也是不可接受的,而仅仅是拥有用户有多偏执的校准。
Cursor 团队: 但即便如此,如果你设定了最大的偏执度,它仍然无法完全理解。
Cursor 团队: 是的,是的,是的。
Lex Fridman: 我的意思是,但这对人类来说也很难理解哪行代码重要,哪行不重要。我认为你们网站上的一个原则说,如果一段代码可能造成很大损害,应该添加注释说,“这行代码很危险。”
Cursor 团队: 并且用全大写,重复 10 次。
Cursor 团队: (众人笑)
Lex Fridman: 不,你说对于函数内的每一行代码你都必须这样做,这相当深刻,这反映了人类的一些特性,因为工程师会离开,即使是同一个人也可能忘记一个函数是如何导致泰坦尼克号沉没的。你可能无法通过看单段代码就直观地清楚地意识到这一点。
Cursor 团队: 是的,我认为那部分原因也是针对今天的 AI 模型,如果你真的在每一行都写上“危险,危险,危险”,模型会更关注那个区域,并且更有可能在那个区域找到 bug。
Lex Fridman: 这实际上就是一个非常好的实践,标记代码可能造成的损害程度。
Cursor 团队: 是的,我的意思是,这有争议。有些人觉得它丑陋。Sualeh 就不喜欢。
Cursor 团队: 事实上,我实际上认为这是我从 Arvid 那里学到的东西之一。从美学上讲,我不喜欢它,但我认为肯定有它的用处,对模型有用,而且人类就是很健忘,很容易犯一个小错误就让服务器宕机。当然,我们做了很多测试之类的,但总有这些事情你必须非常小心。
Cursor 团队: 是的,就像普通的文档字符串(docstrings)一样,我认为人们在做改动时常常会略读它,然后想,“哦,我知道怎么做,”你真的需要向他们指出来,这样才不会漏掉。
Lex Fridman: 是的,你必须被提醒你可能会造成很大的损害,这就像我们通常不会那样想。你会想,“好吧,我怎么弄清楚这东西是怎么工作的,这样我才能改进它?” 你不会从另一个方向去想它可能会...
Cursor 团队: 直到我们对所有东西都有了形式化验证(formal verification),那时你就可以为所欲为,并且如果你通过了证明(proof pass),你就能确定你没有引入 bug。
Lex Fridman: 嗯,具体来说,你认为那个未来会是什么样子?
Cursor 团队: 我认为人们将不再写测试了。你写一个函数,模型会建议一个规范(spec),你审查这个规范。与此同时,智能推理模型计算出一个证明,证明实现遵循了规范,我认为大多数函数都会这样。
Lex Fridman: 你认为这是否触及了你之前谈到的一些关于指定软件意图困难的问题?有时可能因为意图真的很难指定,所以也很难证明它实际上符合你的任何意图?
Cursor 团队: 你认为规范很难生成吗?
Cursor 团队: 是的,或者对于一个给定的规范。我认为存在一个问题,你是否真的能做形式化验证?那可能吗?我认为那里还有更多值得挖掘的地方,但还有...
Lex Fridman: 即使你有了规范?
Cursor 团队: 如果你有了规范...
Lex Fridman: 即使你有了规范,规范是用自然语言写的吗?还是...
Cursor 团队: 不,规范将是形式化的。
Lex Fridman: 但那会有多容易(听不清)。
Cursor 团队: 好的,那么我认为你关心的事情将是那些不容易在规范语言中被很好地指定的东西。
Cursor 团队: 我明白了,我明白了,是的,是的。
Lex Fridman: 这或许可以作为反对“形式化验证就是你所需要的一切”的一个论点。
Cursor 团队: 担心的是有这个庞大的文档...
Cursor 团队: 替代像单元测试这样的东西,当然。
Cursor 团队: 是的,是的。我认为你可能也可以改进规范语言,以捕捉一些它们现在还不能真正捕捉到的东西。我不知道,我觉得这非常令人兴奋。
Lex Fridman: 你说的不仅仅是单个函数,你说的是整个代码库。
Cursor 团队: 我认为整个代码库更难,但那是我希望拥有的,我认为这应该是可能的。最近有很多工作,你可以进行形式化验证,一直验证到硬件。你形式化验证 C 代码,然后你通过 GCC 编译器进行形式化验证,然后通过 Verilog 一直到硬件。这是一个极其庞大的系统,但它确实有效。我认为大型代码库在某种程度上类似,它们就像多层系统。如果你能分解它并形式化验证每个部分,那么我认为应该是可能的。我认为这个规范问题是一个真正的问题。
Lex Fridman: 你如何处理副作用(side effects)?或者你如何处理,我猜,外部依赖,比如调用 Stripe API?
Cursor 团队: 也许 Stripe 会为他们的 API 写一个规范。
Lex Fridman: 但你不能为你使用的所有东西都这样做。你能为你使用的所有东西都这样做吗?也许人们会使用语言模型作为他们编写的程序中的原语(primitives),并且存在对它的依赖,你现在如何将其包含进来?
Cursor 团队: 我认为你也许仍然可以证明这一点。
Lex Fridman: 证明关于语言模型的什么?
Cursor 团队: 我认为感觉有可能你实际上可以证明一个语言模型是对齐的(aligned),例如,或者你可以证明它实际上给出了正确的答案。
Lex Fridman: 那是梦想。
Cursor 团队: 是的,我的意思是,如果可能的话。那是你的“我有一个梦想”演讲。如果可能的话,那肯定有助于确保你的代码没有 bug,并确保 AI 不会摧毁所有人类文明。所以,从 AI 安全的整个范围到仅仅是发现 bug。所以,你说模型在发现 bug 方面有困难。希望是什么?
Cursor 团队: 我最初的希望是,我也可以让 Michael 插话,但就像是它应该首先帮助解决愚蠢的 bug。它应该快速查询,捕捉愚蠢的差一(off by one)错误。有时你在注释里写了某个东西,然后做了相反的事情。这很常见。我就会这样做。我在注释里写小于号,然后可能写了大于号之类的。模型就像,“嗯,这看起来可疑。你确定要这么做吗?”但最终,它也应该能够捕捉更难的 bug。
Cursor 团队: 是的,我认为同样重要的是要注意到,拥有好的 bug 发现模型似乎是达到让 AI 为你做越来越多编程的最高境界所必需的。如果 AI 为你构建了越来越多的系统,你不仅需要生成,还需要验证。没有验证,我们之前谈到的关于用这些模型编程的一些问题将变得无法控制。所以这不仅仅是针对人类,比如你写了一个 bug,我写了一个 bug,帮我找到 bug,而且能够验证 AI 的代码并检查它也非常重要。
Cursor 团队: 是的,那你实际上如何做到这一点?我们有过很多有争议的晚餐讨论,关于你到底如何训练一个 bug 模型,但一个非常流行的想法是,引入一个 bug 可能比实际找到 bug 更容易。所以,你可以训练一个模型在现有代码中引入 bug,然后你可以训练一个反向的 bug 模型,使用这些合成数据来找到 bug。这是一个例子,但关于如何(听不清)有很多想法。
Cursor 团队: 你也可以做很多工作,甚至不是在模型层面,而是获取最大的模型,然后也许让它们能够访问大量不仅仅是代码的信息。盯着一个文件说,“bug 在哪里?”是很困难的,这对人类来说也常常很难,对吧?所以通常,你必须运行代码,能够看到像跟踪(traces)这样的东西,并通过调试器(debugger)逐步执行,这是另一个完全不同的方向,它倾向于那个。
Cursor 团队: 也可能是这里有两种不同的产品形态。可能你有一个非常专业的模型,它相当快,在后台运行并试图发现 bug。也可能有时候,就像 Arvid 之前举的关于某个邪恶的输入框 bug 的例子。你知道存在一个 bug,你不是在没有假设的情况下检查,你就像,“这是一个问题,我真的想解决它,”然后你用大量大量的计算去处理它,你愿意投入 50 美元来解决那个 bug,甚至更多。
Lex Fridman: 你有没有考虑过把钱整合到这整个事情中?如果你们发现了一个 bug,或者甚至生成了我非常欣赏的代码,我可能会付一大笔钱。几天前我刚开始用 Cursor 时有过那么一刻,它完美地生成了三个函数,用于与 YouTube API 交互,以更新不同语言本地化的字幕。API 文档不太好,而且相关的代码… 我 Google 了好一会儿。我找不到完全一样的,有很多令人困惑的信息,而 Cursor 完美地生成了。我只是坐下来,读了代码,我说,“这是正确的,我测试了,它是正确的。” 我当时想,“我想打赏。”我想要一个按钮,上面写着,“这是 5 美元。”一个是真的很好,可以支持公司和这个界面。另一个是,这可能发送了一个强烈的信号,比如“干得好”。(众人笑)所以,这比仅仅接受代码是强得多的信号,对吧?你实际上发送了一个强烈的“干得好”的信号。那个,以及对于发现 bug,显然,有很多人愿意为 bug 悬赏(bug bounty)支付巨额资金,对吧?你们考虑过这个吗?
Cursor 团队: 是的,这是公司内部一个有争议的想法。我认为这取决于你对人性的信仰程度,几乎是这样。我认为如果你花了零成本去尝试找 bug。如果没找到 bug,你花费 0 美元。然后如果它确实找到了一个 bug,你点击接受,然后它也在括号里显示比如 1 美元。所以,你花费 1 美元来接受这个 bug。这会非常酷。然后,当然,会担心,“好吧,我们花费了大量计算,也许人们只会复制粘贴。”我认为这是一个担忧。然后还有担忧是,在产品中引入金钱。感觉不再那么有趣了。你必须考虑钱。而你只想考虑代码,所以也许把它分开更有意义,你每个月付一些费用,然后你免费获得所有这些东西。
Lex Fridman: 但可能有一个打赏的部分,而不是像“这个要花多少钱”...
Cursor 团队: 是的,但它仍然有那个美元符号。我觉得还好,但我也理解也许你不想引入它。
Cursor 团队: 是的,我想说的是,人们这样做的时候,感觉就像是当他们分享的时候。当他们有一个很棒的例子时,他们只是和朋友分享。
Cursor 团队: 也有可能存在一个技术解决方案来解决这个荣誉系统(honor system)问题,如果我们能够达到一个更理解系统输出的程度,我的意思是,关于我们谈到的用 LSP 进行错误检查以及运行代码。但是如果你能达到一个可以某种程度上实际验证,“哦,我已经修复了 bug”的程度,也许那么悬赏系统就不需要依赖荣誉系统了。
十五、 高级概念:分支与基础设施
Lex Fridman: 终端和代码之间有多少交互?如果代码在终端运行,能获得多少信息?你能否做一个循环,让它运行代码并建议如何更改代码?如果代码在运行时出错?现在是完全分离的世界吗?我知道你可以在终端内使用 control K 来帮助你编写代码。
Cursor 团队: 你也可以在 check Command+K 之类的一切中使用终端上下文。我们还没有循环部分,所以我们怀疑像这样的东西可能很有意义。还有一个问题是它是否也在前台发生,或者是否像我们一直在讨论的那样在后台发生。
Lex Fridman: 当然,后台非常酷。我可以用不同的方式运行代码。另外这里还有一个数据库方面的问题,你如何保护它不修改数据库,但是,好吧。(众人笑)
Cursor 团队: 我的意思是,那里肯定有很酷的解决方案。有一个正在开发的新 API。它不在 AWS 中,但肯定,我认为,它在 PlanetScale 中。我不知道 PlanetScale 是不是第一个使用的。它是一种给数据库添加分支(branches)的能力,就像是如果你正在开发一个功能,你想针对生产数据库进行测试,但你实际上不想针对生产数据库测试,你可以给数据库添加一个分支。他们实现的方式是给预写日志(write-ahead log, WAL)添加一个分支。显然,要正确地做到这一点有很多技术复杂性。我猜数据库公司需要做点新事情。(众人笑)他们现在有好的数据库了。我认为 turbopuffer,我们使用的数据库之一,可能会增加对预写日志的分支支持。所以也许 AI 代理会使用分支,它们会针对某个分支进行测试,这将成为数据库支持分支的一个要求之类的。
Lex Fridman: 如果你能给文件系统做分支,那会非常有趣,对吧?
Cursor 团队: 是的。我觉得所有东西都需要分支。
Cursor 团队: [Aman] 是的。
Cursor 团队: 是的。多元宇宙的问题,对吧?(众人笑)如果你对所有东西都做分支,那工作量就太大了。
Cursor 团队: 显然有这些超级聪明的算法来确保你实际上不会使用大量的空间或 CPU 或其他什么。
Lex Fridman: 好的,这是一个问基础设施的好地方。所以,你们主要使用 AWS,有什么有趣的细节吗?有什么有趣的挑战?为什么选择 AWS?为什么 AWS 仍然在赢?#标签。
Cursor 团队: AWS 就是真的真的很好。它真的很好。每当你使用 AWS 产品时,你就知道它会工作。虽然完成设置步骤可能绝对是地狱。
Lex Fridman: 为什么界面那么糟糕?
Cursor 团队: 因为它。(笑)
Cursor 团队: 它就是太好了。它不需要...
Cursor 团队: 这就是赢家的本性。
Cursor 团队: (众人笑)
Cursor 团队: 我认为正是如此,这只是他们赢的本性。
Lex Fridman: 是的,是的。但是 AWS 我们总是可以信任,它总会工作。如果有问题,那可能是你的问题。(Lex 笑)是的。
Lex Fridman: 好的,有没有一些有趣的挑战,你们作为一个相当新的初创公司,在扩展到如此多用户时遇到的?
Cursor 团队: 是的,我认为在每秒请求数(request per second)上每增加一个零,都是一段有趣的旅程。(Lex 笑)你会遇到所有这些问题,你使用的通用组件,比如缓存和数据库,随着规模越来越大都会出问题,现在我们达到了这样的规模,会遇到表溢出之类的事情。然后,还有一些我们构建的自定义系统。例如,我们的检索系统,用于计算你代码库的语义索引并回答关于代码库的问题,我感觉这一直是扩展起来比较棘手的事情之一。
Cursor 团队: 我有几个朋友是超级资深的工程师,他们的一句话是,很难预测系统在扩展时会在哪里崩溃。你可以尝试提前预测,但当你增加这些额外的零时,总会有一些奇怪的事情发生。你以为你考虑了所有事情,但实际上你并没有。但我认为对于那个特定的系统,我们把你所有的代码分块(chunk up),然后我们把代码发送去嵌入(embedding),我们嵌入代码。然后,我们把嵌入结果存储在数据库里,但我们实际上不存储任何代码。然后有一些原因是为了确保我们不会引入客户端 bug,因为我们对客户端 bug 非常非常偏执。我们在服务器上存储了大部分细节。所有东西都是加密的。所以,技术挑战之一总是确保本地索引,本地代码库状态与服务器上的状态相同。我们最终的技术实现方式是,对于每个文件,你可以保留一个哈希(hash),然后对于每个文件夹,你可以保留一个哈希,即其所有子项的哈希。你可以递归地这样做直到顶层。为什么要搞这么复杂?一种方法是,你可以为每个文件保留一个哈希,然后每分钟,你可以尝试下载服务器上的哈希,找出服务器上不存在的文件。也许你刚创建了一个新文件,也许你刚删了一个文件,也许你切换到了一个新分支,然后尝试协调客户端和服务器之间的状态。但这会带来巨大的网络开销,无论是在客户端。没人真的希望我们一直占用他们的 WiFi,如果你在使用 Cursor 的话。而且,这也会给数据库带来巨大的开销。它会每秒读取这个几十 TB,接近 20 TB 或什么的数据库。那简直是疯了。你绝对不想那样做。所以你做的就是,你只尝试协调项目根目录下的那个单一哈希。然后如果有什么不匹配,你再去,找到所有不一致的地方。也许你看看子项,看哈希是否匹配。如果哈希不匹配,再去看它们的子项,依此类推。但你只在不匹配的情况下才这样做。对大多数人来说,大多数时候,哈希是匹配的。
Lex Fridman: 所以这就像一个分层的哈希协调。
Cursor 团队: 是的,类似的东西。
Lex Fridman: 是的,这叫做默克尔树(Merkle tree)。
Cursor 团队: 是的,默克尔。
Cursor 团队: 是的。
Lex Fridman: 是的。看到你们必须思考所有这些问题,这很酷。
Cursor 团队: 变得困难的原因仅仅是因为使用它的人数,以及你们的一些客户拥有非常非常大的代码库。我们最初是基于我们黑暗的代码库(注:可能是指内部代码库)来重新排序的,它很大,但就是没有一些已经存在了 20 年的公司那么大,它们有巨大的文件数量,你想将其扩展到所有程序员。所有这些细节,构建简单的东西很容易,但将其扩展到很多人、很多公司显然是一个难题,这与,实际上,所以这是扩展的一部分。我们目前的解决方案也是提出新想法,显然我们正在努力,然后在过去几周、几个月内扩展所有这些。
Cursor 团队: 是的。这个索引系统还有很多聪明的、额外的东西。例如,成本方面的瓶颈不是在向量数据库或数据库中存储东西,而是实际嵌入代码。你不想为公司里使用完全相同代码的每个人都重新嵌入代码库,除非他们可能在不同的分支上,有几个不同的文件,或者他们做了一些本地更改。因为再次强调,嵌入是瓶颈,你可以做一个聪明的技巧,而不用担心处理分支和其他数据库的复杂性,即你只需要对根据给定块(chunk)的哈希计算出的实际向量进行缓存。
Lex Fridman: 嗯哼。
Cursor 团队: 这意味着当公司的第 N 个人去嵌入他们的代码库时,速度会非常非常快。你做所有这些,而根本不需要在我们的服务器上存储任何代码。没有代码数据被存储。我们只在向量数据库和向量缓存中存储向量。
Lex Fridman: 目前你们从索引代码库中获得的最大收益是什么?只是出于好奇,用户有什么好处?似乎长期来看,好处会越来越多,但在短期内,仅仅是向代码库提问,这有多大用处?
Cursor 团队: 我认为最明显的一个就是,你想在你庞大的代码库中找出某件事情发生在哪里,你有一个模糊的记忆,“好吧,我想找到我们做 X 的地方,”但你不知道在普通的文本搜索中确切地要搜索什么。所以你问聊天机器人,你按 Command+Enter 来用代码库聊天提问。然后很多时候,它就能找到你正在想的那个正确的地方。
Cursor 团队: 就像你提到的,未来,我认为只会变得越来越强大,我们正在努力提高我们检索的质量。我认为这方面的上限真的真的比人们认为的要高得多。
Lex Fridman: 这里有个好问题可以问,你们有没有考虑过以及为什么没有做太多本地化的事情?似乎刚才讨论的一切都异常困难。上云,你必须考虑所有这些关于缓存和大型代码库的问题,当大量程序员使用同一个代码库时。你必须解开那个谜题。很多,大多数软件只是在本地做这些繁重的计算工作。那么,你们有没有考虑过在本地做嵌入?
Cursor 团队: 是的,我们考虑过,我认为在本地做会很酷。我只是觉得真的很难。需要记住的一点是,我们的一些用户使用最新的 MacBook Pro,但我们的大多数用户,超过 80% 的用户使用 Windows 机器,其中许多性能并不强大。所以,本地模型真的只在最新的电脑上才有效,而且将其内置进去也是一个巨大的开销。所以即使我们想这样做,目前也不是我们能够专注的事情。我认为有些人这样做,我觉得那很棒,但特别是随着模型变得越来越大,你想用更大的模型做更花哨的事情,在本地做就变得更加困难。
Cursor 团队: 是的,这不是性能较弱的电脑的问题。只是例如,如果你是一家大公司,你有大公司的代码库。即使在性能最强的 MacBook Pro 上处理大公司代码库也非常非常困难。这甚至不是你只是个学生之类的问题。我认为,即使你是大公司里最好的程序员,如果你所有事情都在本地做,你的体验仍然会很糟糕,你也许可以勉强应付,但同样,那就不再有趣了。
Cursor 团队: 是的,比如在这个巨大的代码库上进行近似最近邻(approximate nearest neighbors)搜索会耗尽你的内存和 CPU,就是这样。这仅仅是这一点。我们再谈谈建模方面,正如 Arvid 所说,本地模型面临着巨大的阻力,一方面,事情似乎在向 MOE 发展,其一个好处是也许它们更受内存带宽限制,这对本地有利,而不是使用 GPU 或使用 Nvidia GPU。但缺点是,这些模型总体上就是更大,它们需要适应,通常甚至不是单个节点,而是多个节点。这根本不可能装进即使是非常好的 MacBook 里。我认为尤其对于编码来说,问题不完全在于,模型是否达到了某个门槛,足够好能做这些事情,然后我们就满意了?对于其他问题,也许是这样,也许本地模型在那里会发光,但人们总是想要最好的、最智能的、最有能力的东西,而对于几乎所有人来说,在本地运行这些都将非常非常困难。
Lex Fridman: 你难道不想要最有能力的模型吗?你也想要 Sonnet 吗?
Cursor 团队: 还有 o1...(Lex 笑)
Lex Fridman: 我喜欢你向我推销的方式。(众人笑)
Cursor 团队: O1 是另一个...
Lex Fridman: 你会满足于一个次等的模型吗?听着,是的,我是那些人之一,但有些人喜欢在本地做事,真的,有一个整个开源运动在抵制。他们存在实际上是件好事,因为你想抵制正在增长的权力中心...
Cursor 团队: 实际上有一个本地模型的替代方案,我个人特别喜欢。我认为它很大程度上仍处于研究阶段,但你可以想象为语言模型推理做同态加密(homomorphic encryption)。你在你的本地机器上加密你的输入,然后你把它发送上去,然后服务器可以使用大量的计算。他们可以在这个加密数据上运行你本地无法运行的模型,但他们看不到数据是什么,然后他们把答案发回来,你解密答案,只有你能看到答案。所以我认为这很大程度上仍然是研究,所有这一切都是关于试图降低开销,因为现在,开销真的很大,但如果你能实现这一点,我认为那会非常非常酷,我认为那会非常有影响力,因为我认为一件真正令人担忧的事情是,随着这些模型变得越来越好,它们将在经济上变得越来越有用。因此,世界上越来越多的信息和数据将流经一两个中心化的参与者。然后就有了担忧,可能会有传统的黑客攻击,但这也创造了一个可怕的部分,如果世界上所有的信息都以明文形式流经一个节点,你可能会以非常糟糕的方式进行监视。最初会有好的理由。人们会想试图防止不良行为者以不良方式使用 AI 模型,然后你会加入一些监视代码。然后,其他人会进来,你就走上了一个滑坡,然后你开始用世界上大量的数据做坏事。所以,我非常希望我们能解决语言模型推理的同态加密问题。
Lex Fridman: 是的,做隐私保护的机器学习。但我想说,这是我们如今所有软件面临的挑战。就像,云端可以提供如此多的功能,我们所有人都越来越依赖它,让我们的生活变得很棒。但也有弊端,这就是为什么你依赖非常好的安全性来防范基本攻击。但同时也只有少数公司控制着这些数据,它们显然拥有影响力,并且可能以各种方式被渗透。这就是我们生活的世界。
Cursor 团队: 是的,我只是真正担心的那件事是,Anthropic 有这个负责任扩展政策(responsible scaling policy),我们处于模型的低 ASL(Anthropic 安全级别或其他什么)级别。但是当我们达到所谓的“ASL-3,ASL-4”或其他什么的非常强大的模型时。但主要是出于合理的安全原因,你会想要监控所有的提示。但我认为这是合理的,可以理解大家出发点。但是天哪,如果世界上所有的信息都被如此严密地监控,那就太可怕了,太中心化了。这就像你在走一条非常细的线,一方面,你不希望模型失控。另一方面,人类就像,我不知道我是否信任世界上所有的信息都通过三个模型提供商。
Lex Fridman: 是的。
Lex Fridman: 为什么你认为这和云提供商不同?
Cursor 团队: 因为我认为很多这些数据一开始就永远不会进入云提供商那里。你想给 AI 模型更多的数据,你想给那些你一开始就永远不会放到网上的个人数据给这些公司或这些模型。这也集中了控制权,而现在,对于云,你通常可以使用自己的加密密钥,AWS 实际上做不了太多。但在这里,就是中心化的参与者能看到所有东西的确切明文。
十六、 上下文、检索与模型训练
Lex Fridman: 关于上下文的话题,这对我来说确实一直是个痛点。当我在 Python 中写代码时,会导入很多东西。你或许可以凭直觉判断出我想要包含在上下文中的那种东西。自动找出上下文有多难?
Cursor 团队: 这很棘手。我认为未来我们可以在自动计算上下文方面做得更好。需要注意的一点是,包含自动上下文存在权衡。首先,你为这些模型包含的上下文越多,它们就越慢,那些请求就越贵,这意味着你能做的模型调用就越少,在后台能做的花哨事情就越少。而且,对于很多这些模型,如果你在提示中放入大量信息,它们会感到困惑。所以你包含的上下文的准确性和相关性门槛应该相当高。我们已经在产品内部的一些地方做了一些自动上下文处理。这绝对是我们想要做得更好的地方。我认为那里有很多很酷的想法可以尝试,既包括学习更好的检索系统,比如更好的嵌入模型、更好的重排器(rerankers)。我认为也有一些很酷的学术想法,我们内部尝试过,但整个领域也在努力解决的一个大问题是,你能否让语言模型达到一个可以实际让模型本身理解一个新的信息语料库的程度?最常被谈论的版本是,你能否让上下文窗口无限大?然后如果你让上下文窗口无限大,你能否让模型实际关注无限的上下文?然后,在你让它关注无限上下文之后,为了让它实际可行,你能否为那个无限上下文做缓存?这样你就不必一直重新计算。但还有其他很酷的想法正在被尝试,它们更类似于微调(fine-tuning),即真正在模型的权重(weights)中学习这些信息。也许如果你更多地在权重层面进行,而不是在上下文学习(in-context learning)层面进行,你实际上会得到一种性质上不同的理解。我认为关于这一切最终将如何运作,目前还没有定论。但在此期间,作为一家公司,我们对更好的检索系统非常兴奋,挑选出与你正在做的事情最相关的代码库部分,我们可以在这方面做得更好。
Cursor 团队: 一个有趣的、证明“将知识直接学习到权重中”可行性的例子是 VS Code。我们在一个 VS Code 分支中,而 VS Code 的代码都是公开的。所以这些模型在预训练中已经看到了所有代码。它们可能也看到了关于它的问答。然后,它们被微调和 RLHF(基于人类反馈的强化学习)以能够回答关于一般代码的问题。所以当你问它一个关于 VS Code 的问题时,有时它会产生幻觉,但有时它在回答问题方面做得相当不错。它碰巧还行,但如果你能专门训练或后训练(post-train)一个模型,让它真正被构建来理解这个代码库呢?这是一个开放的研究问题,我们对此非常感兴趣。然后还不确定的是,你是否希望模型是端到端做所有事情的东西,即它在内部进行检索,然后回答问题,创建代码,或者你是否想将检索与前沿模型分开,也许你会在几个月内得到一些比最好的开源模型好得多的、非常有能力的模型?然后,你会想单独训练一个非常好的开源模型作为检索器,作为向这些更大的模型提供上下文的东西。
Lex Fridman: 你能多谈谈“后训练一个模型来理解代码库”吗?你指的是什么?这是合成数据(synthetic data)的方向吗?还是...
Cursor 团队: 是的,你可以尝试很多可能的方法。肯定不缺想法。问题只是去尝试所有这些方法,并根据经验判断哪种效果最好。一个非常朴素的方法是尝试复制在 VS Code 和这些前沿模型上所做的事情。所以,让我们继续预训练(continued pre-training)。某种形式的持续预训练,既包含通用代码数据,也加入你关心的某个特定仓库的数据。然后在后训练(post-training)中,意思是,让我们从指令微调(instruction fine-tuning)开始。你有一个关于代码的普通指令微调数据集。然后你加入大量关于那个仓库代码的问题。所以,你可以要么获得真实的(ground truth)问题,这可能很困难,要么你可以做你暗示或建议的,使用合成数据,即让模型对代码库最近的各个部分提问。所以你获取代码片段,然后提示模型或让一个模型为那段代码提出一个问题,然后将这些作为指令微调数据点添加进去。理论上,这可能会解锁模型回答关于那个代码库问题的能力。
十七、 OpenAI o1 与测试时计算
Lex Fridman: 让我问问你关于 OpenAI o1 的事情。你认为那种测试时计算(test time compute)系统在编程中扮演什么角色?
Cursor 团队: 我认为测试时计算非常非常有趣。所以,一直有预训练这个机制,当你扩大数据量和模型大小时,性能会越来越好,无论是在损失上,还是在下游基准测试和通用性能上,比如我们用它来编码或其他任务。我们开始有点撞上数据墙(data wall),意思是,继续扩大这个机制将变得困难。所以,扩大测试时计算是一个有趣的方式,如果现在增加推理时(inference time)的 FLOPs 数量。是的,当你增加推理时使用的 FLOPs 数量时,这些模型的性能会相应提高。传统上,我们必须直接训练一个更大的模型,它总是使用那么多额外的 FLOPs,但现在,我们也许可以使用相同大小的模型,运行更长时间,来获得一个相当于大得多的模型质量的答案。所以,我喜欢这个的真正有趣之处在于,有些问题可能需要一个在 100 万亿 token 上训练的 100 万亿参数模型的智能。但这也许只占所有查询的 1%,也许是 0.1%。那么你是否会花费所有这些努力、所有这些计算来训练一个成本如此之高然后运行频率如此之低的模型?你训练那个能够处理 99.9% 查询的模型,然后你有一种方法可以在推理时为那些少数真正真正想要最大智能的人运行更长时间。
Lex Fridman: 你如何判断哪个问题需要什么级别的智能?有没有可能动态地判断何时使用 GPT-4,何时使用小模型,以及何时需要 o1?(众人笑)
Cursor 团队: 是的,这当然是一个开放的研究问题。我认为还没有人真正很好地解决了这个模型路由(model routing)问题。我们对像 Cursor Tab 这样的东西有初步的实现,但在 4o Sonnet 到 o1 之间切换的层面上,就有点棘手了。还有一个问题是,你需要什么级别的智能来判断某件事对于 4 级模型来说太难了?也许你需要 o1 级别的模型。这真的不清楚。
Lex Fridman: 但是你提到了这个。所以,有预训练过程,然后有后训练,然后有测试时计算。这样分开公平吗?最大的收益在哪里?
Cursor 团队: 嗯,这很奇怪,因为测试时计算,需要一整套训练策略才能让测试时计算奏效。另一个关于这个非常奇怪的事情是,除了大型实验室,甚至可能只有 OpenAI,没有人真正知道它是如何工作的。有一些非常有趣的论文展示了他们可能在做什么的线索。所以,也许他们在使用过程奖励模型(process reward models)进行树搜索(tree search)。但是是的,我认为问题在于我们不太确切知道它是什么样子的,所以很难评论它适合放在哪里。我会把它放在后训练中,但也许为了让测试时计算对一个模型起作用而花费的计算最终会超过预训练。
Lex Fridman: 所以我们甚至不知道 o1 是否只是在使用思维链(chain of thought),或者我们不知道它们是如何使用这些的?我们什么都不知道?
Cursor 团队: 推测很有趣。(众人笑)
Lex Fridman: 如果你要构建一个竞争模型,你会怎么做?
Cursor 团队: 是的,所以要做的一件事是,我认为你可能需要训练一个过程奖励模型(process reward model)。也许我们可以深入探讨奖励模型,结果奖励模型(outcome reward models)与过程奖励模型。结果奖励模型是人们为语言建模训练的传统奖励模型,它只看最终结果。所以如果你在做一个数学问题,只看那个最终结果。你做完了所有事情,然后给它打分,我们认为可能性有多大。这个结果的奖励是多少?而过程奖励模型则试图对思维链进行评分。所以 OpenAI 去年夏天对此有一篇初步论文,他们使用人类标注员(labelers)来获得一个相当大的、数十万的数据集,用于创建思维链。最终,感觉我没有看到人们使用过程奖励模型的任何有趣方式,除了将其作为一种影响我们如何在众多样本中进行选择的手段。所以,在所有这些论文中,人们所做的就是从语言模型中采样大量输出,然后使用过程奖励模型对所有这些生成结果进行评分,可能还会结合一些其他启发式方法,然后用它来选择最佳答案。人们认为可能有效并且希望有效的真正有趣的事情是使用这些过程奖励模型进行树搜索(tree search)。因为如果你真的能对思维链的每一步进行评分,那么你就可以分支出来探索这个思维链的多个路径,然后使用这些过程奖励模型来评估你正在走的这个分支有多好。
Lex Fridman: 是的,当分支的质量与最终结果的质量在某种程度上强相关时,所以你有一个好的模型知道该走哪个分支。不仅仅是短期,还有长期?
Cursor 团队: 是的。我认为已经完成的有趣工作是弄清楚如何正确地训练过程(process),或者说已经开源并且我认为人们在谈论的有趣工作是,如何训练过程奖励模型,也许以更自动化的方式。我可能错了,可能没有提到一些论文。我没有看到任何似乎在创造性地使用过程奖励模型进行树搜索和编码方面效果很好的东西。
Lex Fridman: 这是一个 AI 安全,也许有点哲学的问题。OpenAI 说他们对用户隐藏了思维链,他们说这是一个艰难的决定。他们不展示思维链,而是让模型总结思维链。他们还在后台说他们会监控思维链,以确保模型没有试图操纵用户,这是一个令人着迷的可能性。但无论如何,你对隐藏思维链怎么看?
Cursor 团队: OpenAI 的一个考虑因素,这完全是推测,可能是他们想让人们难以从他们的模型中“蒸馏”(distill)出这些能力。如果你能访问那个隐藏的思维链,复制这项技术可能实际上更容易,因为这是非常重要的数据,比如看到模型为达到最终结果所采取的步骤。
Lex Fridman: 所以,你可能也可以在那上面进行训练?
Cursor 团队: 对于一些大型语言模型提供商也存在类似的情况,这也是推测,但其中一些 API 过去曾提供对其生成的所有 token 的对数概率(log probabilities)以及提示 token 的对数概率的轻松访问。然后其中一些 API 取消了这些。再次强调,完全是推测,但其中一个想法是,取消这些的原因是,如果你能访问对数概率,类似于这个隐藏的思维链,那可以给你更多信息,试图将这些能力从 API、从这些最大的模型中“蒸馏”到你控制的模型中。作为对我们之前讨论整合 o1 的一个补充说明,我认为我们仍在学习如何使用这个模型。所以,我们在 Cursor 中提供了 o1,因为当我们拿到模型时,我们非常想尝试一下。我认为很多程序员都会有兴趣尝试。O1 并不是默认 Cursor 体验的任何一部分,我们还没有找到一种方法能将其整合到编辑器中,让我们每小时甚至每天都会去使用它。所以,我认为关于如何使用这个模型还没有定论,我们还没有看到人们发布的东西中,有例子能非常清楚地表明,“哦,那就是现在的用例了。” 最显而易见的方向是,也许这可以让你更容易地运行这些后台任务,让这些模型处于循环中,让这些模型具有代理性。但我们仍在探索中。
Cursor 团队: 需要明确的是,我们有想法。我们只是需要尝试并做出一些极其有用的东西,然后才发布出来。
Cursor 团队: 但它有这些显著的局限性。即使不考虑能力,它也不能流式输出(stream)。这意味着对于那些你想要监督输出的事情来说,使用起来非常非常痛苦。相反,你只是等着一堵文字墙出现。而且,感觉这确实是测试时计算和搜索的早期阶段,它非常非常像一个 v0 版本,有很多东西感觉不太对。我怀疑,在人们增加预训练数据量和模型大小并在预训练中找到技巧的同时,你现在会有另一条线索,即让搜索变得越来越好。
Lex Fridman: 好吧,让我问问你关于“草莓明天眼睛”(strawberry tomorrow eyes,注:可能是指 GitHub Copilot Workspace 的代号或类似说法)。看起来 GitHub Copilot 可能正在以某种方式整合 o1,我认为一些评论在说,这是否意味着 Cursor 完蛋了?(众人笑)我想我看到一条评论是这么说的。
Cursor 团队: 是时候关闭 Cursor 了,是的。
Lex Fridman: 是时候关闭 Cursor 了,谢谢。(众人笑)那么,是时候关闭 Cursor 了吗?
Cursor 团队: 我认为这个领域与过去 2010 年代的软件领域有点不同,我认为这里的天花板真的真的非常非常高。所以,我认为三到四年后最好的产品将比今天最好的产品有用得多得多。你可以诗意地谈论护城河这个那个,品牌那个那个,这是我们的优势,但我认为最终,如果你停止在产品上创新,你就会输。这对初创公司也很好,对试图进入这个市场的人也很好,因为这意味着你有机会通过构建更好的东西来战胜那些已经拥有大量用户的人。所以,我认为在未来几年,关键就在于构建最好的产品,构建最好的系统,这既涉及到建模引擎方面,也涉及到编辑体验方面。
Cursor 团队: 是的,我认为 Cursor 相对于其他所有产品的附加价值,不仅仅是快速集成像 o1 这样的新模型。它来自于所有那些深入到定制模型中的深度,那些你在产品的每个方面都意识不到却在为你工作的模型,以及每个功能背后深思熟虑的用户体验。
十八、 合成数据分类
Lex Fridman: 好的,从那个深刻的回答,让我们回到技术层面。你提到你们有一个合成数据(synthetic data)的分类法。
Cursor 团队: (笑)哦,是的。
Lex Fridman: 能请你解释一下吗?
Cursor 团队: 是的,我认为主要有三种合成数据。首先,什么是合成数据?有普通数据,即非合成数据,就是自然产生的数据,即通常是人类做事情的结果。所以,从某些人类过程中你得到这些数据。合成数据,第一种是蒸馏(distillation)。让一个语言模型输出 token 或 token 的概率分布,然后你可以用这些来训练一些能力较弱的模型。这种方法不会让你得到比最初产生 token 的模型能力更强的模型,但如果你想从某个非常昂贵、高延迟的模型中引出某种能力,它就非常有用。你可以将其蒸馏到一个更小的、特定任务的模型中。第二种是当问题的一个方向比反向更容易时。一个很好的例子是 bug 检测,就像我们之前提到的,引入看起来合理的 bug 比实际检测它们要容易得多。这可能对人类也是如此。所以你可以做的是,让一个没有在那么多数据上训练、不那么聪明的模型在代码中引入一堆 bug。然后,你可以用这些合成数据来训练一个在检测 bug 方面可能非常出色的模型。最后一类我认为是,我猜是主要的,感觉大型实验室正在做的合成数据,那就是用语言模型产生可以被轻松验证(verified easily)的文本。一个极端的例子是,如果你有一个验证系统可以检测语言是否达到莎士比亚水平,然后你有一群猴子在打字机上打字。你最终可以获得足够的训练数据来训练一个莎士比亚水平的语言模型。我的意思是这在数学领域非常适用,因为对于形式化语言,验证实际上非常非常容易。然后你可以做的是,让一个还不错的模型生成大量的推演(rollouts),然后选择那些你知道确实证明了真实定理(ground truth theorems)的推演,并在此基础上进一步训练。对于像 LeetCode 这样的代码问题,你也可以做类似的事情,如果你有一组测试,你知道如果某东西通过了这些测试,它就确实解决了问题。你可以做同样的事情,验证它通过了测试,然后在通过测试的输出上训练模型。我认为让这个在所有领域都奏效,或者仅仅是普遍适用,会有点棘手。拥有完美的验证器感觉非常非常难,对于开放式的、杂项的任务来说。你给模型或者更长期的任务,即使在编码中。
Lex Fridman: [Lex] 那是因为你不如 Arvid 乐观。
Cursor 团队: 但是,是的,所以,(Aman 笑)那第三类需要有一个验证器。
Cursor 团队: 是的。验证,感觉最好是当你确切知道它是正确的时候。那就不像是使用语言模型来验证,而是使用测试或形式化系统。
Cursor 团队: 或者运行那个东西。做人类形式的验证,即你只是做手动质量控制。
Lex Fridman: 是的。
Cursor 团队: 是的。
Cursor 团队: 但是语言模型版本的那个,即它运行东西并且实际理解输出。
Lex Fridman: 是的,不,那是...
Cursor 团队: 我确定它介于两者之间。
Cursor 团队: 是的。我认为那一类最有可能带来巨大收益。
十九、 强化学习:RLHF vs. RLAIF
Lex Fridman: 关于带有反馈的强化学习,RLHF 与 RLAIF 呢?它们在提升模型性能方面扮演什么角色?
Cursor 团队: 是的。所以,RLHF(Reinforcement Learning from Human Feedback)是指你使用的奖励模型是从你收集的人类反馈标签中训练出来的。我认为如果你有能力为你关心的这类任务获得大量人类反馈,这是可行的。RLAIF(Reinforcement Learning from AI Feedback)很有趣,因为它依赖于这样一个约束条件:验证实际上比生成要容易得多。因为它感觉像是,好吧,你在做什么?你在用这个语言模型看语言模型的输出,然后改进语言模型吗?但不,如果语言模型验证某个解决方案比生成它要容易得多,它实际上可能有效。那么你也许真的可以得到这个递归循环。但我认为它不会完全是那个样子。你可以做的另一件事,我们有点在做的,是 RLAIF 和 RLHF 的混合,通常模型实际上是相当正确的,这就是 precursor tap(注:应指 Cursor Tab)在两个可能的生成结果中选择哪个是更好的情况。然后,它只需要一点点人类的推动,仅仅需要大约 50 到 100 个例子,就能将模型已有的先验知识与你真正想要的东西对齐。这看起来不同于我认为的普通 RLHF,后者通常在大量例子上训练这些奖励模型。
二十、 AI 与科学/数学突破
Lex Fridman: 当你比较生成和验证,或者生成和排序时,你的直觉是什么?排序比生成容易得多吗?
Cursor 团队: 我的直觉会说,是的,应该是。就像,如果你相信 P 不等于 NP (),那么就有一大类问题,给定证明去验证要比实际证明它容易得多得多。
Lex Fridman: 我想知道是否会是同一个东西证明 P 不等于 NP () 或 P 等于 NP ()。
Cursor 团队: (笑)那会非常酷。
Lex Fridman: 那将是 AI 获得的菲尔兹奖之类的。(众人咯咯笑)谁获得荣誉?另一个开放的哲学问题。(众人笑)
Cursor 团队: 谁提示的。(众人笑)
Lex Fridman: 我实际上出奇地好奇,关于 AI 何时能获得菲尔兹奖的一个好的赌注会是什么。我实际上没有...
Lex Fridman: 这难道不是 Aman 的专长吗?
Cursor 团队: 我不知道 Aman 在这里的赌注是什么。
Lex Fridman: 哦,抱歉,诺贝尔奖还是菲尔兹奖先?
Cursor 团队: 菲尔兹奖...
Lex Fridman: 哦,菲尔兹奖级别?
Cursor 团队: 我认为菲尔兹奖会先来。
Lex Fridman: 菲尔兹奖会先来。嗯,你当然会这么说。(众人笑)
Cursor 团队: 但它也是一个你可以验证的孤立系统。
Lex Fridman: 当然。
Cursor 团队: 是的。
Cursor 团队: 我甚至不知道我是否...
Lex Fridman: 你不需要做(听不清)。
Cursor 团队: 我觉得我在那里还有很多事情要做。感觉通往 IMO 的路径要更清晰一些。因为它已经能解决一些 IMO 问题,并且根据当时的文献,关于人们可以采取什么策略,有很多低垂的果实。我认为我,第一,现在对定理证明领域不那么精通了。第二,对于我们距离解决那些非常非常困难的开放问题有多近,直觉较少。
Lex Fridman: 所以你认为会先是菲尔兹奖?不会是在物理学或...
Cursor 团队: 哦,100%,我认为那可能更有可能。可能更有可能它会在… 是的,是的,是的。嗯,我认为两者都,我不知道,BSD(Birch and Swinnerton-Dyer conjecture,贝赫和斯维讷通-戴尔猜想),或者(听不清)iPods,或者任何这些困难的数学问题实际上都非常非常难。甚至通往解决方案的路径是什么都还不清楚。我们甚至不知道路径是什么样子的,更不用说(听不清)。
Lex Fridman: 你不相信这只是一个孤立系统,你可以拥有一个好的奖励系统,并且感觉为此训练更容易的想法吗?
Cursor 团队: 我认为我们可能会在 AGI 之前获得菲尔兹奖。
Cursor 团队: 我的意思是,我会非常高兴。我会非常高兴。但我不知道我是否认为是在 2028 年,2030 年。(Aman 笑)
Lex Fridman: 对于菲尔兹奖?
Cursor 团队: 菲尔兹奖。
Lex Fridman: 好吧。考虑到事情进展如此之快,那感觉像是永远之后的事情。说到事情进展如此之快,让我们谈谈 Scaling Laws 。
二十一、 规模法则(Scaling Laws)再思考
Lex Fridman: 所以,对于不了解的人来说,也许谈谈 Scaling Laws 的整个想法是件好事。它们是什么,你认为它们现在处于什么位置,你认为事情将走向何方?
Cursor 团队: 我认为有趣的是。OpenAI 最初的 Scaling Laws 论文有点错误。我认为是因为他们在学习率调度(learning rate schedules)方面做的一些问题。然后,Chinchilla 展示了一个更正的版本。然后,从那时起,人们再次偏离了做计算最优(compute optimal)的事情。因为人们现在开始更多地优化,以便在给定的推理预算(inference budget)下让东西工作得非常好。我认为这些曲线比我们最初使用的维度要多得多,不仅仅是计算量、参数数量和数据量。像推理计算是显而易见的一个。我认为上下文长度是另一个显而易见的。假设你关心推理计算和上下文窗口这两件事,也许你想训练的是某种 SSM(State Space Model,状态空间模型)。因为它们在非常非常长的上下文上要便宜得多、快得多。即使,也许它在训练期间的扩展特性(scaling properties)差 10 倍,意思是,你花费 10 倍的计算来训练它以达到相同水平的能力,也是值得的,因为你最关心的是在非常长上下文窗口下的那个推理预算。所以,看人们如何玩转所有这些维度将会很有趣。
Lex Fridman: 所以,是的,我的意思是,你谈到了多个维度,显然。最初的概念只是看模型大小(以参数衡量)和数据大小(以 token 数量衡量)这两个变量,以及两者之间的比率。
Cursor 团队: 是的。
Lex Fridman: 并且存在一个数字,或者至少是一个最小值,这个概念有点引人注目。而且似乎有一个正在浮现。你仍然相信某种程度上“越大越好”吗?
Cursor 团队: 我的意思是,我认为对于纯粹的性能(raw performance)来说,更大肯定更好。
Lex Fridman: 以及原始智能(raw intelligence)。
Cursor 团队: 以及原始智能。我认为人们可能采取的路径,我特别看好蒸馏(distillation)。以及你能调整多少旋钮,如果我们花费巨额资金进行训练,来获得最有能力的廉价模型。真正尽可能地关心。因为对推理时间计算尽可能关心的朴素版本,是人们已经用 Llama 模型做过的事情。或者只是在远超计算最优的 token 数量上过度训练(over-training the shit out of)7B 模型。但如果你真的关心它,也许该做的是像 Gamma 做的那样,让我们不只是在 token 上训练,让我们字面上在最小化与 gemma 27B 分布的 KL 散度(KL divergence)上训练,对吧?所以是知识蒸馏(knowledge distillation)。你花费字面上训练这个 270 亿参数模型在所有这些 token 上的计算,只是为了得到那个,我不知道,更小的模型。
Lex Fridman: 而蒸馏只是给你一个更快的模型,更小意味着更快。
Cursor 团队: 是的,蒸馏理论上是,我认为,从你正在训练的数据中获取更多信号。这也许是克服,不是完全克服,而是部分帮助解决数据墙问题的另一种方式。你只有这么多数据可以训练,让我们在这个所有这些 token 上训练这个非常非常大的模型,然后我们将其蒸馏到一个更小的模型中。也许对于这个小得多的模型,我们可以比我们最初训练它时获得每 token 更多的信号。
Lex Fridman: 所以如果我给你 10 万亿美元,你会怎么花?(Aman 笑)我的意思是,你不能买个岛之类的。你会如何在改进大模型和可能支付 RLHF 中的 HF(人类反馈)之间分配它?
Cursor 团队: 是的,是的。我认为,有很多关于训练这些大型模型的秘密和细节我就是不知道,只有大型实验室才知道。问题是,如果我尝试这样做,我会浪费很多钱,因为我不知道那些事情。抛开很多疑虑,假设你拥有了专业知识,或者如果你是说你必须在你现在有限的信息下操作。
Lex Fridman: 不,不,不,实际上,我想说,你突然介入,获得了所有信息,所有的小技巧,所有的小参数,所有定义事物如何训练的参数。如果我们着眼于未来五年如何投资以最大化你所说的原始智能。
Cursor 团队: 我的意思是,答案不是很简单吗?你只需要尝试获得尽可能多的计算能力。归根结底,你只需要购买 GPU。你可以调整你是想预训练一个大模型还是一个小模型。
Lex Fridman: 嗯,这就涉及到你是否真的受限于计算和金钱,还是受限于其他这些东西的问题?
Cursor 团队: 我更倾向于 Arvid 的信念,即我们受限于想法(idea-limited),但总有那种...
Cursor 团队: 但如果你有很多计算能力,你可以运行很多实验。
Lex Fridman: 所以你会运行很多实验,而不是用那些计算来训练一个巨大的模型?
Cursor 团队: 我会的,但我确实相信我们在想法方面是受限的。
Cursor 团队: 我认为是的,因为即使拥有所有这些计算能力,以及你能收集到的世界上所有数据,我认为你最终还是受限于,甚至不是想法,而是真正优秀的工程能力。世界上真正能在这里产生影响的人并不多。而且研究中有如此多的工作,仅仅是纯粹的、非常非常困难的工程工作。作为一个非常粗略的例子,如果你看最初的 Transformer 论文,有多少工作是将文献中嵌入的许多这些非常有趣的概念结合在一起,相对于然后去编写所有代码,也许是 CUDA 内核,也许是其他什么。我不知道它最初是在 GPU 还是 TPU 上运行的。以至于它实际上饱和了 GPU 性能。让 GNOME Azure(注:可能指参与者或相关项目)去完成所有这些代码。而 GNOME 可能(是/曾是)世界上最好的工程师之一。或者再进一步,比如下一代模型,拥有这些东西。比如让模型并行(model parallelism)工作,并在数千个,也许是数万个 V100 上扩展它,我认为 GBDE-III(注:应指 GPT-3)可能就是这样。所有这些事情都需要投入如此多的工程努力才能让它工作。如果你真的把那个成本降到也许不是零,而是让它容易 10 倍,让一个有非常棒想法的人超级容易地就能实现他们梦想中的新架构版本,并且在他们的 GPU 上获得 50%、40% 的利用率,我认为那会让研究速度快很多。
Cursor 团队: 我的意思是,我认为如果你看到一条清晰的改进路径,你应该总是先摘取低垂的果实,对吧?我认为可能 OpenAI 和所有其他实验室做了正确的事情,去摘取低垂的果实。低垂的果实就像是,你可以扩展到 GPT-4.25 的规模,你只是不断扩展,事情不断变好。当一切都在工作时,没有必要去试验新想法。你应该坚持下去,试图榨取尽可能多的汁液。我认为如果你花费 10 万亿美元,你可能想花一些,然后真正重新评估你的想法,可能在那个时候你的想法有点过时了。
Cursor 团队: 我认为我们所有人都相信可能需要新想法才能一路走到 AGI。我们所有人也可能相信存在在较小规模上测试那些想法并相当有信心地认为它们会成功的方法。只是对于实验室来说,在他们目前的位置,将他们非常有限的研究和工程人才投入到探索所有这些其他想法上是相当困难的,而核心的东西可能会在相当长一段时间内提高性能。
Cursor 团队: 是的,而且,这些大实验室喜欢赢。(Lex 笑)所以,它们就是疯狂地前进。好的。(众人笑)
二十二、 编程的未来
Lex Fridman: 好吧。所以,一个大问题,展望未来。你们现在处于编程世界的中心。你认为编程,编程的本质在未来几个月、下一年、未来两年、未来五年、十年会如何改变?
Cursor 团队: 我认为我们对这样一个未来感到非常兴奋:程序员在很长一段时间内都处于主导地位(in the driver's seat)。你已经听我们谈到过一些了,但这是一个强调速度、程序员的自主性(agency)和控制力的未来。能够修改任何你想修改的东西的能力,能够对你正在构建的东西进行快速迭代的能力。我认为这与一些人在这个领域跳跃到的方向有点不同。我认为一个吸引人们的想法是,你能和你的电脑对话吗?你能让它为你构建软件吗?就像你通过 Slack 与一个工程部门或工程师交谈一样。它能仅仅是这样一个孤立的文本框吗?我们对此不兴奋的部分原因是我们已经谈到的一些关于延迟的问题,但一个重要的原因是我们对此不兴奋是因为那样做意味着放弃大量的控制权。当你在文本框中交谈时,要做到非常具体要困难得多。而且如果你必然要像与工程部门沟通那样与一个东西沟通,你实际上是将大量非常重要的决策委托给了这个机器人。这有点触及了工程的根本。我认为一些离工程稍远的人可能会认为规范是完全写好的,然后工程师只是来执行。仅仅是让事情在代码中发生,让事情存在。但我认为很多最好的工程,我们享受的工程,涉及到大量关于你究竟在构建什么的微小决策,以及关于速度、成本和系统中涉及的所有其他事情之间非常困难的权衡。只要人类实际上是设计软件的人,是指定他们想要构建什么的人,而不是像公司完全由 AI 运营那样,我们认为你真的会希望人类处于主导地位,来决定这些决策。所以关于那会是什么样子还没有定论。我认为一个关于那可能是什么样子的奇怪想法是,它可能看起来像你可以控制你查看代码库的抽象层级。你可以指向代码库的特定部分,比如,也许你通过查看伪代码(pseudocode)的形式来理解一个代码库。你实际上也可以编辑那个伪代码,然后让更改在形式化编程语言层面发生。你可以指向你软件组件编程中的任何逻辑片段。你保留编程的流式文本编辑组件,你保留控制权,你甚至可以深入到代码中,你可以在更高的抽象层级上操作,同时也给你带来这些巨大的生产力提升。
Lex Fridman: 如果你能在抽象层级上上下移动,那会很好。
Cursor 团队: 是的。那里有很多细节需要弄清楚,那有点像一个模糊的想法。时间会证明它是否真的有效。但是控制和速度以及人类处于主导地位这些原则,我们认为非常重要。我们认为对于某些事情,就像 Arvid 之前提到的,对于某些编程风格,你可以像聊天机器人那样交接任务。如果你有一个定义非常明确的 bug。但那不是大多数编程,那也不是我们认为很多人看重的大多数编程。
Lex Fridman: 那编程的基本技能呢?现在有很多年轻人感到害怕,因为他们热爱编程,但他们害怕,“如果我追求这条职业道路,我还能有未来吗?”你认为编程这项技能本身会发生根本性的改变吗?
Cursor 团队: 我实际上认为现在是构建软件的一个非常非常激动人心的时刻。我们记得 2013 年、2012 年左右编程是什么样子。那时有更多的冗余代码(cruft)和样板代码(boilerplate),以及查找一些非常棘手的东西。那些东西仍然存在,绝对没有归零。但是今天的编程比那时有趣得多。感觉我们真的在深入到乐趣的精华部分。所有真正吸引人们编程的东西,例如,能够非常快速地构建东西和速度的这个元素,以及个人控制权,所有这些都被极大地放大了。所以我认为对于构建软件的人来说,这将是一个非常非常有趣的时代。我认为技能可能也会改变。我认为人们的品味(taste)和创造性想法(creative ideas)将被放大。也许会少一些关于样板代码文本编辑。也许甚至会少一些关于细心(carefulness),我认为这在今天对于程序员来说非常重要。我认为会更有趣得多。
Lex Fridman: 你们怎么看?
Cursor 团队: 我同意。我对能够改变感到非常兴奋。最近发生的一件事是,我们想对我们的代码库进行一次相对较大的迁移。我们之前在 Node.js 中使用 AsyncLocalStorage,众所周知它的性能不太好,我们想迁移到一个上下文对象(context object)。这是一个大的迁移,影响整个代码库。Sualeh 和我花了,我不知道,五天时间来完成这个,即使有今天的 AI 工具。我真的非常期待这样一个未来:我可以只展示几个例子,然后 AI 将其应用到所有位置。然后它高亮显示,“哦,这是一个新例子,我该怎么做?”然后,我准确地展示在那里该怎么做。然后,这可以在 10 分钟内完成。然后,你可以迭代得快得多得多。然后,你就不必预先思考那么多,站在黑板前思考,“我们到底要怎么做,因为成本太高了?”而是你可以先尝试一些东西,然后你意识到,“哦,这实际上不完全是我想要的。”然后,你可以再次立即更改它。所以,是的,我认为未来成为一名程序员将会非常有趣。
Cursor 团队: 是的,我真的很喜欢那一点。感觉很多时候编程,你可以有两种方式进行。一种是你预先非常努力、仔细地思考最好的可能方法,然后你花费有限的工程时间去实际实现它。但我更喜欢直接进入代码,尝试一下,看看它如何布局,然后在此基础上快速迭代。那样感觉更有趣。
Lex Fridman: 是的,仅仅是说生成样板代码,就很棒。这样你就专注于细微的、困难的设计决策。迁移,我觉得这是一个很酷的应用。看起来更大的语言模型基本上能够从一种编程语言翻译到另一种。或者翻译,迁移在迁移(migrate)的通常意义上。但那是在当前时刻。所以意味着恐惧与此有关,好吧,随着这些模型变得越来越好,那么你做的创造性决策就越来越少。它是否会走向一个你在自然语言的设计空间中操作的地方,自然语言成为主要的编程语言?而且,我猜,我可以通过建议的方式来问这个问题。如果有人现在对编程感兴趣,你认为他们应该学什么?你们开始是学一些 Java。(众人笑)我忘了,哦,一些 PHP。
Cursor 团队: PHP。
Cursor 团队: Objective-C。
Lex Fridman: Objective-C,就是这个。我的意思是,最终,我们都知道 JavaScript 会赢(众人笑),而不是 TypeScript。它会是像原生 JavaScript。它就是会吞噬世界,也许和 PHP 共存。我的意思是,这也引出了一个问题,我认为 Don Knuth 有个想法,即一定比例的人口是极客(geeks),编程需要特定类型的心理和思维。感觉越来越多的人,能够进行出色编程的人的类型可能会扩大。
Cursor 团队: 我认为不同的人出于不同的原因进行编程。但我认为真正的,也许是最好的程序员是那些真正热爱,绝对热爱编程的人。例如,我们团队中有一些人,他们 буквально(注:字面意义上)下班回家后,他们会去,然后启动 Cursor,然后开始在他们的副项目上编码一整晚,他们会熬到凌晨 3 点做这个。当他们难过时,他们说,“我就是真的需要编码。”(众人笑)我认为存在那种级别的程序员,这种对编程的痴迷和热爱,我认为,真正造就了最好的程序员。我认为这类人会真正深入了解事物如何运作的细节。
Lex Fridman: 我猜我问的问题是,就是那个程序员,让我们想想那个人。当超级 Tab,那个超级棒的、值得赞美的 Tab 成功时,你不停地按 Tab。
Cursor 团队: 团队里的那个人比任何人都更爱 Cursor Tab,对吧?
Lex Fridman: 是的。按 Tab 只是按 Tab。这是用流行语简单地说。但你按 Tab 时实际在做的是,你一直在注入意图。有时你拒绝它,有时你多输入几个字符。这就是你塑造正在被创造的东西的方式。我认为编程将发生很大变化,变成仅仅是,“你想要创造什么?”
Cursor 团队: 这有点像是更高带宽。与计算机的通信带宽变得越来越高,相对于仅仅打字来说,打字的带宽比传达意图要低得多。
Lex Fridman: 我的意思是,这涉及到你们题为“工程天才”(Engineering Genius)的宣言。“我们是一家应用研究实验室,构建极其高效的人类-AI 系统。”所以,谈到了这种混合元素。“首先,我们正在构建未来的工程师,一个比任何单个工程师效率高一个数量级的人类-AI 程序员。这位混合工程师将能毫不费力地控制他们的代码库,并且没有低熵的击键。他们将以他们的判断速度进行迭代,即使在最复杂的系统中也是如此。结合 AI 和人类的创造力,他们将在智力和工程能力上超越最好的纯 AI 系统。我们是一群研究人员和工程师。我们构建软件和模型,在有用和可能的边缘进行发明。我们的工作已经改善了数十万程序员的生活。”在通往那个目标的路上,我们至少会让编程更有趣。所以,感谢你们今天的谈话。
Cursor 团队: 谢谢你。
Cursor 团队: 感谢邀请我们。
Cursor 团队: 谢谢你。
Cursor 团队: 谢谢你。
Lex Fridman: 感谢收听这次与 Michael, Sualeh, Arvid 和 Aman 的对话。若要支持本播客,请查看描述中的赞助商链接。现在,让我留给你们一句我在 Reddit 上看到的随机、有趣,或许也深刻的编程代码:“没有什么比一个能用的临时解决方案更持久的了。”感谢收听,希望下次再见。
要点回顾
一、 引言与代码编辑器的基础
- 访谈嘉宾:Cursor 团队创始成员 Michael Truell, Sualeh Asif, Arvid Lunnemark, Aman Sanger。
- Cursor 简介:一个基于 VS Code 的代码编辑器,专注于 AI 辅助编程,在编程和 AI 社区引起广泛关注。
- 访谈主题:深入探讨 AI 在编程中的作用,未来编程,以及人机协作设计复杂系统。
- 代码编辑器的作用:
- 构建软件的主要场所。
- 传统上是文本编辑形式化编程语言的地方。
- 可视为程序员的“超级文字处理器”,因代码结构化而功能强大(如语法高亮、代码导航、错误检查)。
- 未来十年,代码编辑器的定义可能随软件构建方式的演变而改变。
- 代码编辑器的重要特质:
- 应该有趣(Fun)。这是 Cursor 团队决定构建什么的一个被低估的方面,不好玩的功能会被舍弃。
- 速度快(Fast is fun)。快速迭代是编程吸引人的核心特点之一。
二、 从 Vim 到 VS Code 与 GitHub Copilot
- 团队成员的编辑器历程:
- 最初都是 Vim 用户(纯 Vim)。
- 因 GitHub Copilot(2021年左右)的出现而转向 VS Code,因为 Copilot 最初只在 VS Code 可用。
- Copilot 结合 VS Code 的体验足以让他们转换编辑器。
- GitHub Copilot 的功能与体验:
- 优秀的自动补全工具,能建议多行代码。
- 体验:好的时候感觉像朋友补全你的句子,有“懂我”的亲密感;不好的时候令人不快。
- 优点:即使建议错误,用户只需多输入几个字符即可修正或获得新的建议,干扰相对较小。
- 重要性:是第一个真正的 AI 语言模型消费级产品,LLM 的首个杀手级应用。
三、 Cursor 的诞生:动机与愿景
- 起源动力:
- OpenAI 的 Scaling Laws 论文(约2020年)揭示了 AI 能力可通过增加计算和数据进行可预测的提升 。
- 早期使用 Copilot Beta 的体验很神奇。
- 接触 GPT-4(2022年底)感受到能力的巨大飞跃,让理论预测变得具体。
- 从具体工具到整体环境:
- 早期探索:为特定人群(金融专业人士的 Jupyter 工具)或特定任务(静态分析)开发工具。
- GPT-4 后的转变:意识到 AI 将渗透整个编程过程,需要一个全新的编程环境,而非点状解决方案。
- 团队信念:早期成员(如 Aman)对 AI 在特定领域(如数学 IMO 竞赛)的潜力有强烈信念。
- 为何选择构建编辑器而非插件:
- 插件对编辑器的控制有限,无法实现团队对未来编程方式的设想。
- AI 能力的提升将彻底改变软件构建方式,需要更深层次的集成。
四、 Cursor 的竞争优势与开发理念
- 如何与 VS Code + Copilot 竞争:
- 创新速度:AI 编程领域,几个月甚至一年的领先就能带来显著的产品优势。初创公司在快速迭代和实验上更灵活。
- Cursor 的目标是让今天的版本在一年后显得过时。
- 开发优势:
- 自用驱动:为解决自身在使用现有工具时的痛点和不满(如 Copilot 更新缓慢)而开发。
- 一体化开发:UX 设计和模型开发紧密结合(有时是同一个人),实现端到端的体验优化。
- 使用 Cursor 开发 Cursor。
五、 Cursor 核心功能:Cursor Tab
- Cursor 的两大核心能力(当前):
- AI 像快速的同事一样“在你身后观察”,预测你的下一步操作(超越简单补全)。
- 帮助将用户的指令(自然语言)转化为代码。
- Cursor Tab 的目标:
- 超越字符级别的补全,预测用户下一个完整的代码更改(diff)、下一个光标跳转位置。
- 消除所有“零熵”的操作:当用户意图明确时,模型应能“读心”,用户只需按 Tab 键即可完成。
- 利用代码比自然语言熵更低(更可预测)的特性,尤其是在编辑现有代码时。
- Tab 的能力范围:
- 生成代码、填充空白。
- 跨多行编辑代码。
- 在同一文件内跳转。
- 未来:跨文件跳转,预测下一个动作(包括终端命令、导航到定义以提供上下文)。
- 终极愿景:预测接下来几分钟内可预测的编程任务,让用户通过连续按 Tab 键完成。
六、 用户体验:Diff 界面与代码验证
- Diff(差异比较)的重要性:Cursor 大量使用 Diff 界面(红绿标识)来展示 AI 建议的代码修改。
- Diff 界面设计:
- 为不同场景(自动补全、大块代码审查、多文件修改)优化了多种 Diff 显示方式,核心是快速易读。
- 迭代过程:尝试过删除线(像 Google Docs)、按键(Option)触发显示、最终到侧边框显示。仍在探索最佳方案。
- 验证难题(Verification Problem):
- 审查大型或多文件 Diff 很困难。
- 解决方案探索:AI 辅助审查,如高亮重要部分、淡化重复部分、标记潜在 Bug 区域。
- 目标:随着 AI 提出更大规模的修改,有效引导用户进行验证。
- 多文件 Diff 的改进:超越传统 Code Review,AI 可根据逻辑依赖关系引导审查顺序。
七、 交互模型:自然语言及其他
- 自然语言的角色:是编程交互的一部分,但不是全部。
- 类比:结对编程时,有时口头指令有效,有时需要直接上手演示(写示例代码)。
- 多样化交互:展示示例、拖拽/绘图(UI 设计)、未来可能包括脑机接口等,最佳方式取决于任务。
八、 底层机器学习技术
- 核心技术:结合了定制训练模型和前沿大模型(如 o1, Sonnet)。
- 定制模型应用:
- Cursor Tab:专门训练,低延迟,性能优于通用大模型。使用稀疏 MoE 模型(适合长输入短输出)和“推测性编辑”(Speculative Edits)。KV 缓存至关重要。
- Apply 功能:前沿模型擅长规划代码草图,但在大型文件中精确应用 Diff(如行号计算)时表现不佳。Cursor 训练了专门的“Apply”模型来精确执行 Diff,这并非简单的确定性匹配。允许智能模型规划,较简单模型执行。
- 性能优化 - 使 Tab 快速:
- 推测性编辑(Speculative Edits):一种推测解码变体。利用现有代码作为强先验,并行处理匹配的代码块,直到出现分歧,再生成新内容。比完全重写快,支持流式输出和提前审查。
- 推测(Speculation)是通用思想(CPU、数据库等)。
九、 大语言模型(LLM)比较与评估
- 编程最佳 LLM:没有绝对最优模型,需权衡速度、编辑能力、上下文长度、编码能力等。
- 当前综合最佳:Sonnet(推理能力强,能较好理解模糊意图)。
- o1:在难题(如 LeetCode)上表现好,但在理解一般意图方面可能不如 Sonnet。
- 其他模型:可能在基准测试上表现好,但在分布外任务上能力下降。Sonnet 泛化性较好。
- 基准测试(Benchmark)的局限性:
- 与真实编程差异:真实编程通常是模糊的、非良构的、上下文依赖的,而非规范化的问题。
- 数据污染:公开基准测试(如 SWE-Bench)可能存在于模型训练数据中,导致模型在没有上下文的情况下也能“猜”对答案。
- 替代评估方法:人类定性反馈(“Vibe Check”)、内部私有评估。
- 模型变“笨”的感觉:可能是主观的,也可能有技术原因(如不同芯片的数值计算差异影响量化模型,如 Claude on AWS)。系统 Bug 难以避免。
十、 提示工程(Prompt Engineering)与上下文管理
- 提示的重要性:模型(尤其是早期模型)对提示敏感。如何在有限上下文中有效输入信息(文档、文件、历史记录)是个挑战。
- 长上下文的问题:速度慢,可能干扰模型。
- Cursor 的 “Preempt” 系统:
- 受 React/JSX 启发,用声明式方式定义提示内容(文件、光标位置、历史等)及其优先级。
- 渲染引擎根据优先级和上下文限制动态构建最终提示。
- 优点:处理动态输入、适应不同上下文长度、便于调试。
- 用户交互目标:用户自然输入,系统智能检索并构建上下文。
- 处理模糊性:模型提问澄清、提供多种选项、建议添加相关文件作为上下文。
十一、 AI 代理(Agents)在编程中的应用
- AI Agents 现状:概念酷炫,接近 AGI 感觉,但目前在多数任务中实用性有限,正在接近实用阶段。
- 潜在应用场景:
- 处理定义明确、可委托的任务(如修复特定 Bug)。Agent 在后台执行,用户后续审查。
- 自动化设置(开发环境、部署)。
- 局限性:不适合需要即时反馈和迭代探索需求的任务。
- 混合模式:后台 Agent 处理任务的一部分(如 PR 的后端),用户处理另一部分(前端),Agent 提供初步代码供用户迭代。
十二、 性能优化策略
- 关键技术:
- 缓存预热(Cache Warming):用户输入时预先加载可能需要的上下文(如当前文件)到 KV 缓存,减少提交后的预填充时间,降低 TTFT。
- KV 缓存:存储 Attention 机制的键值对,避免重复计算,提高生成效率。
- 高级缓存/推测:假设用户接受当前建议,提前计算下一个 Tab 建议。
- RL 优化:通过强化学习训练模型(如 Tab)偏好人类喜欢的输出(利用 Passive K 采样思想),可能让小模型达到大模型效果。
- 高效 Attention 机制:从 MHA 转向 GQA/MQA,减少 KV 缓存大小,提高在内存带宽受限场景(长上下文、大批量)下的生成吞吐量。MLA(Multi-Latent Attention)是更进一步的压缩技术。
- 效果:支持更大上下文、更积极缓存、更高并发吞吐量、允许更长的提示。
十三、 后台处理与影子工作区(Shadow Workspace)
- 目标:利用后台计算处理更长远的任务(超越预测下几行)。
- 反馈机制:后台任务需要反馈才能改进。语言服务器协议(LSP)提供类型检查、定义跳转等信息。
- 影子工作区概念:
- 在后台运行一个隐藏的 Cursor 实例。
- AI Agent 在此实例的内存中修改代码,获取 LSP 反馈(Linting、类型检查等)。
- 不影响用户当前视图,不实际保存文件。
- 挑战:安全地在后台运行代码/测试,需要精确复制用户环境。
- 方案探索:文件系统镜像(Linux)、保存锁(macOS/Windows 技巧)、沙盒化远程环境(适用于长任务)。
十四、 调试、代码验证与潜在商业模式
- AI 调试能力现状:直接提示时,模型在发现 Bug 方面表现不佳,校准差。
- 原因:预训练数据缺少 Bug 检测样本;难以校准 Bug 严重性(涉及人类经验和文化);难以判断用户所需的谨慎程度。
- 提升 Bug 检测能力:
- 从简单 Bug 入手(差一错误、注释与代码不一致)。
- 提供更多信息(运行时跟踪、调试器信息)。
- 合成数据:训练一个模型引入 Bug,再训练另一个模型检测 Bug。
- 专门模型:快速后台模型检测 + 高算力模型处理已知特定 Bug。
- 验证的重要性:AI 生成代码需要验证,因此 Bug 检测能力对 AI 编程至关重要。
- 付费模式思考:
- 为优质建议/Bug 修复提供“小费”按钮?
- 优点:提供强烈的积极信号。
- 缺点:引入金钱因素可能降低趣味性;存在“复制代码不付费”的道德风险。
- 当前替代:用户分享成功案例作为反馈。
- 技术解决?:自动验证 Bug 修复后再收费。
十五、 高级概念:分支与基础设施
- 终端集成:可将终端上下文用于提示。运行代码 -> 获取错误 -> 建议修复的循环尚未实现,但有意义。
- 万物皆可分支(Branching):
- 数据库分支(如 PlanetScale 基于 WAL 实现)允许隔离测试。
- 文件系统分支也很有用。
- AI Agents 可利用分支进行测试。
- 基础设施:主要使用 AWS(可靠,尽管配置复杂)。
- 扩展挑战:请求量增长(每秒请求数增加一个数量级)会暴露未知瓶颈。扩展代码检索系统(语义索引)尤其困难。
- 代码索引实现:
- 分块 -> 嵌入 -> 存储向量(非代码)-> 检索。
- 状态同步:本地与服务器索引状态同步需高效。使用 Merkle 树进行分层哈希比较,减少网络开销。
- 扩展性:嵌入是成本瓶颈。通过缓存向量(基于块哈希)在团队/用户间复用嵌入结果。
- 本地 vs. 云端:
- 本地模型挑战:多数用户设备性能不足;模型越来越大(MoE);本地部署复杂。
- 云端优势:可使用最强模型;易于扩展。
- 隐私考量:
- 中心化模型接触大量数据。
- 同态加密(Homomorphic Encryption)是研究方向,允许云端计算而不暴露数据,但目前性能开销大。
- AI 模型可能处理比传统云应用更敏感的数据。需平衡负责任扩展与监控风险。
十六、 上下文、检索与模型训练
- 自动上下文挑战:需要权衡(更多上下文=慢、贵、可能干扰模型),要求高相关性。
- 改进上下文检索:更好的嵌入模型、重排器。
- 模型直接理解代码库:
- 研究方向:无限上下文窗口、模型注意力、高效缓存。
- 权重内学习:通过持续预训练或指令微调(可能使用合成数据 Q&A)让模型“学习”特定代码库。效果待定。
- 分离 vs. 集成:是单独训练检索器,还是让大模型内部完成检索?
十七、 OpenAI o1 与测试时计算
- o1 特点:扩展测试时计算(推理 FLOPs),而非仅依赖模型规模/训练数据。可能缓解数据瓶颈。
- 优势:用同一模型,通过增加推理时间处理难题(可能只占少数查询),避免为罕见任务训练超大模型。
- 挑战:如何动态分配计算资源?o1 内部机制未知(树搜索?过程奖励模型?)。
- 过程奖励模型 vs. 结果奖励模型:过程奖励模型评估推理步骤,可能对搜索有用,但训练和有效应用仍是研究难题。
- 隐藏 o1 思维链:原因猜测(防止技术蒸馏、保护 IP)。
- o1 在 Cursor 中的应用:已提供给用户实验,但尚未深度集成。存在局限性(非流式输出、感觉像 V0 版本)。应用场景仍在探索(后台 Agent、循环任务是可能方向)。
- 竞争态势:Cursor 的价值在于整个系统(定制模型、UX、快速创新),而非仅仅快速集成最新模型。AI 编程工具的天花板极高,产品本身是关键。
十八、 合成数据分类
- 定义:非人类直接产生的,通过程序或 AI 生成的数据。
- 类型:
- 蒸馏(Distillation):用大模型输出训练小模型。传递能力,但不超越教师。用于创建专用小模型。
- 正向易/反向难(Easier Forward/Harder Reverse):利用易于生成的方向(如引入 Bug)的数据,训练模型解决困难的反向问题(如检测 Bug)。
- 生成+验证(Generation + Verification):大量生成候选答案,用可靠验证器(测试、形式化方法、人类/AI)筛选正确样本进行训练。需要可靠的验证器。在数学、有明确测试用例的代码问题上效果好。
十九、 强化学习:RLHF vs. RLAIF
- RLHF(Reinforcement Learning from Human Feedback):使用基于人类反馈训练的奖励模型。需要大量标注。
- RLAIF(Reinforcement Learning from AI Feedback):使用 AI 模型提供反馈。依赖于验证比生成更容易的假设。可能实现自举改进。
- Cursor 的实践:混合方法。模型通常大致正确,少量人类反馈用于微调 AI 的偏好(如对 Tab 建议的选择),数据需求低于传统 RLHF。
二十、 AI 与科学/数学突破
- 验证 vs. 生成:直觉上验证更容易(类比 P vs NP)。
- AI 获奖预测:AI 可能先获得菲尔兹奖(数学是封闭、可验证系统),后获得诺贝尔奖。解决顶级数学难题(如 BSD 猜想)的路径尚不清晰。
二十一、 规模法则(Scaling Laws)再思考
- 发展历程:早期论文 -> Chinchilla (计算最优) -> 当前实践 (为推理预算等其他维度优化)。
- 多维度考量:推理计算、上下文长度等影响架构选择(如 SSM 可能适用于长上下文)。
- 越大越好?:对原始智能(raw intelligence)是的。但蒸馏可能通过提高每 Token 信号量来得到更优的(更小、更快)模型,部分缓解数据限制。
- 投资方向:购买 GPU 是基础,但瓶颈可能在于想法和工程能力。需要更好的工具加速从想法到实现的转化。初期依赖规模扩展是正确的,但实现 AGI 可能需要新想法。
二十二、 编程的未来
- Cursor 的愿景:
- 程序员长期处于主导地位(in the driver's seat)。
- 强调速度、自主性(agency)、控制力。快速迭代,随心所欲修改。
- 区别于纯对话式交互(后者有延迟、失控风险)。工程不仅是执行规范,更是充满微决策和权衡。
- 人机混合(Human-AI Hybrid):
- 未来的工程师是人与 AI 的结合体,效率提升一个数量级。
- 消除低熵击键,以思维速度迭代。
- 在智能和工程能力上超越纯 AI 系统。
- 未来交互界面:可调整代码抽象层级(查看/编辑伪代码)、手势操作逻辑区域。保留文本编辑,增加高层控制。
- 对程序员的影响:
- 编程变得更有趣,减少繁琐工作。
- 技能重点转向:创造力、品味、设计决策、指导 AI 的能力。可能降低对纯粹编码和细致性的要求(若 AI 负责验证)。
- 赋能:使大型重构等任务变得更容易,支持快速试错。
- 编程技能学习:对编程的热爱是核心。基础依然重要。与 AI 协作、表达意图、做设计决策的能力愈发关键。可能扩大能有效编程的人群范围。
- Cursor Tab 体验的本质:按 Tab 键并非被动接受,而是持续注入和塑造意图的过程,是更高带宽的人机交互。