DLAI-大模型非结构化数据预处理笔记-全-
DLAI 大模型非结构化数据预处理笔记(全)
001:课程介绍 🎯
在本节课中,我们将学习如何为大型语言模型(LLM)应用程序,特别是检索增强生成(RAG)管线,预处理各种非结构化数据。我们将了解数据加载和分块的挑战,以及如何从不同格式的文档中提取、规范化并丰富信息,使LLM能够有效利用这些数据。
检索增强生成(RAG)正在许多企业中被广泛采用。一个典型的RAG管线包含几个关键组件:数据加载、分块、嵌入、存储在向量数据库中,以及后续的检索。
上一节我们介绍了RAG的基本流程,本节中我们来看看数据预处理的具体挑战。RAG中一个特别具有挑战性的任务是数据加载和分块,因为数据存储在许多不同的文件类型和数据格式中。
以下是常见的数据来源示例:
- 数值数据:可能存储在Excel电子表格中。
- 文本报告:可能存储在PDF或Markdown文档中。
- 演示文稿:可能存储在PowerPoint、幻灯片或Keynote演示文稿中。
- 通信记录:可能存储在Outlook、Slack或Teams中。
此外,每种文件类型本身也可能包含多种数据格式。例如,一个PDF或PowerPoint文件内部可能包含表格、图像或项目符号列表。
因此,数据加载器首先必须能够解析许多不同的文件格式。但是,一旦解析了这些数据,接下来该如何处理呢?事实证明,将来自这些不同来源的数据进行规范化非常有用。

例如,当您将来自PDF或PowerPoint等文档中的表格进行规范化处理后,所有这些表格都可以用类似的方式表示。同样,来自PDF或电子邮件中的项目符号列表也可以被规范化表示。
除了规范化,保留原始文档的某种结构也很有用,通常通过元数据来实现。例如,一个段落可能有一个父项,即它所属章节的标题。这样,匹配该章节标题的查询可以扩展为返回其下的所有子文本。
在下面的示例中,数据被组织成了树形层次结构:
文档
├── 章节标题 1
│ ├── 段落 1.1
│ └── 段落 1.2
└── 章节标题 2
└── 段落 2.1

接下来,我们请到Matt Robinson,他是Unstructured公司的产品主管,他将为我们解释如何实现上述所有过程。Matt的团队负责开发专为LLM设计的非结构化数据摄取工具,他帮助了许多开发人员构建能够使用和整合不同来源数据的LLM应用程序。
本课程解决了LLM应用程序开发中一个关键但常被忽视的方面——数据预处理。您将学习如何从各种文档类型(包括PDF、PowerPoint、Word和HTML)中提取和规范化内容,使您的LLM能够访问多样化的信息。
您还将学习如何使用元数据丰富这些内容,从而增强RAG的结果,并支持更细致的搜索功能。本课程将涵盖文档图像分析技术,如文档布局检测和视觉变换器(ViT),并教您如何提取和解释表格。

最后,您将应用这些技术,构建一个能够使用PDF、PowerPoint和Markdown等文档的RAG机器人,从而整合您所学到的一切。

本节课中,我们一起学习了为LLM应用预处理非结构化数据的重要性与基本目标。我们了解到,数据工程是让LLM获得所需上下文的关键,直接影响其在应用程序中的表现。在接下来的课程中,您将开始学习如何从各种类型的文档中提取和规范化内容,以便您的LLM可以引用来自PDF、PowerPoint、Word文档、HTML等来源的信息。
002:概述 📚
在本节课中,我们将学习LLM数据预处理的基础知识,理解为何在构建使用多源、多格式、多结构数据的LLM应用时,这是一个重要且具有挑战性的环节。
数据预处理在RAG架构中的位置 🗺️
在深入学习如何预处理特定数据类型之前,了解这个过程在整个应用架构中的位置非常重要。首先,需要理解检索增强生成,即 RAG。这是一种让LLM的响应基于经过验证的外部信息(例如企业内部数据)的技术。
这些信息可以包含在各种文档类型中,例如电子邮件、PDF或PowerPoint幻灯片。从概念上讲,RAG应用程序将这些外部上下文加载到数据库中,然后检索相关内容,并将其插入到用户提示中。

随后,这个包含了外部信息的提示会被传递给LLM。这样,当问题或提示传递到LLM时,LLM就能利用这些外部信息来构建其响应。这在企业应用中非常关键,因为组织数据通常以多种格式存在。
文档预处理的步骤 🔄
文档预处理包含几个关键步骤。以下是其核心流程:

- 提取文档内容:这是指从文档中提取出可用于构建提示的文本内容。
- 提取文档元素:这些是文档的基本构建块,例如标题、叙述文本、列表和表格。可以利用这些元素执行对RAG应用至关重要的任务,例如分块和过滤。
- 提取元素元数据:例如页码或文件类型等信息也非常重要。在课程后期,将学习如何在执行混合搜索时利用此信息,以便在构建提示时过滤从向量数据库中提取的内容。
数据预处理的挑战 ⚠️
那么,为什么数据预处理具有挑战性?主要有以下几个原因:
- 文档类型多样:不同类型的文档使用不同的内容标识方式。例如,HTML文件使用标签名称来指示文本是标题还是列表,而PDF文件则依赖视觉布局。因此,需要理解不同文档类型如何标识其内部元素。
- 格式标准化困难:文档以各种格式存在。需要将它们标准化,以便应用程序能以统一的方式处理。理想情况下,应用程序只需关注信息本身,而不必关心源文档是HTML还是PDF。然而,标准化很困难,因为不同格式的文档使用不同的元素标识方式。
- 内容结构多变:不同的文档具有不同的内容结构。例如,期刊文章和表格就截然不同。因此,数据预处理技术需要能够适应这种多样性。
- 结构信息利用:需要理解文档的结构信息,以提取有意义的元数据。这些元数据可用于RAG应用中的各种操作,例如过滤。
总的来说,数据预处理涉及许多需要考虑的要素,它并非一项简单的任务,但却是启动和运行RAG应用程序的重要组成部分。
总结 📝

