切片断裂是什么
切片断裂指入库的片段在语义上不完整:以半句话开头、结论与条件分家、表头与数据行分离、列表被拦腰截断。这种破损在检索阶段看不出来——片段照样被召回、分数也不低——但生成时模型拿到的是残缺信息,表现为回答缺前提、数字对不上、把上一节的结论套到本节。修复分两步:改用结构感知切分减少断裂来源,再用抽样脚本检查块首尾是否完整。
基本信息
| 典型症状 | 回答缺主语或条件、表格数字错行、条目只剩后半句 |
|---|---|
| 常见原因 | 纯字符滑窗切分、表格未单独处理、标题层级未参与切分 |
| 检查方式 | 随机抽样打印每块前 60 字与后 60 字,人工确认 |
| 主要手段 | 按标题层级切、句子边界切、表格整块保留、适度重叠 |
修复手段清单
- 按标题层级先切大节,再在大节内按句子边界细分,语义边界优先于长度上限
- 表格整体保留:小表整表一块,大表按行分组并复制表头
- 适度重叠:取块长的 10%~20% 兜住跨块句子,但不要用大重叠掩盖切分问题
- 元数据补全:块首写入所属标题路径与页码,即使被切开也能恢复阅读语境
- 入库前抽样检查:块首尾是否完整、块长分布是否有异常尖峰
结构感知切分(示意)
结构感知切分(示意)
from langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter
headers = [('#', 'h1'), ('##', 'h2'), ('###', 'h3')]
sections = MarkdownHeaderTextSplitter(headers_to_split_on=headers).split_text(md_text)
recursive = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=80)
chunks = [c for s in sections for c in recursive.split_text(s.page_content)]
chunks = [c for c in chunks if len(c.strip()) >= 50] # 丢掉只含标题的碎块抽样检查首尾
抽样检查首尾
import random
for c in random.sample(chunks, min(20, len(chunks))):
print(repr(c.text[:60]), ' ... ', repr(c.text[-60:]))
# 确认没有以半个句子、半个表格开头或结尾标题与页码写入元数据后,即使某块被切开,生成端仍能补回上下文;这是比无限加大重叠更省预算的兜底方式。