免费POC, 零成本试错
AI知识库

AI知识库

学习大模型的前沿技术与行业落地应用


收藏

RAG如何选择最佳分块大小?

发布日期:2025-04-03 12:52:10 浏览次数: 3239
作者:三黄工作室

微信搜一搜,关注“三黄工作室”

推荐语

探索如何通过最佳分块策略优化大语言模型应用,提高语义搜索和Chatbot的效率和准确性。

核心内容:
1. 分块在大语言模型中的作用与重要性
2. 分块策略对语义搜索和Chatbot的影响
3. 选择合适的分块大小和方法的权衡因素

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

今天和大家讲一下Chunking(分块) 在构建LLM(大语言模型)相关应用中的重要性。

如果你经常接触LLM相关的项目,这里提到的“分块”就显得尤为重要了。简单来说,分块就是把一大段文本拆分成更小的部分。这个过程对于优化从向量数据库中检索到的内容的相关性非常关键,尤其是在我们用LLM对内容进行嵌入时。

我们都知道现在任何内容被索引之前,都需要先进行嵌入处理。而分块的主要目的就是为了确保我们在嵌入的时候,能够尽量减少噪声,同时让语义保持相关性。

举个例子,在语义搜索中,我们需要索引大量文档,每篇文档都包含某个特定主题的重要信息。通过有效的分块策略,我们可以确保搜索结果能精准地捕捉用户的查询意图。如果分块太小或太大,就会导致搜索结果不够精确,甚至会错过一些重要的相关内容。

一般的经验法则是:如果一段文本在没有上下文的情况下对人类是有意义的,那么它对语言模型也会有意义。因此,找到适合文档集合的最佳分块大小,是确保搜索结果准确性和相关性的关键。

当然,分块的策略不仅仅适用于语义搜索,还广泛应用于对话AI(Chatbot)。在Chatbot中,嵌入后的分块内容会被用来构建基于知识库的上下文,从而让ChatBot有可靠的依据去生成回答。在这种场景下,选择正确的分块策略非常重要,主要有两个原因:

第一,这决定了上下文是否真的与我们的提问相关;

第二,这也决定了我们能否在将文本发送给外部模型提供者(例如OpenAI)之前,将其适配到有限的token窗口内。

在某些情况下,比如使用GPT-4这种支持32k上下文窗口的模型时,适应大块文本可能不是问题。但我们仍然需要谨慎对待过大块的情况,因为这可能会影响检索到的结果的相关性。

在这篇文章里,我们会探讨几种不同的分块方法,并讨论在选择分块大小和方法时需要考虑的权衡因素。最后,会给出一些建议,帮助你为自己的应用选择最佳的分块大小和方法。

 嵌入短内容和长内容的不同表现 

当我们对内容进行嵌入时,可以预见根据内容长短的不同,嵌入的表现也会有所区别。短内容(如句子)和长内容(如段落或整篇文章)的处理方式会有显著差异。

当一个句子被嵌入时,生成的向量主要聚焦于该句子的具体含义。比较也自然会在这样的粒度上进行。不过,这种方式可能会忽略掉段落或文档中更广泛的上下文信息。

相比之下,当整个段落或文档被嵌入时,嵌入过程会同时考虑整体上下文以及句子和短语之间的关系。这样得到的向量表示往往更加全面,能够捕捉到文本的宏观意义和主题。但另一方面,较大的输入文本可能会引入噪音,稀释个别句子或短语的重要性,从而使得在查询索引时难以找到精确匹配。

此外,查询的长度也会影响嵌入之间的关联性。较短的查询(如单句或短语)会更关注细节,因此更适合与句子级别的嵌入进行匹配。而较长的查询(如多句或多段)则可能更适合与段落或文档级别的嵌入进行匹配,因为它通常寻找的是更广义的上下文或主题。

索引也可能呈现非同质化的特点,即其中包含不同大小的分块嵌入。这种情况既带来挑战,也可能有一些积极的效果。一方面,由于长内容和短内容的语义表征存在差异,查询结果的相关性可能会波动。另一方面,非同质化的索引有可能捕捉到更广泛的上下文和信息,因为不同大小的分块代表了文本的不同粒度,这可以让系统更灵活地应对各种类型的查询。

 分块策略要考虑的因素 

