跳到主要内容

你的 RAG 分块器是一项无人 Review 代码的数据库 Schema

· 阅读需 13 分钟
Tian Pan
Software Engineer

当检索质量回退(retrieval quality regression)第一次出现在你的值班频道(on-call channel)时,调试路径几乎总是指向一些令人意外的地方。不是嵌入模型(embedding model),不是重排序器(reranker),也不是提示词(prompt)。罪魁祸首通常是对分块器(chunker)的一行改动——比如更换了分词器、调整了边界规则或步幅(stride)——而这行代码是三个冲刺(sprint)前有人合并进预处理 notebook 的。这次修复没有触及任何生产代码。它在夜间重建了索引。而现在,所有租户的准确率都下降了四个百分点。

分块器就是数据库 Schema。你提取的每个字段、划定的每个边界、选择的每个步幅,都定义了存入向量索引的“行”的形状。修改其中任何一项,你就在改变索引的 Schema。而你系统的其他部分——检索逻辑、重排序特征、评估框架、下游提示词——都依赖于这个索引,并假设它是稳定的。但由于分块器通常存在于 notebook 或一个没人将其视为“基础设施”的小型 Python 模块中,这些改动在上线时往往只被当作配置微调,但其爆炸半径却相当于执行了一次 ALTER TABLE

这篇文章的核心观点就是严肃对待这一构想。如果分块器是 Schema,那么每一次分块逻辑的改动都是一次迁移。每一次重新嵌入都是一次索引重建。每一条边界规则都是一份契约。如果一个组织通过 notebook 的 PR 来发布分块改动,却通过另一个独立的团队进行检索评估,那么这就是治理上的缺口,而不仅仅是工作流的偏好。将分块视为简单的预处理,是导致优秀团队在悄无声息中丢失一个月检索质量,却始终无法追溯到具体提交(commit)的原因。

分块决策即 Schema 决策

梳理一下分块流水线实际确定的参数,你会发现 Schema 这一构想不仅巧妙,而且理所当然。

分块大小(Chunk size)决定了行宽。重叠(Overlap)决定了跨行存在多少冗余数据。边界规则——段落、句子、Markdown 标题、语义断句、固定 Token 数——决定了每行内容的形状。步幅(Stride)决定了行在源数据中是密集还是稀疏。元数据字段(章节标题、页码、文档 ID、时间戳、作者、敏感度)定义了过滤器和重排序器依赖的索引列。预处理转换(空格归一化、表格展平、脚注剥离)则定义了下游看到的所有内容的规范文本。

这些都不是表面文章。Chroma 在 2026 年的分块评估显示,超过 20% 的重叠会导致精确率急剧下降,而召回率几乎没有提升;Vectara 的基准测试发现,递归 512-token 切分能达到 69% 的准确率,而盲目应用语义分块(semantic chunking)则下降到 54%,因为它产生了 43-token 的碎片,太短了以至于生成器无法进行逻辑推理。分块器不仅决定了什么被索引;它还决定了检索可能恢复什么,以及模型有多少“思考空间”。一个 43-token 的片段并不是同一 Schema 下更小的分块。它是一个完全不同的 Schema。

Schema 构想还解释了最令人沮丧的 RAG 事故类型:分块器改动上线后,离线评估的检索召回率看起来没问题,但用户报告的准确率却一落千丈。检索出来的分块很干净。但这些分块无法回答任何问题。这是因为在下游消费者(生成器)的底层,Schema 发生了变化,而该生成器是针对不同的行宽进行过调优的。

每一次分块器的改动都是一次迁移

一旦你接受了分块器定义 Schema 的观点,操作上的含义就会变得异常清晰。

你无法在不重新嵌入整个语料库的情况下更改分块器。旧的向量是由旧的分块生成的;新的分块需要新的向量;边界的改变意味着旧行和新行不是一一对应的,因此你无法通过 ID 进行 diff。你需要完整的重建、双索引窗口、针对预留查询(held-out queries)的质量审计以及切换计划。生产环境中的主流模式——由 Google Cloud、Langchain 和几乎每家向量数据库供应商所记录——是蓝绿索引(blue/green indexing):在旧索引的阴影下建立新索引,在摄取期间进行双写,针对两者运行查询并对比,然后将一定比例的流量引导至新索引,随着信心增强逐步提升比例。

这不是可选的严谨性。这是判断新分块器是变好了、变坏了,还是其形状改变大到足以让“平均水平的提升”掩盖了“在排名前五的查询类型中出现灾难性退化”的唯一方法。夜间静默的重新嵌入无法提供任何这类信号。你在三天后客户投诉时才发现回退,而那时你为了节省存储空间已经删除了旧索引。

成本和时机也很重要。重新嵌入一个包含数百万文档的语料库并非免费——计算资源、阴影索引的存储、对比期间的双重查询成本,以及审计结果的人力成本。将分块改动视为预处理的团队往往会低估这些成本,这导致了最糟糕的失败模式:一个只部署了一半的分块迁移,让旧索引和新索引以一种意想不到的方式并存,并在某人意识到关于同一政策的两份文档会根据分片返回不同的分块之前,检索质量可能已经损坏了数周。

观测性缺口:分块 Bug 在三步之外显现

将分块器(chunker)视为模式(schema)最难的部分在于,分块器 Bug 很少以分块器 Bug 的形式呈现。

考虑一个常见的故障模式:分块边界恰好落在通用规则及其例外情况之间。“退款在七个工作日内处理。”位于一个分块中。“企业账户的退款需要 CFO 批准,可能需要长达三十天。”位于下一个分块中。针对“企业退款需要多久”的查询,检索到了第一个分块,生成器自信地回答“七个工作日”,客户得到了错误的答案。这会出现在哪里?在 LLM 评估中。追踪记录会显示:检索召回率(retrieval recall)看起来没问题,生成效果看起来没问题,但与地面真值(ground truth)不匹配——可能需要更好的提示词工程(prompting)。

不。它需要让例外情况与规则存在于同一个分块中。这个 Bug 是分块器 Bug,但信号却是生成质量信号,距离原因有三层间接关系。这就是观测性缺口,它使得分块在操作上变得非常困难。你检测了检索召回率、回答忠实度(answer faithfulness)、引用正确性和延迟——而当边界规则产生语义断裂的行时,这些指标都不会报警。即使是投资于 RAG 观测栈(如 Langfuse、DeepEval、Braintrust 风格的追踪)的团队,也很少有“分块边界完整性”指标。

实际的解决办法是添加你的 RAG 管道目前尚未意识到其需要的分块器级测试:

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates