AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


一文带你掌握RAG的第一步-文本分块!人人都能看懂的AI技术原理科普,数据处理、文本切割到底是怎么回事?
发布日期:2024-06-21 03:31:05 浏览次数: 3401 来源:同桌的AI小纸条


小纸条的之前的章为大家介绍过RAG对于模型优化的作用之大,接着概念科普后,今天这篇文章会带着大家直白的搞懂RAG真正落地的过程涉及到的技术,去掉一些RAG技术的复杂滤镜

构建一个检索增强生成 (Retrieval-Augmented Generation, RAG) 应用的初步模型可能看起来不难,但要真正把它用在实际工作中,我们会遇到不少难题。这主要是因为 RAG 系统涉及多个不同的组件,每个部分都得仔细调整和打磨,才能让整个RAG系统运行得既快速又准确。

组成RAG的过程中包括如,外部非结构化数据的清洗和处理、文本分块、Query 的预处理、是否每次 Query 都要进行检索、上下文信息的检索和排序能力、如何评估检索生成质量、知识缓存等等,每个环节都会影响系统的性能。

为了让大家对RAG的过程先有个概念,以上内容简单解释一下:

1. 外部非结构化数据的清洗和处理:处理好从外面收集来的结构不一致对应不上,不全以及不准的数据,把它们变得干净有结构且对应的上;

2. 文本分块:把长文本分成小块(这里后面小纸条会单独给大家讲一篇哦)

3. Query 的预处理:预判并提前处理用户的查询请求

4. 是否每次 Query 都要进行检索:是否每次用户查询时都要重新搜索信息

5. 上下文信息的检索和排序能力:以及如何快速找到最相关的信息并按重要性排序

6. 如何评估检索生成质量:用什么方法,评估生成的内容质量

7. 知识缓存:如何聪明地存储知识,让系统更聪明、反应更快

之前小纸条的文章也介绍过RAG在模型优化这里起到的作用之大,提高 RAG 系统性能是一个持续的过程,需要不断地评估、优化和迭代。


什么是RAG



Meta AI的研究团队在2020年提出了一个新点子,叫做检索增强生成(RAG),用来让大型语言模型(LLM)在特定任务上表现得更出色。LLM是个语言天才,擅长理解语言、推理和创作文字,但它也有短板:

信息更新慢:LLM的知识库是固定的,它学到的东西都是基于训练时用的数据,也就意味着它不能提供最新的信息。

模型幻觉:有时候,生成式AI会编造一些不存在的事情,这在需要确保信息准确的业务场景中,可能会带来问题。

缺少私有数据:LLM主要学习的是互联网上的公开数据,但很多专业领域、公司内部的专属知识,它是学不到的。

RAG的聪明之处在于,它能够找到相关信息给LLM作参考,这样LLM就能写出更有根据的内容。用好RAG,可以让LLM的知识库更广,不仅能访问到那些专属的知识库,还能及时更新数据,让它的回答更准确、更贴近最新情况。

就像下面这张图展示的,RAG应用的基本结构可以分成两个部分:离线和在线。离线部分是在系统不忙的时候进行的,比如更新知识库;在线部分则是实时进行的,比如回答问题。两者结合起来,就能让RAG系统既聪明又反应快。



离线部分:对知识库文档进行解析、拆分、索引构建和入库—我们需要把知识库里的文件拿出来,把它们拆成小块,然后整理好,就像是给书编目录一样。这个过程可能会很繁琐,因为文件的格式多种多样,我们需要把它们都清理干净,确保没有错误。这里有一个不变的定律-「Garbage in, Garbage out」,如果输入的是垃圾,输出的也只能是垃圾。所以,数据的质量对于RAG系统能不能给出好结果非常关键。

在线部分:当用户问问题时,我们得先理解他们的问题,找出关键词,明白他们的意图。然后我们会根据这些信息去知识库里找答案,或者上网搜索相关信息。找到信息后,我们要重新整理,挑出最相关、最重要的内容,然后连同用户的问题一起交给LLM,让它根据这些背景知识给出靠谱的答案。为了确保系统运行得更顺畅,我们还会做一些后置处理的环节,比如检查风险、结果缓存以供快速访问,以及监控系统指标等。

