Skip to content

Latest commit

 

History

History
285 lines (214 loc) · 13.9 KB

File metadata and controls

285 lines (214 loc) · 13.9 KB

本地代码库 RAG —— 目标与方案设计文档

一、项目概述

1.1 背景与动机

当前主流 AI 编程助手在面对大规模、非主流语言、自研框架的代码仓库时效果显著下降。其根本原因不是模型能力不足,而是模型缺少足够的代码库上下文

本项目参考 NVIDIA 与 EA 在大规模 C++ 代码库上的实践思路,构建一个全本地、零云端依赖的代码库索引与检索工具,以 MCP 协议对外暴露服务,使任意支持 MCP 的 AI 编程助手都能获得代码库级别的上下文理解能力。

1.2 核心价值主张

  • 让 AI 编程助手"读懂"你的代码库:通过 RAG 将代码库知识注入 LLM 上下文
  • 开箱即用:一条命令完成索引,一条命令启动服务
  • 完全本地:不依赖任何云端服务,代码不出本机
  • 仓库无关:适用于任意语言、任意框架的新代码仓库

二、目标用户与使用场景

2.1 目标用户

用户类型 典型特征
新加入大型项目的开发者 需要快速理解项目架构与约定
使用自研框架/引擎的团队 框架文档少,AI 无法从公开数据学到相关知识
对代码安全有要求的团队 代码不允许上传到第三方云端
维护遗留代码库的开发者 代码库历史悠久,隐含大量领域知识

2.2 核心使用场景

  1. 代码问答:"这个项目的网络层是怎么做错误重试的?"
  2. 代码搜索:"找到所有处理用户权限校验的代码"
  3. 上下文补全:AI 在生成代码时自动检索相关的项目代码作为参考
  4. 架构理解:"这个仓库的目录结构是什么?各模块职责是什么?"
  5. 文档检索:检索仓库中的 Markdown 文档、注释、README 等

2.3 用户体验目标

# 用户的全部操作 —— 仅此而已
code-rag init /path/to/repo    # 指向仓库,自动完成索引
code-rag serve                  # 启动 MCP 服务

之后在 Claude Code 等工具中即可自动获得代码库上下文能力,无需其他配置。


三、设计原则

原则 说明
全本地运行 索引、嵌入、检索、服务全部在本机完成,不依赖任何外部 API
零配置启动 对于绝大多数仓库,用户不需要写任何配置文件
语言无关 不绑定特定编程语言,通过 Tree-sitter 实现多语言 AST 解析
增量更新 文件变更时只重建受影响部分的索引,而非全量重建
MCP 优先 以 MCP 协议作为唯一对外接口,保证与主流 AI 工具的兼容性
轻量依赖 尽量减少外部依赖,避免用户环境配置困难

四、整体架构

┌──────────────────────────────────────────────────────┐
│                    用户的 AI Agent                     │
│          (Claude Code / Cursor / Copilot 等)          │
└───────────────────────────┬──────────────────────────┘
                            │ MCP Protocol (stdio/SSE)
                            ▼
┌──────────────────────────────────────────────────────┐
│                   MCP Server 层                       │
│                                                      │
│  对外暴露的 Tools:                                    │
│   • search_code    —— 语义/关键词搜索代码             │
│   • search_docs    —— 搜索项目文档                    │
│   • get_file_symbols —— 获取指定文件的符号映射          │
│   • get_repo_structure —— 获取仓库结构概览            │
│   • get_symbol_info —— 查询符号定义/引用              │
└───────────────────────────┬──────────────────────────┘
                            │
                ┌───────────┴───────────┐
                ▼                       ▼
┌────────────────────┐    ┌─────────────────────────┐
│    Retriever 模块   │    │      Indexer 模块        │
│                    │    │                         │
│  • 语义搜索        │     │  • 文件发现与过滤        │
│  • 关键词搜索      │     │  • Tree-sitter AST 解析  │
│  • 混合排序 (RRF)  │     │  • 语义感知分块          │
│  • 结果去重/聚合   │     │  • 本地嵌入生成          │
└─────────┬──────────┘    │  • 文件指纹/增量更新     │
          │               └────────────┬────────────┘
          │                            │
          ▼                            ▼
