老铁们,今天我们来聊聊在构建检索应用时,如何实现按用户检索。这个技术点其实不难,主要是为了确保不同用户之间的数据隔离。你总不能让用户A看到用户B的数据吧?下面就一步一步解析这个过程。
技术背景介绍
在创建检索应用时,我们常常需要考虑多用户场景。这意味着你的应用需要存储不止一个用户的数据,并确保他们之间的数据不会互相可见。为此,你需要配置你的检索链,以便只检索特定的信息。这通常涉及两个步骤。
原理深度解析
步骤1:确保你的检索器支持多用户
目前在LangChain中并没有一个统一的标记或过滤器来处理这个问题。不同的向量存储和检索器可能有自己独特的实现方式,可能叫做"命名空间"或"多租户"等。对于向量存储,通常会有一个关键词参数在similarity_search
中传递。你需要通过查阅文档或源码来确定你使用的检索器是否支持多用户功能,并了解如何使用它。
🚩 注意: 如果你发现某个检索器没有支持多用户功能,可以考虑为LangChain贡献相关的文档或实现。
步骤2:将该参数作为链的可配置字段
这样,你就可以在运行时调用链并配置任何相关的标志。详细信息请参阅相关文档。
实战代码演示
为了让大家更清晰理解,我们使用Pinecone作为示例。
首先,设置Pinecone的环境变量:
PINECONE_API_KEY: Your Pinecone API key
然后,在代码中配置向量存储:
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore
embeddings = OpenAIEmbeddings()
vectorstore = PineconeVectorStore(index_name="test-example", embedding=embeddings)
vectorstore.add_texts(["i worked at kensho"], namespace="harrison")
vectorstore.add_texts(["i worked at facebook"], namespace="ankush")
在这里,Pinecone的namespace
关键字参数用于分隔文档。比如:
# 只获取Ankush的文档
vectorstore.as_retriever(search_kwargs={"namespace": "ankush"}).get_relevant_documents(
"where did i work?"
)
# 只获取Harrison的文档
vectorstore.as_retriever(
search_kwargs={"namespace": "harrison"}
).get_relevant_documents("where did i work?")
优化建议分享
我们接下来创建一个用于问答的链。
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import (
ConfigurableField,
RunnablePassthrough,
)
template = """Answer the question based only on the following context:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
retriever = vectorstore.as_retriever()
configurable_retriever = retriever.configurable_fields(
search_kwargs=ConfigurableField(
id="search_kwargs",
name="Search Kwargs",
description="The search kwargs to use",
)
)
chain = (
{"context": configurable_retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
chain.invoke(
"where did the user work?",
config={"configurable": {"search_kwargs": {"namespace": "harrison"}}},
)
chain.invoke(
"where did the user work?",
config={"configurable": {"search_kwargs": {"namespace": "ankush"}}},
)
补充说明和总结
说白了就是这么个原理,通过配置命名空间参数实现按用户检索。这波操作可以说是相当丝滑。如果你想了解更多多用户场景下的向量存储实现,可以查阅类似Milvus的具体页面。
今天的技术分享就到这里,希望对大家有帮助。开发过程中遇到问题也可以在评论区交流~
—END—