本节课我们一起学习了LLM数据预处理的概述。我们了解了数据预处理在RAG架构中的关键作用,认识了其包含的主要步骤(内容提取、元素提取、元数据提取),并探讨了在处理多样化、非结构化数据时所面临的主要挑战。在下一课中,我们将深入探讨如何预处理一些特定类型的文档。
003:规范化 📄
概述
在本节课中,我们将学习如何从多种文档类型(如PDF、PowerPoint、Word文档和HTML)中提取并规范化内容。规范化的目的是将所有文档转换为一种通用格式,以便您的LLM应用程序能够以统一的方式引用和处理这些信息。
为什么需要规范化文档?
上一节我们介绍了课程的目标,本节中我们来看看为什么规范化是必要的。首先,现实世界中的文档存在多种格式。在组织或大学中,您可能会遇到PDF、Word文档或HTML页面等。当构建LLM应用程序时,您不希望处理逻辑因文档来源不同而变得复杂。理想情况是,所有文档都以一种通用格式呈现,从而在应用程序中以相同的方式处理它们。
因此,规范化的第一步是将文档分解为标题、叙述文本等常见元素。这样做有几个关键好处:
- 统一处理:允许您以相同方式处理任何文档,无论其原始格式如何。例如,您可以统一过滤掉页眉、页脚等不需要的元素,而无需为每种格式编写单独的逻辑。
- 简化下游操作:允许您在所有文档类型上应用相同的下游操作,例如分块。您无需为PDF、HTML等创建不同的分块策略。
- 降低成本与灵活实验:预处理文档最昂贵的部分通常是初始内容提取。下游操作如分块成本较低。通过规范化,您可以以较低的计算成本尝试不同的分块策略。
数据序列化
一旦内容被规范化,通常的下一步是数据序列化。序列化有一些好处,它允许您保存输出,以便日后重复使用,而无需再次预处理原始文档。
在本课程中,我们将把数据序列化为JSON格式。JSON是一个方便的选择,原因如下:
- 通用性:它是一种常见且广为人知的数据结构。
- 标准HTTP响应:当处理需要在API上运行模型工作负载的文档(如PDF和图像)时,JSON是标准的HTTP响应格式。
- 跨语言兼容:JSON可以在多种编程语言中使用。例如,您可以在Python中预处理文档,将输出序列化为JSON,然后在JavaScript应用程序中读取这些输出。
- 支持流式处理:JSON也可用于流式处理用例,例如将文档存储为JSON Lines(JSON-L)格式。
以下是本课程中预处理文档后,序列化输出的一个示例:
[
{
"type": "Title",
"text": "文档标题"
},
{
"type": "NarrativeText",
"text": "这是文档的第一段叙述文本..."
}
]
预处理HTML文档
现在您已经了解了规范化和序列化的概念,本节中我们来看看如何预处理HTML文档。这对于LLM应用非常重要,因为您经常需要从互联网获取内容。理解HTML文档通常需要查看其标记结构。
例如:
H1标签通常表示标题。p(段落)标签通常表示叙述性文本。


除了使用标签,我们还可以结合自然语言处理(NLP)功能来更好地理解内容。例如,在 p 标签内包含多个句子的长内容很可能是叙述性文本,而全大写的短内容则更有可能是标题。因此,我们可以同时利用文档的结构化信息(标签)和非结构化信息(文本内容)来对元素进行分类。
以下是一个实际页面的示例:
- 标题 由
H1标签表示。 - 叙述文本 在
p标签中表示。
实践:预处理HTML文件
现在,让我们将所学知识付诸实践。您将首先导入几个辅助函数。
首先,导入用于过滤警告的模块:
import warnings
warnings.filterwarnings('ignore')
接下来,从 unstructured 开源库中导入处理HTML所需的函数。稍后我们还会用到处理PowerPoint的函数。
from unstructured.partition.html import partition_html
from unstructured.partition.pptx import partition_pptx
此外,还需要设置使用Unstructured API的凭据。当处理PDF或图像这类计算成本较高的基于模型的工作负载时,我们会使用这个API。
# 设置Unstructured API密钥(示例,请替换为您的实际密钥)
api_key = "your_api_key_here"
现在,让我们查看一个示例HTML文件(例如,来自Unstructured博客的一个页面)。假设文件名为 blog_post.html。
预处理HTML文件非常简单:
# 1. 指定文件名
filename = "blog_post.html"
# 2. 使用partition_html函数进行分区
elements = partition_html(filename=filename)
# 3. 将元素转换为字典列表,以便序列化
element_dicts = [el.to_dict() for el in elements]
# 4. 查看JSON序列化后的字符串表示(初步查看)
import json
print(json.dumps(element_dicts[:2], indent=2)) # 打印前两个元素
为了更清晰地导航JSON结构,我们可以使用IPython的显示功能:
from IPython.display import JSON
JSON(element_dicts)
通过浏览输出,您可以验证内容是否被正确提取和分类,例如,将博客的第一段标识为“NarrativeText”。
预处理PowerPoint文档
在企业环境中,能够预处理PowerPoint等文档至关重要,这些文档广泛应用于咨询和一般业务中,对于扩展LLM对组织的知识库非常重要。
Microsoft PowerPoint(.pptx)文件的提取过程与HTML在幕后非常相似。现代的.pptx文件本质上是一组XML文件,我们可以使用基于规则的逻辑进行预处理。对于旧的.ppt文件,可以轻松地将其转换为.pptx格式,然后再进行解析。Python库如 python-pptx 可以帮助浏览这些文件中的元素。
实践:预处理PowerPoint文件
让我们使用一个关于OpenAI的PowerPoint文稿(例如 openai_deck.pptx)进行实践。

预处理过程与HTML类似:
# 1. 指定文件名
pptx_filename = "openai_deck.pptx"
# 2. 使用partition_pptx函数进行分区
pptx_elements = partition_pptx(filename=pptx_filename)


# 3. 转换为字典并序列化为JSON
pptx_dicts = [el.to_dict() for el in pptx_elements]
# 4. 使用JSON显示功能查看结果
JSON(pptx_dicts)
在输出中,您可以看到项目符号列表中的项被正确标识为“ListItem”,文本被提取出来。同时,像“ChatGPT”这样的文本也被标识为“Title”。这再次证明了规范化的价值:一旦文档被规范化,您的应用程序就可以以相同的方式处理它们。

预处理PDF文档
现在您已经了解了如何使用基于规则的逻辑处理HTML和PowerPoint,本节中我们来看一个更复杂的用例:PDF文档。
PDF文档与HTML或PowerPoint有所不同。对于后者,我们主要依赖半结构化信息(如标签)来划分元素。而对于PDF或图像,我们需要寻找视觉线索。

