切片决定检索上限
检索调优的人很多,切片调优的人很少。但切片的边界一旦画错,后面所有环节都是在错误的基础上做优化——重排再准,也排不出一条从中间被切断的答案。
这篇讲两件事:解析该交出去还是自己写,以及切片到底该怎么切。前者决定"有没有东西可检索",后者决定"能不能检索到"。
1. 解析:这一步丢的东西找不回来
解析是把 PDF、Word、HTML、扫描件变成带结构文本的过程。它的问题在于损失不可逆:解析完发现表格变成了一行乱码,只能回去改解析器重跑,没有任何补救办法。
1.1 表格是第一个崩的
一个三列的价格表,被通用解析器压成"型号A 价格100 库存5 型号B 价格200…"这种文本流之后,会发生一件很坑的事:向量检索能找到它(语义上确实相关),但模型读不出哪一列是价格。
结果就是:检索指标看着正常,答案一直错。这类 case 在排查时特别费时间,因为从指标上看不出问题。
正确做法是让表格走独立通道,输出结构化结果(CSV / HTML / Markdown 表格),不要进通用切片器。
1.2 版式、阅读顺序与页眉页脚
双栏论文是最典型的坑:左栏读完接右栏,如果按 PDF 里的物理顺序抽取,读出来是"左1 右1 左2 右2"这种交叉文本。人看还好,模型看就是一堆断裂的句子。
另外三类噪声要单独清掉:页眉页脚、页码、以及每页重复的版权声明。它们在向量空间里彼此高度相似,会形成一批"永远能被召回但毫无用处"的切片,白白占用上下文预算。
1.3 自己写还是用现成的
不要自己写。版式分析、阅读顺序还原、表格重建这三件事,各有专门模型在做,自研的收益远低于成本。
主流的开源选择(2026 年):
| 项目 | 许可 | 特点 | 注意 |
|---|---|---|---|
| Docling(IBM) | MIT | 版式与阅读顺序还原、表格重建,原生对接 LangChain / LlamaIndex | 扫描件 OCR 弱于专用方案 |
| MinerU(上海 AI Lab) | 自定义(基于 Apache-2.0) | 中文与科技文档强,公式、跨页表格处理完整 | 许可带规模与署名门槛,商用前看清条款;双引擎,算力消耗偏高 |
| MarkItDown(微软) | MIT | Office 文档转换轻量好用 | PDF 复杂版式能力弱 |
| Unstructured | Apache-2.0 | 长尾格式覆盖广 | 复杂版式保真度一般 |
许可这项要单独看,而且要拆成"代码"和"权重"两层看。 Marker 是个典型:它的代码是 Apache-2.0,商用没有问题;真正受限的是随仓库下发的模型权重——用的是修改版 OpenRAIL-M 系列条款,营收或融资超过 500 万美元的团队需要单独商业授权。另一个常被一起点名的 Dolphin(字节)仓库用的是 Qwen Research License,仅限非商业用途。这两个"开源"项目在商业产品里直接用的风险都在权重侧,不在代码侧——法务要审的是权重卡,不是仓库根目录那个 LICENSE。
生产环境更稳的做法是按文件类型路由 + 质量回退:Office 走轻量通道,复杂 PDF 走重量通道,解析结果做质量检测(文本长度是否异常、表格数量是否符合预期、跨页表格的表头是否被拼错、连续行列数是否对齐),失败就降级重来。
扫描件和图片走的是另一条路——OCR 加版面分析。通用解析器自带的 OCR 只适合清晰、规整的扫描件;遇到倾斜、盖章、手写批注或者低分辨率,要换专用 OCR(PaddleOCR 是这类场景里最常见的开源选择)。而且图片里的信息大部分进不了文本流,只能以引用形式存在,这部分见《多模态内容怎么入库》。
2. 切片:三种切法
切片的目标只有一个:让每一个可能成为答案的语义单元,都完整地落在某个切片里。所有切法都是围绕这一点做的权衡。
2.1 固定窗口
按固定长度切,通常带一点重叠。
好处是实现简单、切片大小均匀、长度可控;坏处是切点完全不看内容,很容易从句子中间、甚至从一个词中间断开。
它适合的是内容本身结构不强的场景(聊天记录、日志、 transcripts),或者是快速验证链路是否跑通的第一版。
2.2 语义块
按段落、小节、标题层级切。块长不齐,但边界落在语义结束的地方。
这是文档类语料的默认选择。切完之后每条切片是"完整的一段话",模型读到的是能独立成立的内容,而不是半句话。
代价是要处理极端情况:一个特别长的段落会超出长度上限,需要再按句子二次切;一个特别短的段落(比如只有一句标题)信息量太少,需要和上一段合并。
2.3 父子块
小块用于检索,命中之后回传它所属的父块给模型。
这个结构解决的是一个具体矛盾:小块检索准,但信息不完整;大块信息完整,但检索不准。小块负责"找到",父块负责"读懂"。
2.3.1 什么时候值得用
不是所有场景都需要。判断标准是:切片是否需要上下文才成立。
产品手册里"按这个按钮三秒"这句话,脱离了"哪个产品的哪个界面"就没法理解——这种语料上父子块收益明显。反之,FAQ 类语料每条自成一问一答,用父子块只是平白增加一层复杂度。
2.4 句子窗口检索(small-to-big)
还有一种解决同一个矛盾的办法:以单个句子作为检索单元,命中之后不回传固定的父块,而是回传"这个句子前后各 k 句"组成的窗口。
它和父子块针对的是同一个问题(检索单元要小、生成单元要大),但组织方式不同:
| 父子块 | 句子窗口 | |
|---|---|---|
| 结构 | 固定两级:子块 + 父块 | 单层,句子既是检索单元也是索引单元 |
| 命中后回传 | 该子块所属的整个父块 | 命中句 ± k 句的滑动窗口 |
| 窗口位置 | 由父块边界决定,可能离命中处很远 | 始终以命中句为中心 |
| 是否重叠 | 父子之间不重叠 | 相邻句子的窗口天然大量重叠 |
| 索引规模 | 子块数量 + 父块数量 | 句子数量,通常最大 |
| 适合 | 有稳定章节层级的文档 | 答案散落在单句、上下文需求量不固定的语料 |
选哪个看语料结构:文档有稳定的章节层级时,父子块更省事,回传的父块本身就是一段能独立成立的内容;答案是"一句话一个事实"、且用户问法差异很大时,句子窗口的"以命中句为中心"更贴合——它不会因为父块边界划得不好而把命中句挤到一大段无关内容里。
k 同样是经验值(常见 1 到 3),用自己的问题集试:太小则上下文不完整,太大就退回到"大块检索"的老问题——信号被稀释、上下文预算被吃掉。
2.5 语义切分与 late chunking
还有两种更"自动"的切法,值得知道,但不要当默认。
语义切分按相邻句子的 embedding 相似度找变化点,在语义转折处下刀。好处是切点确实落在话题切换的地方;代价是切片之前要先对全文做一次 embedding 计算,比"切完再嵌"更贵,而且相似度阈值同样要调。
late chunking 反过来:先用一个长窗口(比如 8192 token)过 embedding 模型,拿到带全文视角的 token 级表示,再按句子切分,每个切片取它覆盖范围内 token 表示的平均。它解决的是"切碎了再嵌,每一片都丢了全文视角"的问题——切片边界不再造成语义缺损。但它的前提是 embedding 模型能按 token 粒度取用(多数 API 只返回整段向量,这条路只对自部署模型成立),且计算量随窗口线性增长。
两者的共同问题是切点不可读:出问题时,你没法像看固定窗口那样一眼说出"这条为什么从这儿断"。所以文档类语料的默认选择仍然是 2.2 的按结构切,这两种留给特定场景。
3. 尺寸和重叠:没有统一推荐值
网上能查到各种推荐值,但它们差异很大,原因是语料和评测集不同,没有哪个数字可以照抄。
能确定的是这三条:
切片太小 —— 信息不完整。 一句话被切出来,模型不知道主语是谁。
切片太大 —— 噪声淹没信号。 5000 字的切片里有一句是答案,向量是整个切片的平均,这一句的信号被稀释掉了;而且它进了上下文会占掉大量预算。
重叠的作用是兜住边界。 相邻切片之间留一段重复内容,让跨边界的信息至少在其中一个切片里完整。至于留多少,不同来源的建议从 0 到 100 token 都有,包括认为重叠没有可测量收益的研究结论——在自己语料上试,别直接抄。
比较稳的起步区间是 300–600 token、重叠 10%–20%,然后用真实问题集去验证,只相信自己的数据。
4. 三个常被忽略的细节
元数据要跟着切片一起存。 每条切片都应该带上:来源文档、章节标题、版本号、更新时间、语种、权限标签。没有元数据的切片,后面既没法过滤(权限、语种、版本),也没法做引用展示(不知道来自哪一节)。
切片和重灌要能追溯。 换 embedding 模型、改切片策略,都要全量重灌。重灌期间索引处于混合状态(一半旧向量一半新向量),检索结果会莫名其妙。要么建新索引再切换,要么接受这段时间的结果不可信。
切片编号要稳定。 用 hash(文档路径 + 章节标题路径 + 切片规范化文本) 生成稳定 ID,不要用数组下标,也不要用序号——序号同样会在文档开头插入一段时整体后移,导致后面所有切片的 ID 全变,缓存、引用、反馈信号一起失效。
5. 怎么判断切得好不好
不看指标,看三条切片。
抽 30 条切片,人眼看。 有没有从中间断开的句子、有没有把表格压成一行、有没有混进页眉页脚。这 30 条基本能暴露所有解析和切片的问题,比任何自动化指标都直接。
用真实问题反查。 拿 20 个用户真正会问的问题,看答案所在的原文落在哪条切片里,那条切片是不是完整包含了答案。如果答案跨了两条切片,就是切点画错了。
看有没有"永远被召回但没用"的切片。 统计一段时间内被召回次数最多的切片,如果前几条是版权声明、目录、或者空白页,说明噪声没清干净。
切片这步做对了,后面的检索调优才有意义;做错了,后面花的所有力气都是在给一个错误的前提打补丁。参见《RAG 链路与失败模式》里关于"该动手哪一段"的判断方式。