代码索引(三档能力)
一句话讲清楚
代码不是文档。把代码当文档塞向量库里能用,但回答"这个函数被谁调用了?""改这一行影响哪些测试?"这种问题,向量检索完全做不到。
平台把"代码进库"拆成 三档索引能力——你愿意付出多少初始化时间,决定了之后能回答多深的问题。
索引侧 ≠ 检索侧。这一页讲的是"代码怎么进库、建什么索引"。 "建好之后怎么搜"是检索工具的事——读
unified_search和code_search。 关系:索引档位决定了检索工具能用哪些 mode——零索引只能text/astgrep,轻索引解锁semantic,重索引解锁navigate(精确跨文件导航)。
Ragbase 代码索引全栈(L1〜L6)
销售材料里包装的 「零 / 轻 / 重」三档,是产品在下面 L1〜L6 之上做的组合卖法; 研发对齐、写标书或做验收时请以这一张分层表为准——它覆盖 任何 parser,不止
code-aware。
| 层 | 索引类型 | 来源 | 触发条件 | 干什么用 |
|---|---|---|---|---|
| L1 | 文本分块 + embeddings | 任何 parser | 永远 | 语义检索 / 相似度召回 |
| L2 | BM25 全文倒排(content_ltks 等) | 任何 parser | 永远 | 关键词检索 |
| L3 | AST 分块 | tree-sitter | parser_id=code-aware 且语言在矩阵里 L3 ✓ | 按函数 / 类 / 方法切 chunk,单 chunk 是完整语义单元 |
| L4 | R8 关键词字段(function_decls / class_decls / import_decls / unresolved_refs / fqn / outline_path …) | tree-sitter AST 派生 | parser_id=code-aware 且 L3 跑通 | 「这段代码里有什么符号」——可精准 filter / facet |
| L5 | audit_findings | ast-grep YAML 规则 | parser_id=code-aware 且 ast-grep 二进制可用 | 静态分析告警(NPE / 硬编码 / 危险 API …) |
| L6 | SCIP 语义图(index.scip) | scip-java / scip-python / tree-sitter emit | parser_id=code-aware 且 parser_config.index_tier=heavy 且语言在矩阵里 L6 ✓ | 跨文件 go-to-def / find-references / impact |
怎么跟「零 / 轻 / 重」大致对齐:
- 零索引:业务上仍可上传;多数文件 L1/L2/L3 不写库——靠 LLM / grep 兜底。
- 轻索引:L1+L2 必开;
code-aware再叠 L3+L4+L5(不要求heavy)。 - 重索引:在轻索引基础上,为满足条件的语言再做 L6 SCIP 全图(最重、最慢、最准)。
三档对比一张图
| 能力档位 | 你需要做什么 | 多久能用 | 能回答的问题 | 适合谁 |
|---|---|---|---|---|
| 零索引 | 直接扔仓库就能搜 | 即时 | "这个仓库里有处理鉴权的代码吗?""哪些文件提到了某个 API?" | 临时排查、刚接手的代码、不打算长期维护的小仓库 |
| 轻索引 | 等首次同步(仓库大小决定,分钟级) | 改一个文件后秒级就能搜到 | "这个函数定义在哪?""谁调用了它?""它的所有 import 是啥?" | 日常代码评审、新人 onboarding、绝大多数业务仓库 |
| 重索引 | 提前接好编译环境(项目结构决定,10 分钟~小时级) | 全量分析完后才可用 | "改这一行影响哪些下游?""这个继承层级长什么样?""跨编译单元的所有引用" | 老旧 C/C++ 项目、安全审核、跨模块大重构 |
零索引:拿来就搜
不建索引,全靠语法层面的智能匹配 + LLM 自己读相关文件。
适合的提问:
- "这个仓库主要做什么?给我一个概览"
- "搜一下处理超时的代码片段"
- "我记得有个文件叫
payment_*.py,帮我找出来"
不适合的:
- "这个函数被谁调用了"——零索引看不到调用关系,只能告诉你字面包含了这个名字的地方
- 跨语言调用、跨文件继承推理
务实的建议:如果你只是想让 AI 帮你"看一眼这个仓库",零索引就够了。它最大的优点是没有等待。
轻索引:日常用的主力
平台用本地工具(基于 tree-sitter 一类的语法分析)建轻量索引,对每种语言抽出函数、类、变量、import 的位置,存进搜索引擎。
关键升级(M4 / R8 之后):
- 改一个文件,新内容秒级可搜——以前要等几分钟,现在不用了
- 老的"批量等待 / 批量重建"机制取消了,写完代码立刻就能问
适合的提问:
- "
processOrder这个函数定义在哪、谁调用了它" - "这个类继承自哪?子类有哪些"
- "整个项目里有几个地方在用
redis.Pipeline"
不适合的:
- 需要类型推导才能解的问题(比如 C++ 模板实例化、Python 鸭子类型的真实运行时类型)
- 跨编译单元、跨链接边界的引用
重索引:审计 / 重构 / 老 C/C++ 项目
把项目真的"半编译"一遍,建立类型完整的代码图谱。这一档最贵也最准。
适合的场景:
- 老 C/C++ 项目:宏、模板、include 关系复杂,没有类型信息根本审不动
- 安全审计:跟踪用户输入流到敏感函数的完整路径(污点分析)
- 跨模块重构:改一个核心接口,必须先看清所有下游
- 代码合规审核:MISRA / ASPICE 等标准要求"完整调用链可追溯"
前置条件:
- 你的项目能在我们的环境里编过去(CMake / Bazel / Maven 等其中一种)
- 接受一次性 10 分钟到小时级的初始化时间
例子:在汽车 ECU 代码上,能回答"我改了 can_send_frame 这个函数,最终影响哪几条 CAN 总线、对应哪几个 ASIL 等级的需求条目"——这种问题轻索引和零索引都给不了答案。
怎么选?决策三问
-
你需要"调用关系"吗?
- 不需要 → 零索引
- 需要 → 至少轻索引
-
你的代码会持续改、需要 AI 跟得上吗?
- 是 → 轻索引(增量秒级)
- 否,就一次性看 → 零索引
-
你的项目是 C/C++ 老代码,或要做安全 / 合规审核吗?
- 是 → 重索引
- 否 → 轻索引一般够用
一个知识库放几个仓库?单 repo vs 多 repo
平台默认支持 multi-repo——一个知识库(KB)可以同时装多个代码仓库,靠顶层文件夹区分:
平台按顶层目录名自动认作 repo_kwd,每个 repo 各自维护:
- 自己的符号索引(
symbol_index_<repo>) - 自己的 repo 大纲(
repo_map_<repo>) - 自己的 audit / 引用关系
多 repo 模式给你什么
| 能力 | 说明 |
|---|---|
| 单 repo 真增量 | 改 / 加 / 删 repo-A 的某个文件,只动那一个文件的索引,repo-B / repo-C 完全不动 |
| 跨 repo 引用反查 | repo-B 里 import com.foo.UserService、repo-A 提供这个类——一次检索就能跨 repo 命中 |
| per-repo 重建 | 单独重建某个 repo 的重索引(SCIP),不影响其他 repo 的服务可用性 |
| 同名歧义自动消解 | 两个 repo 里都有 UserService?检索结果会按 repo_kwd 标注归属,不会混 |
单 repo 怎么用?
完全等价——KB 里就放一个顶层目录:
或者直接把代码摊在 KB 根目录(平台会用一个默认 repo_kwd)。单 repo 是 multi-repo 的退化,不需要额外配置。
文件夹组织建议
| 场景 | 推荐组织 |
|---|---|
| 单一代码仓 | kb/<repo-name>/... 或直接 kb/... |
| 多个微服务 / 多个组件库 | 每个 repo 一个顶层目录 |
| Monorepo(一个 git 仓但多个子项目) | 把 monorepo 当一个 repo(一个顶层目录),子项目靠 outline_path 自动区分 |
| 同一项目多个分支 / 版本对比 | 每个分支一个顶层目录(repo-A-main / repo-A-release-2026Q2) |
不要把多个 repo 拍平到 KB 根目录混一起——那样平台没法做 per-repo 隔离,跨 repo 引用反查也会失准。
支持的代码类型
本节第二张表就是你要找的 「语言 ×(L3–L6)矩阵」。
底座 L1〜L6 对每个 parser(含文档)都一样;本节只展开code-aware+ 内置语言包。
以下专指 parser_id = code-aware——普通 PDF / Markdown 走别的 parser(只有 L1/L2 或字符级兜底,见矩阵末行)。
控制台上在哪儿改解析方法 / 索引档位?
不走 API 时:Combospace → 知识库 → 点进任一知识库 → 左侧 配置 Tab。
字段对应关系一览(界面文案随语言略有差异,中文版如下):

