LangChain-8-长期记忆store

短期记忆使Agent能够在单次会话中维持对话的连贯性,而长期记忆则赋予了Agent跨会话学习和积累知识的能力。这样Agent能够构建持久的用户画像,形成经验库,并持续优化自身行为,从而提供真正个性化、智能化的服务。

长期记忆介绍

长期记忆是一种用于存储用户特定信息或应用级数据的系统,其核心特点是跨越会话和线程共享。与短期记忆局限于单一线程(thread_id)不同,长期记忆中的数据可以被任何时间、在任何线程中召回。其存储范围(作用域)被定义在自定义的命名空间中,而非单个线程ID内

在LangChain框架中,长期记忆通过存储(Store)组件来实现,Store允许你将记忆保存为JSON文档,并通过命名空间(namespace)和键(Key)进行组织和管理,便于后续的检索、更新与删除。

  • 命名空间(namespace):类似于文件夹,用于对记忆进行逻辑分组(例如,按应用场景划分)。
  • 键(key):命名空间内每个文档的唯一标识符。

Store存储支持基本的put(写入)、get(读取)、delete(删除)、search(搜索)操作

示例:

复制代码
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()

namespace = ("user1", "perferences")
#添加记忆
store.put(namespace, "fruit", {"likes": ["苹果", "香蕉"], "dislike": ["橙子"]})

#获取记忆
memory = store.get(namespace, "fruit")
print(memory)

store.put(namespace, "chat", {"language": "中文", "emotion": "高兴"})

memory = store.get(namespace, "chat")
print(memory)

#搜索所有记忆
memories = store.search(namespace)
print(memories)

#更新记忆
store.put(namespace, "chat",{"language": "英文", "emotion": "happy"})
memory = store.get(namespace, "chat")
print(memory)

#删除记忆
store.delete(namespace, "chat")
memory = store.get(namespace, "chat")
print(memory)

Agent中使用长期记忆方式

长期记忆的核心作用是实现跨会话、跨节点的数据共享。在 LangChain 中,单个 Agent 通过将 Store注入到不同会话(thread_id)中,实现跨会话状态持久化。Agent中设置长期记忆的方式和短期记忆类似,长期记忆可以存在内存或者数据库中

复制代码
from langchain.agents import AgentState, create_agent
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.prebuilt import ToolRuntime
from langgraph.store.memory import InMemoryStore

from agent.my_llm import llm

class CustomerAgentState(AgentState):
    user_id: str #用户唯一标识

store = InMemoryStore()
store.put(("users",), 123,  {"name":"张三", "age": 28, "hobby": "旅游、滑雪、喝茶"})
store.put(("users",), 124,  {"name":"李四", "age": 32, "hobby": "编程、阅读、电影"})


@tool
def get_user_info(runtime: ToolRuntime):
    """获取用户信息"""
    user_id = runtime.state["user_id"]
    store = runtime.store
    if user_id:
        item = store.get(("users",),user_id)
        info = item.value
        return f"姓名: {info['name']}, 年龄: {info['age']}岁, 爱好: {info['hobby']}"
    return "用户不存在"

agent = create_agent(
    model=llm,
    tools=[get_user_info],
    checkpointer= InMemorySaver(),
    store=store,
    state_schema=CustomerAgentState
)
# 使用相同thread_id维持对话上下文
config = {"configurable": {"thread_id": "123abc"}}

#对话
while True:
    question = input("用户:")
    if question != 'q' and question != 'quit':
        resp = agent.invoke( input={"messages":[HumanMessage(content=question)], "user_id":123}, config=config)
        print("AI:"+resp["messages"][-1].content)
    else:
        break

print("="*20)
#获取agent 记忆状态
state = agent.get_state(config)
print(type(state))
print(state)

config = {"configurable": {"thread_id": "124abc"}}
while True:
    question = input("用户:")
    if question != 'q' and question != 'quit':
        resp = agent.invoke( input={"messages":[HumanMessage(content=question)], "user_id":124}, config=config)
        print("AI:"+resp["messages"][-1].content)
    else:
        break

print("="*20)
#获取agent 记忆状态
state = agent.get_state(config)
print(type(state))
print(state)

Agent创建中通过Store参数指定长期记忆对象,使用长期记忆时,可以同时使用短期记忆(checkpointer指定),也可以不使用短期记忆,但一般两者会同时使用

使用数据库存储长期记忆,代码大体相同,大致如下:

复制代码
# 配置 MySQL 连接 D
B_URI = "mysql+pymysql://root:123456@localhost:3306/langchain_db?charset=utf8mb4" with ( 
    PyMySQLSaver.from_conn_string(DB_URI) as checkpointer,                            
    PyMySQLStore.from_conn_string(DB_URI) as store 
): 
    # 自动创建checkpointer数据库表(首次运行) 
    checkpointer.setup() 
    # 2. 自动创建store数据库表(首次运行) 
    store.setup()

    """其它代码和案例1相同  此处省略......"""

