Skip to content

indexing相关面试题 ​

题目1 ​

RAG 的 indexing 阶段一般包含哪些步骤?每一步分别解决什么问题?

参考答案:

RAG 的 indexing 阶段,本质上就是把原始文档加工成后续可检索的索引数据。一般我会把它分成 6 步:

  1. 加载文档:先把数据拿进来,比如本地文件、数据库、CMS 或 PDF 解析结果,解决“数据从哪里来”的问题。
  2. 文档预处理:做清洗、去重、格式标准化,解决“原始数据能不能直接用”的问题。
  3. 文档切块:把长文档切成合适粒度的 chunk,解决“知识以什么单位进入向量库”的问题。
  4. 元数据补充:给 chunk 加上标题、来源、标签、权限这类 metadata,方便后续过滤、追踪和展示。
  5. 向量化:用 embedding 模型把 chunk 转成向量,解决“文本怎么变成可检索的语义表示”的问题。
  6. 写入索引存储:最后把向量和 metadata 写进向量库,供后续 retrieval 阶段使用。

也就是说:indexing 的核心,就是把原始文档变成结构清晰、语义可检索、可被后续检索流程直接消费的索引数据。

题目2 ​

chunking 为什么会直接影响 RAG 的最终效果?常见的 chunking 策略有哪些?

参考答案

chunking 会直接影响 RAG 效果,核心原因是:RAG 检索回来的不是整篇文档,而是一个个 chunk。 所以 chunk 怎么切,基本就决定了模型后面能拿到什么样的上下文。

  • 如果切得太大,相关信息可能被淹没,检索不够聚焦;
  • 如果切得太小,上下文又容易残缺;
  • 如果切得不符合语义边界,比如一句话被硬拆开,那模型拿到的内容就会不自然。

所以本质上,chunking 影响的是两件事:

  1. 检索粒度
  2. 上下文质量

常见的 chunking 策略有几种:

  1. 固定长度切分:最简单,适合快速落地,但容易破坏语义。
  2. 带 overlap 的固定长度切分:在固定长度基础上增加重叠,缓解信息被截断的问题。
  3. Recursive Chunking:先按标题、段落这些大结构切,不够再继续细分,比较适合结构化文档。
  4. Semantic Chunking:按语义边界切,更强调 chunk 的语义完整性,通常效果更好,但实现也更复杂。

因此,chunking 决定了知识进入向量库时的最小检索单位,所以它会直接影响召回质量和最终回答质量。

题目3 ​

为什么固定长度切分往往不够?Semantic Chunking 和 Recursive Chunking 分别适合什么场景?

参考答案

固定长度切分往往不够,核心原因是它只看长度,不看语义。它不会关心一句话是不是被切到一半,也不会关心一段内容是不是属于同一个完整主题。所以它虽然简单,但很容易带来两个问题:

  1. chunk 语义不完整
  2. 检索回来的上下文不自然

尤其是技术文档、FAQ、教程这类本身有明显结构的内容,如果一律按固定长度切,其实会浪费掉原本的结构信息。

  • Semantic Chunking 更强调按语义边界来切,也就是希望每个 chunk 本身就是一个相对完整的语义单元。它更适合对上下文完整性要求高的场景,比如知识文章、FAQ、概念说明这类内容。
  • Recursive Chunking 更像一种工程上比较常用的折中方案。它会先按标题、段落这些大结构切,如果还太长,再继续往下细分。它比较适合 Markdown、制度文档、技术文档这类结构比较规整的内容。

如果一句话总结就是:固定长度切分适合做基础方案,Recursive Chunking 更适合大多数工程场景,Semantic Chunking 更适合追求语义完整性和检索质量的场景。

题目4 ​

在构建索引时,metadata 为什么重要?通常会抽取哪些 metadata,它们在后续检索阶段有什么作用?

参考答案

我觉得 metadata 在 RAG 里很重要,核心原因是:向量只能表达语义相似性,但很多检索决策不能只靠语义。

