发布于2026-04-21 阅读(0)
扫一扫,手机访问
本文详解如何基于 LangChain + FastAPI 构建支持上下文感知的 PDF 智能问答系统,重点解决“无法记住历史提问”问题,通过 ConversationBufferMemory 实现真正的多轮对话连贯性。
本文详解如何基于 LangChain + FastAPI 构建支持上下文感知的 PDF 智能问答系统,重点解决“无法记住历史提问”问题,通过 ConversationBufferMemory 实现真正的多轮对话连贯性。
在构建 PDF 智能问答服务时,一个常见痛点是:单次提问能返回准确答案,但后续追问(如“它提到的日期是多少?”、“这个结论的依据是什么?”)却无法关联前文——系统“失忆”了。根本原因在于原始代码中每次调用 /process/ 都新建独立链(RetrievalQA),未共享对话状态。解决方案不是简单启用 memory 参数,而是将 ConversationBufferMemory 与 load_qa_chain 深度集成,并配合自定义 Prompt 模板显式注入聊天历史。
全局初始化内存实例(非每次请求新建)
memory = ConversationBufferMemory(
memory_key="chat_history",
input_key="human_input",
return_messages=True # 返回 Message 对象而非字符串,兼容新版 LangChain
)⚠️ 注意:必须声明为模块级变量(如 global memory 或使用依赖注入),否则每次请求都会重置。
构造带历史上下文的 Prompt 模板
模板需明确预留 {chat_history} 占位符,并确保其位置在问题之前,让 LLM 理解对话流:
template = """You are a helpful assistant answering questions about a document.
Context from document:
{context}
Previous conversation:
{chat_history}
Human: {human_input}
Assistant:"""
prompt = PromptTemplate(
input_variables=["chat_history", "human_input", "context"],
template=template
)使用 load_qa_chain 并传入 memory 和 prompt
替代已弃用的 ConversationalRetrievalChain(v0.1+ 中行为不稳定):
chain = load_qa_chain(
llm=OpenAI(temperature=0.0),
chain_type="stuff",
memory=memory,
prompt=prompt
)
response = chain.invoke({
"input_documents": docs,
"human_input": question
}, return_only_outputs=True)假设用户上传一份《2023 年公司年报.pdf》,随后发起以下对话:
这依赖于 memory 自动将 Q1 的问答对存入 chat_history,并在 Q2 请求时通过 Prompt 注入上下文。
实现 PDF 多轮问答的核心不在于“加个 memory”,而在于三者协同:
① 全局可复用的 ConversationBufferMemory 实例;
② 显式包含 {chat_history} 占位符的 Prompt 模板;
③ 使用 load_qa_chain(而非 RetrievalQA)并正确传递 memory 和 prompt。
如此,你的 FastAPI 后端即可像人类一样“记住上一句”,真正理解 follow-up 问题中的指代与隐含前提。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8