RAG 高效应用指南

构建一个检索增强生成 (Retrieval-Augmented Generation, RAG) 应用的概念验证过程相对简单,但要将其推广到生产环境中则会面临多方面的挑战。这主要是因为 RAG 系统涉及多个不同的组件,每个组件都需要精心设计和优化,以确保整体性能达到令人满意的水平。在这一过程中,外部非结构化数据的清洗和处理、文本分块、Query 的预处理、是不是每次 Query 都要进行检索、上下文信息的检索和排序能力、如何评估检索生成质量、知识缓存等环节都会影响系统的性能。

『RAG 高效应用指南』系列将就如何提高 RAG 系统性能进行深入探讨,提供一系列具体的方法和建议。同时读者也需要记住,提高 RAG 系统性能是一个持续的过程,需要不断地评估、优化和迭代。

本文是『RAG 高效应用指南』系列的第 1 篇文章,本文将首先对 RAG 系统前置离线环节的文档解析和文本分块进行深入探讨。

RAG 简介

2020 年,Meta AI 研究人员提出了检索增强生成(RAG)的方法,用于提高 LLM 在特定任务上的性能。LLM 擅长语言理解、推理和生成等任务,但也存在一些问题:

  • 信息滞后:LLM 的知识是静态的,来源于当时训练时的数据,也就是 LLM 无法直接提供最新的信息。

  • 模型幻觉:实践表明,当前的生成式 AI 技术存在一定的幻觉,而在一些常见的业务应用中,我们是希望保证事实性的。

  • 私有数据匮乏:LLM 的训练数据主要来源于互联网公开的数据,而垂类领域、企业内部等有很多专属知识,这部分是 LLM 无法直接提供的。

RAG 通过将检索到的相关信息提供给 LLM,让 LLM 进行参考生成,可以较好地缓解上述问题。因此,合理使用 RAG 可以拓展 LLM 的知识边界,使其不仅能够访问专属知识库,还能动态地引入最新的数据,从而在生成响应时提供更准确、更新的信息。

如图所示,是一个 RAG 应用的基本架构,可以分为离线和在线两部分。

  • 离线:对知识库文档进行解析、拆分、索引构建和入库。这部分可以说是 dirty work,因为需要对多种不同格式的文档数据进行大量的清洗和处理等;但同时又是非常重要的工作,因为 「Garbage in, Garbage out」,数据质量是影响 RAG 最终效果的重要因素。

  • 在线:当用户输入问题之后,我们会对 query 进行分析,如关键词提取、意图识别等,然后再根据路由条件进行知识库的多种召回检索或者联网搜索等,接着进行重排以提取最重要最相关的上下文信息,然后将用户问题和上下文信息一起提交给 LLM,让 LLM 根据背景知识提供可靠的回答。另外,为了进一步提高系统的性能,我们也会引入后置处理的环节,如风控检测、结果缓存和 RAG 相关指标的监控上报等。

文档智能解析

解析文档内容是 RAG 系统最重要的前置工作之一。很多时候,企业内部数据以各种各样的文件格式存在,如 PDF、Word 文档、PPT 和 Excel 表格等。如何从大量非结构化数据中提取出内容,就需要文档智能解析技术了。

文档智能解析是指利用机器学习算法,对文档内容进行自动识别、理解和处理的过程。它不仅包括文本内容的识别,还涉及到图像、图表和表格等非文本元素的解析。

一般而言,对于不同类型的文件,有不同的解析方法,如 HTML/XML 解析、PDF 解析等。这里我们以图片形式的文档(如对纸质文档进行了扫描、拍照等)为例进行说明。

首先,我们需要对文档进行版面分析(Layout Analysis,也称布局分析),用于识别和理解文档中的视觉和结构布局。这里会使用到区域检测和区域分类等技术。区域检测用于识别文档中的不同区域,如文本块、图像、表格和图表等。而区域分类则将检测到的区域进一步分类,如文本可以进一步被细分为标题、副标题、正文文本等;图像可能被分类为图片、图表或公式等;表格需要识别为包含数据的结构化形式。

在这里插入图片描述

然后,对这些区域分别进行识别。比如,对于表格区域,它们会被输入表格识别(TSR,Table Structure Recognition)模块进行结构化识别,包含解析表格的行和列,识别单元格边界,提取结构化数据。对于文本区域,使用 OCR 引擎将图像中的文字转为机器可读的字符。

随着大语言模型(LLM)和多模态技术的发展,文档理解领域逐渐出现了端到端的多模态模型,它们将文档内容和文档图像进行联合学习,这样一来,模型可以学习到不同文档模板类型的局部不变性信息,当模型需要迁移到另一种模板类型时,只需要人工标注少量的样本就可以对模型进行调优。