长期记忆的核心使用场景是在工具中进行读写操作。LangChain通过ToolRuntime将store和context注入到工具函数中,使工具能够访问和修改长期记忆。如下案例中通过工具使用长期记忆记录用户偏好。

复制代码
import uuid
from typing import Literal

from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.prebuilt import ToolRuntime
from langgraph.store.memory import InMemoryStore
from pydantic import BaseModel, Field

from agent.my_llm import llm


class UserContext(BaseModel):
    user_id: str

#定义工具输入的类型
class UserPreference(BaseModel):
    category: Literal["color", "food", "music"] = Field(description="用户偏好类别必须是color,food,music中的一个")
    preference: str = Field(description="具体偏好内容,如'红色'、'中国美食'等")

store = InMemoryStore()
checkpointer = InMemorySaver()

@tool(args_schema=UserPreference)
def save_user_preference(category: str, preference: str, runtime: ToolRuntime) -> str:
    """保存用户偏好到长期记忆"""
    user_id = runtime.context.user_id
    namespace = (user_id, "preferences")
    memory_id = str(uuid.uuid4())

    memory_value = {
        "category": category,
        "preference": preference
    }

    runtime.store.put(namespace, memory_id, memory_value)
    return f"已成功保存你的{category}偏好:{preference}"


@tool
def get_user_preferences(runtime: ToolRuntime) -> str:
    """从长期记忆中获取用户特定类别的所有偏好"""
    user_id = runtime.context.user_id
    namespace = (user_id, "preferences")
    memories = runtime.store.search(namespace)

    if not memories:
        return f"您还没有保存过偏好"
    print("memories:", memories)

    preferences_list = []
    for mem in memories:
        pref = mem.value
        preferences_list.append(f"- 种类:{pref['category']},偏好:{pref['preference']}")

    return f"你的偏好有: \n" + "\n".join(preferences_list)


agent = create_agent(
    model=llm,
    tools=[save_user_preference, get_user_preferences],
    checkpointer=checkpointer,
    store=store,
    context_schema = UserContext
)

# 使用相同thread_id维持对话上下文
config = {"configurable": {"thread_id": "123abc"}}

#对话
while True:
    question = input("用户:")
    if question != 'q' and question != 'quit':
        resp = agent.invoke(input={"messages":[HumanMessage(content=question)]}, context=UserContext(user_id='123456'), config=config)
        print("AI:"+resp["messages"][-1].content)
    else:
        break

print("="*20)
#获取agent 记忆状态
state = agent.get_state(config)
print(type(state))
print(state)

短期记忆和长期记忆区别总结

如下是短期记忆和长期记忆区别:

对比维度 短期记忆(Short-term Memory) 长期记忆(Long-term Memory)
作用域 线程/会话范围记忆 (Thread-scoped)。与单个会话线程 (thread_id) 绑定。 跨线程/会话记忆。存储在自定义命名空间 (namespace) 中,可被多个线程共享。
核心目的 保证单次对话的连贯性和上下文感知。 实现跨对话的个性化、知识积累和持续学习。
主要存储内容 对话的原始历史 (messages列表) 以及当前会话的状态数据。 从交互中提炼的结构化知识(如用户事实、行为经验、优化规则)。
管理组件 检查点 (Checkpointer),如 InMemorySaver、PyMySQLSaver。 存储 (Store),如 InMemoryStore、PostgresStore。
生命周期 随线程的创建而开始,随线程的销毁(或超时清理)而结束。 独立于任何特定线程,除非被显式删除,否则永久或长期存在。
访问方式 自动管理。Agent的状态在每个步骤后自动持久化到检查点,并在下次恢复。 手动控制。必须在工具(Tool) 或自定义逻辑中,通过代码显式地调用 store.put()或 store.get()。
典型应用场景 维持聊天上下文,让Agent记得用户在当前对话中刚说过的话。 记住用户的身份、偏好、历史行为。
相关推荐
yanghuashuiyue4 小时前
LangGraph框架研究-生产
python·langchain·langgraph
花千树-0104 小时前
使用 LangSmith 专业调试 AI Agent:追踪、评估与问题定位
langchain·agent·function call·langgraph·mcp·langsmith·harness
不会敲代码15 小时前
MCP 进阶实战:用 LangChain 将 MCP 工具集成到你的 AI Agent 程序
langchain·node.js·mcp
xiaotao1316 小时前
03-深度学习基础:LangChain应用开发
人工智能·深度学习·langchain
BU摆烂会噶6 小时前
【LangGraph】实战:基于 LangGraph 实现的智能文档问答系统
人工智能·python·langchain
花千树-0106 小时前
LangGraph 与 ReAct Agent 调试技巧:从日志到可视化全解析
langchain·react·function call·ai agent·langgraph·mcp·j-langchain
怕浪猫6 小时前
第16章 、LangChain错误处理与鲁棒性设计
langchain·openai·ai编程
庚昀◟6 小时前
基于 LangChain、RAG、LoRA 、Streamlit 的知识库问答客服系统从零到一(附项目源码)
人工智能·langchain·milvus