langchain各类文档加载
·
LangChain文档加载器提供了两种核心加载方式:load()一次性加载全部文档和lazy_load()延迟流式加载文档,后者特别适合处理大型数据集以避免内存溢出问题。
一、文档加载器核心加载方法
两种加载模式详解
-
load() - 一次性加载模式,将所有文档一次性加载到内存中,返回完整的Document对象列表,适合小型数据集(如单个PDF、小型文本文件)
代码示例:
from langchain_community.document_loaders import PyPDFLoader loader = PyPDFLoader("./data/small.pdf") documents = loader.load() # 一次性加载所有页面 print(f"共加载 {len(documents)} 个文档") -
lazy_load() - 延迟流式加载模式
按需加载文档,仅在迭代时才实际加载内容
返回一个生成器对象,避免一次性占用大量内存
特别适合大型数据集(如GB级日志文件、大型PDF文档集)代码示例:
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基类中定义了这两种方法的关系:
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(最常用):
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)} 字符") -
关键参数说明:
mode="page"(默认):每页生成一个Document,metadata包含页码 mode="single":将整个PDF作为单个Document对象 password:用于解锁加密PDF
2、文本文件加载
-
TextLoader(TXT/Markdown等纯文本):
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(批量处理文件夹):
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(抓取网页内容):
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(表格数据):
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数据):
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()的流式处理管道:
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]) -
使用多线程加速目录加载:
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方案:
from langchain_community.document_loaders import UnstructuredPDFLoader
loader = UnstructuredPDFLoader(
"./data/scanned.pdf",
strategy="ocr", # 启用OCR
mode="page"
)
通过合理选择load()或lazy_load()方法,结合适当的分块策略和处理技巧,您可以高效地加载各种类型的文档,为RAG系统构建坚实的知识库基础。对于大型数据集,强烈推荐使用lazy_load()方法以避免内存问题,并结合流式处理管道实现高效的知识库构建。
更多推荐
所有评论(0)