基于LangChain与Pinecone搭建限定检索知识的带记忆MapReduce Chain咨询
解决方案与问题解答
关于检索器的两个问题
- 检索逻辑:Pinecone向量检索器默认基于语义相似度匹配,通过计算查询文本的向量与存储在向量库中文本块的向量距离(通常是余弦相似度),返回距离最近(相似度最高)的文本块。
- 默认检索数量:LangChain中
vectorstore.as_retriever()的默认返回数量是k=4,可以通过search_kwargs参数修改,比如vectorstore.as_retriever(search_kwargs={"k": 6})就能指定返回6个结果。
集成对话记忆、MapReduce检索链的最优实现方案
你的代码用了Agent框架,但如果只需要调用知识库这单一工具,直接使用带对话记忆的RetrievalQA链会更简洁高效,同时能严格限制仅基于检索内容作答。核心优化点:
- 给检索链的prompt添加强制约束指令,杜绝模型编造内容
- 正确集成对话记忆,让模型能结合历史对话理解当前问题
- 用MapReduce链处理长文档拆分后的检索结果
优化后的代码实现
from langchain.chat_models import ChatOpenAI from langchain.memory import ConversationSummaryBufferMemory from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate # 初始化LLM llm = ChatOpenAI( openai_api_key=OPENAI_API_KEY, model_name='gpt-3.5-turbo', temperature=0.0 # 温度设为0保证输出稳定 ) # 对话记忆:用SummaryBuffer避免历史过长占用token conversational_memory = ConversationSummaryBufferMemory( llm=llm, memory_key='chat_history', max_token_limit=1000, return_messages=True, output_key='result' # 要和RetrievalQA的输出key匹配 ) # 自定义Prompt:强制要求仅基于检索到的内容回答 custom_prompt = PromptTemplate( template="""使用以下上下文和对话历史来回答用户的问题。 严格注意:**只能使用检索到的上下文内容回答,绝对不能编造任何不在上下文中的信息**。如果上下文无法回答问题,直接说"我无法基于现有知识回答这个问题"。 对话历史: {chat_history} 检索到的上下文: {context} 用户问题:{question} 回答:""", input_variables=["chat_history", "context", "question"] ) # 初始化MapReduce类型的RetrievalQA链,集成记忆和自定义Prompt qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="map_reduce", retriever=vectorstore.as_retriever(search_kwargs={"k": 5}), # 自定义检索数量 memory=conversational_memory, chain_type_kwargs={"prompt": custom_prompt}, return_source_documents=True # 可选:返回检索到的来源文档,方便验证 ) # 交互示例 while True: query = input("Ask me anything: ") result = qa_chain({"query": query}) print("回答:", result["result"]) # 可选:打印来源文档 # print("来源文档:", [doc.page_content[:100] for doc in result["source_documents"]])
关键优化说明
- Prompt约束:通过明确的指令强制模型仅使用检索内容,避免幻觉
- 记忆集成:
ConversationSummaryBufferMemory会自动总结过长的对话历史,减少token消耗,同时保留对话上下文 - MapReduce链:适合处理大文档拆分后的多个文本块,先对每个文本块生成初步回答,再合并成最终结果,比
stuff链更适合大知识库 - 检索数量控制:通过
search_kwargs自定义返回的文本块数量,平衡信息丰富度和token消耗
如果你确实需要使用Agent框架(比如后续要添加其他工具),可以调整工具描述和Agent的系统prompt添加约束:
# 修改Agent的初始化代码,添加系统提示约束 agent = initialize_agent( agent='chat-conversational-react-description', tools=tools, llm=llm, verbose=True, max_iterations=3, early_stopping_method='generate', memory=conversational_memory, agent_kwargs={ "system_message": """你是一个只能基于知识库工具回答问题的助手。**必须调用知识库工具获取信息,绝对不能直接回答问题**。如果工具返回的内容无法回答,直接说"我无法基于现有知识回答这个问题"。""" } )
内容的提问来源于stack exchange,提问作者tpaus
相关产品推荐
相关产品推荐