在PDF中,我们会查看文档的格式设置:
- 被设置为粗体、加大字号或带有下划线的文本更可能是标题。
- 较长、包含多个句子且没有特殊格式强调的文本更可能是叙述性文本。
通过分析这些视觉信息,我们可以预处理PDF文档。例如,在一个PDF中,顶部粗体显示的“All Experimental Results”很可能是一个标题,而其下方的普通段落则是叙述性文本。PDF中也可能包含需要特殊处理的表格。
实践:预处理PDF文件
让我们在一篇关于思维链推理的学术论文PDF上实践一下。假设文件名为 chain_of_thought.pdf。
这次,我们将使用Unstructured API来处理PDF,因为PDF解析是一种计算密集型的基于模型的工作负载,使用API更为方便。
from unstructured_client import UnstructuredClient
from unstructured_client.models import shared
# 1. 初始化客户端(假设凭据已通过环境变量等方式设置)
client = UnstructuredClient(api_key_auth=api_key)
# 2. 指定文件名
pdf_filename = "chain_of_thought.pdf"
# 3. 准备请求
with open(pdf_filename, "rb") as f:
file_content = f.read()
request = shared.PartitionParameters(
files=shared.Files(
content=file_content,
file_name=pdf_filename,
),
strategy="hi_res", # 使用高分辨率策略处理复杂PDF
languages=["eng"], # 指定语言
)
# 4. 发出请求(可能需要几秒钟)
try:
response = client.general.partition(request)
pdf_elements = response.elements
except Exception as e:
print(f"处理PDF时发生错误: {e}")
pdf_elements = []
# 5. 转换为字典并查看
pdf_dicts = [el.to_dict() for el in pdf_elements]
JSON(pdf_dicts[:5]) # 查看前几个元素
在输出中,您可以验证“All Experimental Results”被标识为“Title”,这与我们在幻灯片和HTML文件中看到的规范化类型一致。关键在于,如果您有一个包含幻灯片、HTML和PDF的文档语料库,您现在可以以相同的格式处理它们,并为后续的RAG(检索增强生成)应用等打下基础。
动手尝试
现在,您可以尝试使用文件上传功能处理自己的文档。以下是一个简单的示例,允许您上传文件并查看预处理结果:
# 示例:使用ipywidgets上传文件(在Jupyter环境中)
import ipywidgets as widgets
from IPython.display import display, clear_output
uploader = widgets.FileUpload(accept='.html,.pdf,.pptx', multiple=False)
display(uploader)
def on_upload_change(change):
if uploader.value:
uploaded_file = list(uploader.value.values())[0]
content = uploaded_file['content']
filename = uploaded_file['name']
with open(filename, 'wb') as f:
f.write(content)
print(f"文件 '{filename}' 已上传。")
# 这里可以根据文件扩展名调用相应的分区函数
# 例如:if filename.endswith('.html'): elements = partition_html(filename=filename)
uploader.observe(on_upload_change, names='value')
您可以将上传的文件传递给之前介绍的分区函数(如 partition_html, partition_pptx 或通过API处理PDF),观察输出结果。

总结
本节课中,我们一起学习了为LLM应用程序预处理非结构化数据的核心步骤——规范化。我们了解了为什么需要将不同格式(HTML、PowerPoint、PDF)的文档转换为统一的元素表示(如标题、叙述文本),以及如何将结果序列化为JSON以便重用。通过实践,我们掌握了使用 unstructured 库处理HTML和PowerPoint文件,以及使用Unstructured API处理PDF文件的基本方法。规范化使得下游处理(如分块、检索)变得一致且高效,是构建强大LLM应用的关键基础。在下一课中,我们将学习更多重要的预处理技术,包括元数据的提取和使用。
004:元数据 📄
概述
在本节课中,我们将要学习如何为从文档中提取的内容添加元数据。元数据是描述数据的数据,例如文档的创建日期、章节标题或元素类型。我们将了解如何利用这些元数据来支持混合搜索,从而更智能地对内容进行分块,并最终改善下游检索增强生成(RAG)系统的结果。
什么是元数据?🔍
上一节我们介绍了文档预处理的基本概念,本节中我们来看看什么是元数据。

元数据是在对文档进行预处理时提取的附加信息。元数据可以是文档级别的,也可以是元素级别的。它可以是直接从文档信息本身提取的内容,比如最后修改日期或文件名。它也可以是在预处理文档时推断出的内容,例如元素类型的类别或不同元素类型之间的层次关系。
这些元数据字段将在创建RAG应用程序时发挥作用,特别是对于像混合搜索这样的应用程序。
以下是元数据在实践中的样子:
- 文本:这是从文档中提取的实际原始内容。
- 元数据:所有其他附加信息,例如页码、语言、文件名、元素类型等。
当开始为RAG应用程序构建混合搜索系统时,所有这些信息都会派上用场。


语义搜索基础 📚
在深入了解元数据如何用于混合搜索之前,首先了解一些关于LLM语义搜索的基础知识是很重要的。
在检索增强生成系统中,第一步通常是从向量数据库中检索文档。最基本的方法是通过语义搜索,即查找与用户查询语义相似的内容。
在将文档加载到向量数据库后,运行一个查询,然后根据它们的相似度得分搜索文档,该得分基于向量空间中的距离度量。例如,向量“番茄狗”在向量空间中与“番茄”和“狗”都很接近。同时,“动物”类的概念会被聚集在一起,因为它们语义相似,而“动物”与“番茄”之间的距离较远,因为“番茄”是水果。

这里的核心思想是,如果正在搜索一系列文档,可以要求向量数据库返回与查询语义相似的文档,然后可以将这些文档插入到供LLM使用的提示中。这通常是在RAG应用程序的语义搜索部分中尝试做的事情。
混合搜索的必要性 ⚖️

现在您已经了解了相似性搜索的基础知识,那么问题出在哪里?
有些情况下,仅依靠语义相似性搜索并不理想,无法为RAG系统返回最合适的信息。
- 匹配项过多:当文档涉及相同主题时,搜索该主题会得到大量信息,需要进一步筛选。
- 需要结果偏向:可能希望根据其他信息(如更近期的日期)来偏向搜索结果。例如,不只想要最相似的内容,而是希望在一定时间范围内发生的最相似的内容。
- 丢失结构化信息:仅搜索语义相似性时,会丢失文档中包含的一些重要结构化信息,例如章节信息,这可能会影响搜索结果。

那么,这就是混合搜索发挥作用的地方。
混合搜索允许将语义相似度搜索与从文档中提取的结构化信息(元数据)相结合。因此,可以使用元数据作为过滤选项。
- 如果想将搜索限制在特定章节,可以根据该元数据字段进行过滤。
- 如果想将结果限制在更近期的信息上,可以构造查询,以便仅返回在特定日期之后的文档。

例如,第一个文档显示了2月12日超级碗的结果,而第二个文档是关于2月11日谁可能赢得超级碗的文章。如果对这两个文档进行相似度搜索,查询“告诉我关于超级碗的最新信息”,可能会得到其中任何一个。但是,如果超级碗已经结束,可能对赛前信息不那么感兴趣。在这种情况下,可以使用混合搜索来将搜索结果限制为在超级碗完成后(即2月12日之后)发生的信息。通过这样做,将获得当天相关的结果,并过滤掉之前的结果。

