You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为基于LangChain的AI聊天机器人添加对话记忆功能?

问题排查与解决方案

你的对话记忆失效核心有三个原因:一是默认的OpenAI工具Agent Prompt不包含记忆变量,二是你手动维护的历史和LangChain的Memory没关联,三是调用方式错误。下面是具体修复步骤:

1. 调整Prompt,加入对话记忆变量

你拉取的hwchase17/openai-tools-agent默认Prompt没有预留chat_history输入位,Agent根本不会读取记忆内容。需要修改Prompt模板,把对话历史加入进去:

# 替换原prompt拉取代码,自定义适配记忆的Prompt
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个可以调用数据库和货币转换工具的AI助手,根据用户问题和对话历史提供准确回答。你可以使用以下工具:\n{tools}\n\n工具使用格式参考:\n{{{{tool_call}}}}"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

2. 正确配置ConversationSummaryMemory

需要指定memory_key和Prompt中的变量名一致(这里用chat_history),同时设置return_messages=True让Memory返回消息对象,适配ChatPromptTemplate:

# 替换原memory初始化代码
memory = ConversationSummaryMemory(
    llm=llm,
    memory_key="chat_history",
    return_messages=True,
    verbose=True  # 可选,方便调试记忆生成情况
)

3. 移除手动维护的历史同步,让Memory自动管理

你之前手动把对话加到st.session_state.history里,但这和LangChain的Memory是两套独立的存储,完全没关联。直接让Memory处理历史,同时把Memory的内容同步到Streamlit的messages用于展示:

修改页面渲染部分:

# 替换原历史消息渲染代码,从Memory读取历史并同步到st.session_state.messages
if "messages" not in st.session_state:
    st.session_state.messages = []

# 从Memory同步历史到Streamlit消息
if memory.chat_memory.messages:
    # 清空旧消息,避免重复渲染
    st.session_state.messages = []
    for msg in memory.chat_memory.messages:
        role = "user" if isinstance(msg, HumanMessage) else "assistant"
        st.session_state.messages.append({"role": role, "content": msg.content})

# 渲染消息
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

4. 修正AgentExecutor调用方式

不需要手动传入history参数,因为AgentExecutor已经绑定了Memory,会自动把历史注入到Prompt中:

# 替换原invoke代码
full_response = agent_executor.invoke({
    "input": question 
})["output"]
# 这里不需要手动加历史到st.session_state.history,Memory已经自动记录了

完整修复后的代码

import streamlit as st
from langchain_openai import ChatOpenAI
from sqlalchemy import create_engine
from configs import OAI_MODEL
from langchain.chains.conversation.memory import ConversationSummaryMemory
from langchain_community.utilities import SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain
from langchain_community.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import AIMessage, HumanMessage
from langchain.tools import StructuredTool
from langchain_community.callbacks.manager import get_openai_callback
from langchain_experimental.tools.python.tool import PythonREPLTool
from dotenv import find_dotenv, load_dotenv
from custom_agents.exchange import get_exchange_conv_rate, get_latest_currences

load_dotenv(find_dotenv(), override=True)

# 初始化Streamlit会话状态
if "messages" not in st.session_state:
    st.session_state.messages = []

llm = ChatOpenAI(
    temperature=0.5,
    max_tokens=3000,
    model_name=OAI_MODEL,
    verbose=False
)

# 配置对话记忆
memory = ConversationSummaryMemory(
    llm=llm,
    memory_key="chat_history",
    return_messages=True,
    verbose=True
)

# 同步记忆到Streamlit消息
if memory.chat_memory.messages:
    st.session_state.messages = []
    for msg in memory.chat_memory.messages:
        role = "user" if isinstance(msg, HumanMessage) else "assistant"
        st.session_state.messages.append({"role": role, "content": msg.content})

# 渲染历史消息
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

# 自定义带记忆的Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个可以调用数据库和货币转换工具的AI助手,根据用户问题和对话历史提供准确回答。你可以使用以下工具:\n{tools}\n\n工具调用必须按照指定格式,完成思考后再输出最终回答。"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

# 初始化工具
tools = [
    StructuredTool.from_function(get_exchange_conv_rate),
    StructuredTool.from_function(get_latest_currences),
]

# 添加SQL数据库工具
db_path = "second_project/data.db"
engine = create_engine(f"sqlite:///{db_path}")
database = SQLDatabase(engine)
sql_toolkit = SQLDatabaseToolkit(db=database, llm=llm)
tools.extend(sql_toolkit.get_tools())

# 添加算术工具
arithmetic_tool = PythonREPLTool()
tools.append(arithmetic_tool)

# 创建Agent和Executor
agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
    agent=agent,
    memory=memory,
    tools=tools, 
    verbose=True,
    handle_parsing_errors=True  # 可选,处理工具调用格式错误
)

# 处理用户输入
question = st.chat_input("Please, enter your message")
if question:
    st.session_state.messages.append({"role": "user", "content": question})
    with st.chat_message("user"):
        st.markdown(question)

    with st.chat_message("assistant"):
        message_placeholder = st.empty()
        with get_openai_callback() as cb:
            full_response = agent_executor.invoke({"input": question})["output"]
            message_placeholder.markdown(full_response)
            print(cb)
        st.session_state.messages.append({"role": "assistant", "content": full_response})

关键说明

  • 自定义Prompt必须包含chat_history和agent_scratchpad两个MessagesPlaceholder,前者用于注入对话历史,后者用于Agent的思考过程。
  • ConversationSummaryMemory会自动把对话历史压缩成摘要,避免Token超限,同时return_messages=True确保输出格式和ChatPromptTemplate兼容。
  • 不再需要手动维护st.session_state.history,所有历史由LangChain的Memory统一管理,再同步到Streamlit的messages展示即可。

内容的提问来源于stack exchange,提问作者ShadowFly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:12:32