问题与目标
整篇文档往往超过检索和模型上下文的合理范围,切得太碎又会把条件与结论分开。Chunk Size 和 Overlap 没有通用最优值,它们需要同时服从文档结构、Embedding 模型、检索方式和用户问题。
本篇比较固定长度、递归字符和 Markdown 标题切分,并用一组可复查问题检查答案片段是否仍然完整。语义模型切分只作为后续优化,不在这里增加额外模型依赖。
核心概念
- 固定长度:实现简单、吞吐稳定,但容易从句子中间切开。
- 递归字符:优先按段落、换行、句号等边界切分,是通用文本的可靠起点。
- 结构切分:利用 Markdown 标题、HTML 标签或 PDF 页码,适合层级清晰的文档。
- Overlap:让边界附近内容重复出现,能补上下文,但会增加索引量和重复召回。
切分单位应尽量接近所用模型的 Token 计数。按字符设定只是近似值,中文、英文和代码的字符/Token 比例不同。
可运行实现
bash
python -m pip install "langchain-text-splitters>=1,<2"
python
from langchain_core.documents import Document
from langchain_text_splitters import (
MarkdownHeaderTextSplitter,
RecursiveCharacterTextSplitter,
)
text = """# 值班规则
## 告警升级
一般告警由当班人员在15分钟内确认。关键告警需要立即通知负责人。
## 恢复检查
告警恢复后仍需观察10分钟,并记录设备编号、恢复时间和处理人。
"""
headers = [("#", "h1"), ("##", "h2")]
sections = MarkdownHeaderTextSplitter(headers_to_split_on=headers).split_text(text)
splitter = RecursiveCharacterTextSplitter(
chunk_size=70,
chunk_overlap=15,
separators=["\n\n", "。", ";", ",", "\n", ""],
)
chunks = splitter.split_documents([
Document(page_content=section.page_content, metadata={
**section.metadata,
"source": "duty-rules.md",
"version": "v1",
})
for section in sections
])
for index, chunk in enumerate(chunks):
chunk.metadata["chunk_id"] = f"duty-rules:v1:{index:03d}"
print(chunk.metadata, repr(chunk.page_content))
不要只打印平均长度。建立几条人工问题,并检查至少一个 Chunk 是否同时包含问题所需条件与答案:
python
checks = {
"关键告警如何处理?": ["关键告警", "立即通知负责人"],
"恢复后观察多久?": ["恢复后", "10分钟"],
}
for question, terms in checks.items():
matched = [c for c in chunks if all(term in c.page_content for term in terms)]
print(question, "PASS" if matched else "FAIL")
同一批文档分别测试不同 chunk_size 和 chunk_overlap,记录 Chunk 数、重复率、问题覆盖率和检索结果,再选择参数。
常见问题与排查
Chunk 越小检索越准
小片段更聚焦,但可能丢失主语、适用条件和来源层级。查看失败问题是“没召回”还是“召回片段缺答案”,再调参数。
Overlap 设置成 Chunk 的一半
高重叠会让 Top-k 被相邻重复片段占满。先从较小比例开始,配合相邻片段合并或去重。
只保存 Chunk 文本
必须继承 source/page/version/access_scope,并生成稳定 chunk_id。否则引用、更新和权限过滤都无法可靠实现。
改了切分参数却增量写入旧索引
切分策略变化等于索引版本变化。使用新的版本标识重建,验证后切换;不要让两种 Chunk 混在同一命名空间。
小结
切分不是机械预处理,而是 RAG 的第一项质量决策。可靠做法是保留结构与来源,用固定问题集检查答案边界,并把参数、版本和结果一起记录,而不是凭一个默认长度决定全部文档。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