比如,微软的 LayoutLM 系列模型将视觉特征、文本和布局信息进行了联合预训练,在多种文档理解任务上取得了显著提升;OpenAI 的 GPT-4V 能够分析用户输入的图像,并为有关图像的问题提供文本回应,它结合了自然语言处理和视觉理解;微软的 Table Transformer 可以从非结构化文档中提取表格;基于 Transformer 的 Donut 模型无需 OCR 就可以进行文档理解;旷世科技近期发布的 OneChart 模型可以对图表(如折线图、柱状图和饼图等)信息进行结构化提取。

长期来看,大模型和文档理解进行结合应该是一个趋势。但就目前而言,多模态大模型与传统的 SOTA 方案相比,还不具备很好的竞争力,尤其是在处理细粒度文本的场景下。

在这里,笔者推荐几个用于文档解析的开源项目,如果读者有更好的方案推荐,也欢迎留言。

  • RAGFlow

RAGFlow[https://github.com/infiniflow/ragflow] 是一款基于深度文档理解构建的开源 RAG 引擎。RAGFlow 的最大特色,就是多样化的文档智能处理,它没有采用现成的 RAG 中间件,而是完全重新研发了一套智能文档理解系统,确保数据 Garbage In Garbage Out 变为 Quality In Quality Out,并以此为依托构建 RAG 任务编排体系。对于用户上传的文档,它会自动识别文档的布局,包括标题、段落、换行等,还包含图片和表格等。RAGFlow 的 DeepDoc 模块提供了对多种不同格式文档的深度解析。

  • Unstructured

Unstructured[https://github.com/Unstructured-IO/unstructured] 是一个灵活的Python 库,专门用于处理非结构化数据,它可以处理各种文档格式,包括 PDF、CSV 和 PPT 等。该库被多个项目用于非结构化数据的提取,如网易有道的QAnything、Dify 等。

  • PaddleOCR

PaddleOCR[https://github.com/PaddlePaddle/PaddleOCR] 是由百度推出的 OCR 开源项目,旨在提供全面且高效的文字识别和信息提取功能。PaddleOCR 提供了版面分析、表格识别和文字识别等多种功能。PaddleOCR的应用场景广泛,包括金融、教育、法律等多个行业,其高效的处理速度和准确率使其成为业界领先的 OCR 解决方案之一。

文档智能解析技术的应用非常广泛,可用于法律文档的信息提取、财务报表的数据整理、医疗记录的分析等多个领域,它是搭建企业 RAG 系统不可或缺的部分。

文本分块

文本分块(text chunking),或称为文本分割(text splitting),是指将长文本分解为较小的文本块,这些块被嵌入、索引、存储,然后用于后续的检索。通过将大型文档分解成易于管理的部分(如章节、段落,甚至是句子),文本分块可以提高搜索准确性和模型性能。

  • 提高搜索准确性:较小的文本块允许基于关键词匹配和语义相似性进行更精确的检索。

  • 提升模型性能:LLM 在处理过长的文本时可能会遇到性能瓶颈。通过将文本分割成较小的片段,可以使模型更有效地处理和理解每一部分,同时也有助于模型根据查询返回更准确的信息。

因此,文本分块是很重要的一个环节,在 RAG 的众多环节中,它也许是我们容易做到高质量的一个环节

下面我们来看看有哪些分块的策略。

按大小分块

按大小分块是指将文本按固定字符数或单词数进行分割,这是最直接、最经济的分块方法,但也存在明显的问题,也就是语义不连贯。按大小分块通常不考虑文本的语义内容,因此有可能将相关联的信息切割开,导致分出的文本块在内容上缺乏连贯性和完整性。例如,一个完整的句子或一段函数代码可能会被截断在两个不同的块中,使得单独的块难以理解。

下面是一个使用 Langchain 的 CharacterTextSplitter 按大小分块的示例:

from langchain_text_splitters.character import CharacterTextSplitter  
  
def test_character_text_splitter() -> None:  
    """Test splitting by character count."""  
    text = "foo bar baz 123"  
    splitter = CharacterTextSplitter(separator=" ", chunk_size=7, chunk_overlap=3)  
    output = splitter.split_text(text)  
    expected_output = ["foo bar", "bar baz", "baz 123"]  
    assert output == expected_output

可以看到,CharacterTextSplitter 设置了 3 个参数:

  • 分割符(separator):空格

  • 文本块的最大长度(chunk_size):7

  • 文本块之间的最大重叠长度(chunk_overlap):3,chunk_overlap 这个参数很重要,表示两个切分文本之间的重合度,设置重叠大小可以保持文本块之间的连续性。

特定格式分块

特定格式分块是针对具有特定结构或语法特征的文本文件进行分块的一种方法,如 Markdown、LaTeX、Python 代码等。这种分块方式依据各自格式的特定字符或结构标记来实现,以保证分块后的内容在结构上的完整性和逻辑上的连贯性。比如 Markdown 文本可以使用标题(#)、列表(-)、引用(>)等来进行分块。

针对特定格式的分块,langchain 提供了相应的方法,如:

  • MarkdownTextSplitter:根据 markdown 的标题、列表或引用等规则来分割文本

  • LatexTextSplitter:根据 latex 的 chapter、section 或 subsection 等规则来分割文本

  • HTMLHeaderTextSplitter:根据 html 特定字符串分割文本,如 h1、h2、h3 等

  • PythonCodeTextSplitter:根据 python 特定的字符串分割文本,如 class、def 等,总共有 15 种不同的语言可供选择

递归分块

递归分块以一组分隔符为参数,以递归的方式将文本分成更小的块。如果在第一次分割时无法得到所需长度的块,它将递归地继续尝试。每次递归都会尝试更细粒度的分割符号,直到块的长度满足要求。这样可以确保即使初始块很大,最终也能得到较为合适的小块。例如,可以先尝试按照句子结束符来分割(如句号或问号),如果这样分割出的文本块太长,就会依次尝试其他的标记,例如逗号或者空格。通过这种方式,我们可以找到比较合适的分割点,同时尽量避免破坏文本的语义结构。

下面是一个使用 Langchain 的 RecursiveCharacterTextSplitter 进行递归分块的示例:

from langchain_text_splitters import RecursiveCharacterTextSplitter  
  
def test_iterative_text_splitter() -> None:  
    """Test iterative text splitter."""  
    text = """Hi.\n\nI'm Harrison.\n\nHow? Are? You?\nOkay then f f f f.  
This is a weird text to write, but gotta test the splittingggg some how.  
  
Bye!\n\n-H."""  
    # 分隔符列表是["\n\n", "\n", " ", ""]  
    splitter = RecursiveCharacterTextSplitter(  
    separators=["\n\n", "\n", " ", ""],  
    chunk_size=10,   
    chunk_overlap=1)  
  
    output = splitter.split_text(text)  
    expected_output = [  
        "Hi.",  
        "I'm",  
        "Harrison.",  
        "How? Are?",  
        "You?",  
        "Okay then",  
        "f f f f.",  
        "This is a",  
        "weird",  
        "text to",  
        "write,",  
        "but gotta",  
        "test the",  
        "splitting",  
        "gggg",  
        "some how.",  
        "Bye!",  
        "-H.",  
    ]  
    assert output == expected_output

语义分块

语义分块(semantic chunking)首先在句子之间进行分割,句子通常是一个语义单位,它包含关于一个主题的单一想法;然后使用 Embedding 表征句子;最后将相似的句子组合在一起形成块,同时保持句子的顺序。

命题分块

命题分块(propositional chunking)也是一种语义分块,它的原理是基于 LLM,逐步构建块。

  • 首先从基于段落的句法分块迭代开始。

  • 对于每个段落,使用 LLM 生成独立的陈述(或者命题),比如我们可以使用简单的提示「这段文字讨论了哪些主题」。

  • 移除冗余命题。

  • 索引并存储生成的命题。

  • 在查询时,从命题语料库中检索,而不是原始文档语料库。

除了上面所说的分块策略,也还有很多其他的分块策略,比如 langchain 提供了根据 OpenAI 的 token 数进行分割的 TokenTextSplitter,还有使用 NLTK 分割器的 NLTKTextSplitter 等。

文本分块并没有固定的最佳策略。选择哪种方式取决于具体的需求和场景,需要根据业务情况进行调整和优化。关键是找到适合当前应用的分块策略,而不是追求单一的完美方案。有时候,为了获得更准确的查询结果,我们甚至需要灵活地使用多种策略相结合。

另外,为了直观分析文本分割器是如何工作的,我们可以使用 ChunkViz 工具进行可视化,它会展示文本是如何被分割的,可以帮助我们调整分割参数。

在这里插入图片描述

总结

RAG 是扩展 LLM 知识边界的利器,本文对 RAG 系统前置的文档解析和文本分块两个环节进行深入了探讨。

文档智能理解从各种各样非结构化的文档中提取内容,是构建高质量 RAG 系统的基础。数据质量决定成效。Garbage in, Garbage out. Quality in, Quality out.

文本分块将长文本分解为较小的文本块,这些块被嵌入、索引、存储,然后用于后续的检索。文本分块并没有固定的最佳策略,每种策略各有优缺点,关键在于根据具体的需求和场景,灵活运用不同策略,提高搜索准确性与模型性能。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值