拆解Cursor与Copilot如何真正读懂你的代码

AI代码编辑器靠精心组装的上下文片段——而非读完整仓库——来实现"读心术"般的代码补全。
AI代码编辑器的核心限制是语言模型只能看到提示词窗口内的内容,真正的工程挑战在于决定哪些代码进入这个窗口。传统Copilot自动补全依靠光标前后代码和邻近标签页;更强大的检索方案则用Tree-sitter解析AST、嵌入向量、Merkle树增量更新,实现跨未打开文件的语义搜索。然而Cursor在2026年7月关闭了嵌入索引,转向本地grep加并行子Agent——因为模型的工具调用能力已强到让"笨办法"的精确grep比向量检索更划算。两款工具都不会读完整仓库,决定补全质量的始终是最终组装进提示词的那个"行李箱"里装了什么。
你敲下三个字母,编辑器就补全了整个函数,仿佛它读懂了你的整个项目。真的如此吗?诚实的答案取决于你用哪款工具、触发了哪个功能,以及——截至今夏——你是在哪个月提出这个问题。让我们掀开引擎盖,看看AI代码编辑器究竟是怎样"看见"你的代码的。
一个绕不开的硬约束:上下文窗口
所有这类工具都共享同一个限制:语言模型只知道提示词(prompt)里有什么。一个代码仓库可能包含成千上万个文件,而提示词却是一个固定大小的窗口。窗口确实在不断变大,但塞满它既慢又贵,而且更多的上下文并不等于更好的上下文。
所以真正的工程挑战不在模型本身,而在于决定哪几百行代码能搭上这趟车。GitHub把负责这件事的代码称为它的"prompt library"。这个取舍决定了AI补全是"读心术"般精准,还是莫名其妙地跑偏。
经典Copilot自动补全:看邻居
传统的Copilot自动补全依靠"附近的东西"来回答问题。它会读取光标之前的代码和光标之后的代码——这个技巧叫做"中间填充"(fill in the middle),让它能够补全一个缺口,而不仅仅是补完一行的结尾。
除此之外,它还会向"邻近标签页"借东西:扫描你打开的其他文件,寻找与当前书写内容相似的片段。GitHub曾报告,仅"邻近标签页"这一项就让被采纳的建议相对提升了约5%。这个方式快速又便宜。
但它的盲区也很明显:如果你需要的辅助函数藏在一个你从未打开过的文件里,自动补全根本看不到它。要回答"我们在哪里校验支付?"这类问题,工具需要一张整个仓库的地图。

