引言
在基于大型语言模型 (LLM) 的应用中,常常需要从数据库或文件(如PDF)中提取数据,并将其转换为LLM可以利用的格式。在LangChain中,这通常涉及创建包含提取文本及元数据的Document对象,以便LLM用于生成所需响应。本指南将演示如何编写自定义文档加载器和文件解析逻辑。
主要内容
1. 标准文档加载器
一个标准文档加载器可以通过从BaseLoader
子类化来实现,它提供了一种标准接口来加载文档。
接口介绍
方法名称 | 解释 |
---|---|
lazy_load | 懒加载文档,一个一个地加载,适合生产环境 |
alazy_load | lazy_load 的异步版本 |
load | 把所有文档加载到内存,适合原型设计 |
aload | load 的异步版本 |
实现
下面是一个示例,展示如何创建一个从文件逐行加载文档的加载器:
from typing import AsyncIterator, Iterator
from langchain_core.document_loaders import BaseLoader
from langchain_core.documents import Document
class CustomDocumentLoader(BaseLoader):
"""逐行读取文件的示例文档加载器。"""
def __init__(self, file_path: str) -> None:
self.file_path = file_path
def lazy_load(self) -> Iterator[Document]:
with open(self.file_path, encoding="utf-8") as f:
line_number = 0
for line in f:
yield Document(
page_content=line,
metadata={"line_number": line_number, "source": self.file_path},
)
line_number += 1
async def alazy_load(self) -> AsyncIterator[Document]:
import aiofiles
async with aiofiles.open(self.file_path, encoding="utf-8") as f:
line_number = 0
async for line in f:
yield Document(
page_content=line,
metadata={"line_number": line_number, "source": self.file_path},
)
line_number += 1
2. 文件解析与Blob
解析文件通常与加载文件略有不同,LangChain提供了一种解耦的方式:
BaseBlobParser
BaseBlobParser
接受一个Blob
并输出Document
对象。
from langchain_core.document_loaders import BaseBlobParser, Blob
class MyParser(BaseBlobParser):
def lazy_parse(self, blob: Blob) -> Iterator[Document]:
line_number = 0
with blob.as_bytes_io() as f:
for line in f:
line_number += 1
yield Document(
page_content=line,
metadata={"line_number": line_number, "source": blob.source},
)
3. 使用Blob和Blob Loader
Blob API可以让你直接从内存加载内容,而不必读取文件。
from langchain_community.document_loaders.blob_loaders import FileSystemBlobLoader
blob_loader = FileSystemBlobLoader(path=".", glob="*.mdx", show_progress=True)
4. 创建自定义解析器
通过子类化GenericLoader
,你可以把逻辑封装到一个类中:
from typing import Any
from langchain_community.document_loaders.generic import GenericLoader
class MyCustomLoader(GenericLoader):
@staticmethod
def get_parser(**kwargs: Any) -> BaseBlobParser:
return MyParser()
loader = MyCustomLoader.from_filesystem(path=".", glob="*.mdx", show_progress=True)
代码示例
with open("./meow.txt", "w", encoding="utf-8") as f:
quality_content = "meow meow🐱 \n meow meow🐱 \n meow😻😻"
f.write(quality_content)
loader = CustomDocumentLoader("./meow.txt")
for doc in loader.lazy_load():
print(type(doc))
print(doc)
async for doc in loader.alazy_load():
print(type(doc))
print(doc)
常见问题和解决方案
- 内存不足: 在大数据集上使用
lazy_load
或alazy_load
以避免将所有内容加载到内存。 - 异步限制: 使用
aiofiles
进行异步文件读取以提高效率。
总结和进一步学习资源
本文演示了如何创建自定义文档加载器和解析器,以便更好地服务于LLM应用。建议进一步阅读LangChain的官方文档和GitHub资源以了解更多详细信息。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
—END—