Appearance
Q28 · 文本切块应该怎么设计?有哪些常见坑?
假设客服有一份很长的耳机售后政策。用户问:“耳机已拆封,签收 10 天后出现杂音,能无理由退货吗?还能申请质量问题售后吗?”如果把整份政策直接塞给大模型,可能超过可放入的文本长度,也会把许多无关条款一起送进去;如果机械地每隔几百字切一刀,又可能把“7 天内”与“未拆封”分开,让检索系统只找到半句话。切块的目标是让一次检索能取回足以回答问题的完整证据,同时控制噪声与成本。
这里讨论的是 RAG(Retrieval-Augmented Generation,检索增强生成):应用先从自己的资料中找相关内容,再把找到的内容交给大模型回答。大模型不会因为我们建立了知识库就自动读懂整库;它通常只看到本次检索送来的少数片段。因此,资料怎样切、怎样找、怎样交给模型,会影响最终答案。Azure AI Search 的切块指南也把文档切块与模型长度限制、检索质量联系在一起。
先认清术语与例子中的记号
| 词或记号 | 直白解释 | 本文中的对应物 |
|---|---|---|
| 文档 | 原始资料,可能有标题、段落、表格和版本 | 一份《耳机售后政策》V2 |
| 切块(chunking)/ 块(chunk) | 把文档分成可单独索引和取回的片段;每片叫一个块 | “无理由退货”与“质量问题”各成一块 |
| 索引 | 为块建立可搜索的记录 | 保存每块文本及其来源,供以后查找 |
| 检索 / 召回 | 根据问题找出可能有用的块;“召回”强调目标证据有没有被找回来 | 找到退货条件、质量问题条款和例外说明 |
| 向量 / 嵌入(embedding) | 把文本编码为一串数字,供相似度搜索使用 | 把问题和政策块变成可比较的表示 |
| Token | 模型处理文本时使用的计量单位;不等于一个汉字,也不等于一个单词 | chunk_size=300 若按 Token 计,表示约束块的 Token 数 |
| chunk size | 允许或目标的块长度,必须说明按 Token、字符还是其他单位计算 | 试验一组不同的块长度 |
| overlap(重叠) | 相邻两块重复保留的一段内容 | 让跨边界的句子在两块中都出现 |
| 元数据 | 跟块一起保存、用于过滤和溯源的信息 | 文档 ID、V2、生效日期、章节、权限范围、原文位置 |
top-k | 检索后最多送出的前 k 个候选块;k 是数量 | top-3 表示先取三块候选证据 |
| 证据 | 足以支持答案中某个具体判断的原文 | “7 天内且未拆封”支持拒绝本例无理由退货 |
向量搜索只是找块的一种方法;关键词搜索、两种方法一起用,或之后再对候选块排序,都可以接在同一套切块设计后面。**块相似不等于块完整,块被召回也不等于答案已经正确。**后面会沿着同一个问题区分这几步。
用一份固定政策判断切块是否完整
以下政策和日期都是虚构教学数据,不代表真实商家的规则。假设 V2 从 2026 年 9 月 1 日生效,问题中的“签收 10 天”从签收日算起;系统已经确认用户问的是适用 V2 的订单。
text
《耳机售后政策》V2,2026-09-01 生效
一、无理由退货
签收后 7 天内且商品未拆封,可以申请无理由退货。
二、质量问题
签收后 30 天内出现非人为故障,可以提交售后检测申请。
是否退货或维修,以检测结果和订单信息为准。
三、例外说明
已拆封商品不适用无理由退货,但不因此失去申请质量问题售后的资格。对“已拆封、签收 10 天、有杂音”的问题,完整而谨慎的回答是:按本例政策,不能申请无理由退货,因为超过 7 天且已经拆封;可以提交质量问题检测申请,因为仍在签收后 30 天内,但“有杂音”是否属于非人为故障、最后退货还是维修,必须等待检测和订单核实。不能把“可申请检测”偷换成“保证退货”。
如果系统只取回“签收后 30 天内可以提交售后检测申请”,却漏掉“非人为故障”和“以检测结果为准”,模型就可能把一个有条件的申请资格说成确定的退款权。切块设计必须保护这些条件、结论和例外之间的关系。
任意截断与按条款切,会留下不同证据
机械定长切法只看“到第几个字”,可能把标题放在块 A、条件放在块 B。例如块 A 只有“无理由退货”,块 B 只有“签收后 7 天内且商品未拆封,可以申请”。检索到 A 不足以判断期限;检索到 B 又可能不知道它属于哪种售后。如果切口恰好落在“且”附近,连两个条件必须同时满足的逻辑也可能被冲淡。这不是模型靠多想几步就一定能补回的;关键事实没有一起到达输入里。
更好的起点是先识别文档结构,再按能独立表达规则的单元切。针对上面的短文,可以得到三块:
| 块 | 实际可检索文本的核心内容 | 该块能支持的判断 |
|---|---|---|
| A | 耳机售后政策 V2 > 无理由退货;“签收后 7 天内且未拆封,可申请无理由退货” | 本例已过 7 天且已拆封,不满足无理由退货条件 |
| B | 耳机售后政策 V2 > 质量问题;“30 天内出现非人为故障,可提交检测;退货或维修以检测与订单信息为准” | 本例仍在申请窗口内;最终处理方式未确定 |
| C | 耳机售后政策 V2 > 例外说明;“拆封不适用无理由退货,但不失去质量问题售后申请资格” | 拆封不能用于直接拒绝质量问题申请 |

