( 教学 )Agent 构建 Memory(提示词对话存储)2. ConversationBufferWindowMemory(随时间滑动最近对话交互窗口, 版

20 阅读4分钟

( 教学 )Agent 构建 Memory(提示词对话存储)1. ConversationBufferWindowMemory(随时间滑动最近对话交互窗口, 版本>1.0和<1.0的区别)

ConversationBufferWindowMemory,它维护一个随时间滑动的最近对话交互窗口。

与使用所有对话内容不同,ConversationBufferWindowMemory 只保留 最近 K 次 交互内容。

这可以防止内存缓冲区变得过大。

从算法思想上看,就是一个很常见的滑动窗口逻辑。

所以针对,这思想,其实也不要单独一个类来维护,通过编写也可以很好处理。

该类,是之前的版本1.0以前的,版本1.0以后的。我会列出两个版本的使用方式和特点。

在线银行开户会话示例

演示如何使用 ConversationBufferWindowMemory 来模拟虚拟银行助手对话。

流程涵盖了典型的在线银行开户过程,从初始问候到账户创建确认,仅在内存中保留最近的交互记录。

from langchain_classic.memory import ConversationBufferWindowMemory

memory = ConversationBufferWindowMemory(k=2, return_messages=True)

memory.save_context(
    inputs={
        "human": "你好,我想在线开立一个银行账户。我该如何开始?"
    },
    outputs={
        "ai": "你好!很高兴你想开立账户。首先,请准备好你的身份证件以供验证好吗?"
    },
)
memory.save_context(
    inputs={"human": "是的,我已经准备好身份证了。下一步该怎么做?"},
    outputs={
        "ai": "谢谢。请拍摄你的身份证正反面的清晰照片并上传。然后我们将进行身份验证流程。"
    },
)
memory.save_context(
    inputs={
        "human": "我已经上传了照片。身份验证是如何进行的?"
    },
    outputs={
        "ai": "我已确认收到你上传的照片。现在,请进行手机验证。你将收到一条短信验证码 - 请输入该验证码。"
    },
)
memory.save_context(
    inputs={
        "human": "我已经输入了验证码。如何继续开户流程?"
    },
    outputs={
        "ai": "你的身份已验证通过。现在,请选择你想要的账户类型并输入所需信息。你可以选择存款类型、币种和其他选项。"
    },
)
memory.save_context(
    inputs={"human": "我已经输入了所有信息。下一步是什么?"},
    outputs={
        "ai": "我已确认你的信息。开户流程即将完成。最后,请同意服务条款并确认开户。"
    },
)
memory.save_context(
    inputs={"human": "我已完成所有步骤。账户开立成功了吗?"},
    outputs={
        "ai": "是的,你的账户已成功开立。你的账号和相关信息已发送至你注册的邮箱。如需任何帮助,请随时告诉我们。谢谢!"
    },
)
获取对话历史

使用 load_memory_variables() 方法来检查存储的对话历史,以验证我们基于窗口的记忆保留情况。

memory.load_memory_variables({})["history"]

打印结果

[HumanMessage(content='我已经输入了所有信息。下一步是什么?', additional_kwargs={}, response_metadata={}), AIMessage(content='我已确认你的信息。开户流程即将完成。最后,请同意服务条款并确认开户。', additional_kwargs={}, response_metadata={}), HumanMessage(content='我已完成所有步骤。账户开立成功了吗?', additional_kwargs={}, response_metadata={}), AIMessage(content='是的,你的账户已成功开立。你的账号和相关信息已发送至你注册的邮箱。如需任何帮助,请随时告诉我们。谢谢!', additional_kwargs={}, response_metadata={})]

使用最新版本逻辑实现

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import MessagesState, START, StateGraph
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage
import operator

checkpointer = MemorySaver()

def chat_with_window(state: MessagesState):
    """保留最近 3 条消息的窗口记忆"""
    messages = state["messages"]
    
    # 窗口逻辑:只保留最近 3 条消息(1 AI + 2 Human)
    window_size = 3
    if len(messages) > window_size:
        messages = messages[-window_size:]
    
    model = ChatOpenAI(model="gpt-4o-mini")
    response = model.invoke(messages)
    return {"messages": [response]}

builder = StateGraph(state_schema=MessagesState)
builder.add_node("chat", chat_with_window)
builder.add_edge(START, "chat")
graph = builder.compile(checkpointer=checkpointer)

config = {"configurable": {"thread_id": "user-1"}}

# 模拟多轮对话
inputs = [
    HumanMessage(content="你好,我想在线开立一个银行账户。我该如何开始?"),
    AIMessage(content="你好!很高兴你想开立账户。首先,请准备好你的身份证件以供验证好吗?"),
    HumanMessage(content="是的,我已经准备好身份证了。下一步该怎么做?"),
    AIMessage(content="谢谢。请拍摄你的身份证正反面的清晰照片并上传。然后我们将进行身份验证流程。"),
    HumanMessage(content= "我已经上传了照片。身份验证是如何进行的?"),
    AIMessage(content="我已确认收到你上传的照片。现在,请进行手机验证。你将收到一条短信验证码 - 请输入该验证码。"),
    HumanMessage(content="我前面说了什么?")  # 窗口内能记住消息3
]

for chunk in graph.stream({"messages": [inputs[0]]}, config, stream_mode="values"):
    pass

for msg in inputs[1:]:
    for chunk in graph.stream({"messages": [msg]}, config, stream_mode="values"):
        print(chunk["messages"][-1].content)