【LangChain开发】LangChain——文档加载器和文本分割器


🚀 欢迎来到我的CSDN博客:Optimistic _ chen
一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!


🚀我的专栏推荐

专栏内容特色适合人群
🔥C语言从入门到精通系统讲解基础语法、指针、内存管理、项目实战零基础新手、考研党、复习
🔥Java基础语法系统解释了基础语法、类与对象、继承Java初学者
🔥Java核心技术面向对象、集合框架、多线程、网络编程、新特性解析有一定语法基础的开发者
🔥Java EE 进阶实战Servlet、JSP、SpringBoot、MyBatis、项目案例拆解想快速入门Java Web开发的同学
🔥Java数据结构与算法图解数据结构、LeetCode刷题解析、大厂面试算法题面试备战、算法爱好者、计算机专业学生
🔥Redis系列从数据类型到核心特性解析项目必备

🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例

✅ 持续更新:专栏内容定期更新,紧跟技术趋势

✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)


🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨

📌 标签:#技术博客#编程学习#Java#C语言#算法#程序员

文档加载器Document loaders

文档加载器(Document Loaders)是 LangChain 中负责从各种数据源读取数据,并将其转换为标准化 Document 对象的组件。它是构建任何需要外部知识的 LLM 应用(如 RAG)的第一步 。

核心价值:解决了 LLM 应用开发中的关键问题:数据异构性。现实世界的数据格式多样(PDF、网页、数据库等),LLM 无法直接理解。加载器的作用就是提供一个标准接口,将不同来源、不同格式的数据,统一处理成 LangChain 可以操作的 Document 对象。

LangChain 生态提供了极其丰富的文档加载器,数量超过上百种,官方按数据来源进行了分类,分别对应不同的文档进行加载器:

  • TextLoader:加载纯文本文件
  • CSVLoader:加载csv文件,每行作为一个文档
  • PyPDFLoader:加载并解析PDF文件
  • JSONLoader:使用JSON Pointer提取指定字段
  • UnstructuredLoader:支持多种格式加载

RAG检索增强生成

RAG阶段(Retrieval-AugmentedGeneration,检索增强⽣成),作为构建外部知识库的 LLM 应用的第一步 。搜索引擎可以帮我们解决实时数据的获取,但获取到的数据也是受限的。它只能获取到公开在⽹络中的数据,⽽⽆法获取到⼀些本地数据,或企业内部的私有数据等,此时该如何操作?

当然是使用RAG技术,当用户向LLM提问时,系统首先在知识库中进行语义搜索,找到最相关内容,然后将这些内容和问题一起交给LLM来生成答案。
这部分的具体内容,【AI Agent 全栈开发】RAG(检索增强生成)有详细介绍,可以移步学习。这里只是简单示例

Document文档类

LangChain⽂档加载器可以将各种数据源加载成⼀系列的⽂档对象Document,用于存储一段文本和相关元数据的类。

documents=[
	Document(
		#内容字符串
		page_content="狗是人类的好朋友,冠以忠诚和友好之名",
		#元数据字典
		metadata={"scoure":"mammal-pets-doc"},
	),
	Document(
		page_content="猫与人类相互陪伴,躲避无人的孤寂",
		metadata={"scoure":"mammal-pets-doc"},
	)
]

我们定义了一个documents文档列表,其中包含两个Document文档对象。
在这里插入图片描述

from langchain_community.document_loaders import PyPDFLoader

file_path=""
loader=PyPDFLoader(file_path)

# 将 PDF ⽂件的每⼀⻚转换为⼀个独⽴的 Document 对象,并存储在列表 docs 中。
docs=loader.load()

加载PDF文档

将本地PDF文档加载到LangChain中,其实就是把PDF文档转化为一个个Document对象,使用PyPDFLoader文档加载器完成这一功能。

在这里插入图片描述
随着AI的发展,LLM支持多模态输入,某些应用程序可能会跳过PDF解析,直接将PDF转化为图像传给LLM可能更准确。

加载Markdown文件

将本地的Markdown ⽂档加载到LangChain中,需要我们使⽤UnstructuredMarkdownLoader文档加载器来完成。
在这里插入图片描述

