LLM 大文本分块技术详解与最佳实践
在构建基于大语言模型(LLM)的应用程序背景下,**分块(Chunking)**是将大段文本分解成较小片段的过程。这是一项必不可少的技术,有助于优化我们使用 LLM 嵌入内容后从矢量数据库获取的内容的相关性。在这篇文章中,我们将探讨它是否以及如何有助于提高 LLM 相关应用程序的效率和准确性。
分块的主要原因是为了确保我们嵌入的内容尽可能少地包含噪音,同时仍然具有语义相关性。
例如,在语义搜索中,我们会对文档语料库进行索引,每个文档都包含有关特定主题的宝贵信息。通过应用有效的分块策略,我们可以确保搜索结果准确捕捉用户查询的本质。如果我们的分块太小或太大,可能会导致搜索结果不准确或错失显示相关内容的机会。根据经验,如果文本块在没有周围上下文的情况下对人类有意义,那么对语言模型来说也是如此。因此,找到语料库中文档的最佳分块大小对于确保搜索结果准确且相关至关重要。
另一个例子是对话代理(Agent)。我们使用嵌入的块基于知识库为对话代理构建上下文,该知识库为代理提供可信信息。在这种情况下,正确选择分块策略很重要,原因有二:首先,它将确定上下文是否与我们的提示真正相关。其次,考虑到我们可以为每个请求发送的令牌数量有限,它将确定我们是否能够在将检索到的文本发送给外部模型提供商(例如 OpenAI)之前将其放入上下文中。在某些情况下,例如当使用带有 32k 上下文窗口的 GPT-4 时,拟合块可能不是问题。不过,我们需要注意何时使用非常大的块,因为这可能会对我们从知识库中获得的结果的相关性产生不利影响。
在本文中,我们将探讨几种分块方法,并讨论在选择分块大小和方法时应考虑的权衡因素。最后,我们将提供一些建议,以确定最适合您的应用程序的分块大小和方法。
嵌入短内容和长内容
当我们嵌入内容时,我们可以根据内容是短(如句子)还是长(如段落或整个文档)预测不同的行为。
句子级嵌入
当句子被嵌入时,生成的向量会关注句子的具体含义。与其他句子嵌入相比,比较自然会在这个层面上进行。这也意味着嵌入可能会错过段落或文档中更广泛的上下文信息。这对于需要精确匹配关键词或短语的场景非常有效,但在处理复杂推理任务时可能显得不足。
段落或文档级嵌入
嵌入完整段落或文档时,嵌入过程会考虑整体上下文以及文本中句子和短语之间的关系。这可以产生更全面的矢量表示,以捕捉文本的更广泛含义和主题。另一方面,较大的输入文本大小可能会引入噪音或削弱单个句子或短语的重要性,使得在查询索引时找到精确匹配变得更加困难。
查询长度的影响
查询的长度也会影响嵌入之间的关系。较短的查询(例如单个句子或短语)将集中于具体内容,可能更适合与句子级嵌入进行匹配。较长的查询(跨越多个句子或段落)可能更适合段落或文档级的嵌入,因为它可能会寻找更广泛的上下文或主题。
非同质索引
索引也可能是非同质的,包含不同大小块的嵌入。这可能会对查询结果相关性造成挑战,但也可能带来一些积极的影响。一方面,由于长内容和短内容的语义表示存在差异,查询结果的相关性可能会波动。另一方面,非同质索引可能会捕获更广泛的上下文和信息,因为不同的块大小代表文本中不同级别的粒度。这可以更灵活地适应不同类型的查询。
分块注意事项
有几个变量在确定最佳分块策略时发挥作用,这些变量根据用例而变化。以下是需要记住的一些关键方面:
- 被索引的内容的性质是什么? 您处理的是长文档(例如文章或书籍),还是短内容(例如推文或即时消息)?答案将决定哪种模型更适合您的目标,以及应应用哪种分块策略。
- 您使用的是哪种嵌入模型?它在哪些块大小上表现最佳? 例如,Sentence Transformers 模型在单个句子上效果很好,但像 BERT 这样的模型在包含 256 或 512 个标记的块上表现更好。查阅所选模型的官方文档通常能提供最佳实践建议。
- 您对用户查询的长度和复杂度有何期望? 查询内容是简短而具体,还是冗长而复杂?这也可能影响您选择对内容进行分块的方式,以便嵌入查询和嵌入块之间有更紧密的关联。
- 检索到的结果将如何在您的特定应用程序中使用? 例如,它们将用于语义搜索、问答、摘要还是其他目的?例如,如果您的结果需要输入到另一个具有令牌限制的 LLM,您必须考虑到这一点,并根据您希望在对 LLM 的请求中容纳的块数来限制块的大小。
回答这些问题将使您能够制定一个平衡性能和准确性的分块策略,这反过来将确保查询结果更加相关。
分块方法
组块划分的方法有很多种,每种方法可能适用于不同的情况。通过研究每种方法的优缺点,我们的目标是确定适合应用它们的场景。
固定大小分块
这是最常见、最直接的分块方法:我们只需决定块中的标记数量,以及(可选)它们之间是否应该有重叠。一般来说,我们希望在块之间保留一些重叠,以确保语义上下文不会在块之间丢失。在大多数情况下,固定大小的分块将是最佳路径。与其他形式的分块相比,固定大小的分块在计算上便宜且易于使用,因为它不需要使用任何 NLP 库。


