langchain各类文档加载

LangChain文档加载器提供了两种核心加载方式:load()一次性加载全部文档和lazy_load()延迟流式加载文档,后者特别适合处理大型数据集以避免内存溢出问题。

一、文档加载器核心加载方法

两种加载模式详解

load() - 一次性加载模式,将所有文档一次性加载到内存中,返回完整的Document对象列表,适合小型数据集(如单个PDF、小型文本文件)

代码示例:

python 复制代码
from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader("./data/small.pdf")
documents = loader.load()  # 一次性加载所有页面
print(f"共加载 {len(documents)} 个文档")
lazy_load() - 延迟流式加载模式

按需加载文档,仅在迭代时才实际加载内容

返回一个生成器对象,避免一次性占用大量内存

特别适合大型数据集(如GB级日志文件、大型PDF文档集)

代码示例:

python 复制代码
from langchain_community.document_loaders import TextLoader

loader = TextLoader("./data/large_log.txt", encoding="utf-8")
for doc in loader.lazy_load():  # 逐块加载,而非一次性加载
	print(f"处理文档块:{doc.page_content[:100]}")
	# 可在此处进行分块处理、向量化等操作

两种加载方式的底层关系

LangChain的BaseLoader基类中定义了这两种方法的关系:
python 复制代码
def load(self) -> List[Document]:
	"""一次性加载所有文档"""
	return list(self.lazy_load())

def lazy_load(self) -> Iterator[Document]:
	"""延迟加载文档(生成器)"""
	if type(self).load != BaseLoader.load:
    	return iter(self.load())  # 向后兼容:如果子类实现了load但没实现lazy_load
	raise NotImplementedError(f"{self.__class__.__name__} does not implement lazy_load()")
这种设计确保了:

新代码推荐使用lazy_load():更内存友好

旧代码兼容性:如果子类只实现了load(),lazy_load()会自动调用它

灵活性:开发者可以根据数据规模选择合适的加载方式

二、各种文档类型的具体加载方法

1、PDF文档加载

PyPDFLoader(最常用):
python 复制代码
from langchain_community.document_loaders import PyPDFLoader

# 一次性加载所有页面
loader = PyPDFLoader("./data/document.pdf", mode="page")
pages = loader.load()  # 返回每页一个Document对象

# 或使用延迟加载(推荐大型PDF)
for page in loader.lazy_load():
	print(f"第 {page.metadata.get('page', '未知')} 页: {len(page.page_content)} 字符")
关键参数说明:
powershell 复制代码
mode="page"(默认):每页生成一个Document,metadata包含页码
mode="single":将整个PDF作为单个Document对象
password:用于解锁加密PDF

2、文本文件加载

TextLoader(TXT/Markdown等纯文本):

python 复制代码
from langchain_community.document_loaders import TextLoader

# 一次性加载
loader = TextLoader("./data/sample.txt", encoding="utf-8")
documents = loader.load()

# 延迟加载(推荐大型文件)
loader = TextLoader("./data/large_file.md", encoding="utf-8")
for doc in loader.lazy_load():
    print(f"文档内容预览: {doc.page_content[:200]}...")
    print(f"来源: {doc.metadata['source']}")

3、目录批量加载

DirectoryLoader(批量处理文件夹):
python 复制代码
from langchain_community.document_loaders import DirectoryLoader

# 一次性加载所有txt文件
loader = DirectoryLoader(
    "./documents/",
    glob="**/*.txt",
    show_progress=True,
    use_multithreading=True
)
documents = loader.load()

# 延迟加载(推荐大型目录)
for doc in loader.lazy_load():
    print(f"处理文件: {doc.metadata['source']}")
    # 可在此处进行分块、向量化等操作

4、网页内容加载

WebBaseLoader(抓取网页内容):
python 复制代码
from langchain_community.document_loaders import WebBaseLoader

# 一次性加载
loader = WebBaseLoader("https://example.com")
data = loader.load()

# 延迟加载(推荐抓取多个网页)
urls = ["https://example.com/page1", "https://example.com/page2"]
loader = WebBaseLoader(urls)
for doc in loader.lazy_load():
    print(f"网页标题: {doc.metadata.get('title', '未知')}")
    print(f"内容长度: {len(doc.page_content)} 字符")

5、结构化数据加载

CSVLoader(表格数据):
python 复制代码
from langchain_community.document_loaders import CSVLoader

loader = CSVLoader(
    file_path="./data/sales.csv",
    csv_args={
        "delimiter": ",",
        "quotechar": '"',
        "fieldnames": ["Product", "Sales", "Region"]
    }
)

# 一次性加载
data = loader.load()