┌──────────────────────────────────────────────────────┐
│                  本地存储层                            │
│                                                      │
│  • 向量索引 —— Dense Vectors (语义搜索)               │
│  • 倒排索引 —— BM25 (关键词搜索)                      │
│  • 元数据存储 —— 文件路径、符号信息、分块映射           │
│  • 全部持久化到本地磁盘                                │
└──────────────────────────────────────────────────────┘

五、关键技术选型

5.1 总览

模块 选型 选择理由
对外协议 MCP (Model Context Protocol) 行业标准,Claude Code / Cursor 等原生支持
MCP 框架 FastMCP (Python) 官方推荐,API 简洁,社区活跃
AST 解析 Tree-sitter 支持 40+ 语言,增量解析,性能优异
本地嵌入模型 ONNX Runtime + bge-small / CUDA + bge-large 系列 纯本地推理,前者CPU,后者GPU
向量数据库 ChromaDB 嵌入式模式,跨平台,HNSW 索引,零运维
关键词检索 BM25 (内置实现或 rank_bm25) 补充语义搜索的精确匹配能力
开发语言 Python 生态丰富,MCP SDK 成熟,降低维护门槛

5.2 各选型详细论证

5.2.1 对外协议:MCP

为什么不做 IDE 插件或 CLI 工具?

  • IDE 插件需要为每种 IDE 单独开发,维护成本高
  • CLI 工具无法与 AI Agent 的对话流程集成
  • MCP 是一层标准协议,只需实现一次,即可被所有支持 MCP 的 AI 工具调用
  • 未来 MCP 生态只会越来越完善,选择 MCP 是面向未来的决策

5.2.2 AST 解析:Tree-sitter

为什么需要 AST 解析,而不是简单的按行/按字符分块?

  • 简单分块会把一个函数从中间截断,破坏语义完整性
  • AST 解析能以函数、类、方法、结构体为单位进行分块,保证每个代码块是一个语义完整的单元
  • Tree-sitter 的增量解析能力天然适合文件变更时的快速重建

为什么选 Tree-sitter 而非 LSP?

  • LSP 需要为每种语言配置对应的 Language Server,部署复杂
  • Tree-sitter 是纯解析器,不需要编译环境,启动即用
  • 对于索引场景,Tree-sitter 提供的信息粒度已经足够

5.2.3 向量数据库:ChromaDB

为什么不用 Milvus Lite / Faiss / SQLite-VSS?

方案 优点 缺点
Faiss 性能极好 不是数据库,无持久化/元数据管理,需自行封装
Milvus Lite 嵌入式运行、原生混合搜索 不支持 Windows,索引类型仅支持 FLAT
SQLite-VSS 极轻量 向量检索能力弱,不支持 HNSW 等高效索引
ChromaDB 嵌入式运行、跨平台(Windows/Linux/macOS)、HNSW 索引、持久化到本地目录 在超大规模数据下性能略弱于 Faiss(可接受)

ChromaDB 的关键优势:

  • pip install chromadb 即可使用,无需单独部署服务
  • 原生支持 HNSW 索引,检索质量好
  • 跨平台:Windows、Linux、macOS 均可运行
  • 数据持久化为本地目录,重启后无需重建索引
  • API 简洁,测试中无需 mock(嵌入式直接使用)

5.2.4 混合检索策略:语义搜索 + BM25 + RRF

为什么需要混合检索?

  • 纯语义搜索的问题:用户搜索具体的函数名 handleAuthCallback 时,语义搜索可能返回语义相似但名称不同的代码
  • 纯关键词搜索的问题:用户提问 "这个项目怎么处理认证回调" 时,关键词无法匹配到 handleAuthCallback
  • 混合检索通过 RRF (Reciprocal Rank Fusion) 将两路结果合并排序,兼顾精确匹配与语义理解

六、索引策略设计

6.0 过滤规则

用户可以自行设置白名单或黑名单,可以通过 --include / --exclude 选项覆盖。或使用过滤规则(.coderagfilter 文件)

6.1 分块策略

