【NLP】利用 RAG 模分块技术提升文档处理效能

news2024/11/15 21:57:06

f0a23f4cb1ba45768387b1257022b780.webp

将大型文档划分为较小的部分是一项至关重要但又复杂的任务,它对检索增强生成 (RAG) 系统的性能有重大影响。这些系统旨在通过结合基于检索和基于生成的方法,提高输出的质量和相关性。有效的分块,即将文档拆分为可管理的片段的过程,对于优化 RAG 系统的检索和嵌入步骤至关重要。各种框架提供了几种分块方法,每种方法都有自己的优势和用例。在本文中,我介绍了一种新技术,它利用句子嵌入来识别文档中的主题变化,从而确保每个块都封装一个主题。这种方法增强了系统生成连贯且适合上下文的响应的能力,我们之前已经在主题建模的背景下探索过这一点。

了解检索增强生成 (RAG) 系统

检索增强生成 (RAG) 系统是一种复杂的机器学习模型,它将基于检索的技术与生成模型相结合。RAG 系统的主要目标是通过整合从大型数据集中检索到的信息来提高生成内容的质量和相关性。以下是 RAG 系统工作原理的细分:

  1. 检索阶段:系统首先根据输入查询检索相关文档或信息。此阶段依靠搜索算法和索引方法从大量数据中快速识别最相关的数据。
  2. 生成阶段:检索到相关文档后,将使用生成模型(通常是基于转换器的语言模型,如 GPT-4)来创建连贯且适合上下文的响应。该模型使用检索到的信息来确保生成的内容准确且信息丰富。

RAG 系统的混合特性使其特别适用于复杂或知识密集型任务,其中检索和生成的结合显著提高了整体性能。

文档拆分探索

在深入研究新分块技术的细节之前,了解文档拆分的标准方法至关重要。文档拆分是许多自然语言处理 (NLP) 任务的基础步骤,并且采用各种技术来确保以保留含义和上下文的方式划分文本。以下是一些常用方法,使用广泛采用的 Langchain 框架进行说明:

  1. 递归字符文本分割器:此方法通过基于字符递归地划分文本来分割文档。每个块的长度保持在指定长度以下,这对于具有自然段落或句子分隔的文档特别有用。此方法可确保块易于管理且易于处理,而不会丢失文档的固有结构。
  2. 标记分割器:此技术使用标记(可以是单词或子单词)来分割文档。在使用具有标记限制的语言模型时,它非常有用,因为它可以确保每个块都符合模型的限制。基于标记的分割通常用于 NLP 任务中,以在遵守模型限制的同时保持文本的完整性。
  3. 句子分割器:通过在句子边界处分割文档,此方法可保持文本的上下文完整性。句子通常代表完整的想法,因此这种方法非常适合需要连贯理解内容的任务。
  4. 正则表达式拆分器:此方法使用正则表达式来定义自定义拆分点。它提供了最高的灵活性,允许用户根据特定于其用例的模式拆分文档。例如,可以在每个特定关键字或标点符号实例处拆分文档。
  5. Markdown 拆分器:此方法专为 Markdown 文档量身定制,可根据标题、列表和代码块等 Markdown 特定元素拆分文本。它保留了 Markdown 文档的结构和格式,适合用于技术文档和内容管理。

高级分块方法

根据手头任务的具体要求,可以以各种方式应用分块。以下是满足不同需求的高级分块方法的概述:

  1. 按字符:此方法将文本分解为单个字符。它对于需要深入细致的文本分析的任务很有用,例如字符级语言模型或某些类型的文本预处理。
  2. 按字符 + SimplerLLM:此技术位于 SimplerLLM 库中,按字符对文本进行分块,同时保留句子结构。通过保持基于字符的块内句子的完整性,它可以提供更好、更有意义的片段。
  3. 按标记:将文本分割为标记(例如单词或子单词)是自然语言处理中的标准方法。基于标记的分块对于文本分类、语言建模和其他依赖标记化输入的 NLP 应用程序等任务至关重要。
  4. 按段落:按段落分块文本有助于维护文档的整体结构和流程。此方法非常适合需要更多上下文的任务,例如文档摘要或内容提取。
  5. 递归分块:这涉及反复将数据分解为较小的块,通常用于分层数据结构。递归分块对于需要多级分析的任务(例如主题建模或分层聚类)非常有用。
  6. 语义分块:对于需要理解数据上下文的任务来说,根据含义而不是结构元素对文本进行分组至关重要。语义分块利用句子嵌入等技术来确保每个块代表一个连贯的主题或想法。
  7. 代理分块:此方法侧重于根据所涉及的代理(例如人员或组织)识别和分组文本。它在信息提取和实体识别任务中很有用,在这些任务中,了解不同实体之间的角色和关系非常重要。

