赞
踩
将大型文档划分为较小的部分是一项至关重要但又复杂的任务,它对检索增强生成 (RAG) 系统的性能有重大影响。这些系统旨在通过结合基于检索和基于生成的方法,提高输出的质量和相关性。有效的分块,即将文档拆分为可管理的片段的过程,对于优化 RAG 系统的检索和嵌入步骤至关重要。各种框架提供了几种分块方法,每种方法都有自己的优势和用例。在本文中,我介绍了一种新技术,它利用句子嵌入来识别文档中的主题变化,从而确保每个块都封装一个主题。这种方法增强了系统生成连贯且适合上下文的响应的能力,我们之前已经在主题建模的背景下探索过这一点。
检索增强生成 (RAG) 系统是一种复杂的机器学习模型,它将基于检索的技术与生成模型相结合。RAG 系统的主要目标是通过整合从大型数据集中检索到的信息来提高生成内容的质量和相关性。以下是 RAG 系统工作原理的细分:
RAG 系统的混合特性使其特别适用于复杂或知识密集型任务,其中检索和生成的结合显著提高了整体性能。
在深入研究新分块技术的细节之前,了解文档拆分的标准方法至关重要。文档拆分是许多自然语言处理 (NLP) 任务的基础步骤,并且采用各种技术来确保以保留含义和上下文的方式划分文本。以下是一些常用方法,使用广泛采用的 Langchain 框架进行说明:
根据手头任务的具体要求,可以以各种方式应用分块。以下是满足不同需求的高级分块方法的概述:
我介绍的新分块技术旨在使用句子嵌入来识别文档中主题的变化。通过识别主题发生变化的点,该技术可确保每个块都封装一个连贯的主题。此方法利用先进的 NLP 技术来增强 RAG 系统的性能:
这种技术已在主题建模中得到证实,但它同样适用于 RAG 系统。通过采用这种方法,RAG 系统可以在其生成的内容中实现更高的准确性和相关性,使其更有效地完成复杂且知识密集型的任务。
在上一节中,我们探讨了各种文档拆分方法及其在检索增强生成 (RAG) 系统中的应用。现在,让我们深入研究使用 LangChain 框架实现这些技术的实际示例。此外,我们将介绍一种新颖的主题感知分块方法,该方法利用句子嵌入来识别文档中的主题转变。
以下是 LangChain 中文档拆分方法的一些示例,以及详细的解释和代码片段来演示它们的用法:
递归字符文本分割器方法根据字符数将文本分成多个块,确保每个块的长度不超过指定长度。此方法对于在文档中保持自然的段落或句子分隔非常有用。
- # 从 langchain 导入 RecursiveCharacterTextSplitter 类
- from langchain.text_splitter import RecursiveCharacterTextSplitter
-
- # 示例长文档文本
- text = "您的长文档文本在此处..."
-
- # 使用 1000 个字符的块大小和 50 个字符的重叠部分初始化 RecursiveCharacterTextSplitter
- splitter = RecursiveCharacterTextSplitter(chunk_size= 1000 , chunk_overlap= 50 )
-
- # 将文本拆分为块
- chunks = splitter.split_text(text)
-
- # 打印每个块
- for chunk in chunks:
- print (chunk)
2. Token拆分器
Token Splitter 方法根据 token(例如单词或子单词)划分文本。在使用具有 token 限制的语言模型时,这种方法非常有用。
- # 从 langchain 导入 TokenSplitter 类
- from langchain.text_splitter import TokenSplitter
-
- # 示例长文档文本
- text = "您的长文档文本在此处..."
-
- # 使用最大 token 限制 512 初始化 TokenSplitter
- splitter = TokenSplitter(max_tokens= 512 )
-
- # 将文本拆分为块
- chunks = splitter.split_text(text)
-
- # 打印每个块
- for chunk in chunks:
- print (chunk)
3.句子分割器
句子分割器方法在句子边界处分割文本,保留文本的上下文完整性。此方法非常适合需要连贯完整思想的任务。
- # 从 langchain 导入 SentenceSplitter 类
- from langchain.text_splitter import SentenceSplitter
-
- # 示例长文档文本
- text = "您的长文档文本在此处..."
-
- # 初始化 SentenceSplitter,每个块的最大长度为 5 个句子
- splitter = SentenceSplitter(max_length= 5 )
-
- # 将文本拆分为块
- chunks = splitter.split_text(text)
-
- # 打印每个块
- for chunk in chunks:
- print (chunk)
4.正则表达式分割器
Regex Splitter 方法使用正则表达式来定义自定义分割点,为各种用例提供高度的灵活性。
- # 从 langchain 导入 RegexSplitter 类
- from langchain.text_splitter import RegexSplitter
-
- # 示例长文档文本
- text = "您的长文档文本在此处..."
-
- # 使用模式初始化 RegexSplitter,在双换行符处拆分文本
- splitter = RegexSplitter(pattern= r'\n\n+' )
-
- # 将文本拆分为块
- chunks = splitter.split_text(text)
-
- # 打印每个块
- for chunk in chunks:
- print (chunk)
5. Markdown 分割器
Markdown Splitter 方法是针对 markdown 文档量身定制的,根据 markdown 特定元素(如标题、列表和代码块)拆分文本。
- # 从 langchain 导入 MarkdownSplitter 类
- from langchain.text_splitter import MarkdownSplitter
-
- # 长 markdown 文档示例文本
- text = "您的长 markdown 文档在此处..."
-
- # 初始化 MarkdownSplitter
- splitter = MarkdownSplitter()
-
- # 将文本拆分为块
- chunks = splitter.split_text(text)
-
- # 打印每个块
- for chunk in chunks:
- print (chunk)
将大型文档分割成连贯的主题部分是数字内容分析中的一项重大挑战。如上所述,传统方法通常难以准确检测细微的主题变化。我们的新方法利用句子嵌入来增强分割过程,提供更精确、更有意义的区块。
大型文档(例如学术论文、长篇报告和详细文章)通常包含多个主题。传统的分割技术(从简单的基于规则的方法到高级机器学习算法)都难以识别主题转换的精确点。这些方法通常会错过细微的转换或错误地识别它们,从而导致部分内容支离破碎或重叠。
我们的方法采用 Sentence-BERT (SBERT) 为单个句子生成嵌入。这些嵌入是封装句子语义内容的密集向量表示。
SBERT 用于为文档中的每个句子生成嵌入。这些嵌入可以捕捉句子的语义,使我们能够衡量它们的相似性。
- from sentence_transformers import SentenceTransformer
-
- # 例句
- sentences = [ "句子 1..." , "句子 2..." , ...]
-
- # 初始化 SBERT 模型
- model = SentenceTransformer( 'paraphrase-MiniLM-L6-v2' )
-
- # 为每个句子生成嵌入
- embeddings = model.encode(sentences)
2. 计算相似度
句子之间的相似度使用余弦相似度或其他距离测量方法(如曼哈顿距离或欧几里得距离)来衡量。这有助于识别连续句子之间的连贯性。
- from sklearn.metrics.pairwise import cosine_similarity
-
- # 计算嵌入之间的余弦相似度
- similarity_matrix = cosine_similarity(embeddings)
-
3.差距得分和平滑
为了检测主题转换,我们定义了一个参数n
来指定要比较的句子数量。该算法根据余弦相似度计算差距分数。
- import numpy as np
-
- # 定义参数 n
- n = 2
-
- # 计算差距分数
- gap_scores = []
- for i in range ( len (embeddings) - n):
- similarity = cosine_similarity(embeddings[i:i+n], embeddings[i+n:i+ 2 *n])
- gap_scores.append(np.mean(similarity))
为了解决差距分数中的噪音问题,我们采用了平滑算法。窗口大小k
决定了平滑的程度。
- # 定义窗口大小 k
- k = 3
-
- # 平滑差距分数
- smoothed_gap_scores = np.convolve(gap_scores, np.ones(k)/k, mode= 'valid' )
4.边界检测
分析平滑后的差距分数以识别局部最小值,这表明潜在的主题转换。c
使用阈值来确定重要边界。
- # 检测局部最小值
- local_minima = (np.diff(np.sign(np.diff(smoothed_gap_scores))) > 0 ).nonzero()[ 0 ] + 1
-
- # 设置阈值 c
- c = 1.5
-
- # 识别显著边界
- significance_boundaries = [i for i in local_minima if smoothed_gap_scores[i] < np.mean(smoothed_gap_scores) - c * np.std(smoothed_gap_scores)]
5.聚类片段
对于较长的文档,类似的主题可能会重复出现。为了解决这个问题,该算法将具有类似内容的片段聚类,从而减少冗余并确保每个主题都有唯一的表示。
- from sklearn.cluster import KMeans
-
-
- # 将文本段转换为嵌入
- segment_embeddings = [np.mean(embeddings[start:end], axis= 0 ) for start, end in zip (significant_boundaries[:- 1 ], significance_boundaries[ 1 :])]
-
- # 应用聚类
- kmeans = KMeans(n_clusters= 5 )
- clusters = kmeans.fit_predict(segment_embeddings)
该方法提出了一种复杂的文档分割方法,将传统原理与尖端的句子嵌入相结合。未来的研究可以探索以下领域以进一步增强该方法:
我们的方法为大型文档中的精确主题建模提供了一种强大而有效的解决方案。通过利用 SBERT 和先进的平滑和聚类技术,这种方法比传统的文档分割方法有了显著的改进。这项创新提高了 RAG 系统的性能,使它们能够为复杂且知识密集型的任务生成更相关、更连贯的内容。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。