实践:使用元数据进行混合搜索 🛠️

现在您已经了解了元数据和混合搜索的概念,让我们看看这在实践中是什么样子。

就像上一课一样,可以从非结构化库中导入一些辅助函数。在这一课中,有一个额外的重要导入要强调:ChromaDB。ChromaDB是一个内存中的向量数据库,在本课程中,将使用它进行相似性搜索。
示例目标与文档
在这个例子中,将使用一份关于瑞士冬季运动的电子出版物。本例中的目标是能够为文档中的每个部分识别章节,然后进行混合搜索,在这个混合搜索中,将提出关于文档中特定章节的问题。


首先,可以查看文档。对于这个应用程序来说更重要的是目录。在这个应用程序中,将查找目录中的标题。当对这个文档进行预处理时,将获得一个名为parent_id的元数据字段,它将每个元素附加到一个标题,这个标题是一个章节的标题。然后,将使用该元数据来构建混合搜索,从而在文档中搜索特定章节或章节内容。

步骤一:通过API预处理文档
该过程的第一步是通过非结构化API运行文档。在这种情况下,将使用非结构化API而不是开源库,因为电子出版物在预处理之前会转换为HTML,因此需要一些额外的依赖项。我们将依赖API来处理这些。
一旦向非结构化API发出请求,将收到响应。这是一个大型文档,因此API可能需要几秒钟来预处理它。处理完文档后,就可以使用在上一课中学到的JSON显示函数来探索结果。可以看到它捕获的第一个元素是书的标题,并将该元素分类为标题,可以在下面看到一些元数据。

步骤二:识别章节元素
流程的下一步是查找与章节相关联的元素。为了做到这一点,将使用parent_id元数据字段,该字段将一个在章节内的元素与父元素关联起来,在本例中,即章节的标题。

因此,可以在这里看到一个示例。在这种情况下,我们执行了一个过滤操作。我们过滤出包含单词“hockey”的标题元素。因此,在这种情况下,能够在目录中发现冰球标题,还有开始冰球章节的冰球标题。在这种情况下,将通过parent_id查找与冰球章节标题相关的元素,该parent_id将对应于冰球标题元素的此元素ID。

值得注意的是,这是一个过滤操作,在这种情况下,我们过滤到标题。还可以尝试将自己缩小到各种其他元素类型,例如叙述文本。但是对于这个用例,我们感兴趣的是标题。
步骤三:建立章节映射

现在知道如何进行过滤,可以设置章节的名称。因此,可以从目录中的章节列表中获取这些名称。
一旦获得这些章节名称,可以循环遍历提取的所有元素,并找到与这些章节标题相关联的元素标识符。为什么这很重要呢?这些标题的元素标识符将显示为那些位于该章节内的元素的父标识符。通过这样做,能够识别章节内的元素,这使您能够对章节进行混合搜索。例如,仅搜索出现在冰球章节内的内容。
那么,当这样做时,得到的是一个将父元素标识符映射到章节名称的映射。
一旦获得了该映射,就可以轻松地将父标识符转换为章节名称。因此,这是一个位于冰球章节内的元素的示例。它具有对应于冰球标题的元素标识符的父标识符。因此,我们知道具有此父标识符的任何元素都是冰球章节内的元素。
步骤四:加载到向量数据库并执行混合搜索
现在我们已经确定了文档中的元素,并确定了每个元素所属的章节。下一步是将所有这些内容加载到向量数据库中,这将使我们能够执行混合搜索。
在这种情况下,将使用Chroma作为向量数据库,因为它运行在内存中,通常是一个很好的选择。首先设置Chroma数据库,然后设置一个集合。需要将一些信息传递给create_collection函数,包括集合名称和一些用于配置向量数据库本身的元数据(例如,指定使用余弦相似度进行相似性搜索)。
设置好后,可以使用章节映射将文档插入到带有章节元数据的向量数据库中。特定章节内的元素具有与章节标题的元素ID对应的父级ID。因此,将使用之前创建的映射来获取章节的名称,以便更容易地进行搜索。然后,在将其加载到向量数据库中时,可以将该章节名称用作元数据。

现在元素都已加载到向量数据库中。可以使用collection.peek()方法查看加载的内容。
元素已经加载到带有元数据的向量数据库中,现在可以在该向量数据库上执行带有元数据的混合搜索。
首先,设置一个查询,其中包含查询文本。例如,询问“团队有多少名球员”,并通过将搜索条件设置为“出现在冰球章节中”来执行混合搜索。这很重要,因为这将限制结果仅显示在该章节中出现的信息。如果文档中还有其他团队运动,将无法获取那些信息,只会得到有关冰球的信息。

可以运行查询并查看结果,例如看到一些关于冰球队有多少球员的信息。可以尝试使用不同的查询,或者在另一章节上进行过滤。


利用元数据进行智能分块 🧩

现在您已经了解了在预处理过程中提取元数据以及如何将其作为混合搜索的一部分使用。事实证明,元数据不仅对混合搜索有用,还对其他操作有用,例如分块。
为什么需要分块?
分块意味着将长篇文本(如大型文档)分解为较小的部分,以便可以将这些较小的部分传递到矢量数据库中。然后,可以将这些片段包含在提示模板中,以传递给LLM。
为什么需要这样做?有两个主要原因:
- 上下文窗口限制:一些LLM的上下文窗口有限,因此可以传递给LLM的内容有限。这意味着无法将完整的文档传递给LLM,因此必须将其拆分。
- 成本考虑:在许多情况下,如果使用更大的上下文窗口,LLM的推理成本将更高。将文档分块成较小的部分可以帮助节省成本。
根据如何将内容分块,相似性搜索查询的结果将发生变化。如果不同内容在不同块中分割,可能会收到不同的块。一般来说,更好的分块会导致更好的相似性搜索结果,进而提高查询LLM时的最终结果。
传统分块 vs. 基于元素的分块
最简单的分块方式是创建均匀大小的块。有多种不同的方法可以做到这一点,例如按字符分块或按标记分块。这里的想法是,拿到一个大文档,设定一个阈值,然后每当达到阈值时,就拆分出一个新块。

然而,通过使用我们在上一节中提取的元数据,可以更加智能地进行分块,利用文档中的文档元素信息。
从概念上讲,这里做的事情与传统的分块技术不同:
- 传统分块:将一个大文档拆分为多个部分。
- 基于元素的分块:首先将文档拆分为原子文档元素(如标题、叙述文本),然后将这些元素组合成块。