新颖的分块技术:主题感知句子嵌入

我介绍的新分块技术旨在使用句子嵌入来识别文档中主题的变化。通过识别主题发生变化的点,该技术可确保每个块都封装一个连贯的主题。此方法利用先进的 NLP 技术来增强 RAG 系统的性能:

  1. 句子嵌入:句子嵌入将句子转换为高维向量,以捕捉其语义。通过分析这些向量,我们可以识别主题发生变化的点。
  2. 主题检测:该技术使用专为主题建模而设计的算法,检测主题的变化并确定拆分文档的最佳点。这确保每个块在主题上都是连贯的。
  3. 增强的检索和嵌入:通过确保每个块代表一个主题,RAG 系统中的检索和嵌入步骤变得更加高效。每个块的嵌入更有意义,从而实现更好的检索性能和更准确的响应。

这种技术已在主题建模中得到证实,但它同样适用于 RAG 系统。通过采用这种方法,RAG 系统可以在其生成的内容中实现更高的准确性和相关性,使其更有效地完成复杂且知识密集型的任务。

使用 LangChain 的高级文档拆分技术

在上一节中,我们探讨了各种文档拆分方法及其在检索增强生成 (RAG) 系统中的应用。现在,让我们深入研究使用 LangChain 框架实现这些技术的实际示例。此外,我们将介绍一种新颖的主题感知分块方法,该方法利用句子嵌入来识别文档中的主题转变。

LangChain 中的文档拆分示例

以下是 LangChain 中文档拆分方法的一些示例,以及详细的解释和代码片段来演示它们的用法:

  1. 递归字符文本分割器

递归字符文本分割器方法根据字符数将文本分成多个块,确保每个块的长度不超过指定长度。此方法对于在文档中保持自然的段落或句子分隔非常有用。

# 从 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) 为单个句子生成嵌入。这些嵌入是封装句子语义内容的密集向量表示。

  1. 生成嵌入

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 将该方法应用于不同的语言。
  • 分层分割:调查多个层次的分割以进行详细的文档分析。
  • 用户界面开发:创建交互式工具,以便更轻松地调整分割结果。
  • 与NLP任务的集成:将算法与其他自然语言处理任务相结合。

结论

我们的方法为大型文档中的精确主题建模提供了一种强大而有效的解决方案。通过利用 SBERT 和先进的平滑和聚类技术,这种方法比传统的文档分割方法有了显著的改进。这项创新提高了 RAG 系统的性能,使它们能够为复杂且知识密集型的任务生成更相关、更连贯的内容。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1909680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百度Feed业务数仓建模实践

作者 | XY 导读 Feed&#xff0c;即个性化推荐信息流&#xff0c;是百度 App 上承载各种类型内容&#xff08;如文章、视频、图集等&#xff09;的重要 topic。本文概要讲述了随着业务发展&#xff0c;移动生态数据研发部在 Feed 数据宽表建模上的演进过程以及一些实践&#xf…

LeetCode67(二进制求和[位运算,大数运算])

二进制求和 题目要求: 给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 这道题其实有几种解法.我们先来介绍简单的方法. 我们可以将两个字符串的二进制转成十进制,获取对应值相加之后,我们可以不断对2取余,获取尾数拼接即可.也就是像我们平常求一…

记一次线上流量突增问题排查

一.问题 接流量告警出现获取 xx 信息接口调用次数同比往年大促活动猛涨.扩大至 10 倍之多.心里顿时咯噔一下.最近各种严打,顶风作案.某不是摸到电门了.一下子要把自己带走.从此走向求职之路.一时间脑子哇哇的思绪万千. 202x.5.20 大促开门红的调用.这个是往年活动的时候的调用…

01-引论-操作系统的目标和作用

操作系统的目标 1.方便性 2.有效性 3.可扩充性 4.开放性 操作系统的目标与应用环境有关 在不同的应用环境下&#xff0c;操作系统的重点和功能可能会有所不同。例如&#xff0c;对于桌面操作系统&#xff0c;用户界面的友好性和多媒体功能可能是重点&#xff1b;对于服务…

Qt/C++项目积累: 2.主机监控器 - 2.1 项目介绍

修改记录 序号日期说明对应软件版本号120240709对预期功能和已完成功能进行新增无 一&#xff1a;项目主体编写背景 在观察程序的运行状态时&#xff0c;其对系统的CPU&#xff0c;内存&#xff0c;硬盘占用无疑是几项重要参考指标&#xff0c;而现有的监控软件&#xff0c;搜…

2024-07-08 base SAS programming学习笔记10(read data)

1.读入SAS 数据集 格式如下&#xff1a; data sas-data-set; set sas-data-set; run; sas-data-set 是数据集名称&#xff0c;可以是libname.filename的形式 举例如下&#xff1a; 2.在DATA步使用BY 语句 BY variable语句使用方法&#xff1a; a.必须在PROC SORT里面进行排序…