# 延迟加载(推荐大型CSV)
for row in loader.lazy_load():
    print(f"产品: {row.metadata.get('Product', '未知')}")
    print(f"销售额: {row.metadata.get('Sales', '未知')}")
JSONLoader(JSON数据):
python 复制代码
from langchain_community.document_loaders import JSONLoader
	
	loader = JSONLoader(
	    file_path="./data/products.json",
	    jq_schema=".products[]",
	    text_content=False
	)
	
	# 一次性加载
	data = loader.load()
	
	# 延迟加载
	for product in loader.lazy_load():
	    print(f"产品名称: {product.metadata.get('name', '未知')}")
	    print(f"描述: {product.page_content}")

三、加载方法选择的最佳实践

何时使用load() vs lazy_load()

场景 推荐方法 原因
小型文档(<10MB) load() 简单直接,代码简洁
大型文档(>10MB) lazy_load() 避免内存溢出,流式处理更高效
需要随机访问文档 load() 一次性加载后可随机索引
仅需顺序处理文档 lazy_load() 内存效率高,适合管道式处理

大文件处理的高级技巧

结合lazy_load()的流式处理管道:
python 复制代码
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 创建分块器
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", "。", "!", "?", ",", "、", ""]
)

# 流式处理大型文档
loader = TextLoader("./data/very_large_file.txt", encoding="utf-8")
for doc in loader.lazy_load():
    # 逐块分块处理
    chunks = text_splitter.split_documents([doc])
    # 将每个块向量化并存入数据库
    for chunk in chunks:
        vector_db.add_documents([chunk])
使用多线程加速目录加载:
python 复制代码
from langchain_community.document_loaders import DirectoryLoader
	
	loader = DirectoryLoader(
	    "./documents/",
	    glob="**/*.txt",
	    use_multithreading=True,  # 启用多线程
	    threads_per_worker=4      # 每个worker使用4个线程
	)
	
	# 延迟加载结合多线程
	for doc in loader.lazy_load():
	    # 处理文档...
	    pass

四、常见问题解决方案

内存溢出问题

当处理GB级文件时,即使使用lazy_load()也可能遇到内存问题,解决方案:

  • 进一步减小分块大小:将chunk_size从500降低到200-300
  • 增加分块重叠度:设置chunk_overlap=100确保语义连贯
  • 使用更轻量级的模型:选择小型嵌入模型如BAAI/bge-small-zh-v1.5

中文文档处理技巧

  • 指定正确编码:TextLoader(..., encoding="utf-8")
  • 自定义分隔符:针对中文文本,使用separators="\\n\\n", "\\n", "。", "!", "?", ",", "、", ""
  • 启用元素模式:对于Markdown,使用UnstructuredMarkdownLoader(..., mode="elements")

扫描件PDF处理

普通PyPDFLoader无法处理扫描件PDF,需使用OCR方案:
python 复制代码
from langchain_community.document_loaders import UnstructuredPDFLoader

loader = UnstructuredPDFLoader(
    "./data/scanned.pdf",
    strategy="ocr",  # 启用OCR
    mode="page"
)

通过合理选择load()或lazy_load()方法,结合适当的分块策略和处理技巧,您可以高效地加载各种类型的文档,为RAG系统构建坚实的知识库基础。对于大型数据集,强烈推荐使用lazy_load()方法以避免内存问题,并结合流式处理管道实现高效的知识库构建。

相关推荐
J2虾虾7 小时前
Spring AI Alibaba - Skills 技能
人工智能·python·spring
idolao8 小时前
ChemSketch 10安装教程 Windows版:自定义路径+轻量看图软件指南
windows
带派擂总8 小时前
Python全栈开发 Day08_控制文件指针移动 异常捕获 推导式
python
Coder小相8 小时前
LangChain 1.0 第五篇 - Tool与MCP让Agent拥有行动力
人工智能·langchain·ai编程
XLYcmy8 小时前
面向Agent权限系统的快速审计工具
python·网络安全·ai·llm·飞书·agent·字节跳动
范范@8 小时前
Python进阶 多线程、生成器与协程
python
SilentSamsara8 小时前
SQLAlchemy 2.x:异步 ORM 与数据库迁移 Alembic 完整指南
开发语言·数据库·python·sql·青少年编程·oracle·fastapi
27669582928 小时前
京东随机变速滑块拼图验证码识别(京东E卡)
java·服务器·前端·python·京东滑块·京东变速滑块·京东e卡绑卡
weixin_468466858 小时前
支持向量机新手实战指南
人工智能·python·算法·机器学习·支持向量机
程序大视界9 小时前
【Python系列课程】Python面向对象(下):封装、继承与多态
开发语言·python