LLM应用的分块策略

每日推荐一篇专注于解决实际问题的外文,精准翻译并深入解读其要点,助力读者培养实际问题解决和代码动手的能力。

欢迎关注公众号

原文标题:Chunking Strategies for LLM Applications

原文地址:https://www.pinecone.io/learn/chunking-strategies/


LLM应用的分块策略

在构建与LLM相关的应用程序的背景下,分块是将大段文本分解为较小段的过程。这是一种关键的技术,有助于在使用LLM嵌入内容后,优化从矢量数据库获取的内容的相关性。在本博客文章中,我们将探讨分块是否以及如何提高LLM相关应用程序的效率和准确性。

正如我们所知,我们在Pinecone中索引的任何内容都需要首先进行嵌入。分块的主要原因是确保我们嵌入的内容尽可能少地包含噪音,同时仍然在语义上相关。

例如,在语义搜索中,我们索引一系列文档,每个文档都包含特定主题的有价值信息。通过应用有效的分块策略,我们可以确保我们的搜索结果准确捕捉用户查询的本质。如果我们的文本块太小或太大,可能会导致不精确的搜索结果或错过展示相关内容的机会。通常来说,如果文本块在不考虑周围上下文的情况下对人类来说是有意义的,那么对语言模型来说也是有意义的。因此,找到语料库中文档的最佳分块大小对确保搜索结果准确和相关至关重要。

另一个例子是对话代理(我们之前使用Python和Javascript进行了介绍)。我们使用嵌入的块来构建基于知识库的对话代理的上下文,该知识库将代理置于可信的信息中。在这种情况下,选择正确的分块策略非常重要,原因有两个:首先,它将决定上下文是否真正与我们的提示相关。其次,它将决定我们是否能够将检索到的文本适应到上下文中,然后发送给外部模型提供商(例如,OpenAI),考虑到我们每次请求可以发送的令牌数量的限制。在某些情况下,比如在使用具有32k上下文窗口的GPT-4时,适应文本块可能不是问题。然而,我们需要注意,当我们使用非常大的文本块时,这可能会对我们从Pinecone得到的结果的相关性产生负面影响。

在这篇文章中,我们将探讨几种分块方法,并讨论在选择分块大小和方法时应考虑的权衡。最后,我们将给出一些关于确定最佳分块大小和方法的建议,这将适用于您的应用程序。

1.嵌入短内容和长内容

当我们嵌入我们的内容时,我们可以预见到根据内容的长度(如句子或段落,甚至整篇文章)的不同,会有不同的行为。

当一个句子被嵌入时,生成的向量专注于句子的特定含义。与其他句子嵌入比较时,比较通常会在这个层面上进行。这也意味着嵌入可能会错过在段落或文档中发现的更广泛的上下文信息。

当整个段落或文章被嵌入时,嵌入过程会同时考虑整体上下文和文本内部句子和短语之间的关系。这可能导致一个更全面的向量表示,捕捉文本的广泛含义和主题。另一方面,更大的输入文本大小可能会引入噪音或淡化单个句子或短语的重要性,使得在查询索引时找到精确匹配更困难。

查询的长度也会影响嵌入之间的关系。更短的查询,如单个句子或短语,会集中在特定的细节上,可能更适合与句子级别的嵌入进行匹配。超过一句话或一段落的更长查询可能会更符合段落或文档级别的嵌入,因为它可能在寻找更广泛的上下文或主题。

索引也可能是非均匀的,包含各种大小的块嵌入。这可能在查询结果的相关性方面带来挑战,但也可能带来一些积极的影响。一方面,由于长、短内容的语义表示之间的差异,查询结果的相关性可能会波动。另一方面,非均匀索引可能捕获更广泛的上下文和信息,因为不同大小的块代表了文本中不同级别的粒度。这可能更灵活地适应不同类型的查询。

2.分块的考虑因素

确定最佳分块策略的几个变量会根据使用场景的不同而变化。以下是一些需要考虑的关键因素:

(1)被索引的内容是什么性质?你是在处理长的文档,如文章或书籍,还是较短的内容,如推特或即时信息?答案将决定哪个模型更适合你的目标,因此,也会决定应用什么样的分块策略。

(2)你正在使用哪种嵌入模型,以及它对哪种大小的块有最佳的性能?例如,句子-转换器模型在处理单个句子时表现良好,但像text-embedding-ada-002这样的模型在处理包含256或512个标记的块时表现更好。