图只画出最容易看懂的两条规则,省略了第三条例外。真实回答本例时还要取回 C,或者在呈现 B 时由程序补充同文档的相关例外。图中的纸片表示索引中的块,不是把原始文档真的裁碎;原文仍应保留,以便回查和更新。
这里的“每条规则一块”不是绝对公式。如果某条规则横跨两页,包含若干子条件,仍要按逻辑单元细分,或同时保存较小的检索块和较大的原文段落,命中后扩展为完整上下文。反过来,三条短规则也不必为了达到某个固定长度强行合成一个大块。让块能独立说明一件事,比凑整齐字数更有用。Unstructured 的官方切块文档提供了按文档元素和标题切分的做法,也说明表格等元素需要单独处理。
大小与重叠怎么定
先确定检索任务需要多大的证据单元。本例“能否无理由退货”需要标题、期限和未拆封条件;“能否申请质量售后”需要 30 天、非人为故障、检测后的决定方式,以及拆封例外。再用实际文档统计这些单元的长度,确定候选块长度,针对真实问题比较效果。长度参数要写清计量单位:某工具的 chunk_size=300 可能指 300 字符,另一工具可能指 300 Token,不能把两个数字直接比较。LangChain 的递归切分器文档明确说明长度取决于所选的 length_function,重叠是目标值,最终还受分隔符与文本结构影响。
太小:标题、主条件和例外分散在多个块;即使其中一个块排进 top-k,其他块也可能被挤掉。太大:一个块同时谈无理由退货、质量问题、物流和发票,搜索时主题变杂,送给模型时也占更多输入空间。块越多还会增加索引记录和候选排序工作;重复内容越多,索引与模型输入成本也可能上升。Azure 的切块指南给出一些起始参数,但明确的工程做法仍是按内容和检索结果调整;不要把某个“512 Token 加固定重叠”当成所有中文政策、代码和表格的通用最优值。
重叠适合保护确实跨边界的连续叙述,例如一个长段落被迫拆成相邻两块时,让前后各保留一小段。它有代价:同一内容重复入库,检索的前几名可能出现近乎相同的块,挤掉 B 或 C。对于本例已经按完整条款切出的 A、B、C,默认再给每块机械复制邻块的尾部并不能自动解决“例外必须一起出现”;应通过标题路径、同文档关联、命中后扩展或取回多块来处理。Unstructured 的切块说明也区分因超长而被拆开的内容与本来完整的文档元素,提醒全局重叠可能污染干净的语义边界。
一个可操作的起点是:先用标题、段落、列表项等结构产生候选块;超过长度上限时再在句子边界拆;只给被迫拆开的相邻块少量重叠;拿测试问题调大小、重叠和每次取回数量。选择靠评测,不靠“行业默认值”。
标题、表格、代码和扫描件要先恢复结构
标题与列表。 “7 天内且未拆封”脱离“无理由退货”就容易误读。标题路径可以重复写进块文本,或作为检索时可用的字段;“且”“或”“除外”等连接词要和所连接的条件留在一起。列表若写“以下情形不适用”,不能只把某一条列表项单独取走而漏掉总句。
表格。 如果政策改成“售后类型|期限|条件|处理方式”的表格,单独切出“7 天|未拆封”这两个单元格,模型不知道对应哪一行、哪一列。应保留表头和行的绑定关系;表很大时按有意义的行组拆,并把表题、列名随每个行组带上。跨页表格要先识别连续关系。Unstructured 的文档元素切块方法会把表格视为特殊元素,原因正是随意拼进相邻段落会破坏其结构。
代码和技术文档。 代码库中的函数名、签名、注释、输入输出应尽量同块;长函数按逻辑段拆时保留文件、类和函数路径。把一半 if 条件放在上一块、返回值放在下一块,会造成与政策截断同类的问题。技术文档里的命令也不要和适用版本、前置条件分家。
PDF 与扫描件。 先检查文字提取或 OCR(从图片识别文字)是否把页眉、页脚、双栏、跨页表格乱序;“第 2 页第 1 栏”接到“第 1 页页脚”后再切得多精细也没有意义。对重复页脚、目录和导航文字要清理或标记,避免检索总命中它们。对于需要引用的文档,保留页码或原文位置,方便核对。Azure 的 RAG 准备阶段指南强调先弄清数据形态并准备可检验的样本,再选择处理方式。
每块必须能回到正确的原文
除了块文本,A、B、C 还应带上 document_id(原文的稳定标识)、version(V2)、effective_date(生效日期)、section(章节路径)、source_uri(原文位置)和允许访问的权限范围。这里这些英文名只是字段示例,不是某个框架强制要求的 API。若用页码或字符偏移标出原文位置,客服就能检查“模型引用的 30 天”究竟来自哪一版哪一页。
元数据会直接影响检索正确性。本例假设 V2 适用;如果索引同时保留 V1,而旧版写“15 天内”,只比较文字相似度可能取回过期规则。应用应在检索前依据订单日期和生效区间过滤版本,并按登录者权限过滤资料。权限检查必须由系统完成,不能让模型读到无权内容后再要求它“别说出去”。索引更新时删除或失效旧块,避免新旧条款混用。以上是面向业务资料的工程约束;具体字段与版本规则要由实际系统确定。Azure 的 RAG 内容准备与丰富化指南讨论了为块补充可检索的上下文和元数据。
评测时把“没找到”和“没答对”分开
准备一组真实问法,并给每个问题标注必须用到的原文证据。本例至少有三类问法:“签收 3 天未拆封能退吗?”“签收 10 天已拆封有杂音怎么办?”“拆封是否一律不能申请售后?”第二问的期望证据是 A、B、C;期望回答必须同时区分无理由退货、检测申请和最终处理尚未确定。
先测检索:在允许访问且有效版本的候选里,top-k 是否包含期望证据?如果只找回 B,模型即使说出“30 天内可申请检测”,也缺少 A 和 C 来完整回答。再测生成:已经把 A、B、C 给模型,它是否仍把“申请检测”说成“保证退款”,是否正确注明来源?这样能判断问题来自切块/检索,还是回答阶段。还应记录无关块比例、重复块比例、延迟、索引规模和输入 Token,比较不同块大小与重叠,而不是只看某几个回答顺不顺口。Azure 的 RAG 评测指南同样把检索质量与答案的相关性、完整性和有据性分开评估。
若 A、B、C 明明都在索引里却取不到,先看版本/权限过滤是否误杀、问题用词是否和原文差太远、top-k 是否太小,再比较关键词与向量检索、候选排序和块设计。若正确块已送到模型但答案仍错,检查给模型的说明、上下文长度、引用约束和生成结果。不要遇到效果差就一律调 chunk_size;切块只是这条链路中的一环。
面试时怎样回答
可以这样说:“我会先明确 RAG 的检索问题和文档结构,让一个块尽量独立表达一条可引用的事实或规则,保住标题、条件、结论和例外。块大小按实际证据长度、模型输入限制和评测结果选,重叠只用来保护被迫切开的连续内容,不把它当作语义切分的替代品。表格要保留表头与行,代码要保留函数上下文,扫描文档先处理提取顺序。每块保存文档版本、章节、来源位置和权限。最后用标注了期望证据的问题集,分别看检索是否召回正确块,以及模型是否根据这些块准确作答;同时观察重复、噪声、延迟和成本。”
如果追问“块越小是不是越精准”,可以用本例回答:只剩“7 天内”的小块没有“未拆封”和条款标题,检索命中也不能支持结论。如果追问“多加 overlap 能否解决”,可以答:它能减少某些跨边界断句,但也会复制噪声;对独立条款之间的例外关联,需要结构化切块、关联取回或命中后扩展,仍要用问题集验证。
资料
- Microsoft Learn:Chunk large documents for vector search:切块动机、长度和重叠参数及其局限。
- LangChain:RecursiveCharacterTextSplitter:长度计量方式、分隔符和重叠行为。
- Unstructured:Chunking:按元素与标题切块,表格和过长元素的处理。
- Microsoft Learn:RAG 准备阶段、内容丰富化阶段、评测阶段:文档准备、块上下文和检索/答案分层评测。