基于元素分块的优势
首先,像已经学过的那样对文档进行分区。一旦对文档进行了分割,就会得到诸如标题、叙述文本和列表等各个文档元素,可以将其用作分块操作的基础。
一旦获得了这些原子文档元素,可以将它们组合成块。当将它们组合成块时,可以应用断点条件,以便将逻辑上属于一起的内容组合在一起。例如,断点条件可以是:每当遇到标题时,就创建一个新的块。
这为什么重要?因为标题通常表示一个新部分的开始。所以当应用诸如“标题”之类的断点条件时,实际上是将来自同一部分的内容组合在一起。通过这样做,更有可能将属于同一部分的内容放在一起,这使您能够构建更连贯的块。当在向量数据库中执行相似性搜索时,这意味着将获得更相关的内容。
这样做,我们利用了已经对文档结构的了解,这使我们能够以更智能的方式构建块。另一个优点是,分块策略应用于标准化文档元素列表。由于将分块策略应用于该列表,可以将不同的分块策略应用于该初始输出,这使您可以快速尝试不同的分块技术,并查看在LLM最终用户应用中的结果是什么样的。

实践对比
让我们看看这在实践中是什么样子。在这个例子中,将看到使用传统字符分割技术进行分块时的情况。在这种情况下,应用了一个阈值,当达到一定字符数时,将拆分成一个新的块。这里,来自第一部分的信息会渗入到第二个块中。如果搜索“开放域问答”,将从第一个块中获取相关信息,也会从第二个块中获取感兴趣的信息,但同时也包括了关于“抽象问答”的不相关信息。
如果可以根据这些部分进行分块,结果会更好。当使用文档元素进行分块时,会得到更接近这样的结果:找到标题,当遇到新标题时,拆分成新的块。当这样做时,可以将属于同一部分的内容保持在一起。这一次,当查询关于“开放域问答”的信息时,只会获得关于开放域问答的内容,不会得到任何关于不感兴趣的“抽象问答”的内容。当查询向量数据库时,会得到更好的结果,这将导致语言模型的更好提示,从而得到更好的答案。
动手操作
现在可以看到在实践中使用文档元素信息进行分块是什么样子。可以通过使用文档元素信息反序列化序列化的JSON内容来开始。要做到这一点,可以使用来自非结构化开源库的dict_to_elements函数。
一旦拥有这个,使用非结构化开源库中的chunk_by_title功能再次对此内容进行分块就很容易了。这是在反序列化的元素上操作。还可以查看这里的一些设置:
max_characters:对块的大小设置一个字符限制。如果一个块超过了这个限制,将分割成一个新的块。merge_text_under_n_chars:指导分块策略在元素中少于N个字符时合并块,这可以防止非常小的块。
在设置了这些参数之后,可以对内容进行分块,并通过使用JSON显示函数查看这个内容的样子。可以看到书的标题与相关信息被分块在一起。可以验证内容确实已被分块,因为分块输出中的块数(例如255个)少于原始元素数(例如752个),这意味着块确实合并了不同的元素,现在我们拥有了更少但更大的块。
总结

本节课中我们一起学习了元数据在LLM应用程序预处理中的关键作用。
首先,我们定义了元数据,并了解了它可以是文档级别或元素级别的附加信息。接着,我们回顾了语义搜索的基础,并指出了其局限性,从而引出了混合搜索的概念。混合搜索通过结合语义相似度和元数据过滤,能更精准地检索信息。

然后,我们通过一个实践示例,演示了如何从文档中提取章节信息作为元数据,建立映射,并将其用于Chroma向量数据库的混合搜索查询中。
最后,我们探讨了元数据的另一个重要应用:智能分块。与传统的均匀分块相比,基于文档元素(如标题)的分块能创建更连贯、语义更完整的块,从而提升后续检索和LLM回答的质量。

在下一课中,您将学习更多关于在PDF文档和图像上运行的复杂预处理技术。
005:预处理PDF与图像文档
在本节课中,我们将要学习如何为大型语言模型(LLM)应用程序预处理PDF和图像这类非结构化文档。我们将重点介绍两种关键的文档图像分析技术:文档布局检测和视觉转换器,并了解它们如何从视觉信息中提取结构化的文本内容。
概述
到目前为止,我们已经学习了如何预处理HTML、Word文档和PowerPoint这类本身包含结构化信息的文档。然而,像PDF和图片这样的文档,其内部通常没有可用的结构化标记。对于这些文档,我们需要借助视觉信息来理解其布局和内容。本节课程将介绍两种基于视觉的预处理方法。
文档图像分析技术简介
上一节我们介绍了基于规则解析器的应用,本节中我们来看看如何利用视觉信息处理非结构化文档。文档图像分析允许我们从文档的原始图像中提取格式化信息和文本。以下是两种主要的方法:
- 文档布局检测:使用目标检测模型识别并标记文档中的不同元素。
- 视觉转换器:以整个文档图像作为输入,直接生成结构化的文本输出。
文档布局检测
文档布局检测模型通过两个步骤工作:首先识别并分类文档中各个元素(如标题、段落、列表)的边界框,然后从这些边界框内提取文本。
以下是其工作流程的两个核心步骤:
- 绘制与标记边界框:模型在文档图像中为每个视觉元素(如叙述性文本、标题、项目符号列表)绘制一个边界框,并为其分类。
- 提取文本:根据文档类型,有两种提取文本的方式:
- 对于纯图像或扫描件,需要应用光学字符识别(OCR)技术来识别文本。
- 对于某些包含可选中文本层的PDF,可以直接利用边界框坐标信息,从原始文档中提取对应区域的文本。
一个常用于文档布局检测的模型是YOLOX。其架构是一个典型的目标检测模型,专门针对文档中的元素进行训练。
作为实践示例,下图展示了文档布局检测的结果。模型成功地在标题、叙述性文本和表格等元素周围绘制了边界框。在确定并标记这些边界框之后,就可以进行文本提取。

视觉转换器
与需要多步处理的文档布局检测不同,视觉转换器提供了一种更直接的解决方案。它可以在一个步骤中从PDF和图像中提取内容。
视觉转换器接受文档图像作为输入,并直接生成文本作为输出。在这个过程中,无需单独调用OCR模型。一种常见的视觉转换器架构是Donut(文档理解转换器)。
这种模型可以被训练为生成结构化的输出,例如一个有效的JSON字符串。这个JSON可以包含我们感兴趣的文档元素及其类别。
下图展示了Donut模型的架构。模型处理图像后,会输出一个字符串。

