如何进行每用户检索
本指南假设您熟悉以下内容
在构建检索应用程序时,您通常需要针对多个用户进行构建。这意味着您可能存储的不仅仅是一个用户的,而是许多不同用户的,并且他们不应该看到彼此的数据。这意味着您需要能够配置您的检索链,使其仅检索特定信息。这通常涉及两个步骤。
步骤 1:确保您使用的检索器支持多个用户
目前,LangChain 中没有为此提供统一的标志或过滤器。相反,每个向量存储和检索器可能都有自己的标志或过滤器,并且可能被叫做不同的名称(命名空间、多租户等)。对于向量存储,这通常作为 similaritySearch
期间传递的关键字参数公开。通过阅读文档或源代码,确定您使用的检索器是否支持多个用户,以及如果支持,如何使用它。
步骤 2:将该参数作为可配置字段添加到链中
LangChain 的 config
对象会传递给每个 Runnable。在这里,您可以向 configurable
对象添加任何您想要的字段。稍后,我们可以在链内提取这些字段。
步骤 3:使用该可配置字段调用链
现在,您可以在运行时使用可配置字段调用该链。
代码示例
让我们看一下代码中此过程的外观示例。我们将在本示例中使用 Pinecone。
设置
安装依赖项
- npm
- yarn
- pnpm
npm i @langchain/pinecone @langchain/openai @pinecone-database/pinecone @langchain/core
yarn add @langchain/pinecone @langchain/openai @pinecone-database/pinecone @langchain/core
pnpm add @langchain/pinecone @langchain/openai @pinecone-database/pinecone @langchain/core
设置环境变量
我们将在本示例中使用 OpenAI 和 Pinecone
OPENAI_API_KEY=your-api-key
PINECONE_API_KEY=your-api-key
PINECONE_INDEX=your-index-name
# Optional, use LangSmith for best-in-class observability
LANGSMITH_API_KEY=your-api-key
LANGCHAIN_TRACING_V2=true
# Reduce tracing latency if you are not in a serverless environment
# LANGCHAIN_CALLBACKS_BACKGROUND=true
import { OpenAIEmbeddings } from "@langchain/openai";
import { PineconeStore } from "@langchain/pinecone";
import { Pinecone } from "@pinecone-database/pinecone";
import { Document } from "@langchain/core/documents";
const embeddings = new OpenAIEmbeddings();
const pinecone = new Pinecone();
const pineconeIndex = pinecone.Index(Deno.env.get("PINECONE_INDEX"));
/**
* Pinecone allows you to partition the records in an index into namespaces.
* Queries and other operations are then limited to one namespace,
* so different requests can search different subsets of your index.
* Read more about namespaces here: https://docs.pinecone.io/guides/indexes/use-namespaces
*
* NOTE: If you have namespace enabled in your Pinecone index, you must provide the namespace when creating the PineconeStore.
*/
const namespace = "pinecone";
const vectorStore = await PineconeStore.fromExistingIndex(
new OpenAIEmbeddings(),
{ pineconeIndex, namespace }
);
await vectorStore.addDocuments(
[new Document({ pageContent: "i worked at kensho" })],
{ namespace: "harrison" }
);
await vectorStore.addDocuments(
[new Document({ pageContent: "i worked at facebook" })],
{ namespace: "ankush" }
);
[ "77b8f174-9d89-4c6c-b2ab-607fe3913b2d" ]
Pinecone 的 namespace
关键字参数可用于分离文档
// This will only get documents for Ankush
const ankushRetriever = vectorStore.asRetriever({
filter: {
namespace: "ankush",
},
});
await ankushRetriever.invoke("where did i work?");
[ Document { pageContent: "i worked at facebook", metadata: {} } ]
// This will only get documents for Harrison
const harrisonRetriever = vectorStore.asRetriever({
filter: {
namespace: "harrison",
},
});
await harrisonRetriever.invoke("where did i work?");
[ Document { pageContent: "i worked at kensho", metadata: {} } ]
现在,我们可以创建将用于执行问答的链。
import { StringOutputParser } from "@langchain/core/output_parsers";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import {
RunnableBinding,
RunnableLambda,
RunnablePassthrough,
} from "@langchain/core/runnables";
import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
const template = `Answer the question based only on the following context:
{context}
Question: {question}`;
const prompt = ChatPromptTemplate.fromTemplate(template);
const model = new ChatOpenAI({
model: "gpt-3.5-turbo-0125",
temperature: 0,
});
现在,我们可以使用可配置的检索器创建链。它是可配置的,因为我们可以定义任何将传递给链的对象。从那里,我们提取可配置的对象并将其传递给向量存储。
import {
RunnablePassthrough,
RunnableSequence,
} from "@langchain/core/runnables";
const chain = RunnableSequence.from([
RunnablePassthrough.assign({
context: async (input, config) => {
if (!config || !("configurable" in config)) {
throw new Error("No config");
}
const { configurable } = config;
const documents = await vectorStore
.asRetriever(configurable)
.invoke(input.question, config);
return documents.map((doc) => doc.pageContent).join("\n\n");
},
}),
prompt,
model,
new StringOutputParser(),
]);
现在,我们可以使用可配置选项调用链。search_kwargs
是可配置字段的 ID。该值是用于 Pinecone 的搜索关键字参数
await chain.invoke(
{ question: "where did the user work?" },
{ configurable: { filter: { namespace: "harrison" } } }
);
"The user worked at Kensho."
await chain.invoke(
{ question: "where did the user work?" },
{ configurable: { filter: { namespace: "ankush" } } }
);
"The user worked at Facebook."
有关可以支持多个用户的更多向量存储实现,请参阅特定页面,例如Milvus.
后续步骤
您现在已经看到了支持从多个用户检索数据的一种方法。
接下来,查看一些关于 RAG 的其他操作指南,例如 返回来源。