传统的文本分块机制就像用尺子切割布料 —— 不管布料的花纹如何,只按固定长度下刀。这种 "一刀切" 的方式常常导致语义割裂:明明是一个完整的论点,却被硬生生拆成两半;本该分开的两个主题,反而被塞进同一个块里。
而语义分块的核心思路是:让意思相近的内容 "抱团"。它借助文本嵌入(Embedding)技术,像磁铁一样把语义相似的句子吸在一起,从而实现更符合人类理解习惯的分块效果。本文将详解两种语义分块实现方法,从原理到代码带你全面掌握这一技术。
1、方法 1
按语义流自然分割
实现原理
这种方法保留原文的句子顺序,通过分析相邻句子的语义关联度,找到最适合分割的 "自然断点"。
实现步骤
1. 文本加载与预处理
先把文本拆成独立句子,为后续分析做准备。
加载文本:以 Paul Graham 的 MIT 论文为例。
结构化处理:转换成字典列表,方便后续添加嵌入、距离等信息。
2.句子合并:给每个句子 "加前后缀"
单个句子的语义往往不完整(比如含代词、省略成分),因此需要结合上下文。通过滑动窗口合并相邻句子,让每个句子 "带上" 前后文信息:
3. 生成句子嵌入:把文字变成 "语义向量"
使用SentenceTransformer的嵌入模型all-MiniLM-L6-v2对组合后的句子进行嵌入,并将嵌入结果添加到字典列表中,这些嵌入捕捉了句子的语义信息。
4. 计算语义距离:找到句子间的 "隐形鸿沟"
通过余弦相似度计算相邻句子的语义关联度,较大的距离表示句子之间的语义变化较大,可能是一个自然的分割点。
5. 识别断点:用数据可视化定位分割点
把语义距离绘制成折线图,超过阈值的峰值就是最佳分割点:
6. 合并成块:按断点组装语义完整的文本块
根据识别出的断点,将句子合并成长度适中的语义块,确保每个块的长度不超过设定的最大长度。
2、方法2
让相似语义 "跨位置相聚"
如果说方法 1 是 "顺流而下" 的自然分割,方法 2 则像 "主题拼图"—— 不管句子在原文中的位置,只要语义相似就放到一起。
实现原理
通过聚类算法,把所有句子按语义相似度分组,打破原文顺序限制,适合需要跨段落整合同类信息的场景(如文献综述、主题归纳)。
核心流程
1. 生成嵌入与相似度矩阵
与方法 1 类似,但需要计算所有句子之间的相似度(而非仅相邻句子):
2. 用并查集算法聚类
通过 Union-Find(并查集)算法,把相似度高于阈值的句子归为一类:
3. 合并聚类结果
将同一类的句子合并成块,同时控制块大小不超过最大token数:
完整流程
- 获取嵌入get_embeddings方法接收一个包含文本块的列表(每个文本块是一个字典,包含text和其他元数据),并使用 Sentence Transformer 模型为每个文本块生成嵌入向量。
- 计算相似性矩阵compute_similarity方法使用cosine_similarity函数计算嵌入向量之间的相似性矩阵。相似性矩阵是一个二维数组,其中每个元素表示两个文本块之间的相似性。
- 聚类文本块cluster_chunks方法基于相似性矩阵和给定的阈值(cluster_threshold),使用并查集(Union-Find)算法将文本块聚类。具体步骤如下:
- 初始化每个文本块为一个独立的集合。
- 遍历相似性矩阵,如果两个文本块之间的相似性大于或等于阈值,则将它们合并到同一个集合中。
- 最终,每个文本块被分配到一个聚类中。
- 合并文本块merge_chunks方法根据聚类结果将文本块合并。它会尝试将同一聚类中的文本块合并为一个更大的文本块,同时确保合并后的文本块不超过max_tokens的限制。如果合并后的文本块超出限制,则会创建一个新的文本块。
- 查找语义对find_top_semantic_pairs方法从相似性矩阵中查找语义相似的文本块对。它会筛选出相似性大于或等于similarity_threshold的文本块对,并按相似性降序排列,返回前top_k对。
3、两种方法对比与适用场景
SemanticTextChunker 更侧重于文本的分割,通过识别语义断点来实现,而 SemanticChunker 更侧重于文本块的合并,通过聚类和合并策略来实现。这两个类都利用了语义嵌入和相似度计算,但在具体实现和应用场景上有所不同。
方法 | 核心逻辑 | 优势 | 适用场景 |
方法1:不改变文本顺序 | 按语义流找断点,保留原文结构 | 符合阅读习惯,适合长文分段 | 文档摘要、上下文问答 |
方法2:改变文本顺序 | 按语义聚类重组,打破原文顺序 | 聚焦主题整合,适合跨段归纳 | 主题分析、文献综述 |
4、总结
这种语义分块方法通过嵌入技术让文本分割从 "按长度算" 进化到 "按意思分",但目前仍有优化空间:
- 动态阈值调整:不同类型文本(如论文 / 小说)的语义密度不同,需自适应调整阈值
- 递归分块:对超大型文本块进行二次分割,平衡语义完整性和长度限制
- 解决代词歧义:结合指代消解技术,避免 "他 / 它" 等代词因分块导致的指代混乱
最终,语义分块的效果需要通过 RAG(检索增强生成)评估来验证 —— 能让 AI 回答更准确的分块,才是好的分块。