国产芯片四大流派,你最看好哪一条?

曾经&#xff0c;我们以为“地球村”是大势所趋&#xff0c;大家取长补短&#xff0c;合作共赢。 然而&#xff0c;2018年开始的那一场断供&#xff0c;让芯片自主从一个产业的隐忧变成了我国的一个“明伤”。近几年“卡脖子”事件屡屡上演&#xff0c;“缺芯”、“芯痛”成为…

Redis连接Resp图形化工具和springboot

Redis连接Resp图形化工具和springboot 1.redis配置1.1 备份、修改conf文件1.2 Redis的其它常见配置&#xff1a;1.3 启动Redis&#xff1a;1.4 停止服务&#xff1a;1.5 开机自启&#xff1a; 2. resp的安装、配置和连接&#xff1a;2.1 GitHub上下载2.2 开始连接redis ![在这里…

【Dison夏令营 Day 13】使用 Python 创建扫雷游戏

在本文中&#xff0c;我们将介绍如何使用 Python 语言创建自己的基于终端的扫雷程序。 关于游戏 1992年4月6日&#xff0c;扫雷和纸牌、空当接龙等小游戏搭载在Windows 3.1系统中与用户见面&#xff0c;主要目的是让用户训练使用鼠标。扫雷是一款单人游戏&#xff0c;这个游戏…

单例模式(大话设计模式)C/C++版本

单例模式 C 饿汉 /* HM hungry man 饿汉 */ #include <iostream> using namespace std; class Singleton { private:Singleton() { cout << "单例对象创建&#xff01;" << endl; };Singleton(const Singleton &);Singleton &operator(c…

app: 和 android:的区别

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

如何切换手机的ip地址

在数字时代的浪潮中&#xff0c;智能手机已成为我们日常生活中不可或缺的一部分。然而&#xff0c;随着网络安全问题的日益凸显&#xff0c;保护个人隐私和数据安全变得尤为重要。其中&#xff0c;IP地址作为网络身份的重要标识&#xff0c;其安全性与隐私性备受关注。本文将详…

百度旋转验证码

声明(lianxi a15018601872) 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 前言(lianxi a…

OpenWrt入门 (1) - 登录及ssh命令接入wifi

本文参考自: [OpenWrt 维基]在 OpenWrt 上启用 Wi-Fi 接入点 --- [OpenWrt Wiki] Enabling a Wi-Fi access point on OpenWrt 需要详细了解的小伙伴请看原文 基本概念 OpenWrt是适用于嵌入式设备的一个Linux发行版。 相对原厂固件而言&#xff0c;OpenWrt不是一个单一、静态…

手写简单实现IOC

这个小demo是利用反射从最基础一步一步模拟实现了IOC的功能,所有的代码基本都给出了注释,方便大家阅读. 目录结构&#xff1a; 这里需要导入一下junit依赖 <!-- junit测试 --><dependency><groupId>junit</groupId><artifactId>junit</artif…

string类(STL开始)

相信大家都知道STL在C中的重要性&#xff0c;作为其模板库中的一部分&#xff0c;包含了常见的数据结构和算法&#xff0c;是C的标准库 而我们今天要讲的String类&#xff08;String底层是一个字符顺序数组的顺序表对象&#xff0c;可以归类为容器&#xff09;&#xff0c;其实…

JavaWeb系列二十二: 线程数据共享和安全(ThreadLocal)

韩顺平-线程数据共享和安全ThreadLocal 什么是ThreadLocal?ThreadLocal环境搭建ThreadLocal快速入门ThreadLocal源码阅读threadLocal.set()源码threadLocal.get()源码 什么是ThreadLocal? ThreadLocal的作用: 可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.Thr…

一.6 存储设备形成层次结构

在处理器和一个较大的较慢的设备&#xff08;例如主存&#xff09;之间插入一个更小更快的存储设备&#xff08;例如高速缓存&#xff09;的想法已经成为一个普遍的概念。实际上&#xff0c;每个计算机系统重的存储设备都被组织成了一个存储器层次结构&#xff0c;如图1-9所示。…

楼梯导航案例

楼梯导航 <!DOCTYPE html> <html lang"zh-cn"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>滚动到展示区</title><link re…

Python 中将字典内容保存到 Excel 文件使用详解

概要 在数据处理和分析的过程中,经常需要将字典等数据结构保存到Excel文件中,以便于数据的存储、共享和进一步分析。Python提供了丰富的库来实现这一功能,其中最常用的是pandas和openpyxl。本文将详细介绍如何使用这些库将字典内容保存到Excel文件中,并包含具体的示例代码…