Streamlit集成LangChain ConversationBufferMemory无法记录对话历史问题
问题原因及修复方案
核心问题
- 内存对象未持久化:
chain在全局作用域初始化,每次Streamlit页面刷新(比如输入内容后)都会重新调用load_chain创建新的ConversationBufferMemory,之前的对话历史被清空。 - 手动传入history参数冲突:调用
chain.run(input=user_input, history=st.session_state["history"])时,手动传入的history会覆盖LangChain内存组件自动管理的对话历史,导致ConversationBufferMemory未生效。 - Prompt配置不匹配:使用
ConversationChain时,自定义Prompt的MessagesPlaceholder变量名未与内存的memory_key对齐,导致历史对话无法正确注入。
修复后的完整代码
import streamlit as st from streamlit_chat import message from langchain.chains import ConversationChain from langchain.chat_models import AzureChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.prompts import ( ChatPromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate, HumanMessagePromptTemplate ) # 初始化Session State,确保chain和内存持久化 if "chain" not in st.session_state: prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template("The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know."), MessagesPlaceholder(variable_name="history"), # 和memory的memory_key对应 HumanMessagePromptTemplate.from_template("{input}") ]) llm = AzureChatOpenAI( deployment_name='gpt-35-turbo', model_name='gpt-35-turbo', temperature=0, openai_api_key='.....', openai_api_base='.....', openai_api_version="2023-05-15", openai_api_type="azure" ) # 指定memory_key为"history",和Prompt中的变量名一致 memory = ConversationBufferMemory(memory_key="history", return_messages=True) st.session_state["chain"] = ConversationChain( llm=llm, verbose=True, prompt=prompt, memory=memory ) # Streamlit页面配置 st.set_page_config(page_title="LangChain Demo", page_icon=":robot:") st.header("LangChain Demo") if "generated" not in st.session_state: st.session_state["generated"] = [] if "past" not in st.session_state: st.session_state["past"] = [] def get_text(): input_text = st.text_input("You: ", "Hello, how are you?", key="input") return input_text user_input = get_text() if user_input: # 直接调用chain.run,只传input参数,内存由LangChain自动管理 output = st.session_state["chain"].run(input=user_input) st.session_state.past.append(user_input) st.session_state.generated.append(output) if st.session_state["generated"]: for i in range(len(st.session_state["generated"]) - 1, -1, -1): message(st.session_state["generated"][i], key=str(i)) message(st.session_state["past"][i], is_user=True, key=str(i) + "_user")
关键修复点说明
- 持久化chain和内存:把chain的初始化放到
st.session_state中,避免页面刷新时重新创建内存对象,保证对话历史留存。 - 移除手动history参数:调用
chain.run时只传入input,LangChain会自动从ConversationBufferMemory中读取历史对话并填充到Prompt的history占位符。 - 对齐memory_key和Prompt变量名:创建
ConversationBufferMemory时指定memory_key="history",和Prompt中MessagesPlaceholder(variable_name="history")保持一致,确保内存中的历史能正确传入Prompt。
内容的提问来源于stack exchange,提问作者illuminato
相关产品推荐
相关产品推荐

