Langchain中ConversationalRetrievalChain记忆功能失效问题求助
会话上下文关联失效的问题修复方案
核心问题分析
- 重复初始化记忆与链:Streamlit每次交互都会重新执行
main函数,当前代码每次都会创建新的ConversationBufferMemory和ConversationalRetrievalChain,导致之前的会话记忆被清空。 - 手动维护聊天记录与内置记忆冲突:
ConversationalRetrievalChain已通过memory参数绑定记忆组件,无需手动传入chat_history参数;同时手动维护的st.session_state.chat_history与内置记忆逻辑重复,造成冲突。 - 聊天记录存储格式错误:更新
st.session_state.chat_history时,错误地将整个聊天记录列表嵌套追加,导致格式变为多层嵌套,无法被正确识别。
修复后的完整代码
import streamlit as st import openai import os import pinecone from dotenv import load_dotenv from langchain.chat_models import AzureChatOpenAI from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import Pinecone from streamlit_chat import message from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationalRetrievalChain # 加载环境变量 load_dotenv() OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") OPENAI_DEPLOYMENT_ENDPOINT = os.getenv("OPENAI_DEPLOYMENT_ENDPOINT") OPENAI_DEPLOYMENT_NAME = os.getenv("OPENAI_DEPLOYMENT_NAME") OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME") OPENAI_EMBEDDING_DEPLOYMENT_NAME = os.getenv("OPENAI_EMBEDDING_DEPLOYMENT_NAME") OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME") OPENAI_API_VERSION = os.getenv("OPENAI_API_VERSION") OPENAI_API_TYPE = os.getenv("OPENAI_API_TYPE") # Pinecone配置 PINECONE_API_KEY = os.getenv("PINECONE_API_KEY") PINECONE_ENV = os.getenv("PINECONE_ENV") # 初始化Azure OpenAI openai.api_type = OPENAI_API_TYPE openai.api_version = OPENAI_API_VERSION openai.api_base = OPENAI_DEPLOYMENT_ENDPOINT openai.api_key = OPENAI_API_KEY st.set_page_config( page_title="Streamlit Chat - Demo", page_icon=":robot:" ) def get_text(): input_text = st.text_input("You: ","Who is John Doe?", key="input") return input_text def main(): st.title('Scenario 2: Question Aswering on documents with langchain, pinecone and openai') st.markdown( """ This scenario shows how to chat wih a txt file which was indexed in pinecone. """ ) pinecone.init( api_key=PINECONE_API_KEY, environment=PINECONE_ENV ) # 初始化会话状态 if 'generated' not in st.session_state: st.session_state['generated'] = [] if 'past' not in st.session_state: st.session_state['past'] = [] # 仅初始化一次记忆和链 if 'chain' not in st.session_state: index_name = "default" embed = OpenAIEmbeddings(deployment=OPENAI_EMBEDDING_DEPLOYMENT_NAME, model=OPENAI_EMBEDDING_MODEL_NAME, chunk_size=1) retriever = Pinecone.from_existing_index(index_name, embed).as_retriever() llm = AzureChatOpenAI( openai_api_base=OPENAI_DEPLOYMENT_ENDPOINT, openai_api_version=OPENAI_API_VERSION, deployment_name=OPENAI_DEPLOYMENT_NAME, openai_api_key=OPENAI_API_KEY, openai_api_type=OPENAI_API_TYPE, model_name=OPENAI_MODEL_NAME, temperature=0) memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) st.session_state['chain'] = ConversationalRetrievalChain.from_llm(llm, retriever, memory=memory) user_input = get_text() if user_input: # 直接使用已初始化的链,无需手动传入chat_history result = st.session_state['chain']({"question": user_input}) st.session_state.past.append(user_input) st.session_state.generated.append(result['answer']) # 渲染聊天记录 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') if __name__ == "__main__": main()
关键修复点说明
- 将
memory和chain的初始化逻辑放到if 'chain' not in st.session_state:分支中,确保仅在首次加载时创建,避免每次交互重置记忆。 - 移除手动维护的
chat_history相关冗余代码,直接依赖ConversationBufferMemory自动管理会话记忆。 - 调用链时仅传入
question参数,无需额外传入chat_history,链会自动从绑定的记忆中获取上下文。
内容的提问来源于stack exchange,提问作者Luis Valencia
相关产品推荐
相关产品推荐

