专栏名称: Datawhale
一个专注于AI领域的开源组织,汇聚了众多顶尖院校和知名企业的优秀学习者,聚集了一群有开源精神和探索精神的团队成员。愿景-for the learner,和学习者一起成长。
目录
相关文章推荐
51好读  ›  专栏  ›  Datawhale

分块的艺术:提升 RAG 效果的关键!

Datawhale  · 公众号  ·  · 2025-02-22 16:01

正文

聪明人往往很“懒”,但这种“懒”其实是高效的体现。他们总能找到解决复杂问题的最佳路径,用最少的力气获得最大的成果。

在RAG系统中,这种高效的实现往往是通过“分块”来实现的。你可以把它想象成把一本厚书分成几章——这样一来,阅读和理解就轻松多了。同样地,分块技术把大段复杂的文本拆分成更小、更容易处理的片段,让AI能更快、更准确地理解和处理信息。

不过,在深入探讨分块之前,咱们得先聊聊它背后的“大框架”——检索增强生成,也就是RAG。这个技术可是分块能发挥作用的关键哦!

什么是RAG

长话短说,检索增强生成(RAG)是一种巧妙的方法,它把检索机制和大型语言模型(LLM)结合在了一起。简单来说,就是让AI在生成回答之前,先“翻翻资料”——通过检索相关文档来增强自己的能力。这样一来,AI给出的回答不仅更准确,还能带上更多上下文信息,显得更有深度和针对性。

引入分块

分块,说白了就是把一大段文字“切”成更小、更容易处理的片段。这个过程主要分两步走:

第一步:数据准备
首先,我们需要把靠谱的数据源“切”成一个个小文档块,然后存到数据库里。如果这些小文档块还生成了对应的“嵌入”(可以理解成一种数学表示),那这个数据库就可以升级成向量存储,方便后续的快速查找。

第二步:检索
当用户抛出一个问题时,系统就会动起来,通过向量搜索、全文搜索,或者两者结合的方式,去数据库里翻找最相关的小文档块。简单来说,就是快速定位到那些和用户问题最匹配的信息片段。

这样一来,大模型不仅能更快找到答案,还能确保回答得更精准、更有针对性!

为什么分块在 RAG 架构中如此重要?

分块在 RAG 架构里可是个“关键角色”,因为它直接决定了生成式 AI 应用的准确性。可以说,它是整个流程的“第一道关卡”。

1. 小块头,大智慧:提高准确性

分块让系统能把文本切成更小的片段,方便索引和搜索。这样一来,当用户提问时,系统能快速找到最相关的片段,大大提高了检索的准确性。想象一下,与其在一整本书里翻找答案,不如直接定位到某一页的某一段——效率高多了!

2. 大小适中,上下文更给力

不过,分块也不是越小越好。块太小可能会丢失上下文信息,块太大又会让模型难以聚焦。理想的分块大小能让生成模型更好地理解每个片段的上下文,从而生成更连贯、更准确的回答。这样一来,模型就不用在一大堆无关信息里“大海捞针”了。

3. 可扩展性与性能:高效处理大数据

分块还能让 RAG 系统更高效地处理海量数据。通过把数据切成可管理的部分,系统可以并行处理这些块,减少计算负担,提升整体性能。这样一来,RAG 系统不仅能处理更多数据,还能跑得更快、更稳。

总之,分块不仅是 RAG 系统的技术必需品,更是一种战略方法。它提高了检索准确性、处理效率和资源利用率,是 RAG 应用成功的“秘密武器”。

优化分块的技巧:从基础到高级

分块可不是随便“切一切”就完事了,想要让 RAG 系统表现得更出色,得用上一些技巧。下面这些方法,从简单到复杂,总有一款适合你:

1. 固定字符大小:简单粗暴

这是最直接的方法——把文本按固定字符数切成块。比如每 500 个字符切一刀。虽然简单,但有时候效果还不错,尤其是对格式规整的文本。

2. 递归字符文本分割:按标点“下刀”

这种方法更聪明一点,它会根据空格、标点符号(比如句号、逗号)来切分文本。这样一来,切出来的块更有上下文意义,不会把一句话硬生生切成两半。