该字符串是一个有效的JSON,其中每个元素都包含文本内容及其类别信息。获得这个字符串后,我们可以将其转换为我们期望的规范化文档元素格式。
技术选型:如何选择?

那么,在实际应用中,应该何时使用视觉转换器,何时使用文档布局检测模型呢?每种模型都有其优缺点。
以下是文档布局检测模型的优缺点:

- 优点:
- 模型针对一组固定的元素类型进行训练,对这些元素的识别精度通常非常高。
- 提供边界框信息,便于将提取结果追溯回原始文档的特定位置,并且在某些情况下可以不依赖OCR直接提取文本。
- 缺点:
- 在某些情况下需要两次模型调用:首先是目标检测模型,其次是OCR模型。
- 灵活性不足。模型基于固定的元素类型集工作,如果需要提取新的元素类型,可能需要重新训练模型。
以下是视觉转换器的优缺点:
- 优点:
- 对非标准文档类型(如复杂表格)更灵活,能够相对轻松地提取键值对等信息。
- 更容易适应新的元素类型。对于文档布局检测模型,添加新元素类型很困难,但可以通过提示(Prompt)的方式引导视觉转换器识别新类别。
- 缺点:
- 模型具有生成性,因此可能像自然语言模型一样,出现幻觉或重复内容。
- 通常比文档布局检测模型计算量更大,因此需要更多的计算资源或运行速度更慢。
实践练习:预处理同一文档的不同格式
现在我们已经学习了一些预处理PDF和图像的技术,让我们把它们付诸实践。在这个练习中,我们将预处理同一篇文档,先处理其HTML版本,再处理其PDF版本,以展示不同方法如何提取出相似的文档结构。
我们将处理的文档是CNN发布的一篇关于厄尔尼诺气象模式的新闻文章。

首先,导入必要的依赖项。由于处理PDF是基于模型的工作负载,我们将通过API进行调用。
步骤一:预处理HTML文档
首先,我们处理文档的HTML表示形式。使用partition_html函数(来自unstructured开源库)来处理HTML文件。

from unstructured.partition.html import partition_html
elements_html = partition_html(filename="document.html")
查看提取出的元素,函数识别出了叙述性文本、标题等,并利用了HTML标签本身的信息。
步骤二:使用快速策略预处理PDF
接下来,预处理相同文档的PDF表示形式。首先使用unstructured库中的FAST策略。该策略直接从PDF文档中提取文本,适用于像新闻文章这样布局简单的PDF。

from unstructured.partition.pdf import partition_pdf
elements_pdf_fast = partition_pdf(filename="document.pdf", strategy="fast")
查看提取出的元素,它们与从HTML中提取的元素非常相似。
步骤三:使用文档布局检测预处理PDF
现在,使用文档布局检测模型(这里使用YOLOX模型)通过非结构化API来预处理同一个PDF。该模型会绘制边界框并提取文本。
# 通过API调用,指定使用高分辨率模型‘yolox’
elements_pdf_yolox = partition_pdf(filename="document.pdf", strategy="hi_res", model_name="yolox")
这个过程是基于模型的,可能需要一些时间。完成后,查看输出。模型同样识别出了标题和叙述文本,输出结果与HTML和快速策略的输出非常类似。

步骤四:结果对比
现在,我们可以比较这些输出。例如,HTML输出有35个元素,包括23个叙述文本元素和10个标题元素。而文档布局检测(YOLOX)输出有39个元素,包括28个叙述文本元素和10个标题元素(可能细分为页眉、主标题等)。
可以看到,输出并不完全一致,但非常接近。这表明,无论文档是以PDF还是HTML格式呈现,我们都能提取出几乎相同的结构化信息,从而可以在应用程序中统一处理它们。
自主尝试
现在您已经知道如何预处理PDF文档了,可以尝试以下练习:
- 尝试视觉转换器:将上面代码中的
model_name参数从"yolox"改为"chipper"(一种视觉转换器模型),运行并观察输出的不同。 - 处理您自己的文档:找一个您自己的PDF文档,使用上述方法进行预处理,观察效果。
总结
本节课中我们一起学习了如何为LLM应用预处理PDF和图像这类非结构化文档。我们深入探讨了两种核心技术:文档布局检测和视觉转换器。我们了解了它们的工作原理、优缺点,并通过实践练习,使用不同方法处理了同一文档的HTML和PDF版本,验证了它们能提取出相似的结构化信息。
在下一课中,您将学习如何预处理包含更复杂布局(如表格)的PDF文档。


006:提取表格 📊
在本节课中,我们将要学习如何从非结构化文档(如PDF和图像)中提取表格内容,并将其转换为适合LLM处理的格式。表格是许多文档中承载结构化信息的关键部分,掌握其提取技术对于构建高质量的RAG应用程序至关重要。
概述:表格提取的重要性
上一节我们介绍了如何使用视觉线索从PDF和图像中提取信息。本节中,我们来看看更高级的预处理技术——提取表格内容。

大多数RAG应用侧重于文档中的纯文本内容。然而,在一些行业中,非结构化文档中经常包含结构化信息,例如表格。这在金融和保险等行业尤为常见。表格提取使得RAG应用程序能够从非结构化文档中提取包含在表格中的关键信息。

表格提取的挑战与方法
一些文档类型,如HTML和Word文档,其本身包含了表格的结构信息(例如HTML中的<table>标签)。对于这些文档,可以使用基于规则的解析器来提取表格信息。
然而,对于PDF和图像这类文档,需要使用视觉线索来识别文档中的表格区域,然后处理它以提取信息。主要有三种技术可以帮助完成这个任务:
- 表格转换器
- 视觉转换器
- OCR后处理
一旦从表格中提取了内容,通常需要将其转换为HTML输出,以便在将表格传递给LLM时保留其结构信息。
方法一:表格转换器
首先,我们来了解表格转换器。表格转换器是一个模型,它识别表格单元的边界框,然后将输出转换为HTML。



这个过程分为两个步骤:
- 使用文档布局检测模型识别文档中的表格区域。
- 将识别出的表格区域传递给表格转换器模型进行处理。

以下是表格转换器方法的优缺点:
优点:
- 能够追溯到原始文档中每个单元格的边界框信息。
缺点:
- 涉及多次昂贵的模型调用,包括文档布局检测和OCR调用。

表格转换器模型的架构如下图所示。如果您感兴趣,可以查看相关论文。

方法二:视觉转换器
您还可以使用视觉转换器从PDF和图像中提取表格内容,就像在上一课中提取JSON信息一样。但与此前不同的是,本节的目标输出是HTML。


以下是视觉转换器方法的优缺点:
优点:
- 提示更加灵活。
- 只涉及单一模型调用。