插图说明:控制台 UI 会因版本迭代微调;上图由仓库内脚本自动截取。更新命令:
Hikari/scripts/capture-kb-configuration-screenshot.py(直达/combospace/combospace/knowledge/dataset/configuration;冷启动慢时可加大DOC_CAPTURE_NAV_TIMEOUT_MS、DOC_CAPTURE_SELECTOR_TIMEOUT_MS、DOC_CAPTURE_SETTLE_MS)。若本地路径前缀不同,设KB_CAPTURE_PATH_PREFIX。
下面是 每个语言分别在 L3 / L4 / L5 / L6 开到哪一档——与上文 L1〜L6 表逐项对应。
平台对每种语言能开到的能力分四层(表中列名缩写),先看图例再看矩阵:
| 层 | 干什么 | 哪一档用到 |
|---|---|---|
| L3 AST 分块 | 按 tree-sitter 语法树切片,得到带 outline_path 的 chunk | 轻索引、重索引 |
| L4 R8 字段 | 抽出 function_decls / class_decls / import_decls / references / unresolved_refs / fqn / outline_path … | 轻索引(定义 / 调用 / facet) |
| L5 audit (ast-grep) | 静态扫描规则命中(unified_search code_search mode=audit) | 轻索引 + 重索引 |
| L6 SCIP | 编译器级 indexer,得到跨编译单元的精确类型图 | 重索引 |
语言 × 索引层 矩阵
| 语言 | 后缀 | L3 AST 分块 | L4 R8 字段 | L5 audit (ast-grep) | L6 SCIP |
|---|---|---|---|---|---|
| Python | .py .pyi | ✓ | ✓ | ✓ | ✓ scip-python,无需 build 文件 |
| Java | .java | ✓ | ✓ | ✓ | ✓ scip-java,必须 pom.xml / build.gradle* |
| Kotlin | .kt .kts | ✓ | ✓ | ✓ | ✓ 两条路:① 有 build → scip-java;② loose → tree-sitter emit(无需 build) |
| Scala | .scala | ✗(无 tree-sitter 配置) | ✗ | ✓ | ✓ scip-java,必须 build 文件 |
| Go | .go | ✓ | ✓ | ✓ | ✗ 未集成 indexer |
| TypeScript / TSX | .ts .tsx | ✓ | ✓ | ✓ | ✗ 未集成 |
| JavaScript / JSX | .js .jsx .mjs .cjs | ✓ | ✓ | ✓ | ✗ 未集成 |
| C / C++ | .c .cpp .cc .cxx .h .hpp | ✓ | ✓ | ✓ | ⚠ aarch64-linux 无 scip-clang 二进制 → cpp_stub fail-soft |
| Rust | .rs | ✓ | ✓ | ✓ | ✗ 未集成 |
| Ruby / PHP / Swift / Dart / Lua / C# / Elixir | … | ✗ | ✗ | ✓(ast-grep 支持) | ✗ |
其他文本(.md / .txt / Dockerfile / Makefile …) | — | 字符级回退 | ✗ | ✗ | ✗ |
读这张表的三条规则:
- L3 ✓ 的 9 种语言(Python / Java / Kotlin / Go / TS / JS / C·C++ / Rust)——上传后自动走轻索引档(带符号字段),开箱可用。
- L5 audit ✓ 的语言比 L3 多——Scala / Ruby / PHP / Swift / Dart / Lua / C# / Elixir 即使没有 L3 切片,也能用
unified_search code_search mode=audit跑 ast-grep 静态规则。 - L6 SCIP(重索引)只对 Python / Java / Kotlin / Scala / C·C++ 开通——其它 L3 语言(Go / TS / JS / Rust)走 L4 R8 字段反查也能拿到 ~90% 的实用能力,需要补 indexer 联系
info@nox-lumen.com评估。
⚠ C/C++ 当前限制:生产宿主机为 aarch64-linux,没有上游
scip-clang预编译二进制,L6 走cpp_stubfail-soft(仍能基于 L3/L4 给出符号视图,但跨编译单元导航降级)。x86_64 部署不受影响。
不在列表里的语言怎么办
需要其他语言(PHP / Ruby / Swift / Scala / C# / Dart / Lua / Solidity / DSL ...)走轻索引档?自己用 parser-sdk 加一个——
不需要等平台升级,半天到一天就能补上:
- 确认 tree-sitter-language-pack 已包含目标语言的 grammar(覆盖 ~80 种)
- fork 内置
code-aware-parser,在language_configs/里加一个LanguageConfig: - 在
queries/ruby/放对应 tree-sitter query ragbase-cli skill push上线
详细步骤见 parser-sdk · 自定义代码切片器,里头有完整可下载的参考实现。
落地后会自动接入零/轻/重三档检索,跟内置语言完全等价(L3 / L4 都有;L5 audit 自动可用;L6 SCIP 是否覆盖见上文矩阵)。
跨行业举例
汽车研发(auto)
- 轻索引:日常的 ECU 业务代码评审、新人 onboarding
- 重索引:ASPICE 合规审核 / SOTIF 安全分析 / 跨 ECU 接口重构
智能制造(mfg)
- 轻索引:MES / SCADA 业务代码评审
- 零索引:临时接入一个第三方 PLC 厂商的示例代码仓库,看一眼就行,没必要专门建索引
索引档位 vs 检索 mode 对照表
平台对外的两个检索工具(unified_search 和 code_search)能做什么,取决于这个 KB 建的是哪一档索引:
| 检索工具 + mode | 零索引 | 轻索引 | 重索引 |
|---|---|---|---|
code_search(scope="kb", mode="text") rg grep | ✅ | ✅ | ✅ |
code_search(scope="kb", mode="ast") 结构匹配 | ✅ | ✅ | ✅ |
unified_search.code_search(mode="text") | ✅ | ✅ | ✅(trigram 加速) |
unified_search.code_search(mode="ast") | ✅ | ✅ | ✅ |
unified_search.code_search(mode="semantic") 自然语言 | ❌ | ✅ | ✅ |
unified_search.code_search(mode="navigate") 精确跨文件 | ❌ | ⚠️ ES 字段反查(够用) | ✅(SCIP 精确) |
unified_search.code_search(mode="hybrid") text+semantic 融合 | ❌ | ✅ | ✅ |
怎么读这张表:
- 你要用某个
mode,先看你 KB 在哪一档;档位不够就升档(KB 设置里改一个开关) - 升档可以事后做,原数据保留——加一档索引不会丢东西
- 想拿
mode="navigate"的编译器级精确语义图:必须重索引,且语言在下方矩阵里 L6 ✓(见上文 语言矩阵)。
这一档跟"代码评审 SKILL"的关系
代码索引是底层能力,代码评审 SKILL 是上层应用——它会自动按 KB 已开档位选用合适的检索 mode,给你出审核结论。
- 提交评审(PR/MR/CR 三个场景):轻索引就够
- 全分支审 / 全仓审:跑重索引,结果会更深
- 临时看一个无主仓库:零索引,立等可取
相关概念
- Parser SKILL 体系 — 决定了代码进入索引时怎么切块(索引侧入口质量)
unified_search工具 — 检索侧统一入口code_search工具 — 轻量级 grep 入口- 代码评审 SKILL — 直接消费这套索引/检索能力