(3)你对用户查询的长度和复杂性有什么期望?他们会是短而具体,还是长且复杂?这可能会影响你选择如何分块内容,以便嵌入查询和嵌入块之间有更紧密的关联。

(4)在你的特定应用中如何使用检索到的结果?例如,他们会被用于语义搜索,问答,总结,还是其他目的?例如,如果你的结果需要被输入到另一个具有标记限制的LLM中,你就必须考虑这个因素,并根据你希望适应到LLM请求的块数量来限制块的大小。

回答这些问题将使你能够制定出一个平衡性能和精度的分块策略,这反过来也将确保查询结果的相关性更高。

3.分块方法

有多种不同的分块方法,每种方法可能适合不同的情况。通过分析每种方法的优点和缺点,我们的目标是确定适合应用它们的正确场景。

3.1固定大小分块

这是最常见和最直接的分块方法:我们只需决定我们的块中的token数,并选择性地决定它们之间是否应存在任何重叠。一般来说,我们会希望块之间保持一些重叠,以确保语义上下文不会在块之间丢失。固定大小的分块在大多数常见情况下将是最好的路径。与其他形式的分块相比,固定大小的分块在计算上便宜且使用简单,因为它不需要使用任何NLP库。

以下是使用LangChain执行固定大小分块的示例:

text = "..." # your text
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(separator = "\n\n",chunk_size = 256,chunk_overlap  = 20
)
docs = text_splitter.create_documents([text])
3.2内容感知分块

这是一组方法,用于利用我们正在分块的内容的性质,并应用更复杂的分块方法。以下是一些例子:

(1)句子分割

如我们之前提到的,许多模型都是针对嵌入句子级内容进行优化的。自然地,我们会使用句子分块,有几种方法和工具可以执行此操作,包括:

  • 简单分割:最简单的方法是按句号(“。”)和换行符进行分割。虽然这可能很快且简单,但此方法不能考虑所有可能的边缘情况。以下是一个非常简单的例子:
text = "..." # your text
docs = text.split(".")
  • NLTK:自然语言工具包(NLTK)是用于处理人类语言数据的流行Python库。它提供了一个可以将文本分割成句子的句子标记器,有助于创建更有意义的文本块。例如,要将NLTK与LangChain一起使用,您可以执行以下操作:
text = "..." # your text
from langchain.text_splitter import NLTKTextSplitter
text_splitter = NLTKTextSplitter()
docs = text_splitter.split_text(text)
  • spaCy:spaCy是另一个用于NLP任务的强大Python库。它提供了复杂的句子分割功能,可以有效地将文本划分为独立的句子,使得后续块中更好地保留上下文。例如,要将spaCy与LangChain一起使用,您可以执行以下操作:
text = "..." # your text
from langchain.text_splitter import SpacyTextSplitter
text_splitter = SpaCyTextSplitter()
docs = text_splitter.split_text(text)

(2)递归分块

递归分块使用一组分隔符以分层和迭代的方式将输入文本划分为更小的块。如果首次尝试分割文本未能产生所需大小或结构的块,该方法会递归地在结果块上调用自身,并使用不同的分隔符或标准,直到达到所需的块大小或结构。这意味着,虽然块不会完全相同大小,但它们仍会“渴望”达到类似的大小。

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

text = "..." # your text
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(# Set a really small chunk size, just to show.chunk_size = 256,chunk_overlap  = 20
)docs = text_splitter.create_documents([text])

(3)专用分块

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])

4.为您的应用确定最佳的块大小

如果常见的分块方法(如固定分块)不能轻松适用于您的用例,以下是一些提示,帮助您找出最优的块大小。

  • 预处理你的数据 - 在确定应用程序的最佳块大小之前,你首先需要预处理你的数据以确保质量。例如,如果你的数据是从网页获取的,你可能需要删除HTML标签或特定只增加噪音的元素。

  • 选择一定范围的块大小 - 数据预处理完成后,下一步是选择一定范围的潜在块大小进行测试。如前所述,这个选择应考虑到内容的性质(例如,短消息或长篇文档)、你将使用的嵌入模型及其功能(例如,token限制)。目标是在保留上下文和维持准确性之间找到平衡。可以通过探索不同的块大小开始,包括较小的块(例如,128或256 token)用于捕获更细粒度的语义信息,和较大的块(例如,512或1024 token)用于保留更多的上下文。

  • 评估每个块大小的性能 - 为了测试各种块大小,你可以使用多个索引或单个索引与多个命名空间。有了代表性的数据集,创建你想要测试的块大小的嵌入,然后保存在你的索引中。然后你可以运行一系列可以评估质量的查询,并比较各种块大小的性能。这很可能是一个迭代的过程,在这个过程中你要测试各种块大小与不同的查询,直到你能确定最适合你的内容和预期查询的最佳性能的块大小。

