跳转到内容

工作区索引

工作区索引让对话能引入你没有手动附加的代码。twinny 把文件切成分块,用你的嵌入提供者进行嵌入,并把向量和关键词索引存在 ~/.twinny/embeddings/ 下的数据库中。提到 @workspace 的问题会与索引匹配,最佳分块被加入提示。

从侧边栏顶部的数据库图标打开,或运行 Embedding options

设置

  1. 在提供者标签页添加一个嵌入提供者。本地可用 Ollama 上的 nomic-embed-text 作为默认选择;见支持的模型
  2. 在嵌入标签页点击索引工作区。文件嵌入时显示进度;可以取消并稍后继续。

索引完成后,标签页显示索引中的文件和分块数量,以及使用的嵌入模型。

保持最新

  • 更新通过比对文件哈希清单,只嵌入上次运行后有变化的文件。
  • 重建从头开始。更换嵌入模型或分块大小后需要重建,因为不同模型的向量和不同大小的分块不能混用。索引所用模型与当前提供者不同时,标签页会给出警告。
  • 开启 twinny.embeddingUpdateOnSave(默认开启)后,工作区索引完成后保存文件会重新嵌入,删除文件会将其移出索引。

索引哪些内容

只索引源代码、配置和文档文件,按扩展名或常见文件名(MakefileDockerfileREADME.gitignore 等)选择。识别约 150 种扩展名,覆盖 Web、系统、JVM 和 .NET、脚本和函数式语言、数据和配置格式以及文档。

不读取就跳过的:二进制文件、图片(含 SVG)、字体、压缩包、lock 文件(package-lock.jsonyarn.lockCargo.lock……)、压缩后的文件、source map、快照文件,以及工作区 .gitignore 匹配的任何内容。内容看起来像二进制的文件在预览后跳过。

twinny.embeddingIgnoredGlobs 添加自己的排除项,例如 ["**/fixtures/**", "**/*.md", "vendor/**"]

分块

有语法的文件用 tree-sitter 解析并沿语法边界切分,因此一个分块是一个函数、一个类、一个代码块或一段顶层语句,而不是任意切片。分块是源码的精确切片,所以命中可以在其所在行打开。没有语法的文件(散文、少见格式)在空行和 markdown 标题处切分。

对于输入限制小的模型(如 all-minilm 的 256 token),很长的分块会分窗口嵌入,搜索时再合并回一个分块。

在对话中使用

在消息中输入 @workspace 即针对该问题搜索索引。嵌入标签页中的每条消息都使用索引开关让每条消息都搜索,适合大型代码库和能力较强的模型;小型本地模型可能被额外上下文干扰,所以默认关闭。

后续问题会复用上一个问题及其回答所引用的文件,因此“那它在哪里被调用?”能保持在同一话题上。每条回答下方的 context 行显示检索到的内容、分数和预览,并附有在编辑器中打开该分块的链接。没有分块超过阈值时会说明,并提示可以调整什么。

存在索引时,Explain(右键)也会查找相关代码。

检索原理

问题 ──► 嵌入 ──► 向量搜索 ─┐
└─► 关键词 ──► BM25 搜索 ─┴─► 合并 ──► 重排序 ──► 扩展 ──► 提示
  1. 嵌入问题,使用与索引相同的模型。
  2. 两路搜索。 对嵌入做向量搜索,对分块文本做 BM25 关键词搜索。关键词搜索会拆分标识符,因此 getUserName 能匹配 user name,问题中的 camelCase 或 snake_case 能找到同样的代码。
  3. 合并两路候选。
  4. 重排序:一个小型交叉编码器同时读取问题和每个候选,评估其回答问题的可能性。重排序器随扩展打包,在本地工作线程中运行(ONNX);不涉及任何提供者,没有任何内容离开本机。
  5. 阈值与上限。 低于重排序阈值的分块被丢弃;保留最好的几个。
  6. 扩展。 每个命中在预算允许时扩展到所在的函数或类,并加入一次文件的 import,使命中中的名称可以解析。

结果以带文件和行范围的标注块放入提示,前面有一条简短说明,要求引用这些标签并忽略与问题无关的块。

调优

设置(嵌入标签页)默认效果
最大分块大小1000 字符分块最多切到此大小。更小匹配更精确;更大携带更多上下文
最小分块大小100 字符小于此值的分块与相邻分块合并
重叠100 字符相邻分块共享的文本,避免边界上的匹配丢失
重排序阈值0.08低于此分数的分块被排除。回答漏掉你确知存在的代码时调低;引用无关代码时调高
相关代码片段6一个问题最多加入提示的分块数

更改分块大小需要重建。阈值和片段数在下一个问题时生效。

大小与速度

索引保存在磁盘上,~/.twinny/embeddings/ 下每个工作区一个文件夹。索引速度由嵌入服务器决定;GPU 上的小模型每分钟能处理几百个文件。搜索很快:向量和关键词查找只需毫秒,重排序器在笔记本 CPU 上不到一秒就能为几十个候选打分。

隐私

分块会发送到你的嵌入提供者进行嵌入,因此使用托管嵌入提供者(OpenAI)时代码会发给该供应商。使用本地模型时没有任何内容离开本机。数据库是普通的 LanceDB 目录,随时可以删除。