- Continue是一款开源、可高度定制化的AI代码助手,主要集成在VS Code和JetBrains系列IDE中,旨在通过AI技术提升开发效率和代码质量。凭借开源、灵活、安全的特点,成为GitHub Copilot的强有力替代品,尤其适合注重隐私和定制化的开发者。其多模型支持和自然语言交互能力,显著降低了编码门槛,是提升生产力的理想工具。
- 本文主要基于GitHub仓库上开源的代码,简单总结下了Continue中代码索引构建的整个流程
关键知识
索引目录
ini
> ~/.continue/index
-rw-r--r-- 1 [User] staff 16384 1 27 23:01 docs.sqlite
-rw-r--r-- 1 [User] staff 5894144 3 10 10:14 autocompleteCache.sqlite
drwxr-xr-x 74 [User] staff 2368 3 19 20:18 lancedb
-rw-r--r-- 1 [User] staff 32768 3 23 07:51 index.sqlite-shm
-rw-r--r-- 1 [User] staff 1451741184 3 24 14:02 index.sqlite
-rw-r--r-- 1 [User] staff 5393 3 24 14:54 globalContext.json
-rw-r--r-- 1 [User] staff 13332352 3 24 14:54 index.sqlite-wal
使用lancedb来保存Embedding数据
ini
> lancedb ls -lrt
total 0
drwxr-xr-x 5 [User] staff 160 1 10 11:48 Users[User]WorkSpaceCodefassfaas_studyNONEvectordb_TransformersJsEmbeddingsProviderall-MiniLM-L6-v2500.lance
drwxr-xr-x 5 [User] staff 160 1 10 14:06 Users[User]WorkSpaceCodegoCodemini-gamemastervectordb_TransformersJsEmbeddingsProviderall-MiniLM-L6-v2500.lance
...
- Continue 在没有显式配置 embeddingsProvider 的情况下会采用以下策略:
- 默认内置模型
TransformersJsEmbeddingsProvider
是默认的嵌入模型,它使用:
- 模型名称: all-MiniLM-L6-v2
- 提供商: transformers.js
- 标题: Transformers.js (Built-In)
kotlin
> ls -lrt ~/.vscode/extensions/continue.continue-1.0.2-darwin-arm64/models
total 8
drwxr-xr-x 9 [User] staff 288 3 5 12:46 all-MiniLM-L6-v2
-rw-r--r-- 1 [User] staff 119 3 5 12:46 README.md
-
支持的Embedding模型在
core/indexing/allEmbeddingsProviders.ts
中列举了 -
加载配置
core/config/load.ts
-
代码切分
core/indexing/chunk/chunk.ts
中的chunkDocumentWithoutId
中- 首先判断是否为空文件
- 检查文件扩展名是否在支持的语言列表中
- 对于代码文件使用专门的 codeChunker
- 其他文件使用 basicChunker
-
core/indexing/chunk/chunk.ts
中的shouldChunk
中定义了切分限制:1m以上的文件会跳过
graph TD
A[开始索引] --> B[文件遍历]
B --> C{文件类型判断}
C -->|代码文件| D[Tree-sitter解析]
C -->|其他文件| E[基础切分器]
D --> F[AST遍历]
F --> G{节点大小检查}
G -->|小于阈值| H[完整保留]
G -->|大于阈值| I{节点类型判断}
I -->|类定义| J[类处理器]
I -->|函数定义| K[函数处理器]
I -->|其他| L[递归处理子节点]
J --> M[保留类声明]
M --> N[折叠方法体]
K --> O[保留函数签名]
O --> P[折叠函数体]
H --> Q[创建Chunk]
N --> Q
P --> Q
L --> Q
E --> Q
Q --> R[计算Embedding]
R --> S[存储到向量数据库]
S --> T[完成索引]
- collapseChildren的实现:
graph TD
A[开始处理节点] --> B[获取目标块first_child]
B --> C[筛选需要折叠的子节点]
C --> D[逐个处理子节点]
D --> E{超过大小限制?}
E -->|是| F[移除末尾节点]
E -->|否| G[清理空行]
G --> H[返回处理后的代码]
索引构建调用过程
index/forceReIndex
调用refreshCodebaseIndex
sequenceDiagram
participant GUI as GUI/Client
participant Core as Core
participant CodebaseIndexer as CodebaseIndexer
participant SqliteDb as SqliteDb
participant Indexes as CodebaseIndexes
GUI->>Core: post("index/forceReIndex", data)
activate Core
Core->>Core: 检查配置 (config?.disableIndexing)
alt shouldClearIndexes = true
Core->>CodebaseIndexer: clearIndexes()
activate CodebaseIndexer
CodebaseIndexer->>CodebaseIndexer: 删除 SQLite 文件和 LanceDb 文件夹
deactivate CodebaseIndexer
end
Core->>Core: 获取工作区目录 (ide.getWorkspaceDirs())
Core->>Core: refreshCodebaseIndex(dirs)
Core->>CodebaseIndexer: refreshDirs(dirs, abortSignal)
activate CodebaseIndexer
CodebaseIndexer->>CodebaseIndexer: getIndexesToBuild()
CodebaseIndexer-->>Core: 生成 IndexingProgressUpdate 更新
loop 对每个目录
CodebaseIndexer->>CodebaseIndexer: 获取分支和仓库名
CodebaseIndexer->>CodebaseIndexer: 获取文件统计信息
CodebaseIndexer->>SqliteDb: 获取数据库连接
activate SqliteDb
SqliteDb-->>CodebaseIndexer: 返回数据库连接
deactivate SqliteDb
CodebaseIndexer->>CodebaseIndexer: getComputeDeleteAddRemove()
loop 对每个索引
CodebaseIndexer->>Indexes: update(tag, results, markComplete, repoName)
activate Indexes
Indexes->>SqliteDb: 执行数据库操作
Indexes-->>CodebaseIndexer: 返回进度更新
deactivate Indexes
end
end
CodebaseIndexer-->>Core: 完成索引更新
deactivate CodebaseIndexer
Core->>GUI: 发送 "indexProgress" 更新
Core->>GUI: 发送 "refreshSubmenuItems" 更新
deactivate Core
- 调用流程
diff
refreshDirs
indexFiles
getComputeDeleteAddRemove
batchRefreshIndexResults
- CodebaseIndexer中的indexFiles
sequenceDiagram
participant CI as CodebaseIndexer
participant GC as getComputeDeleteAddRemove
participant BR as batchRefreshIndexResults
participant DB as Database
CI->>GC: 传入文件列表
GC->>GC: 检查文件状态
GC-->>CI: 返回操作分类结果
CI->>BR: 传入分类结果
BR->>BR: 将文件分批
loop 每个批次
BR->>DB: 处理 compute 文件
BR->>DB: 处理 delete 文件
BR->>DB: 处理 addTag 文件
BR->>DB: 处理 removeTag 文件
DB-->>BR: 返回处理结果
BR-->>CI: 返回进度更新
end
分块
- 需要建立的索引类型,最后都是调用
update
方法,都是继承CodebaseIndex
1. ChunkCodebaseIndex(分块索引)
是最基础的索引,主要功能:
- 根据代码结构递归地将文件分块
- 为其他索引(如 LanceDB)提供基础的分块数据
- 将分块信息存储在 SQLite 数据库中
2. LanceDbIndex(向量索引)
主要功能:
- 基于 ChunkCodebaseIndex 的分块结果
- 使用嵌入模型为每个代码块计算向量表示
- 将向量数据存储在 LanceDB 向量数据库中
- 支持相似度搜索
- 每个分支在 LanceDB 中创建独立的表
sequenceDiagram
participant LDB as LanceDbIndex
participant CCI as ChunkCodebaseIndex
participant EP as EmbeddingsProvider
participant DB as Databases
LDB->>CCI: 调用 chunkDocument
CCI-->>LDB: 返回代码分块
loop 每个分块
LDB->>EP: 计算向量嵌入
EP-->>LDB: 返回向量
end
LDB->>DB: 存储元数据(SQLite)
LDB->>DB: 存储向量(LanceDB)
- 查询过程
graph TD
A[用户查询] --> B[转换为向量]
B --> C[LanceDB相似度搜索]
C --> D[获取相似文档UUID]
D --> E[SQLite查询完整元数据]
E --> F[返回结果]
3. FullTextSearchCodebaseIndex(全文搜索索引)
主要功能:
- 使用 SQLite FTS5 创建全文搜索索引
- 支持基于关键词的快速搜索
- 使用 trigram 分词器优化搜索效果
- 适合精确匹配和关键词搜索场景
4. CodeSnippetsCodebaseIndex(代码片段索引)
主要功能:
- 使用 tree-sitter 查询来识别代码中的重要结构
- 索引函数、类和其他顶层代码对象
- 保存代码片段的元数据(如标题、路径、行号等)
- 便于快速定位和检索特定代码结构
flowchart TD
A[开始] --> B[初始化 CodeSnippetsCodebaseIndex]
B --> C{执行更新操作}
C --> D[计算新代码片段]
D --> D1[解析文件]
D1 --> D2[获取AST]
D2 --> D3[匹配代码片段]
D3 --> D4[存储到SQLite]
C --> E[删除操作]
E --> E1[查找相关片段]
E1 --> E2[删除片段记录]
E2 --> E3[删除标签关联]
C --> F[添加标签]
F --> F1[解析文件内容]
F1 --> F2[提取代码片段]
F2 --> F3[更新数据库记录]
F3 --> F4[创建标签关联]
C --> G[移除标签]
G --> G1[查找相关片段]
G1 --> G2[移除标签关联]
D4 --> H[完成更新]
E3 --> H
F4 --> H
G2 --> H
H --> I[结束]
subgraph "代码片段提取"
D1
D2
D3
end
subgraph "数据库操作"
D4
E2
E3
F3
F4
G2
end
主要区别
-
用途不同:
- ChunkCodebaseIndex:基础分块,为其他索引提供支持
- LanceDbIndex:语义相似度搜索
- FullTextSearchCodebaseIndex:关键词搜索
- CodeSnippetsCodebaseIndex:结构化代码元素检索
-
存储方式不同:
- ChunkCodebaseIndex:SQLite
- LanceDbIndex:LanceDB(向量数据库)+ SQLite(元数据)
- FullTextSearchCodebaseIndex:SQLite FTS5
- CodeSnippetsCodebaseIndex:SQLite
-
搜索能力不同:
- ChunkCodebaseIndex:不直接用于搜索
- LanceDbIndex:语义相似度搜索
- FullTextSearchCodebaseIndex:文本匹配搜索
- CodeSnippetsCodebaseIndex:结构化搜索
这四种索引相互配合,共同提供了完整的代码搜索和检索能力。 下面是常用的SQLite表数据:
docs.sqlite
- 用途:存储文档相关信息
- 包含表: 中的 docs 表
autocompleteCache.sqlite
- 用途:存储代码自动完成的缓存
- 包含表: 中的 cache 表
lancedb
文件夹
- 这不是 SQLite 文件,而是 LanceDB 向量数据库的存储目录
- 用于存储代码的向量表示
index.sqlite
(包括 -shm 和 -wal 文件)
- 主索引数据库文件
- 包含表:
- tag_catalog
- global_cache
- chunks
- chunk_tags
- lance_db_cache
其中 -shm
和 -wal
文件是 SQLite 的工作文件:
index.sqlite-shm
:共享内存文件index.sqlite-wal
:预写式日志文件,用于提高数据库性能和可靠性
这些文件共同工作,支持系统的不同功能模块。主要的数据存储都集中在 index.sqlite
中,而其他专门的功能(如文档、自动完成)使用单独的数据库文件以提高性能和模块化程度。
最后的表数据都保存在index.sqlite文件中
shell
sqlite> .tables
chunk_tags fts fts_docsize lance_db_cache
chunks fts_config fts_idx tag_catalog
code_snippets fts_content fts_metadata
code_snippets_tags fts_data global_cache