有几个变量会影响最佳分块策略的选择,这些变量因应用场景而异。以下是一些需要注意的关键点:

  1. 要索引的内容性质是什么? 是处理长文档(如文章或书籍)还是短内容(如术语解释或聊天消息)?答案不仅决定了哪种模型最适合你的目标,也决定了应该采用什么样的分块策略。
  2. 使用的是哪种嵌入模型,它在哪些分块大小上表现最佳? 比如,sentence-transformer模型在处理单独句子时表现良好,而像text-embedding-ada-002这样的模型则在包含256或512个token的分块上效果更好。
  3. 用户查询的长度和复杂性预期如何? 查询是简短具体的,还是冗长复杂的?这也会影响你如何选择分块策略,以确保嵌入查询和嵌入分块之间有更好的相关性。
  4. 检索结果将在具体应用中如何使用? 例如,它们是用来做语义搜索、问答、摘要生成还是其他用途?如果结果需要传递给另一个有token限制的LLM,那必须考虑这一点,并根据你想放入请求中的分块数量来限制分块的大小。

回答这些问题将帮助你制定出一种既能平衡性能又能保证准确性的分块策略,从而使查询结果更加相关。

 分块方法 

分块的方法有很多种,每种方法在不同情况下各有优劣。通过分析每种方法的利弊,我们要能够找出最适用自己场景的方法。

固定大小分块

这是最常见的也是最直接的分块方法:我们只需决定每个分块包含的token数量,并且可以选择是否让它们之间有一定的重叠。一般来说,为了让语义上下文不会在分块之间丢失,我们会保留一些重叠部分。固定大小分块在大多数常见情况下都是最优路径。与其他形式的分块相比,这种方法计算成本低且易于使用,因为它不需要依赖任何NLP库。

下面是一个使用LangChain进行固定大小分块的例子:

text = "..." # 文本
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
  separator = "\n",
  chunk_size = 256,
  chunk_overlap = 20
)
docs = text_splitter.create_documents([text])

“内容感知”分块

这是一系列利用待分块内容特性并施加更复杂分块方法的策略。以下是几个例子:

句子分割

正如前面提到的,许多模型在嵌入句子级别内容时表现优异。自然地,我们会使用句子分块,而且有许多方法和工具可以实现这一点,包括:

  • 朴素分割: 最简单的办法是按句号(“.”)和换行符分割句子。虽然这种方法快速简单,但无法考虑到所有可能的边界情况。以下是一个非常简单的例子:
text = "..." # 文本
docs = text.split(".")
  • NLTK:自然语言工具包(NLTK)是一个流行的用于处理人类语言数据的Python库。它提供了句子分词器,可以帮助将文本分割成句子,从而创建更有意义的分块。例如,要结合LangChain使用NLTK,可以这样做:
text = "..." # 文本
from langchain.text_splitter import NLTKTextSplitter
text_splitter = NLTKTextSplitter()
docs = text_splitter.split_text(text)
  • spaCy:spaCy是另一个强大的Python NLP任务库。它提供了复杂的句子分割功能,可以高效地将文本划分为独立的句子,从而更好地保留上下文。例如,结合LangChain使用spaCy,可以这样做:
text = "..." # 文本
from langchain.text_splitter import SpacyTextSplitter
text_splitter = SpaCyTextSplitter()
docs = text_splitter.split_text(text)

递归分块

递归分块以分层和迭代的方式将输入文本划分成更小的块,使用一组分隔符。如果最初的尝试未能产生所需大小或结构的块,该方法会递归调用自身,直到达到所需的块大小或结构为止。这意味着尽管块的大小不一定完全相同,但它们仍然会“趋向”于相似的大小。

以下是如何使用LangChain进行递归分块的示例:

text = "..." # 文本
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
  # 设置一个非常小的块大小,只是为了展示。
  chunk_size = 256,
  chunk_overlap = 20
)
docs = text_splitter.create_documents([text])

专门分块

Markdown和LaTeX是两种常见的结构化和格式化内容的例子。在这些情况下,可以使用专门的分块方法来在分块过程中保留原始结构。

  • Markdown:Markdown是一种常用的轻量级标记语言,用于格式化文本。通过识别Markdown语法(例如标题、列表和代码块),可以智能地根据其结构和层次划分内容,从而生成更具语义一致性的块。例如:
