
本文旨在提供一个在Pinecone向量数据库中,利用元数据高效实现基于用户ID的向量检索过滤的教程。我们将探讨如何将用户ID作为元数据存储,并将其集成到LangChain的`ConversationalRetrievalChain`中,以构建个性化的RAG(检索增强生成)应用,避免为每个用户创建单独索引带来的高昂成本。
在构建个性化RAG(检索增强生成)应用时,一个常见需求是根据当前用户检索其专属的上下文信息。例如,在一个多用户文档问答系统中,每个用户上传的文档应仅供其本人查询。直接为每个用户创建独立的Pinecone索引虽然能实现隔离,但随着用户数量的增长,这将带来高昂的成本和管理复杂性。更高效且推荐的方法是利用Pinecone的元数据过滤功能。
Pinecone允许在存储向量时附加任意的键值对元数据。这些元数据可以在检索时作为过滤条件,从而精确地限定搜索范围。例如,我们可以将user_id作为一个元数据字段与每个向量关联起来。当用户发起查询时,我们只需指定该用户的user_id作为过滤条件,Pinecone便只会返回与该user_id匹配的向量。
要实现基于用户ID的过滤,首先需要在向量索引阶段将user_id作为元数据附加到每个向量上。假设您正在处理文档块并将其嵌入为向量,您需要确保在将这些向量上传到Pinecone时,包含相应的user_id。
以下是一个概念性的Python示例,展示了如何将带有user_id元数据的向量上传到Pinecone:
from pinecone import Pinecone, Index
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore
import os
# 初始化Pinecone和嵌入模型
pinecone_api_key = os.getenv("PINECONE_API_KEY")
pinecone_env = os.getenv("PINECONE_ENVIRONMENT") # 例如 "us-west-2"
index_name = os.getenv("PINECONE_INDEX")
openai_api_key = os.getenv("OPENAI_API_KEY")
# 确保Pinecone索引已存在
pc = Pinecone(api_key=pinecone_api_key)
if index_name not in pc.list_indexes():
pc.create_index(name=index_name, dimension=1536, metric='cosine') # 假设使用OpenAI embeddings,维度为1536
embeddings_model = OpenAIEmbeddings(openai_api_key=openai_api_key)
# 示例数据:包含用户ID的文档块
documents_with_user_id = [
{"text": "这是用户123上传的关于Python编程的文档片段。", "user_id": 123},
{"text": "用户456的机器学习笔记。", "user_id": 456},
{"text": "用户123的另一个关于数据科学的文档。", "user_id": 123},
{"text": "一个公共文档,可能没有user_id或user_id为0。", "user_id": 0}
]
# 将文档块嵌入并上传到Pinecone
# 在LangChain中,通常通过`PineconeVectorStore.from_documents`或`add_texts`方法实现
# 这里为了清晰展示元数据添加,我们模拟其内部逻辑
index = pc.Index(index_name)
vectorstore = PineconeVectorStore(index=index, embedding=embeddings_model)
# 实际上传时,您会通过LangChain的API来完成,例如:
# texts = [doc["text"] for doc in documents_with_user_id]
# metadatas = [{"user_id": doc["user_id"]} for doc in documents_with_user_id]
# vectorstore.add_texts(texts=texts, metadatas=metadatas)
# 假设已经有向量和对应的元数据准备好,直接进行upsert
# 实际场景中,LangChain会为您处理嵌入和格式化
# 这是一个更接近Pinecone原生API的upsert示例,以便理解元数据结构
# from pinecone import Index
# index = Index(index_name)
# for i, doc in enumerate(documents_with_user_id):
# vec_id = f"doc_{doc['user_id']}_{i}"
# # 实际这里会调用embeddings_model.embed_query(doc['text'])获取向量
# # 假设我们已经有了一个模拟的向量
# mock_vector = [0.1] * 1536 # 替换为真实的嵌入向量
# index.upsert(vectors=[
# {"id": vec_id, "values": mock_vector, "metadata": {"user_id": doc["user_id"], "text": doc["text"]}}
# ])
# print("Vectors with user_id metadata uploaded successfully.")
# 为了本教程的后续部分,我们假设向量已经带有正确的user_id元数据一旦向量和相应的user_id元数据被存储在Pinecone中,我们就可以在检索时利用这些元数据进行过滤。在LangChain的ConversationalRetrievalChain中,可以通过retriever的search_kwargs参数来传递Pinecone的过滤条件。
以下是修改后的Flask应用chat函数示例,它接收user_id并将其应用于Pinecone检索器:
import os
from flask import Flask, request, jsonify, session
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferWindowMemory
from langchain_core.prompts import PromptTemplate
from pinecone import Pinecone, Index # 导入Pinecone客户端
app = Flask(__name__)
app.secret_key = os.getenv("FLASK_SECRET_KEY", "super-secret-key") # 设置一个安全的密钥
# 初始化环境变量
openai_api_key = os.getenv("OPENAI_API_KEY")
pinecone_api_key = os.getenv("PINECONE_API_KEY")
pinecone_env = os.getenv("PINECONE_ENVIRONMENT")
index_name = os.getenv("PINECONE_INDEX")
text_field = "text" # 假设您的文本内容存储在元数据的'text'字段中
# 初始化Pinecone客户端和索引
pc = Pinecone(api_key=pinecone_api_key, environment=pinecone_env)
pinecone_index = pc.Index(index_name)
# 初始化嵌入模型
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
# 辅助函数(如果需要,您可以根据实际情况实现)
def get_bot_temperature(user_id):
# 根据user_id获取bot温度,这里仅为示例
return 0.7
def get_custom_prompt(user_id):
# 根据user_id获取自定义提示,这里仅为示例
return "你是一个友好的AI助手,请根据提供的上下文回答问题。"
@app.route('/<int:user_id>/chat', methods=['POST'])
def chat(user_id):
user_message = request.form.get('message')
# 从session加载会话历史,注意key的动态性
conversation_history_key = f'conversation_history_{user_id}'
conversation_history = session.get(conversation_history_key, [])
# 创建Pinecone向量存储对象
vectorstore = PineconeVectorStore(
index=pinecone_index,
embedding=embeddings,
text_key=text_field
)
bot_temperature = get_bot_temperature(user_id)
custom_prompt = get_custom_prompt(user_id)
# 初始化LLM
llm = ChatOpenAI(
openai_api_key=openai_api_key,
model_name='gpt-3.5-turbo',
temperature=bot_temperature
)
# 定义提示模板
prompt_template = f"""
{custom_prompt}
CONTEXT: {{context}}
QUESTION: {{question}}"""
TEST_PROMPT = PromptTemplate(input_variables=["context", "question"], template=prompt_template)
# 创建会话记忆
memory = ConversationBufferWindowMemory(memory_key="chat_history", return_messages=True, k=8)
# 核心:配置带有元数据过滤的检索器
# 通过search_kwargs参数传递Pinecone的过滤条件
# {"user_id": {"$eq": user_id}} 表示元数据字段user_id的值等于当前user_id
retriever = vectorstore.as_retriever(
search_kwargs={"filter": {"user_id": {"$eq": user_id}}}
)
# 创建会话检索链
conversation_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=retriever, # 使用带有过滤条件的检索器
memory=memory,
combine_docs_chain_kwargs={"prompt": TEST_PROMPT},
)
# 处理用户输入并获取响应
response = conversation_chain.run({'question': user_message})
# 保存用户消息和机器人响应到session
conversation_history.append({'input': user_message, 'output': response})
session[conversation_history_key] = conversation_history
return jsonify(response=response)
if __name__ == '__main__':
# 确保设置了环境变量
if not all([openai_api_key, pinecone_api_key, pinecone_env, index_name, app.secret_key]):
print("请设置所有必要的环境变量:OPENAI_API_KEY, PINECONE_API_KEY, PINECONE_ENVIRONMENT, PINECONE_INDEX, FLASK_SECRET_KEY")
exit(1)
app.run(debug=True)代码解析:
通过这种方式,每次用户发起查询时,检索器都会自动应用user_id过滤,确保只检索到与该用户相关的文档块,从而为LLM提供个性化的上下文。
利用Pinecone的元数据过滤功能是实现多用户RAG应用中个性化向量检索的推荐方法。通过在向量索引时附加user_id元数据,并在LangChain检索器中通过search_kwargs传递过滤条件,我们可以高效、经济地为每个用户提供专属的上下文信息,从而构建更智能、更个性化的AI应用。这种方法避免了为每个用户创建单独索引所带来的高昂成本和管理负担,是构建可扩展多租户RAG系统的关键技术。
以上就是在Pinecone中实现基于用户ID的向量检索过滤的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号