今天,我们先来从离线环节的文档解析和文本分块,开始对RAG祛魅!


文档解析



解析文档内容是RAG系统里非常关键的一步。很多企业内部数据以各种各样的文件格式存在,比如PDF、Word文档、PPT幻灯片和Excel电子表格等等。要从这些不统一、不规范的文件里把内容挖出来,我们就需要用到一些聪明的技术-文档智能解析。

文档智能解析是用机器学习的方法对文档内容进行自动识别、理解和处理的过程。这不仅包括文字,还有图片、图表和表格这些非文本元素的内容。

通常,不同的文件类型要用不同的方法来解析。比如,HTML/XML文件有它们自己的解析方法,PDF文件也有专门的解析技术。这里我们拿图片形式的文档来进行下面的举例子说明(比如扫描了一张纸或者拍了张照片)


版面分析



首先,我们得对文档做版面分析(Layout Analysis,也称布局分析),用于识别和理解文档中的视觉和结构布局。就像是给文档做个X光,看看里面都有哪些部分。涉及到的技术包括比如区域检测和区域分类。

区域检测:就是找出文档里不同的区块,比如文字、图片、表格和图表。

区域分类:就是在区域检测的基础上,把找到的区块再分得更细一些。比如,文字可以分成标题、小标题、正文;图片可以分成普通图片、图表或者公式;表格要认出来,因为它们是包含数据的有结构的部分。

通过这样的分析,我们就能更好地理解文档的结构,为下一步的数据处理打下基础。




区域识别



接下来,我们得对文档里的每个区块进行识别。具体来说:

表格区块:把它们送到一个叫做表格结构识别(TSR Table Structure Recognition)的模块里,这个模块的任务就是把表格里的行、列和单元格边界搞清楚,然后把表格里的数据变成我们电脑能处理的格式。

文本区块:用一个叫做OCR的软件,把图片里的文字变成电脑能读的字符。

随着大型语言模型(LLM)和多模态技术越来越厉害,文档理解领域也出现了一些能同时处理文档内容和图像的端到端模型。这些模型能学习不同文档模板的特点,如果需要用在新的模板上,只需要很少的人工标注就能让模型学会新的东西。比如:

微软的LayoutLM系列模型,通过联合预训练视觉特征、文本和布局信息,在很多文档理解任务上取得了显著提升;

OpenAI的GPT-4V能分析图像,然后回答有关图像的问题,将语言处理和视觉理解进行了结合;

微软的Table Transformer能从不规则的文档里提取出表格;

基于Transformer的Donut模型,不需要OCR就能理解文档;