# 导入 UnstructuredMarkdownLoader,用于加载和解析 Markdown 文件
from langchain_community.document_loaders import UnstructuredMarkdownLoader

# 定义一个空字符串作为文件路径(注意:此处路径无效,实际使用时需替换为真实路径)
markdown_path = ""

# 创建加载器实例,传入文件路径
# 默认 mode="single",会将整个文档作为一个 Document 对象返回
loader = UnstructuredMarkdownLoader(markdown_path)

# 调用 load() 方法加载文档,返回一个 Document 对象列表
# 每个 Document 包含 page_content(文本内容)和 metadata(元数据)
data = loader.load()

# 断言:确保加载结果只有一个文档(因为 mode="single")
assert len(data) == 1

# 断言:确保该对象是 Document 类型(来自 langchain_core.documents)
assert isinstance(data[0], Document)

# 打印文档内容的前 200 个字符(用于快速预览)
print(data[0].page_content[:200])

# 打印文档的元数据,通常包含 source(来源路径)等信息
print(data[0].metadata)

文本分割器

上面讲了通过文档加载器完成各种数据源的加载,将其转化为Document文档对象,接下来就是对Document对象的文档分割操作。

⽂档拆分通常是将⼤⽂本分解为更⼩的、易于管理的块。这对于索引数据并将其传递到模型中都很有⽤,因为大块的Document对象不适合LLM有限的上下文窗口。拆分可以提高结果的粒度,从而更加精确的查询相关文档内容。

基于字符长度拆分

根据给定的字符序列进行拆分,拆分的块长度则按字符数来衡量。

#文档加载器
markdown_path=""
loader=UnstructuredMarkdownLoader(markdown_path)
data=loader.load()

#文本分割器
text_splitter=CharacterTextSplitter(
    separator="\n\n",        #选择分隔符
    chunk_size=100,          #设定目标块大小
    chunk_overlap=20,        #设定块之间重叠大小
    length_function=len,     #使用测量长度的函数
    is_separator_regex=False,#分割符是正则表达式吗
)
texts=text_splitter.split_documents(data)

运行后,可能会出现Created a chunk of size xxx, which is longer than the specified 100这类警告,这表示我们设定的chunk_size太小了,为了保证语义完整性,当文本分割器用尽所有指定分隔符都无法将一段文本分割到目标大小时,就会保留整个文本块,保证被分隔出来的块基本上都是语义完整的一段话。

基于Token长度拆分

之前我们讲过,LLM⼤模型实际上并不是直接接收字符串,⽽是需要先做token切分编码。这⾥我们可以借助【tiktoken 分词器】来进⾏token的切分编码。

我们就可以使⽤根据cl100k_base编码方式的tiktoken 分词器来拆分⽂档。这对于OpenAI模型来说,会更准确

#文档加载器
markdown_path=""
loader=UnstructuredMarkdownLoader(markdown_path)
data=loader.load()

#文本分割器(基于token分割)
text_splitter=CharacterTextSplitter.from_tiktoken_encoder(
    encoding_name="cl100k_base",
    chunk_size=200,
    chunk_overlap=50
)
texts=text_splitter.split_documents(data)

特殊文档结构拆分

对于一些特殊的文档,比如代码等可以尝试使用Language提供的不同的分割器(PythonCodeTextSplitter、HTMLHeaderTextSplitter)效果会更好,它们能够理解代码的语法结构

from langchain_text_splitters import RecursiveCharacterTextSplitter, Language

# 1. 准备一段 Python 代码
PYTHON_CODE = """
def hello_world():
    print("Hello, World!")

# Call the function
hello_world()
"""

# 2. 使用 from_language 方法创建针对 Python 优化的拆分器
python_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.PYTHON, 
    chunk_size=50, 
    chunk_overlap=0
)

# 3. 执行拆分
splits = python_splitter.create_documents([PYTHON_CODE])

# 4. 查看拆分结果
for doc in splits:
    print(f"内容:\n{doc.page_content}\n")

在这里插入图片描述

完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~

想获取更多干货? 欢迎关注我的专栏 → optimistic_chen
📌 收藏本文,下次需要时不迷路!

我们下期再见!💫 持续更新中……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Optimistic _ chen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值