LangChain调用invoke方法传递RunnableConfig参数及RAG应用聊天历史管理问题
LangChain调用invoke方法传递RunnableConfig参数及RAG应用聊天历史管理问题
兄弟,我太懂你在做LangChain+Streamlit的RAG应用时,卡在聊天历史管理和RunnableConfig参数传递上的郁闷了!我之前折腾类似项目时也踩过不少坑,给你一步步拆解解决思路:
一、先理清楚你可能遇到的核心问题
从你贴的代码片段来看,大概率是这两个点出了问题:
- 聊天历史(
ChatMessageHistory)没有正确和RAG链绑定,导致模型无法参考之前的对话内容 - 调用
invoke时RunnableConfig参数没传对,或者和回调处理器(RunCollectorCallbackHandler)的整合有问题
二、完善聊天历史与RAG链的绑定
首先,你不能直接把ChatMessageHistory传入链,得把它包装成LangChain的对话记忆组件,常用的是ConversationBufferMemory,如果对话容易过长,也可以用ConversationSummaryMemory来压缩历史。调整你的create_full_chain函数:
from langchain.schema.runnable import RunnableConfig from langchain.callbacks.tracers.run_collector import RunCollectorCallbackHandler from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationalRetrievalChain def create_full_chain(retriever, groq_api_key=None, chat_memory=ChatMessageHistory()): # 把原始ChatMessageHistory包装成对话记忆,指定输入输出key和格式 memory = ConversationBufferMemory( chat_memory=chat_memory, return_messages=True, output_key="answer", input_key="question" ) # 初始化Groq模型(这里假设你的get_model方法已正确返回ChatModel实例) model = get_model("Groq", groq_api_key=groq_api_key) # 构建带聊天历史的检索链,自动关联记忆组件 chain = ConversationalRetrievalChain.from_llm( llm=model, retriever=retriever, memory=memory, combine_docs_chain_kwargs={"prompt": 你的自定义RAG提示词} # 替换成你自己的提示词模板 ) return chain
三、正确传递RunnableConfig参数
在Streamlit里调用链的invoke方法时,要把RunnableConfig和回调处理器整合,同时要靠Streamlit的会话状态保存聊天历史,防止页面刷新重置:
import streamlit as st # 初始化会话状态里的核心变量,避免刷新丢失 if "chat_history" not in st.session_state: st.session_state.chat_history = ChatMessageHistory() if "rag_chain" not in st.session_state: st.session_state.rag_chain = create_full_chain( 你的检索器实例, # 替换成你自己初始化好的retriever groq_api_key=st.secrets["GROQ_API_KEY"] ) # 处理用户输入交互 user_question = st.text_input("请输入你的问题:") if user_question: # 初始化回调处理器,用于追踪链的运行过程 run_collector = RunCollectorCallbackHandler() # 构建RunnableConfig,传入回调和自定义标签 config = RunnableConfig( callbacks=[run_collector], tags=["rag_chat_session"] # 标签方便后续调试追踪 ) # 调用RAG链,聊天历史会通过memory自动注入上下文 response = st.session_state.rag_chain.invoke( {"question": user_question}, config=config ) # 手动更新会话状态的聊天历史(链会自动更新,但手动确认更稳妥) st.session_state.chat_history.add_user_message(user_question) st.session_state.chat_history.add_ai_message(response["answer"]) # 渲染完整对话历史 for msg in st.session_state.chat_history.messages: if msg.type == "human": st.chat_message("user").write(msg.content) else: st.chat_message("assistant").write(msg.content)
四、避坑小提醒
- 如果你用自定义RAG链而非
ConversationalRetrievalChain,一定要在提示词模板里预留chat_history的占位符,比如:from langchain.prompts import PromptTemplate custom_rag_prompt = PromptTemplate( template="""参考以下对话历史和检索到的文档内容回答问题: 对话历史:{chat_history} 文档内容:{context} 用户问题:{question} 请用简洁准确的语言回答:""", input_variables=["chat_history", "context", "question"] ) RunCollectorCallbackHandler主要用于调试,如果你暂时不需要追踪链的运行细节,可以先注释掉,优先保证聊天历史功能正常- 所有需要跨页面刷新保留的变量,一定要存在
st.session_state里,这是Streamlit开发的核心常识!
内容来源于stack exchange
相关产品推荐
相关产品推荐

