RAG企业文档问答系统的Embedding语义切分方法
基于向量相似度的语义切分方法,通过SemanticChunker将句子转为Embedding,利用相邻句子的距离差异结合滑动窗口平滑处理,采用分位数、标准差、四分位距或梯度法确定切分点,有效避免传统固定切分导致的语义碎片化问题。
1 概述
您是否留意过,常见的文本切分方法大多仅依据固定字符数或特定分隔符来执行,完全忽略了语义层面的关联?实际操作中你会发现,这种“一刀切”的策略极易造成片段语义的支离破碎,为后续的文档处理与分析埋下不少隐患。

好在langchain-experimental库提供了一个名为SemanticChunker的工具,它能先将句子转换为嵌入向量,再借助向量间的相似度来判断是否需要分割。由于向量能够精准捕捉句子的语义信息,这种切分方式自然也就具备了“语义”层面的智能。
该实现参考了另一位作者的工作,原始思路来源于:RetrievalTutorials。
2 原理
SemanticChunker的基本逻辑如下:首先通过正则表达式将原始文本拆解为一个个独立的句子:
[sentence_1, sentence_2, sentence_3, sentence_4, sentence_5, sentence_6, sentence_7, sentence_8, sentence_9, ...]
原作者提出了两种实现思路:
带位置奖励的层次聚类:为每个句子计算嵌入向量,然后执行层次聚类。但某些极短的句子若单独切分可能会破坏语义——例如“But because I chose to split on sentences, there was an issue with small short sentences after a long one. You know?”,末尾的“You know?”单独计算相似度显然不合适。所谓“位置奖励”,是指让那些在相邻位置上更可能归属于同一语义的句子在切分时获得“优待”。不过作者本人也承认,这种方法调参过程缓慢且效果不理想(slow and unoptimal),奇怪的是,在实际应用中我们居然获得了不错的表现。
在连续句子中寻找切分点:这一思路非常直观——计算每个句子的嵌入向量,然后评估相邻句子之间的“距离”(1 - 余弦相似度)。一旦距离超过某个阈值,就在该位置进行分割。例如sentence_1、2、3彼此距离很近,但sentence_3与sentence_4之间的距离骤增,则在3与4之间切断,最终将1、2、3合并为一个片段。然而直接使用原始距离容易受噪声干扰,因此作者引入了滑动窗口做“平滑处理”,窗口大小设为3时效果较佳。
注意:窗口大小为3,对应后续代码中SemanticChunker构造函数的buffer_size=1,因为会向前、向后各取buffer_size个句子。
完成上述操作后,横轴为句子索引,纵轴为句子之间的距离,绘制的图表大致如下:
随后找出那些显著高于正常距离的点作为分割位置,便能得到如下的切分结果及对应的片段:
那么什么样的距离才算“显著”呢?langchain-experimental提供了四种判断方法:
percentile(分位数法):默认方法,也是原作者采用的。简单来说,将所有距离从小到大排序,取第95百分位数(默认值95)作为阈值,大于该值的点进行分割。直观且易理解。
standard_deviation(标准差法):适用于数据近似正态分布的场景。阈值 = 距离的均值 + 3 × 标准差(3为默认值)。这是统计学中常用的“异常值”判定方法。
interquartile(四分位距法):对数据分布敏感度较低,因其基于分位数。阈值 = 距离的均值 + 1.5 × 四分位距(IQR)。IQR = 上四分位(Q3) - 下四分位(Q1),即第75百分位数与第25百分位数之差。
gradient(梯度法):稍显复杂。首先计算所有距离的梯度(实际为一阶差分,因为数据离散),然后定位距离变化最剧烈的点,取所有梯度值的第95百分位作为分割点。其核心理念在于:句子之间的距离有增有减,应在“猛增”之处动手——与k-means中肘方法确定聚类数的思路相通。
3 效果
从实际对比来看,采用嵌入向量进行切分(尤其是配合层次聚类方法)的表现明显优于Baseline(基础流程),下图可以清晰地展现这种差异。
4 核心代码
本文配套代码已开源,仓库地址:GitHub - Steven-Luo/MasteringRAG。
使用嵌入向量进行切分的核心代码极为简洁——准备好嵌入模型和目标文档,两行即可完成:
# SemanticChunker
# HuggingFaceBgeEmbeddings
embeddings = HuggingFaceBgeEmbeddings(
model_name="...",
model_kwargs={"device": "cuda"},
encode_kwargs={"normalize_embeddings": True},
query_instruction="..."
)
# 或者 OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
text = open(os.path.join(os.path.pardir, "data", "sample.txt")).read()
text_splitter = SemanticChunker(embeddings)
docs = text_splitter.create_documents([text])
特别注意:SemanticChunker的默认参数是针对英文优化设计的,直接用于中文文本基本无法正常工作。下面列出几个关键参数,以及在中文场景下需要留意的地方。
4.1 注意切分的正则表达式
SemanticChunker的构造器定义如下:
class SemanticChunker(BaseDocumentTransformer):
def __init__(
self,
embeddings: Embeddings,
buffer_size: int = 1,
add_start_index: bool = False,
breakpoint_threshold_type: BreakpointThresholdType = "percentile",
breakpoint_threshold_amount: Optional[float] = None,
number_of_chunks: Optional[int] = None,
sentence_split_regex: str = "(?<=[.?!])\\s+",
min_chunk_size: Optional[int] = None,
):
...
参数sentence_split_regex默认按英文句号、问号、感叹号后跟空白字符进行切分。该模式无法处理中文文本,因此使用中文时必须替换为正则模式,例如:
sentence_split_regex="(?<=[。!?])"
4.2 使用buffer_size控制窗口大小
前文原理部分提到的滑动窗口,通过buffer_size参数进行控制——它决定当前句子前后各取几个句子组成一组,用于计算嵌入向量和相似度。
4.3 注意最小切片大小
与RecursiveCharacterTextSplitter那种“从大到小”的切分策略不同,SemanticChunker采用“从小到大”合并成片段的方式。这意味着如果初始正则切分出的句子非常短,且恰好满足了切分条件,最终可能产生一些极短且无意义的片段。因此min_chunk_size参数值得重点关注。
4.4 注意观察切片后的大小
SemanticChunker有时会生成非常大的切片,远超向量模型的最大长度限制。当然,您可以选择支持更长文本的模型,但过长的句子会稀释信息密度,未必带来正向收益。原作者在相关笔记中建议对大切片进行二次切分,我的示例代码中也包含了这部分尝试——不过效果并不理想,欢迎大家一起探索优化方案。
4.5 使用层次聚类
通过为number_of_chunks赋值一个具体的整数值来启用层次聚类,而非设置一个布尔值。用法示例如下:
text_splitter = SemanticChunker(
embeddings,
number_of_chunks=10
)
docs = text_splitter.create_documents([text]) 你是一名 AI 行业编辑,请围绕下面这条热点输出一份资讯解读:
热点:RAG企业文档问答系统的Embedding语义切分方法要求:
1. 先用一句话解释这条热点在讲什么
2. 再总结它为什么重要
3. 说明会影响哪些 AI 产品或内容方向
4. 最后给出 3 个适合资讯站使用的标题
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
相关热点探索AI领域最新动向,DeepSearcher这个创新工具确实值得仔细看看。它的架构、原理和实际应用,到底能为开发者带来什么?下面一步步拆解。 核心要点: 1 DeepSearcher与同类工具的横向对比 2 架构细节与研究流程解析 3 在智能检索生成技术中的独特优势 近期OpenAI的深度研
机器学习听起来像是个黑盒子,其实剥开来看,它的基本过程和日常做AB测试、写量化策略并没有本质区别——无非是定目标、找问题、想方案、动手干、回头看。只是在这个过程里,我们用的工具、思考的角度,以及需要留意的坑,确实有些不同。 1 基本过程 1 1 机器学习的五步流程 把机器学习当作一个闭环工作项来看
想要顺利交付一个机器学习项目,通常可以遵循以下几个步骤来推进。这套流程并非硬性规定,但在大多数实际场景中,按照这个顺序执行能显著减少返工与调试的麻烦。 1) 明确问题 首先要清楚要达成的业务目标。这一步的关键在于:如果公司已经积累了海量数据,就应当基于现有数据来定义目标;如果数据尚未采集,则需要先锁
瑞萨电子最新发布了一款基于SMARC 2 0架构的可扩展模块化系统(SoM)参考设计。该方案整合了10款瑞萨IC产品,涵盖微处理器、电源芯片和模拟器件,专为AI IoT应用中的面部与物体检测、图像处理以及4K视频回放而打造——广泛应用于监控摄像头、检测设备,以及工业和楼宇自动化中的HMI与嵌入式视觉
- 日榜
- 周榜
- 月榜
热点快看