3. 特定文档的拆分:因地制宜

不同类型的文档(比如 PDF、Markdown)结构不一样,分块方法也得跟着变。比如,PDF 可以按段落切,Markdown 可以按标题切。这种“量身定制”的方法能让分块更精准。

4. 语义分割:按意思切块

这种方法更高级,它会用嵌入技术(embedding)来分析文本的语义,然后根据意思来分块。比如,把讨论同一个话题的句子归到一起。这样一来,切出来的块不仅更连贯,还能更好地保留上下文。

5. 自主分割:让 AI 自己决定

这是最“智能”的方法——直接让大型语言模型(LLM)根据内容和上下文来决定怎么分块。AI 会自己判断哪里该切,哪里该留,确保每个块都有完整的意义。

通过灵活运用这些技巧,RAG 系统的性能和准确性都能大幅提升。分块不仅是技术活儿,更是一门艺术——掌握得好,AI 的表现就能更上一层楼!

固定字符大小分块:简单但有点“呆”

固定字符大小分块是最基础的分块方法,简单来说,就是不管内容如何,直接按固定的字符数把文本“切”成块。比如,每 300 个字符切一刀,完事儿。

固定字符大小分块的优缺点

优点

  1. 简单省事 :这种方法实现起来超级简单,几乎不需要什么计算资源,特别适合快速上手。
  2. 整齐划一 :生成的块大小均匀,方便后续处理,比如存储或检索。

缺点

  1. 忽略上下文 :它完全不管文本的结构和意思,切出来的块可能会把完整的信息拆得支离破碎。
  2. 效率不高 :重要的内容可能会被“拦腰截断”,想要重新拼出有意义的信息,还得额外费功夫。

下面是如何使用代码实现固定字符大小分块的示例:

# 将示例文本分块
text = "This is the text I would like to ch up. It is the example text for this exercise." 

# 设置块大小
chunk_size = 35 
# 初始化一个列表来保存块 chunks
 = [] 
# 遍历文本以创建块
for i in  range ( 0 , len (text), chunk_size): 
    chunk = text[i:i + chunk_size] 
    chunks.append(chunk) 
# 显示块
print (chunks) 
# 输出:['This is the text I would like to ch', 'unk up. It is the example text for ', 'this exercise']

使用 LangChainCharacterTextSplitter 来实现相同的结果:


from langchain.text_splitter import CharacterTextSplitter 

# 使用指定的块大小初始化文本分割器
text_splitter = CharacterTextSplitter(chunk_size= 35 , chunk_overlap= 0 , Separator= '' , strip_whitespace= False ) 
# 使用文本分割器创建文档
documents = text_splitter.create_documents([text]) 
# 显示创建的文档
for doc in documents: 
    print (doc.page_content) 

固定字符大小分块是一种简单但基础的技术,通常在转向更复杂的方法之前用作基准。

递归字符文本分割:保持上下文关联

递归字符文本分割是一种更高级的技术,它考虑了文本的结构。它使用一系列分隔符以递归方式将文本分成块,确保块更有意义且与上下文更相关。

在上面的例子中,我们设置了一个块大小为30个字符,重叠部分为20个字符。RecursiveCharacterTextSplitter这个工具会尽量在保持文本逻辑结构的同时进行拆分。不过,这也暴露了一个问题:由于块大小设置得比较小,它还是有可能在单词或句子中间“咔嚓”一刀,这显然不是我们想要的效果。

优点:

  • 上下文更连贯 :这种方法通过使用段落或句子作为分隔符,能够更好地保留文本的自然结构。
  • 灵活性强 :你可以根据需要调整块的大小和重叠部分,这样就能更精细地控制整个分块过程。

缺点:

  • 块大小是个关键 :块的大小得适中,既要方便处理,又要确保每个块至少包含一个完整的短语或更多内容。否则,我们在检索这些块时,可能会遇到精度问题。
  • 性能消耗 :由于采用了递归拆分和处理多个分隔符的方式,这种方法会消耗更多的计算资源。而且,与固定大小的块相比,它生成的块数量也会更多。






请到「今天看啥」查看全文