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()方法以避免内存问题,并结合流式处理管道实现高效的知识库构建。

相关推荐
2301_782659182 小时前
C#怎么使用LINQ Contains包含判断 C#如何用Contains实现类似SQL IN查询的集合包含判断【语法】
jvm·数据库·python
2301_773553622 小时前
如何优化深分页场景下的回表代价_延迟关联与主键游标分页
jvm·数据库·python
CeshirenTester2 小时前
字节开源 DeerFlow 2.0:智能体开始“自己干活”了
人工智能·python
weixin_568996062 小时前
Golang怎么实现跳表数据结构_Golang如何用Skip List实现有序数据的快速查找【方法】
jvm·数据库·python
网络安全实验室2 小时前
【程序人生】程序员接私活常用平台汇总_嵌入式开发外包平台
网络·python·学习·程序人生·web安全·面试·职场和发展
深度学习lover2 小时前
<数据集>yolo 葡萄叶片病害识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·葡萄叶片病害识别
2401_837163892 小时前
CSS如何实现列表项序号自定义_利用--before与content实现
jvm·数据库·python
u0109147602 小时前
Go语言怎么做WASM_Go语言WebAssembly教程【对比】
jvm·数据库·python
pele2 小时前
HTML5中WebSocket构造函数及其初始化连接规范
jvm·数据库·python