创建自定义信息检索器:从基础到实战

在许多大型语言模型(LLM)应用中,检索外部数据源的信息是必要的,而这通常通过使用检索器(Retriever)来实现。检索器负责从给定的用户查询中检索相关的文档列表。这些检索到的文档通常被格式化成提示,并输入到LLM中,使得LLM能够利用这些信息生成相应的响应,例如,基于知识库回答用户问题。

技术背景介绍

检索器在LLM应用中扮演着至关重要的角色,通过有效地获取相关信息,它可以显著提升模型的回答质量和准确性。创建一个自定义检索器需要继承BaseRetriever类并实现特定的方法。

核心原理解析

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

  • _get_relevant_documents: 用于同步检索查询相关文档,是必需实现的方法。
  • _aget_relevant_documents: 提供异步支持的可选实现,可以提升性能。

通过继承BaseRetriever,你的检索器自动成为一个LangChainRunnable,并可以使用标准Runnable功能。

代码实现演示

下面我们来实现一个简单的检索器,它返回包含用户查询文本的所有文档:

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

    该检索器仅实现同步方法 `_get_relevant_documents`。
    如果检索器涉及文件或网络访问,可以受益于异步实现 `_aget_relevant_documents`。

    使用Runnables时,默认异步实现可以在另一线程上委托给同步实现。
    """

    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

    # 可选:通过重写提供更高效的本地实现
    # async def _aget_relevant_documents(
    #     self, query: str, *, run_manager: AsyncCallbackManagerForRetrieverRun
    # ) -> List[Document]:
    #     """异步获取查询相关的文档。
    #
    #     Args:
    #         query: 用于查找相关文档的字符串
    #         run_manager: 要使用的回调处理器
    #
    #     Returns:
    #         相关文档的列表
    #     """

测试代码实现:

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_documents = retriever.invoke("that")

print(retrieved_documents)

应用场景分析

这种简单的检索器非常适用于小规模的文本匹配应用,尤其在对性能要求不高的小型数据集上。对于需要处理较大数据集或频繁检索操作的场景,实现异步版本将更为实际。

实践建议

  1. 为性能优化,考虑实现异步版本以处理大量文件或需频繁访问网络的场景。
  2. 使用注释详细描述类和方法,以便后续维护和团队协作。
  3. 进行测试以确保检索器的准确性和性能。

如果遇到问题欢迎在评论区交流。

—END—

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值