我们从零开始实现了一个cursor的codebase功能(踩了很多RAG的坑)

简介: VoidMuse 是一个以学习为目标的开源AI IDE插件,支持IntelliJ IDEA与VS Code,集成20+优秀开源组件,助力开发者在实践中掌握AI工程化技术。本文深入解析其基于混合检索的Codebase实现,涵盖向量化、索引构建与检索优化,助你真正理解并应用Function Call等核心技术。

关于VoidMuse: 一个以学习为目标的开源AI IDE插件,支持IntelliJ IDEA和VS Code。通过整合20+优秀开源组件,让你在实际开发中掌握AI工程化技术。不仅提供工具,更重要的是帮你把AI知识真正应用起来,通过实践来学习。

1. 前言

为什么要做这个开源项目?

这两年AI发展非常快,有很多的新概念出现比如 embedding 、RAG、function call等,但这些技术有什么作用,在一个实际的项目中能带来什么样的价值,如何在项目中实践这些技术,这些都是我们很好奇的点,也就萌生了一个想法,构建一个项目,在项目中实践这些技术,在干中学是学习效率最高的,不然对这些知识只是浮于表层,于是我们就构建了一个 VoidMuse 项目,实现一个ai ide coding插件,把我们所想要学习的知识点都实践上

而为什么不直接在 cline 这种开源插件上进行扩展开发,而是从零实现呢, cline 的代码太复杂了,想要从中实践成本很高,直接从零开始做一个简单的项目来实现满足目标就足够了

而这一篇文章是介绍 codebase 的真正实现,我们完整实现了在 chat 页面中调用 codebase 进行代码检索然后加入到 llm 上下文中,这里面也包含了很多优化细节,比如embedding模型的选择坑点,还有单纯向量检索是有局限性的,我们利用了混合检索来提高检索的准确性,这些都是在实践中发现的点,看完本篇文章你会codebase实际的实现有一个更深入的了解

codebase效果.png

2. 完整实现流程

codebase-流程.png

实现codebase功能的关键是有两部分的

  1. 建立codebase索引:对全量代码文件进行向量化,这里涉及到代码分块、向量化、文件选择策略等
  2. 检索codebase索引:根据查询进行向量化检索+文本检索,这里采用了混合检索来提高准确率,并且通过提示词加权来提高检索词的权重

以下详细介绍这两部分实现细节

3. 建立codebase 索引

codebase-建立索引流程.png

3.1 移除文件

一个代码仓库中,有众多文件,包含系统本身的隐藏文件、依赖库(比如node_modules),还有一些协议生成的大文件,比如java项目中使用pb协议生成的java文件非常庞大,这些文件对代码检索没有帮助,所以需要提前去除掉这些文件

筛选策略如下

  1. .gitignore: 代码仓库中通常会有一个 .gitignore 文件,里面列出了需要忽略的文件和目录,我们根据这个文件来移除掉忽略的文件,一般大部分依赖文件都会在这个阶段就被排除掉了
  2. 额外排除“pb 自动生成的文件”: 在java项目中使用pb协议生成的java文件非常庞大,这些文件对代码检索没有帮助,我们的项目中用到挺多pb协议所以专门做了一个移除处理
  3. 空文件和大文件排除掉:我们同时对超过 1MB 的文件进行排除

具体代码可参考 : CheckAutoIndexingTask.startCheckAll 方法

3.2 代码分块

一个文件通常包含多个函数,并且文件行数都是不确定的,有可能一个代码文件几千行代码都是有可能的,而embedding 模型是有上下文长度限制的,所以要对代码文件进行分块,每一个分块单独进行向量化

代码文件分块有两种策略(我们参考了 continue 插件的方案)

  1. 根据代码的结构(如函数、类等)将文件内容分割成多个块生成抽象语法树(AST):就是把代码转成一种更加结构化的数据,能提供更多文本特征,并且是完整的函数表示
  2. 使用字符数或者行数进行分块: continue插件的兜底方法

VoidMuse中我们只实现了最简单的按行数进行分块,对文件按随机行数分块(35-65行),当然这种缺点很明显,有可能一个完整函数会被切割成几块

备注:embedding 模型的踩坑点,一开始我们挑选embedding模型时希望能支持中文,那时选择了开源的 bge-large-zh-v1.5 模型,但这个模型的上下文长度限制是512个token,代码文件分块后挺容易就超过这个限制,就会导致向量化的结果不准确,后续我们是换成了 Qwen3-Embedding-0.6B 模型, 本地就能运行起来了,这个模型的上下文长度限制是32,000个token,一般也满足要求了,在一些做知识库的场景也能满足了,并且向量维度是 1536 ,这就表示一个信息能用到更多维度来表示,向量化更加准确

3.3 调用embedding接口向量化和保存到 lucene

每一个代码块单独调用embedding接口向量化,然后把向量化结果保存到 lucene 索引中,lucene 索引中包含了代码块的文本内容、向量化结果、文件路径、行号等信息

