跳至主要内容

如何进行每用户检索

先决条件

本指南假设您熟悉以下内容

在构建检索应用时,您通常需要考虑多个用户。这意味着您可能不仅为一个用户存储数据,而是为许多不同的用户存储数据,并且他们不应该能够看到彼此的数据。这意味着您需要能够配置检索链以仅检索特定信息。这通常涉及两个步骤。

步骤 1:确保您使用的检索器支持多个用户

目前,LangChain 中没有统一的标志或过滤器用于此。相反,每个向量存储和检索器可能都有自己的标志或过滤器,并且可能被称为不同的名称(命名空间、多租户等)。对于向量存储,这通常以在similaritySearch期间传入的关键字参数的形式公开。通过阅读文档或源代码,找出您使用的检索器是否支持多个用户,如果是,如何使用它。

步骤 2:将该参数添加为链的可配置字段

LangChain config 对象会传递给每个可运行对象。在这里,您可以向configurable 对象添加任何您想要的字段。稍后,在链中,我们可以提取这些字段。

步骤 3:使用该可配置字段调用链

现在,在运行时,您可以使用可配置字段调用此链。

代码示例

让我们看一个代码中如何实现的具体示例。我们将使用 Pinecone 作为示例。

设置

安装依赖项

yarn add @langchain/pinecone @langchain/openai @langchain/core @pinecone-database/pinecone

设置环境变量

我们将在此示例中使用 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(process.env.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 的 kwarg 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: { question: string }, 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 的搜索 kwarg

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 的其他操作指南,例如 返回来源


此页面对您有帮助吗?


您也可以留下详细的反馈 在 GitHub 上.