from langchain.text_splitter import MarkdownTextSplitter
markdown_text = "..."
markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)
docs = markdown_splitter.create_documents([markdown_text])
  • LaTex:LaTeX是一种文档准备系统和标记语言,常用于学术论文和技术文档。通过解析LaTeX命令和环境,可以创建尊重内容逻辑组织的块(例如章节、小节和方程),从而获得更准确和上下文相关的结果。例如:
from langchain.text_splitter import LatexTextSplitter
latex_text = "..."
latex_splitter = LatexTextSplitter(chunk_size=100, chunk_overlap=0)
docs = latex_splitter.create_documents([latex_text])

语义分块

这是一种新的分块方法,由Greg Kamradt首次提出。在他的代码示例中,Kamradt指出,全局分块大小可能过于简单,无法考虑到文档内各段落的含义。如果我们使用这种机制,就无法知道我们是否在组合那些彼此无关的段落。

这是代码示例地址:https://github.com/FullStackRetrieval-com/RetrievalTutorials/blob/main/tutorials/LevelsOfTextSplitting/5_Levels_Of_Text_Splitting.ipynb

这种语义分析可以用来创建围绕同一主题或话题的句子组成的块。

以下是使语义分块工作所需的步骤:

  1. 将文档分解为句子。
  2. 创建句子组:对于每个句子,创建一个包含该句子前后若干句子的组。这个组本质上是由创建它的句子“锚定”的。可以决定在每个组中包含多少前后的句子——但组内的所有句子都将与一个“锚定”句子相关联。
  3. 为每个句子组生成嵌入,并将其与“锚定”句子相关联。
  4. 顺序比较每组之间的距离:依次查看文档中的句子时,只要主题或话题保持不变,当前句子组与其前一句子组的语义距离就会较低。相反,较高的语义距离表明主题或话题发生了变化。这可以有效地将一个块与下一个块区分开来。

LangChain基于Kamradt的工作创建了一个语义分块分割器。

地址为:https://python.langchain.com/docs/modules/data_connection/document_transformers/semantic-chunker/

 找到适合应用的最佳分块大小 

以下建议,可以帮助你在常见的分块方法(如固定分块)不适用时,确定最佳的分块大小。

  • 预处理数据 - 在确定最佳分块大小之前,需要先对数据进行预处理以确保质量。例如,如果数据是从网络上获取的,可能需要移除HTML标签或其他仅增加噪音的元素。
  • 选择一系列分块大小 - 数据预处理完成后,下一步是选择一系列潜在的分块大小进行测试。如前所述,选择应考虑到内容的性质(例如短消息或长文档)、将使用的嵌入模型及其能力(例如token限制)。目标是在保持上下文的同时维持准确性。开始时可以探索多种分块大小,包括较小的块(例如128或256个token)以捕捉更细粒度的语义信息,以及较大的块(例如512或1024个token)以保留更多上下文。
  • 评估每个分块大小的性能 - 为了测试各种分块大小,可以使用多个索引。使用代表性数据集,为要测试的分块大小创建嵌入并保存在索引中。然后运行一系列查询来评估质量,并比较不同分块大小的性能。这是一个迭代过程,需要针对不同的查询测试不同的分块大小,直到能确定最适合内容和预期查询的最佳分块大小。

 结论 

分块没有一刀切的解决方案,所以适合一个用例的方法可能不适合另一个。希望这篇文章能帮助你更好地理解如何为你的应用选择合适的分块策略。

- END -

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询

扫码登录
登录即表示您同意《53AI网站服务协议》
服务协议

欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。

在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。

一、 定义

本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。

会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。

知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。

二、 账号注册与登录

登录方式:本网站支持以下登录方式,您可根据实际情况选择:

微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。

手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。

账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。

实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。

未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。

三、 服务内容与规范

知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。

服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。

禁止行为:您在使用服务时不得实施以下行为:

利用技术手段批量爬取、下载、转存知识库内容;

将知识库内容用于商业目的或未经授权地向第三方传播;

干扰本网站正常运行或侵犯其他用户合法权益;

发布违法违规信息或从事违反公序良俗的活动。

四、 知识产权声明

权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。

有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。

侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。

五、 个人信息保护

我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。

您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。

您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。

六、 免责声明

内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。

不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。

第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。

七、 违约责任

如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。

如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。

八、 法律适用与争议解决

本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。

因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。

九、 其他

本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。

本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。

我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。


已查阅