而这里我们使用 lucene 来存储索引,lucene 是一个基于 java 实现的全文检索引擎,支持中文检索,并且性能非常好,我们在项目中使用 lucene 来存储索引,检索时直接调用 lucene 的 api 即可, 并且我们也想利用到 lucene 提供的文本检索 + 向量检索的功能,来提高检索的准确性

具体代码可参考:LuceneVectorStore.java

4. 检索codebase 索引

codebase-检索流程.png

4.1 优化查询词

我们在测试中发现,直接对查询词进行向量化检索,效果不是特别好,所以我们在查询词向量化前,先对查询词进行了一些优化,转化成更符合进行向量检索的查询词,包括对一些关键词语进行重复3词来提升权重(这一点在平时写长prompt时,想要提升某一段规则的重要性,也可以把这段规则重复几次之后,权重也就提高了)

比如用户查询词是 找出关于订单号 OrderID 生成相关的信息,我们会把查询词优化成 OrderID OrderID OrderID 订单号生成 订单号生成规则 订单号生成逻辑 订单号生成文档,重复3次,来提升订单号这个关键词的权重

具体优化提示词是在: codebaseOptimizePrompt.txt
优化流程是在 GUI 中: IDEService.tsbuildWithCodebaseContext

4.2 对查询词进行embedding

这部分就是对查询内容进行向量化,这里就不再对向量化部分重复介绍

4.3 混合检索(最关键的地方)

一开始我们采用的方案是向量检索,但这种方案是存在局限性的

1.Embedding的语义理解局限性

  • 语义泛化:Embedding模型(如BERT、GPT等)通常通过捕捉文本的语义信息来进行检索。然而,代码的语义与自然语言不同,代码的精确性要求更高。Embedding模型可能会将类名、方法名等符号的语义泛化,导致检索时无法精确匹配。
  • 符号信息丢失:Embedding模型在处理代码时,可能会忽略类名、方法名等符号的精确信息,尤其是在符号本身具有特定含义或命名规则时。这会导致即使提问中指定了类名,模型也无法准确捕捉到这些符号信息。

2.Embedding的上下文依赖

  • 上下文理解偏差:Embedding模型在处理代码时,通常依赖于上下文信息来生成向量表示。如果提问中包含了过多的细节(如类名、方法名等),模型可能会过度依赖这些细节的上下文,而忽略了代码的整体结构或功能,导致检索结果偏离预期。
  • 过拟合问题:当提问过于详细时,Embedding模型可能会“过拟合”到提问中的某些细节,而忽略了代码库中更广泛的相关性。这会导致检索结果过于狭窄,甚至无法找到相关代码片段。

3.代码的结构化特性

  • 符号检索的重要性:代码库中的类名、方法名等符号具有特定的结构和命名规则,这些符号在代码检索中扮演着重要角色。单纯依赖Embedding的向量检索无法充分利用这些符号的结构化信息,导致检索效果不佳。
  • 混合检索的必要性:为了提高代码检索的准确性,通常需要结合符号检索和Embedding的向量检索。符号检索可以精确匹配类名、方法名等符号,而Embedding检索可以捕捉代码的语义信息。两者结合可以更好地平衡检索的精确性和语义理解。

总结:代码检索要使用混合检索技术: 符号检索 + 向量检索

而刚好 lucene 提供了文本检索 + 向量检索的功能,我们是直接利用这个来进行实现

具体代码:LuceneVectorStore.hybridSearch
这里主要特点是

  • 检索文本(根据语义相似度进行搜索 ) + 检索向量,比如输入一个twoStageHybridSearch的具体实现是什么的,会去检索twoStageHybridSearch这个文字的相关数据块,以及整个句子向量化后的数据块,对这两部分数据进行一个混合分数计算,提高整体搜索效果
  • 检索时都要扩大候选集:取多一点数据出来,能提升召回,比如预期是获取10条数据,那么扩大候选集获取30条数据,再进行一个排序
  • 排序处理:检索出来的数据进行混合分数计算,获取top k的数据

5. 扩展阅读:为什么cline不使用向量检索呢

cline插件介绍:cline也是一款开源的插件,但跟cursor有一点挺大的不同,就是cline是不会进行codebase检索的,也就是不会利用向量进行检索

cline是利用了另一种方案: 通过理解代码中的依赖项,比如import这种来不断地读取相关的文件,类似人在理解代码时,是会不断自己跳转到依赖的代码文件进行阅读理解的,这种缺点就是依赖多的话就得不断地进行阅读,上下文会被占挺多的,并且如何判断停止加载新文件了,一个大型仓库里面一直读取依赖项是有可能非常多的(利用的是AST 解析方案,我们之前在做autocompelete时,其实也用到了这种策略,因为要结合一些依赖作为上下文才能更好地预测下一句内容)

那么这点就挺有意思的,cursor是对整个项目进行向量检索,是从技术角度去提取相关性信息,而cline则是从代码的依赖项角度去提取相关性信息,更像是一个人阅读代码的步骤