比如系统还需要知道:

  • 这段内容来自哪里
  • 它是不是最新版本
  • 当前用户有没有权限看
  • 它属于哪个知识库、哪个分类
  • 检索回来之后怎么展示

这些都要靠 metadata。所以可以把 metadata 理解成:给 chunk 补充结构化上下文。

它在后续检索阶段主要有三个作用:

  1. 做过滤:比如按知识库、语言、权限、时间范围筛选内容。
  2. 做展示和解释:比如告诉用户这段内容来自哪篇文档、哪个章节、标题是什么。
  3. 做排序和治理:比如官方文档优先、最新文档优先、某些来源降权。

通常会抽取的 metadata,大致有几类:

  • 来源信息:文档 id、source 路径、URL、知识库
  • 结构信息:标题、章节名、chunkIndex、sourceDocumentId
  • 业务信息:标签、分类、部门、权限级别
  • 时效信息:创建时间、更新时间、版本号

总结一下就是:metadata 让 chunk 不只是“一段文本”,而是一个带来源、结构和业务上下文的知识单元。 真实项目里,过滤、权限、展示、排序这些能力,基本都离不开它。

题目5 ​

如果知识库内容会持续变化,indexing 阶段应该如何处理去重、清洗和增量更新问题?

参考答案

如果知识库内容会持续变化,那 indexing 就不能只看成一次性建库,而要看成一个持续维护的过程。这里通常要同时处理三件事:去重、清洗、增量更新。

  1. 去重解决的是不要把重复知识反复写进向量库,一般要考虑两个层面:
  • 文档级去重:比如按文档 id、来源路径、内容 hash 去重

  • chunk 级去重:比如过滤重复页眉页脚、模板内容、重复 chunk

  1. 清洗解决的是不要把脏数据和噪音写进去,常见做法就是在 chunking 前先清洗原始文档,比如去掉空白、乱码、模板文本、OCR 噪音;chunking 后也可以再做一次轻量过滤,比如去掉空 chunk。

  2. 增量更新解决的是不要每次都全量重建索引。一般会根据更新时间、版本号、内容 hash 之类的信息判断哪些文档变了,然后分三种情况处理:

  • 新增文档:直接新建索引

  • 修改文档:重新切 chunk、重新 embedding,并覆盖旧索引

  • 删除文档:把对应向量一起删掉

如果从工程上看,我会特别关注三点:

  1. 文档 id 要稳定
  2. chunk id 最好有稳定规则
  3. store 最好不仅支持 upsert,也支持 delete

一句话总结就是:当知识库持续变化时,indexing 本质上就不只是建索引,而是“数据治理 + 索引生命周期管理”。

题目6 ​

如果让你设计一个 RAG SDK 的 indexing 模块,你会如何拆分核心组件?为什么这样拆?

参考答案

如果让我设计一个 RAG SDK 的 indexing 模块,我会把它拆成几层:

  1. Loader
  2. Transformer
  3. Chunker
  4. metadataBuilder
  5. Embedder
  6. VectorStore

最后再有一个 runIndexing 负责主流程编排。

这样拆的原因很简单,因为 indexing 本质上是一条数据流水线:

  1. 先把文档加载进来
  2. 做预处理
  3. 再切 chunk
  4. 补 metadata
  5. 做 embedding
  6. 最后写入向量存储

这里面每一层职责都不一样,而且都很容易变化。比如数据源会变、chunking 策略会变、embedding 模型会变、向量库也会变。所以如果不拆开,所有逻辑就会耦合在一起,后面很难扩展和替换。

我会把核心包只保留抽象和流程,把 LangChain、OpenAI、Pinecone 这类第三方能力放到 adapters 层。这样核心流程能保持稳定,外部能力也能灵活接入。

总结一下该设计,就是把 indexing 设计成“可插拔组件 + 主流程编排”的结构,因为它本质上不是一个函数,而是一条可扩展的数据处理链路。


-EOF-