# 深入揭秘:如何创建自定义信息检索器(Retriever)
## 引言
在现代大型语言模型(LLM)应用程序中,检索器(Retriever)起着至关重要的作用。它负责从外部数据源中检索与用户查询相关的文档,并将其格式化为模型的输入提示,从而协助LLM生成合适的响应。在这篇文章中,我们将探讨如何创建一个自定义的检索器。
## 主要内容
### 1. 接口概览
要创建自定义检索器,您需要扩展`BaseRetriever`类并实现以下方法:
- `_get_relevant_documents`: 获取与查询相关的文档(必需)。
- `_aget_relevant_documents`: 提供异步支持的实现(可选)。
通过从`BaseRetriever`继承,您的检索器自动成为一个LangChainRunnable,具有标准的Runnable功能。此外,尽管从RunnableLambda可以实现自定义可运行函数,但`BaseRetriever`作为LangChain实体能够在某些工具中表现更佳,比如提供检索器专用行为的监控工具。
### 2. 实现一个玩具检索器
我们将实现一个简单的检索器,该检索器返回所有包含用户查询的文档文本。
```python
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。
"""
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 方法
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("space"))
常见问题和解决方案
1. 性能优化
在处理大量文档或需要实时响应的场景中,考虑实现异步版本的_aget_relevant_documents。
2. API访问限制
如果检索器需要访问外部API,例如由于网络限制,开发者可能需要考虑使用API代理服务来提高访问的稳定性。
总结与进一步学习资源
自定义检索器在LLM应用中提供了灵活性和扩展性。通过了解接口和方法,实现一个高效的检索器可以显著提升应用的响应质量和速度。建议进一步阅读LangChain的API文档,加深对可运行接口的理解。
参考资料
- LangChain API 文档
- Python 官方文档
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---
&spm=1001.2101.3001.5002&articleId=144573164&d=1&t=3&u=d73aa5d854e54aa88e36b43e91bba05e)
737

被折叠的 条评论
为什么被折叠?