代码仓库
  ├── 代码文件 (.py, .cpp, .java, .ts, ...)
  │     → Tree-sitter 解析 → 按 AST 节点分块
  │     → 每个块 = 一个函数/类/方法 + 其文档注释
  │     → 附带元数据:文件路径、起止行号、符号名、语言
  │
  ├── 文档文件 (.md, .rst, .txt)
  │     → 按标题层级分块(# / ## / ### 为分割边界)
  │     → 附带元数据:文件路径、标题层级
  │
  └── 配置文件 (.json, .yaml, .toml, Makefile, Dockerfile, ...)
        → 整文件作为一个块(通常较小)
        → 附带元数据:文件路径、文件类型

6.1.1 分块大小大于嵌入模型输入token时:

输入: AST 节点
  │
  ├── token_count ≤ max_tokens?
  │     └── YES → ✅ 直接作为一个 chunk
  │
  ├── 有可拆分的子节点?(函数/类/方法)
  │     └── YES → 递归处理每个子节点
  │              → 给每个子 chunk 加父级上下文前缀
  │
  └── 叶子节点仍超限?
        └── 滑动窗口分割
           → overlap = 10% 的 max_tokens
           → 每个窗口加上下文前缀

6.2 增量更新策略

  • 为每个已索引文件记录 文件内容哈希(SHA-256)
  • 执行更新时,遍历仓库文件,比对哈希:
    • 哈希未变 → 跳过
    • 哈希变化 → 删除旧分块,重新解析并入库
    • 文件已删除 → 删除对应分块
  • 可监听文件系统事件(可选),实现后台自动增量更新

6.3 文件支持

代码支持Python, JavaScript, TypeScript, C++, C, Java, C#, Lua, Rust, Go.

也支持用户自定义文件类型,比如.glsl, .fx设置为C模式。


七、MCP 接口设计

7.1 对外暴露的 Tools

Tool 名称 输入参数 返回内容 典型调用场景
search_code query: str, top_k: int, language?: str 相关代码块列表(含文件路径、行号、代码内容) AI 需要查找相关实现
search_docs query: str, top_k: int 相关文档片段列表 AI 需要了解项目文档
get_file_symbols file_path: str 该文件中所有符号的索引信息 AI 正在编辑某文件,或想了解文件内容
get_repo_structure depth?: int 仓库目录树 + 各目录/文件的简要描述 AI 需要了解项目整体结构
get_symbol_info symbol_name: str 符号的定义位置、引用位置、相关代码块 AI 需要理解某个具体符号

7.2 返回格式原则

  • 每个返回结果都包含文件路径 + 行号范围,方便 AI 引用出处
  • 代码块返回时附带上下文窗口(前后各 N 行),避免信息截断
  • 搜索结果按相关性分数降序排列,附带分数供 AI 判断可信度

八、非目标(明确不做的事)

不做的事 理由
模型微调 成本高、复杂度高,与"轻量本地"定位冲突
云端部署 违反全本地原则
IDE 插件 通过 MCP 协议已能覆盖主流工具,不必为特定 IDE 开发插件
代码生成/补全 本工具只负责"检索与提供上下文",生成由 AI Agent 完成
实时编译/类型分析 过重,Tree-sitter 层级的 AST 解析已满足索引需求
多用户/团队协作 第一阶段只面向单机单用户场景

九、成功标准

维度 目标
易用性 用户从下载到服务可用,不超过 3 条命令
索引速度 10 万行代码仓库,首次索引 < 5 分钟(普通笔记本 CPU)
检索质量 对于明确的代码搜索意图,Top-5 结果中至少有 1 条命中相关代码
资源占用 服务运行时常驻内存 < 500 MB(中型仓库)
启动速度 已有索引的情况下,服务启动 < 3 秒
兼容性 至少支持 Claude Code, OpenCode 和 Cursor 三个主流 MCP 客户端

十、开箱即用

采用 uv 进行 Python 环境管理,首次运行时自动完成依赖安装,并根据硬件环境自动适配 CPU/GPU 模型及所需的运行时组件(CUDA、OMNI 等),无需手动配置。