旷视科技最近发布的OneChart模型,能从图表里提取结构化信息(GitHub地址:https://github.com/LingyvKong/OneChart)

从长远来看,把大模型和文档理解结合起来肯定是个大趋势。但现在,这些多模态大模型和目前最好的SOTA 技术方案比起来,竞争力还不是很强,特别是在处理很细致的文本场景下。

SOTA是“State-of-the-Art”的缩写,意思是在某个领域或任务里,这是目前最先进、最高水平的技术,通常用来展示自己在技术、产品、应用等方面的领先地位。

文章末尾贴了几个做文档解析的开源项目,感兴趣的同学可以mark一下!


文本分块



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

说人话的话就是,想象一下你有一本厚厚的书,要把它变成电脑能快速查找和理解的内容。这时候,我们就需要用到文本分块,也就是把长文本拆分成小块小块的,这样电脑就能更容易地处理和搜索了。


那为什么要分块呢?



提高搜索准确性:较小的文本块允许基于关键词匹配和语义相似性进行更精确的检索—把大段文字拆成小段,模型就能更准确地找到关键词,理解它们的意思。

提升模型性能:大型语言模型(LLM)处理很长的文字时可能会遇到性能瓶颈。把文字拆成小块,模型就能更轻松地理解和回应问题,也有助于回答的更准确


文本分块的策略有哪些呢?




第一种:按大小分块



这种方法就是按固定字符数或单词数进行分割,也就是按照一定的字数或字符数把文本切成一块一块的。这听起来简单直接,也是最经济的分块方法,但它有个问题,就是可能会把意思切得不连贯。比如,一句话的分割通常不考虑文本的语义内容,可能会被切成不连贯的两半,或者一段代码被分成了两部分,这样单独看每一块就不容易理解了,内容上缺乏连贯性和完整性。

举个例子,假设我们有以下这段文本:


人工智能助手Kimi诞生于2023年,由月之暗面科技有限公司开发。它具备多语言对话能力,擅长中文和英文。Kimi能够处理长文本,支持最多20万字的输入和输出。此外,Kimi还能阅读多种格式的文件,如TXT、PDF、Word文档等,并结合网页内容进行回复。

现在,我们决定使用按大小分块的方法,以100个字符为界限来分割这段文本(假设每个汉字大约等于2个字符)。那么,分块后的结果可能如下:

文本块1:人工智能助手Kimi诞生于2023年,由月之暗面科技有限公司开发。

文本块2:它具备多语言对话能力,擅长中文和英文。Kimi能够处理长文本,支持最多20万字的输入和输出。

文本块3:此外,Kimi还能阅读多种格式的文件,如TXT、PDF、Word文档等,并结合网页内容进行回复。

在这个例子中,每一块文本都大致保持在100个字符左右。请注意,如果我们严格按照字符数来分割,有时候可能会把一些语义上应该连在一起的内容切开。比如,如果我们的文本中包含较长的专业术语或者网址,那么在分割点上可能会把它们分开,导致每一块文本在语义上不够完整。

这就是按大小分块的一个简单示例,总之,文本分块是让电脑更好地理解和搜索文本的一个重要步骤。虽然看起来简单,但要分得好,让每一块内容都完整有意义,还是需要一些技巧的。


第二种:特定格式分块



特定格式分块是针对具有特定结构或语法特征的文本文件进行分块的一种方法,比如你有一份特别格式的文档,Markdown、LaTeX(一种基于TeX的文字处理系统,特别适合用来排版科技和学术文档,尤其是那些包含复杂数学公式、参考文献、索引的文档)或者Python代码。这些文档有自己的一套规则,比如Markdown用#表示标题,LaTeX用\chapter表示章节开始。特定格式分块就是根据这些规则来切分文档,确保切出来的每一块在结构和逻辑上都是完整的。

特定格式分块的方法:


1. 对于Markdown文档,我们可以用标题(#)、列表(-)、引用(>)这些特殊标记来分块。比如,一个标题下面的内容就是一个块。

2. 对于LaTeX文档,我们可以用章节(\chapter)、小节(\section)或子节(\subsection)这些命令来分块。每个章节或小节的内容就组成一个块。

3. HTML文档可以用h1、h2、h3这些表示标题的字符串来分块。

4. Python代码可以用class、def这些关键字来分块,而且这种方法支持15种不同的编程语言。

langchain 对于以上的规则都提供了相应的方法,分别是MarkdownTextSplitter、LatexTextSplitter、HTMLHeaderTextSplitter、PythonCodeTextSplitter(看个眼熟就行了!)

总之呢,通过特定格式分块,我们可以让电脑更好地理解和处理这些有特殊规则的文档。


第三种:递归分块



递归分块以一组分隔符为参数,以递归的方式将文本分成更小的块。。如果在第一次分割时无法得到所需长度的块,它将递归地继续尝试。每次递归都会尝试更细粒度的分割符号,直到块的长度满足要求。这样可以确保即使初始块很大,最终也能得到较为合适的小块。

就像是分蛋糕。我们有一块大蛋糕(也就是一段长文本),现在要把它切成一小块一小块的,但是要切得既均匀又好吃(也就是内容完整有意义)。我们先试着用大刀(主要分隔符)切,如果切出来的蛋糕块太大,我们就换小一点的刀(次要分隔符)继续切,直到切出满意的小块。

这个过程中,我们先找那些明显的切分点,比如句子结束的地方(句号、问号)。如果这样切出来的块还是太大,我们就看那些不那么明显的切分点,比如逗号或者空格。这样一步步来,我们可以找到比较合适的分割点,同时尽量避免破坏文本的语义结构,直到每一段句子都是我们想要且合适的长度。

继续举一个递归分块的例子,假设我们有这样一段文本:

Kimi是一个人工智能助手,它非常擅长处理文本。Kimi可以阅读和理解各种格式的文件,包括TXT、PDF和Word文档。它还能上网搜索信息,然后结合搜索结果来回答你的问题。Kimi是由月之暗面科技有限公司开发的,这家公司位于中国。

我们想要把这段文本分成几个小段,每段大概包含20个汉字。首先,我们找到句子结束的地方,比如第一个句号:

文本块1:Kimi是一个人工智能助手,它非常擅长处理文本

接下来,剩下的文本还是太长,我们就看逗号和分号,找到第二个切分点:

文本块2:Kimi可以阅读和理解各种格式的文件,包括TXT、PDF和Word文档。

最后,剩下的句子比较短,我们就直接把它作为最后一个块:

文本块3:它还能上网搜索信息,然后结合搜索结果来回答你的问题。Kimi是由月之暗面科技有限公司开发的,这家公司位于中国。

通过递归分块,我们把一段长文本切分成了三个小块,每块都保持了内容的完整性和连贯性。这样,无论是搜索还是模型处理,都能更加高效和准确。


第四种:语义分块



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

翻译一下就是,假如你是一位导演,手里有一份厚厚的剧本,需要把它分成一幕幕的场景。每个场景都要围绕一个中心思想,这样才能让观众容易理解。语义分块也是这个道理,我们先把剧本(长文本)分成一句句的台词(句子),因为每句话都表达了一个完整的意思。接着,我们用一种特殊的方法(Embedding)来理解每句话的深层含义。最后,我们把意思相近的句子放在一起,组成一个个场景,但要确保这些场景的顺序不乱。

举一个语义分块的例子,假设我们有这样一段关于美食节的描述:

美食节上,各种美食琳琅满目。有香气四溢的烧烤摊,新鲜出炉的面包店,还有色彩缤纷的水果摊。游客们在各个摊位前流连忘返,品尝着来自世界各地的美味。孩子们对五彩缤纷的糖果特别感兴趣,而大人们则更喜欢坐下来,慢慢享受一杯香浓的咖啡。

烧烤摊的羊肉串和牛肉串特别受欢迎,不时传来滋滋的烤肉声和诱人的香味。面包店的甜点种类繁多,每天都吸引着大量顾客。水果摊上,新鲜的苹果、橙子和香蕉摆放得整整齐齐,让人垂涎欲滴。


我们首先按照句子分块:

句子1:美食节上,各种美食琳琅满目。

句子2:有香气四溢的烧烤摊,新鲜出炉的面包店,还有色彩缤纷的水果摊。

句子3:游客们在各个摊位前流连忘返,品尝着来自世界各地的美味。

句子4:孩子们对五彩缤纷的糖果特别感兴趣,而大人们则更喜欢坐下来,慢慢享受一杯香浓的咖啡。

句子5:烧烤摊的羊肉串和牛肉串特别受欢迎,不时传来滋滋的烤肉声和诱人的香味。

句子6:面包店的甜点种类繁多,每天都吸引着大量顾客。

句子7:水果摊上,新鲜的苹果、橙子和香蕉摆放得整整齐齐,让人垂涎欲滴。

接下来,我们用Embedding来理解每个句子的含义,并把相似的句子组合在一起,形成几个语义块:

语义块1:包含句子1、2和3,描述了美食节的热闹场景和游客们的行为。

语义块2:包含句子4和5,关注烧烤摊的受欢迎程度和孩子们及大人们的兴趣点。

语义块3:包含句子6和7,讲述了面包店和水果摊的特色。

通过语义分块,我们把一段长文本变成了几个围绕特定主题的小块,每个块都有清晰的中心思想,顺序也保持不变,这样观众(读者)就能更好地理解和感受美食节的氛围。




第五种:命题分块命题分块



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

翻译一下就是,加入你是一位编辑,手头有一大堆文章需要整理成易于读者理解的小块。命题分块就有点像这项工作,但它用到了聪明的语言模型(LLM)来帮忙。这种方法把长文本切分成小的、有意义的单元,我们称之为命题。每个命题都是文本中的一个小故事,表达一个完整的想法。



步骤如下:


1. 开始分割:从段落开始,把每个段落拆成句子。

2. 生成命题:用LLM帮忙,给每个段落生成一些独立的陈述,就像是问模型:“这段文字讨论了哪些主题?”

3. 精简命题:去掉那些重复的或者不重要的命题,只留下精华。

4. 索引存储:把整理好的命题保存起来,做成索引,方便以后查找。

5. 检索查询:当有人需要信息时,我们就直接在这些命题中搜索,而不是回到原始的长文本中去翻找。

继续举例子,假设我们有一段关于美食节的描述:


美食节上,来自世界各地的厨师们带来了他们的拿手好菜。日本的寿司大师展示了新鲜的寿司制作;法国的糕点师傅带来了各式各样的马卡龙;而意大利的厨师则带来了经典的披萨和意面。每个摊位前都排起了长队,人们迫不及待地想要品尝这些美味佳肴。

按照命题分块的方法,我们可能会得到以下命题:


寿司大师在美食节上展示了新鲜的寿司。

法国糕点师傅带来了多种马卡龙。

意大利厨师提供了披萨和意面。

每个摊位都吸引了大量排队的人群。

这样,我们就把这些美食节的精彩瞬间变成了几个简洁明了的命题,方便了搜索和查阅。通过命题分块,我们能够把复杂的文本信息转换成易于管理和检索的知识块,让信息的获取变得更加高效。

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


小结:文本分块的艺术



文本分块就像是烹饪,没有所谓的唯一正确做法,没有固定的最佳策略。选择哪种切分方式,要看你的具体需求和使用场景。重要的是找到适合你当前任务的切分策略,而不是去寻找一个根本不存在的完美切分方法。有时候,为了让搜索结果更精确,我们可能需要像调鸡尾酒一样,把几种不同的策略混合起来使用。

而且,如果你想知道文本分割器是怎么工作的,可以用一个叫做ChunkViz的工具来帮忙。这个工具可以让选择不同的分割方式,调整切分的参数,让我们看到文本是如何被切分的,可视化做的贼棒!

github:https://github.com/gkamradt/ChunkViz

see demo:https://chunkviz.up.railway.app/




开源文档



RAGFlow:这是一个基于深度文档理解的开源RAG引擎。

GitHub地址:https://github.com/infiniflow/ragflow

RAGFlow的特点是它有一套自己的智能文档理解系统,不是用现成的RAG中间件,而是全新研发的。它的目标是把“垃圾进垃圾出”变成“优质进优质出”,并且用这个系统来构建RAG任务的编排。

Unstructured:这是一个灵活的Python库,专门用来处理非结构化数据。

GitHub地址:https://github.com/Unstructured-IO/unstructured

它能处理PDF、CSV、PPT等各种文档格式,很多项目都用它来提取非结构化数据。

PaddleOCR:这是百度推出的OCR开源项目,目的是提供全面高效的文字识别和信息提取功能。

GitHub地址:https://github.com/PaddlePaddle/PaddleOCR

PaddleOCR有版面分析、表格识别和文字识别等功能,应用在金融、教育、法律等行业,处理速度快,准确率高,是业界领先的OCR解决方案之一。


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询