6. 总结

codebas的实现简单说就是rag,对内容进行向量化,使用时使用向量检索,但要做得好的话就要对各种细节进行优化,比如代码分块的策略、搜索词的加权、文本检索的加入等,通过这一次实践,已经能基本了解到 cursor 这类型的ai coding工具的codebase具体实现原理,虽然他们的工程化肯定是更加复杂的,但大概的流程思路是有认识了

后续希望在记忆能力上也能进行一些实践,现在大模型的上下文是有限的,并且新开一次对话,之前累计对话的一些信息要点都丢失了,而记忆能力就能实现对之前对话的一些信息进行保留,并且在后续的对话中能够利用这些信息进行更准确的回答

7. 相关资料

目录
相关文章
|
7月前
|
人工智能 搜索推荐 算法
万字长文深度解密!Cursor Codebase实现原理全公开
VoidMuse 是一个开源AI IDE插件,支持 IntelliJ IDEA 与 VS Code,整合20+优秀组件,通过混合搜索架构(Lucene+向量)实现Codebase智能代码检索,助力开发者在真实项目中掌握AI工程化技术。
1135 4
|
2月前
|
人工智能 安全 Java
给“氛围编程”系上安全带:阿里集团 AI 代码评审实践与 Benchmark 开源
阿里集团历时一年半、经数万亿Token真实场景打磨,推出AI代码评审助手,实现人机协作新范式:AI接管基础评审,人类聚焦核心风险。联合南京大学开源业界首个支持10语言、具备仓库级上下文感知的CodeReview Benchmark(AACR-Bench),由80+资深工程师多轮交叉标注,显著提升隐性缺陷检出率。
给“氛围编程”系上安全带:阿里集团 AI 代码评审实践与 Benchmark 开源
|
4月前
|
存储 人工智能 架构师
构建自己的AI编程助手:基于RAG的上下文感知实现方案
打造智能代码助手,远不止调用API。需构建专为代码设计的RAG系统:基于AST解析保障分块完整性,向量库实现语义检索,结合仓库地图提供全局结构,再通过推理链整合上下文。如此,AI才能真正理解代码,胜任重构、答疑等复杂任务,成为懂你项目的“资深工程师”。
424 7
构建自己的AI编程助手:基于RAG的上下文感知实现方案
|
4月前
|
人工智能 机器人 应用服务中间件
2026年阿里云基于Moltbot(原Clawdbot)构建钉钉AI员工:轻量应用服务器部署指南
Moltbot(原Clawdbot)是一款开源本地优先AI代理与自动化平台,核心能力是整合多渠道通信与大语言模型,创建具备持久记忆、主动执行能力的定制化AI助理。2026年阿里云通过轻量应用服务器提供一键部署方案,支持将Moltbot与钉钉深度集成,构建7×24小时在线的“钉钉AI员工”,可自动完成邮件处理、日程管理、文档生成等办公任务,降低人工成本。本文严格依据阿里云官方流程,详细拆解从Moltbot部署到钉钉集成的全步骤,确保操作可落地、信息无篡改。
837 6
|
10月前
|
存储 缓存 人工智能
好奇心之旅:Cursor代码库索引机制的学习笔记
本文介绍了Cursor等AI编程工具中codebase indexing的技术原理,包括Merkle Tree与向量数据库的应用,以及开源方案Continue的启发。作者通过探索这些工具背后的机制,提升了对AI编程和代码索引技术的理解,也为进一步学习提供了思路。
好奇心之旅:Cursor代码库索引机制的学习笔记
|
4天前
|
人工智能 测试技术 API
Claude Code + MCP:代码助手的边界,正在被重新划线
Claude Code接入MCP协议后,突破本地代码助手边界,可调用GitHub、数据库、浏览器、API等外部工具,实现跨系统任务编排。对测试开发而言,这意味着AI能深度参与需求分析、接口测试、UI脚本生成、数据库校验、回归范围判断与质量报告生成,正从“代码问答工具”升级为“工程执行系统”。
|
2月前
|
SQL 关系型数据库 数据库
告别手写SQL? Cursor智能生成实战指南与避坑技巧
本文深度解析Cursor如何通过RAG架构与代码索引实现智能SQL生成,涵盖原理、实战(Text-to-SQL/CTE/解释优化)、方言边界及六大避坑技巧(如@引用、.cursorrules配置、注释增强等),助开发者高效写出准确、安全、符合业务的SQL。
514 1
告别手写SQL?  Cursor智能生成实战指南与避坑技巧
|
3月前
|
人工智能 运维 安全
黑客松冠军配置!老金拆解8大核心思路,值得反复品味
老金深度拆解开源神库「everything-claude-code」(28.8k星):一套完整的Claude Code工作流方法论,涵盖CLI+Skills替代MCP、5阶段Agent编排、Token优化、验证循环、并行化、双实例启动、记忆钩子与复合效应八大核心,不止于记忆,更系统提效降本。

热门文章

最新文章