构建仓库地图:检索(Retrieval)的三步法
构建这张地图的教科书式方法是检索增强,它通常分三步走。
第一步:解析
像Tree-sitter这样的解析器会把每个文件转换成抽象语法树(AST),也就是把程序的语法结构铺陈为一个个节点——这是一个函数、这是它的函数体、这是一个类。沿着这些节点来切分代码,意味着每一个"块"(chunk)从一开始就是一个完整的函数,而不是半截函数。
Tree-sitter是一个增量式解析库,最初由GitHub开发,现已被几乎所有主流代码编辑器采用。它的核心优势在于"增量":当你修改文件中的一行代码时,Tree-sitter不会重新解析整个文件,而是只更新语法树中受影响的节点,速度极快。抽象语法树(AST)与纯文本切分的根本区别在于语义完整性——按行数硬切可能在函数中间断开,导致送入嵌入模型的代码块缺乏语义,匹配质量下降;而沿AST节点切分,每个块天然对应一个完整的语法单元(函数、类、方法),嵌入后的向量能更准确地代表该代码块的语义意图。
第二步:嵌入
每个代码块会经过一个嵌入模型,输出为一个向量——一串数字,让语义相近的代码在向量空间中彼此靠近。
嵌入(Embedding)是将离散的文本或代码转化为高维连续向量的过程。所谓"语义相近的代码在向量空间中彼此靠近",意味着即使两段代码的变量名完全不同,只要它们执行类似的逻辑(比如两种不同写法的排序函数),它们的向量距离也会很小。这与传统的关键词搜索形成鲜明对比:grep只能找到你已知的符号名称,而语义检索能找到你"不知道它叫什么名字"的功能。专门针对代码训练的嵌入模型(如CodeBERT、UniXcoder等)比通用文本嵌入模型表现更好,因为它们理解缩进、括号匹配和API调用模式等代码特有的结构信号。
第三步:保持新鲜
Cursor的工程博客描述了它如何把每个文件哈希进一棵Merkle树。每次同步时,系统只需遍历那些哈希值发生变化的分支,并只对这些改动的代码块重新嵌入。这样就避免了每次全量重建索引的巨大开销。
当你提问时,你的问题也会被嵌入,索引返回最接近的代码块,编辑器随后组装提示词:顶部是指令,接着是检索到的片段,然后是你当前打开的文件,最后是你的问题,整体裁剪到适合窗口的大小。
模型从来没有看过你的整个仓库,它看到的只是一个精心打包的行李箱。
Merkle树是一种哈希树数据结构:叶节点存储各代码块的哈希值,父节点存储其所有子节点哈希的组合哈希。这一特性使得增量检测极为高效——当任何一个代码块发生变化时,其哈希改变会向上传播,只要比较根节点哈希就能知道整棵树是否有变动,再沿变化分支向下定位,就能精确找到哪些代码块需要重新嵌入。这与Git的内部存储机制采用的是同一种数据结构,本质上都是在解决"高效检测大量内容中哪些部分发生了变化"这个问题。对于一个拥有数万个函数的大型仓库,这种增量更新机制可以将索引维护成本降低几个数量级。
GitHub Copilot的现状:语义索引
GitHub Copilot在聊天和Agent场景中仍然采用这套检索方案。VS Code的文档说明,Copilot会自动为你的工作区构建语义索引——对于托管在GitHub上的仓库在远端构建,对于其他文件夹则在本地构建,并把它作为一个基于代码的搜索工具暴露出来。
当你问"支付在哪里被校验",它就能从那些你从未打开过的文件里拉取出相关函数。这正是语义检索相比纯邻近补全的核心优势。
Cursor的反转:关掉嵌入索引
剧情出现了转折。Cursor的这套检索流水线曾是业界文档最完善的实现之一,但在2026年7月,它关闭了嵌入索引。
就在当年6月,Cursor的文档还写着:将语义搜索与grep结合,能让回答质量提升约12.5%。但其工程人员解释说,模型已经变得极其擅长grep风格的搜索,专门的语义检索路径不再带来有意义的提升。
如今Cursor的Agent改用一个本地即时grep索引——对符号、字符串和模式进行精确匹配,再加上普通的文件读取,以及一个能够并行运行大量搜索的子Agent(subagent)。换句话说,当底层模型的工具调用能力足够强时,"笨办法"的高速grep反而比精巧的向量检索更划算。
这一转变折射出大模型工具调用能力的快速演进。早期Agent受制于模型对工具的理解能力,需要外部检索系统预先"翻译"自然语言查询为相关代码片段再喂给模型。而当模型自身能够精准地将"找到处理支付校验的函数"转化为多条具体的grep指令并并行执行时,中间的语义检索层反而成了延迟和误差的来源——嵌入索引有更新延迟,向量相似度有召回噪声,而grep是精确且零延迟的。Cursor的这一决策本质上是把"理解查询意图"的任务从检索系统迁移到了语言模型本身,这一路线只有在模型能力达到足够高度后才可行,也预示着随着模型能力继续提升,AI工具的内部架构还将持续重构。
谁看得更清楚?这其实是个错误的问题
到底哪款编辑器更"懂"你的代码库?这个问题本身就提错了。
两款编辑器如今都让Agent主动去"找":一个带着语义地图和搜索能力,另一个带着极快的grep。它们谁都不会读完全部代码。真正决定结果的,是最终落进提示词里的内容。
下次当一条建议感觉像读心术般精准、或是明显错得离谱时,不妨换个角度问自己:这次的"行李箱"里装了什么? 理解了上下文的组装机制,你才能真正理解AI编程助手的能力边界与失效原因。
相关推荐

Gemini 4 Argon API实战:思考等级、后台模式一次讲透
Free Code Camp 出品的 Gemini 4 Argon API 速成教程:从申请密钥、发送首次请求,到用思考等级控制推理成本、用 previous_interaction_id 实现多轮对话,再到后台模式一句话生成打砖块游戏,附 Google 工程师对模型能力的解读。

强化学习通关《抡大锤》:63%进度背后的分布式训练策略
开发者用深度强化学习挑战《抡大锤》,智能体从底部攀爬至63%进度,卡在铁砧部分。项目开源,采用分治训练和CPU训练策略,寻求社区协作突破瓶颈。

AAAI 2027二审放榜在即:社区热议评审公平与投稿生态
AAAI 2027第二阶段评审结果即将公布,Reddit社区热议评审一致性与流程透明度。本文梳理放榜前的社区情绪、顶会评审的结构性矛盾,以及作者应对二审结果的务实策略。