缺点:
- 属于生成式方法,容易产生“幻觉”(输出不准确的内容)。
- 不会保留单元格的边界框信息。
这种方法的过程示例如下:从文档图像开始,通过视觉转换器运行,最终得到表格的HTML文本表示。
方法三:OCR后处理
您可以用于预处理包含表格的文档的最后一种技术,是对表格进行光学字符识别(OCR)后处理。

在这种技术中:
- 使用文档布局检测模型识别表格。
- 对表格区域进行OCR,获取文本。
- 使用基于规则或统计的方法处理OCR文本,以重建表格结构。
以下是OCR后处理方法的优缺点:

优点:
- 处理速度快。
- 对于格式规范、简单的表格,可以非常准确。
缺点:
- 依赖于统计或基于规则的解析,比其他方法更脆弱、不够灵活。
- 对于复杂的表格,效果可能不理想。

下图展示了使用文档布局检测模型识别表格,并对OCR输出进行后处理,最终构造出HTML表示的示例。


实践:使用非结构化API提取表格
现在,您已经学会了从非结构化文档中提取表格的一些技术,接下来可以将其付诸实践。

首先,导入在之前课程中使用过的一些辅助函数。由于表格提取是基于模型的,我们将再次使用非结构化API,因为它已经为您设置好了所有需要的模型。

# 导入必要的库和辅助函数
from unstructured.partition.pdf import partition_pdf
在上一课中,我们处理了一些简单的PDF示例。现在,我们将预处理一个包含表格和图像的更复杂文档。




您可以在下面看到这个文档的样子。我们的目标是从该文档的特定页面中提取“表1”的内容。



现在,开始进行预处理。要将文档传递给非结构化API,需要注意以下参数:
# 调用API提取元素,包括表格
elements = partition_pdf(
filename="complex_document.pdf",
infer_table_structure=True, # 关键参数:告诉API提取表格结构
skip_infer_table_types=[], # 不对任何文档类型跳过表格推断
strategy="hi_res", # 使用高分辨率策略
model_name="yolox" # 指定布局检测模型
)
infer_table_structure=True:这个参数告诉API我们想要提取表格的结构信息。skip_infer_table_types=[]:这个参数指示API不要跳过任何文档类型的表格提取。

现在,可以运行API调用了。请注意,此过程需要多个模型调用,可能需要几分钟时间。
API调用完成后,可以通过过滤操作,将文档中的内容缩小到仅包含表格元素。我们将查找类别(category)为“Table”的元素。
# 过滤出所有表格元素
tables = [el for el in elements if el.category == "Table"]
查看与使用提取结果

现在您有了表格元素,可以使用元素的.text属性查看表格中的文本内容。

# 查看第一个表格的文本内容
print(tables[0].text)
然而,正如之前所学,将表格信息以HTML格式传递给LLM有助于保持表格结构。这些信息存储在元素的元数据中,作为一个名为“html”的字段。
# 查看表格的HTML表示
table_html = tables[0].metadata.html
print(table_html)

您可以使用以下代码块查看元数据字段中的HTML是什么样子。如您所见,这是文档中表格的HTML表示。



如果您有兴趣在Notebook中显示此表格,也可以使用IPython的HTML显示功能。

from IPython.display import HTML, display
display(HTML(table_html))




为表格生成摘要

一旦从文档中提取了表格内容并将其转换为HTML,为这些表格生成摘要也很有帮助。这样,在RAG架构中执行相似性搜索时,就可以搜索这些摘要。
为此,我们将使用LangChain中的一些实用工具。LangChain是一个用于编排LLM应用的流行框架。
from langchain.chains.summarize import load_summarize_chain
from langchain.schema import Document
from langchain_openai import ChatOpenAI
# 实例化LLM
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 创建摘要链
chain = load_summarize_chain(llm, chain_type="stuff")
# 将表格HTML内容包装成LangChain文档对象
table_doc = Document(page_content=table_html)
# 对表格进行摘要
summary = chain.run([table_doc])
print(summary)


正如您所看到的,模型成功地对表格进行了摘要。现在,我们既有了表格的HTML表示,也有了一个文本摘要,可以在RAG系统内进行相似性搜索时使用。
总结与练习
本节课中,我们一起学习了如何从PDF和图像中提取表格内容。我们介绍了三种主要方法:表格转换器、视觉转换器和OCR后处理,并重点实践了使用非结构化API进行表格提取和摘要的完整流程。
现在您知道如何提取表格内容了,请尝试在您自己的文件上实践一下。如果您有兴趣尝试不同的参数,还可以将high_res策略下的model_name参数更改为“chipper”,以便比较视觉转换器与表格转换器的输出效果。
在下一课中,我们将把所有技能结合起来,为您自己构建一个完整的文档预处理流程。
007:构建RAG机器人 🚀
在本节课中,我们将综合运用之前学到的所有技巧,构建一个RAG机器人。这个机器人将使用一个包含PDF、PowerPoint和Markdown文档的语料库。我们将编写代码,整合预处理、向量数据库查询和LLM提示构建等步骤,最终实现一个能与文档对话的智能应用。
准备工作

上一节我们介绍了多种文档预处理技巧,本节中我们来看看如何将它们整合到一个完整的应用程序中。首先,你需要准备好语料库和必要的工具。

以下是构建RAG机器人前需要完成的准备工作:
- 导入辅助函数:导入在整个课程中已见过的函数,并针对新文档类型(如Markdown)添加新的处理函数(例如
partition_markdown)。 - 设置非结构化客户端:因为语料库包含PDF文档,除了基于规则的解析外,还需要使用非结构化API。
- 准备语料库:本教程的语料库包含三份关于“甜甜圈模型”的文档:
- 一份包含复杂表格的PDF论文。
- 一份包含相关信息的PowerPoint演示文稿。
- 一份来自GitHub仓库的Markdown格式的README文件。

预处理PDF文档

现在,我们开始对PDF文档进行预处理。我们将应用在课程中学到的知识,使用非结构化API调用YOLOx模型进行文档布局检测。

# 示例:使用非结构化API处理PDF
processed_pdf_elements = unstructured_client.process_pdf("donut_paper.pdf", strategy="hi_res")

这是一个基于昂贵模型的工作负载,如果处理需要几分钟,属于正常现象。预处理完成后,可以查看结果。例如,以下是一个被识别为“标题”的元素:
print(processed_pdf_elements[0].text) # 输出标题文本

PDF中的表格信息被保存在元素的元数据中,以HTML格式存储。你可以在组装RAG应用程序后查询这些表格。

过滤无关内容