5.结论

在大多数情况下,对您的内容进行分块是相当简单的 - 但当您开始走出常规思维时,它可能会带来一些挑战。分块没有一种适合所有情况的解决方案,所以对一个用例有效的方法可能对另一个用例无效。希望这篇文章可以帮助您更好地理解如何为您的应用程序进行分块的方法。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。

在数字化时代,采购管理也正经历着前所未有的变革。全过程数字化采购管理成为了企业追求高效、透明和规范的关键。该系统通过Spring Cloud、Spring Boot2、Mybatis等先进技术,打造了从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通过…

MySQL 数值函数,字符串函数与多表查询

MySQL像其他语言一样,也提供了很多库函数,分为单行函数和分组函数(聚合函数),我们这里先简易介绍一些函数,熟悉就行,知道怎么使用即可. 数值函数 三角函数 指数与对数函数 进制间的转换函数 字符串函数 注:LPAD函数是右对齐,RPAD函数是左对齐 多表查询 注:如果为表起了别名,就…

Origin 2021软件安装包下载及安装教程

Origin 2021下载链接:https://docs.qq.com/doc/DUnJNb3p4VWJtUUhP 1.选中下载的压缩包,然后鼠标右键选择解压到"Origin 2021"文件夹 2.双击打开“Setup”文件夹 3.选中“Setup.exe”鼠标右键点击“以管理员身份运行” 4.点击“下一步" 5…

Photoshop显示16位/32位像素值

打开“信息”窗口-单击“画笔”图标-子菜单中选择16位/32位

c++_09_继承

1 继承 C的继承是弱继承 继承的语法: class 子类 : 继承方式1 基类1, 继承方式2 基类2, ... { ... }; 继承方式: 共有继承 public 保护继承 protected 私有继承 private 2 继承的基本属性(3种继承方式均有) 继承所…

TypeScript 之 interface 和 type 的区别

结论: 1、可以声明的数据类型 type 可以修饰任何类型 (值类型和引用数据类型) interface 只能修饰引用类型 (对象、数组、函数) //interface 声明对象属性 interface ins {a: string;b?: number; //可选项 }// int…

spring创建与使用

spring创建与使用 创建 Spring 项⽬创建⼀个 Maven 项⽬添加 Spring 框架⽀持添加启动类 存储 Bean 对象创建 Bean将 Bean 注册到容器 获取并使⽤ Bean 对象创建 Spring 上下⽂获取指定的 Bean 对象获取bean对象的方法 使⽤ Bean 总结 创建 Spring 项⽬ 接下来使⽤ Maven ⽅式…

简写英语单词

题目: 思路: 这段代码的主要思路是读取一个字符串,然后将其中每个单词的首字母大写输出。具体来说,程序首先使用 fgets 函数读取一个字符串,然后遍历该字符串中的每个字符。当程序遇到一个字母时,如果此时…

Django开发3

Django开发3 Django开发编辑用户9.靓号管理9.1 表结构9.2 靓号列表9.3 新建靓号9.4 编辑靓号9.5 搜索手机号9.6 分页 10.时间插件11.ModelForm和BootStrap操作 各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料! Django开发 部门管…

系统功能测试的最好方法

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情 测试系统功能是软件开发和工程过程中的关键步骤。 它确保系统或软件应用程序按预期运行、满足用户要求并可靠运行。 在这里,我们深入探讨最佳方法&a…

软件测试/测试开发丨Linux进程与线程学习笔记

1、进程 可执行程序的运行态操作系统调度的基本单位线程容器进程本身包含指令、数据等资源 2、 线程 进程中被执行的最小单元cpu 调度的基本单位线程带有指令、数据等资源 3、 进程的生命周期 如执行sleep 100或者执行一个python脚本 创建:created sleep 100 ./…

JavaScript的三种引入的方式

目录 (一).什么是JS1.1JS的特点1.2JS的组成 (二).JS引用的三种方式2.1标签引用(或嵌入式)2.2文件引用(外链式)2.3行内式 (三).JS三种引用方式的优缺点1.行内方式:2.标签引用(或嵌入式):3.文件引…