LLM之RAG实战(二十)| RAG分块策略的五个level

38 篇文章 40 订阅

       在RAG系统中,包括检索和生成两大组件,而检索的关键是对数据的分块策略,本文将根据Greg Kamradt的视频(https://www.youtube.com/watch?v=8OJC21T2SL4)整理如下五个分块级别策略,代码实现在参考文献[2]

级别1:Fixed Size Chunking

       这是最粗糙和最简单的文本分割方法。它将文本分解为指定数量的字符块,而不考虑其内容或结构。

   Langchain和llamaindex框架为这种分块技术提供了CharacterTextSplitterSentenceSplitter(默认为对句子进行拆分)类。需要记住的几个概念:

  • 文本的拆分方式:按单个字符
  • 区块大小的测量方式:按字符数
  • chunk_size:块中的字符数
  • chunk_overlap:在顺序块中重叠的字符数。跨块保留重复数据
  • 分隔符:用于分割文本的字符(默认为“”)

级别2:Recursive Chunking

       虽然固定大小的分块更容易实现,但它不考虑文本的结构。递归分块使用一组分隔符,以分层和迭代的方式将文本划分为更小的块。如果最初分割文本的尝试没有产生所需大小的块,则该方法会使用不同的分隔符递归地调用结果块,直到达到所需的块大小。

       Langchain框架提供了RecursiveCharacterTextSplitter类,该类使用默认分隔符(“\n\n”, “\n”, “ “,””)分割文本

级别3:Document Based Chunking

       在这种分块方法中,我们根据文档的固有结构对其进行拆分。这种方法考虑了内容的流动和结构,但可能不是缺乏明确结构的文件。

  • Document with Markdown:Langchain提供MarkdownTextSplitter类,以分隔符的方式分割Markdown文件。
  • Document with Python/JS:Langchain提供了PythonCodeTextSplitter来根据类、函数等对Python程序进行拆分,我们可以将语言提供到RecursiveCharacterTextSplitter类的from_langage方法中。
  • Document with tables:在处理表时,基于级别1和级别2的拆分可能会丢失行和列之间的表格关系。为了保持这种关系,以语言模型能够理解的方式格式化表内容(例如,使用HTML中的<table>标记、以“;”分隔的CSV格式等)。在语义搜索过程中,直接从表中匹配嵌入可能很有挑战性。开发人员可以在提取表格内容后进行摘要提取,然后针对该摘要生成嵌入,从而进行语义匹配。
  • Document with images (Multi- Modal):图像和文本的嵌入内容可能不同(尽管CLIP模型支持这一点)。理想的策略是使用多模态模型(如GPT-4视觉)来生成图像的摘要并存储其嵌入。Unstructured.io提供了partition_pdf方法可以从pdf文档中提取图像。

第4级:语义块

       以上三个级别都处理文档的内容和结构,并且需要保持块大小的恒定值。这种分块方法旨在从嵌入中提取语义,然后评估这些分块之间的语义关系。核心思想是将语义相似的块放在一起。

      LlamaIndex具有SemanticSplitterNodeParser类,该类允许使用块之间的上下文关系将文档拆分为块,使用嵌入相似性自适应地选择句子之间的断点。

SemanticSplitterNodeParser超参数介绍:

  • buffer_size:配置块的初始窗口大小;
  • breakpoint_percentile_threshold:决定在何处分割块的阈值;
  • embed_model:使用的嵌入模型。

第5级:代理分块

       这种分块策略探索了使用LLM来根据上下文确定块中应包含多少文本以及哪些文本的可能性。

       为了生成初始块,参考论文《Dense X Retrieval: What Retrieval Granularity Should We Use?》,从原始文本中提取独立语句。Langchain提供了propositional-retrieval模板(https://templates.langchain.com/new?integration_name=propositional-retrieval)来实现这一点。

       在生成命题之后,这些命题输入到基于LLM的代理。该代理确定命题是否应包括在现有块中,或者是否应创建新块。

参考文献:

[1] https://medium.com/@anuragmishra_27746/five-levels-of-chunking-strategies-in-rag-notes-from-gregs-video-7b735895694d

[2] https://github.com/FullStackRetrieval-com/RetrievalTutorials/blob/main/5_Levels_Of_Text_Splitting.ipynb

[3] https://docs.llamaindex.ai/en/stable/examples/node_parsers/semantic_chunking.html

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的引用内容,可以得知prompt+RAG的流程如下: 1. 首先,使用Retriever部分在知识库中检索出top-k个匹配的文档zi。 2. 然后,将query和k个文档拼接起来作为QA的prompt,送入seq2seq模型。 3. seq2seq模型生成回复y。 4. 如果需要进行Re-rank,可以使用LLM来rerank,给LLM写好prompt即可。 下面是一个简单的示例代码,演示如何使用prompt+RAG: ```python from transformers import RagTokenizer, RagRetriever, RagSequenceForGeneration # 初始化tokenizer、retriever和seq2seq模型 tokenizer = RagTokenizer.from_pretrained('facebook/rag-token-base') retriever = RagRetriever.from_pretrained('facebook/rag-token-base', index_name='exact', use_dummy_dataset=True) model = RagSequenceForGeneration.from_pretrained('facebook/rag-token-base') # 设置query和context query = "What is the capital of France?" context = "France is a country located in Western Europe. Paris, the capital city of France, is known for its romantic ambiance and iconic landmarks such as the Eiffel Tower." # 使用Retriever部分检索top-k个匹配的文档 retrieved_docs = retriever(query) # 将query和k个文档拼接起来作为QA的prompt input_dict = tokenizer.prepare_seq2seq_batch(query, retrieved_docs[:2], return_tensors='pt') generated = model.generate(input_ids=input_dict['input_ids'], attention_mask=input_dict['attention_mask']) # 输出生成的回复 generated_text = tokenizer.batch_decode(generated, skip_special_tokens=True)[0] print(generated_text) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wshzd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值