Semantic Chunking
语义分块会在主题变化处拆分文档,并通过比较相邻句子的嵌入相似度来判断分界,让每个文本块都表达一个观点。
语义分块会在主题发生变化的位置将文档拆分成块,用于检索增强生成(RAG)和搜索。它通过比较相邻句子的嵌入来找出变化点,而不是每隔固定数量的字符或 token 就切分一次。这样每个块都涵盖一个观点,因此它在向量数据库中的单个向量能很好地代表该观点;检索到的块也能向大型语言模型(LLM)提供完整的意思,而不是上一节的结尾和下一节的开头。
语义分块的工作原理#
由 Greg Kamradt 的文本拆分教程推广、并在 LangChain 中以 SemanticChunker 实现的常见算法包含四个步骤。文本先拆分成句子,然后为每个句子生成嵌入;为减少噪声,通常会将句子与相邻句子组合后再处理。接着,将每对连续句子之间的余弦相似度转换为距离。阈值会在距离异常大的位置标记分界点:LangChain 默认使用文档中所有距离的第 95 百分位数,也提供标准差、四分位间距和梯度阈值。分界点之间的句子组成一个分块。LlamaIndex 的语义拆分器也使用相同的百分位数分界点。
import numpy as np
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
sentences = [
"The XR-12 coolant pump circulates water through the press line.",
"Inspect the XR-12 pump seals for leaks every week.",
"A worn pump bearing grinds loudly before it fails.",
"The staff cafeteria now opens for breakfast at 7:00.",
"The cafeteria menu adds vegetarian lunches in May.",
]
# 每个句子与下一个句子之间的余弦距离
embeddings = model.encode(sentences, normalize_embeddings=True)
distances = 1 - np.sum(embeddings[:-1] * embeddings[1:], axis=1)
# 距离超过第 95 百分位数时开始一个新分块
threshold = np.percentile(distances, 95)
chunks = [[sentences[0]]]
for sentence, distance in zip(sentences[1:], distances):
if distance > threshold:
chunks.append([])
chunks[-1].append(sentence)
print(np.round(distances, 2))
print(*[" ".join(chunk) for chunk in chunks], sep="\n")相邻句子之间的距离分别为 0.56、0.64、0.98 和 0.62,因此唯一的分界点位于从泵轴承话题跳到食堂话题时出现的 0.98 距离处。输出结果是一个讨论 XR-12 泵的三句分块,以及一个讨论食堂的两句分块。
分块策略对比#
- 固定大小分块:每 N 个 token 拆分一次,相邻分块之间通常会有一些重叠。这种方式速度快、可预测,但不考虑主题边界。
- 递归拆分:先按段落拆分,再按换行拆分,接着按句子拆分,直到每个部分都符合大小限制。LangChain 建议对通用文本使用递归字符拆分器。
- 结构感知拆分:遵循标题、Markdown 章节、HTML 元素或 PDF 页面布局进行拆分。
- 语义分块:根据含义变化进行拆分,但索引时需要为每个句子生成嵌入,而且分块大小可能差异很大,因此实现中会设置最小和最大长度。
- 延迟分块和上下文检索:用于解决分块缺少所在文档其余部分上下文的问题,例如代词所指对象位于较早的分块中;这两种方法可与上述任意边界划分方法结合使用。
机器人学中的动作分块只是名称相同:在该领域,策略会将一系列未来运动指令作为一个整体进行预测。
文本之外的语义分块#
语音转文本系统生成的转录文本没有段落分隔,因此,基于嵌入的分界点是找出会议或播客话题变化位置的常用方法。视频也可以按内容分块,让每个片段呈现一个事件,用于视频理解或多模态 RAG,而不是任意截取 10 秒。Ultralytics YOLO26 可以为包含人物和车辆的场景提供此类边界:跟踪模式会为每个检测到的物体分配一个跨帧持续有效的 ID,因此,处理流程可以在新 ID 进入场景时开始录制片段,并在所有跟踪 ID 都离开后结束录制。
语义分块能改善检索效果吗?#
当彼此无关的主题紧挨着出现且没有标题时,基于主题的边界最为重要,例如在转录文本、抓取的网页和拼接的笔记中。语义分块还取决于嵌入模型和阈值,因此任一项发生变化,同一文档的分块方式也会随之改变;应根据真实查询对两者进行调优,以提升召回率。研究语义分块值得付出计算成本吗? (2024) 比较了语义分块和固定大小分块在文档检索、证据检索和基于检索的答案生成中的表现,发现语义分块增加的计算开销并未带来相较于固定大小分块的稳定提升。