预处理后的文档可能包含我们不希望被检索到的内容,例如参考文献和页眉。我们可以利用提取的元数据进行过滤。
过滤参考文献


首先,我们过滤掉参考文献部分。参考文献不包含叙述性内容,对问答应用价值不大。

- 定位参考文献标题:通过检查元素的类别和文本内容,找到“References”或“参考文献”标题元素。
- 获取其元素ID:将该标题元素的ID保存下来。
- 过滤子元素:查找所有“父ID”等于该标题元素ID的元素,这些就是参考文献条目。
- 执行过滤:从元素集合中移除这些条目。
# 伪代码:过滤参考文献
reference_title_id = find_element_id_by_text(elements, "References")
elements = [el for el in elements if el.metadata.parent_id != reference_title_id]
过滤页眉信息

接下来,我们过滤掉每页顶部的页眉信息(如文档标题和页码),这些信息会破坏文档的叙事结构。
- 识别页眉元素:页眉元素的元数据中,
category字段通常为Header。 - 执行过滤:直接从元素集合中移除类别为
Header的元素。

# 伪代码:过滤页眉
elements = [el for el in elements if el.metadata.category != "Header"]

完成这两步过滤后,我们的元素集就只包含核心的叙述性内容了。


预处理其他文档类型
处理完PDF后,我们继续预处理PowerPoint和Markdown文档。方法与我们早期课程中学到的一致。

- 预处理PowerPoint:使用非结构化开源库中的
partition_pptx函数。 - 预处理Markdown:使用非结构化开源库中的
partition_md函数。
from unstructured.partition.pptx import partition_pptx
from unstructured.partition.md import partition_md

ppt_elements = partition_pptx("donut_presentation.pptx")
md_elements = partition_md("README.md")

分块与加载到向量数据库

现在我们已经预处理了所有文档,下一步是将它们合并为单个语料库,并进行分块处理。
- 合并与分块:使用在元数据和分块课程中学到的
chunk_by_title函数对所有文档元素进行分块。 - 准备加载:将分块后的文档转换为适合加载的格式,并包含元数据(如来源文件名),以便后续进行混合搜索。
- 嵌入与加载:使用OpenAI Embeddings为文档块生成向量,然后利用LangChain的工具将其加载到Chroma向量数据库中。

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
# 假设 `all_chunks` 是分块后的文档列表,包含文本和元数据
vectorstore = Chroma.from_documents(
documents=all_chunks,
embedding=OpenAIEmbeddings(),
persist_directory="./chroma_db"
)

设置检索器与提示模板
向量数据库准备就绪后,我们需要设置检索器和与大模型对话的提示模板。

-
设置检索器:创建一个基于向量相似度的检索器,用于从数据库中查找与问题相关的文档块。
retriever = vectorstore.as_retriever(search_kwargs={"k": 6}) -
创建提示模板:使用LangChain定义提示模板,指导LLM如何基于检索到的上下文回答问题,并声明在不知道答案时应如实回答。
from langchain.prompts import PromptTemplate template = """你是一个AI助手,请根据以下上下文回答问题。 如果你不知道答案,就说你不知道。不要编造答案。 上下文:{context} 问题:{question} 答案:""" PROMPT = PromptTemplate(template=template, input_variables=["context", "question"])

构建对话链并进行查询
最后,我们将所有组件连接起来,构建一个完整的对话链。
-
构建对话链:使用LangChain的
ConversationalRetrievalChain,它集成了检索、历史管理和提示填充功能。from langchain.chains import ConversationalRetrievalChain from langchain.chat_models import ChatOpenAI qa_chain = ConversationalRetrievalChain.from_llm( llm=ChatOpenAI(temperature=0), retriever=retriever, combine_docs_chain_kwargs={"prompt": PROMPT} )

-
进行查询:现在可以向你的RAG机器人提问了。
-
示例问题1:“Donut模型与其他文档理解模型有何不同?”
- 机器人回答:正确指出Donut是一个不依赖OCR的文档理解模型,并引用了其来源(论文和幻灯片)。
-
示例问题2(混合搜索):如果你只想从README文件中查找信息,可以设置一个能过滤元数据(如文件名)的检索器。
# 创建过滤特定来源的检索器 filtered_retriever = vectorstore.as_retriever( search_kwargs={"k": 6, "filter": {"source": "README.md"}} ) # 用新的检索器创建链并提问提问:“如何使用Donut对文档进行分类?” 机器人将只用README文件中的内容来回答。
-
总结与拓展
本节课中我们一起学习了如何构建一个完整的RAG机器人。我们从预处理混合格式的文档开始,经历了过滤无关内容、分块、嵌入并加载到向量数据库,最后设置了检索器和提示模板,通过LangChain链实现了智能问答。

你现在已经拥有了构建自己RAG应用的基础。可以尝试以下方式进行改进:
- 加入你自己的文档(如Word文档)。
- 尝试提出更复杂的问题。
- 在混合搜索中利用其他元数据字段(如作者、章节)进行过滤。

现在,你已经准备好基于对你自己或你的组织重要的各种文档信息,创建专属的智能问答机器人了。
008:总结 🎯
在本节课中,我们将一起回顾整个课程的核心内容,总结从非结构化数据预处理到构建功能完善的RAG应用程序的关键步骤。
课程概述
在本课程中,我们学习了如何为大型语言模型应用程序处理和准备非结构化数据。主要内容包括从多种数据源摄取内容、对内容进行规范化处理、利用元数据增强检索增强生成应用程序,以及应用高级技术从PDF和图像中提取信息。
核心内容回顾
上一节我们介绍了各种高级建模技术,本节中我们来对整个课程进行总结。
以下是本课程涵盖的主要学习要点:
- 数据摄取与规范化:您学习了如何从各种不同的数据源中摄取和规范化内容。
- 元数据的使用:您学习了如何在预处理过程中使用提取的元数据来丰富RAG应用程序。
- 高级内容提取技术:您学习了用于解锁PDF和图像中内容的高级建模技术。
- 构建完整应用:您学会了如何将数据预处理的输出转换为一个功能完善的RAG机器人。
最终成果与展望

现在,您已经掌握了构建一个了解您特定项目或组织信息的RAG机器人所需的核心技能。通过本课程的学习,您已经准备好将理论应用于实践,开始构建属于自己的智能问答或信息检索系统。

总结
本节课中我们一起回顾了为LLM应用程序预处理非结构化数据的完整流程。从最初的数据处理到最终构建出可用的RAG机器人,您已经走过了一条完整的学习路径。掌握这些技能是开发现实世界中高效、准确的大型语言模型应用的重要基础。


浙公网安备 33010602011771号