当前位置: 首页 > news >正文

LangGraph基础知识(Store )(四)

背景

仅使用`checkpointer`,我们无法做到跨线程共享信息。LangGraph 提出了Store(仓库)概念。

Store介绍

`LangGraph`通过`BaseStore`接口提供内置文档存储。与通过线程 ID 保存状态的`checkpointer`不同,存储使用自定义命名空间来组织数据。常见用例包括存储用户配置文件、构建知识库以及管理所有线程的全局首选项。具体的**实现形式是:`LangGraph` 将长期记忆作为 `JSON` 文档存储在`Store`中,每个`memory`都组织在自定义`namespace`(类似于文件夹)和不同的`key` (例如文件名)下。命名空间通常包含用户或组织 ID 或其他标签,以便更轻松地组织信息。这种结构可以实现存储器的分层组织。然后通过内容过滤器支持跨命名空间搜索。

整体而言,`LangGraph` 中的长期记忆允许系统保留不同对话或会话中的信息。与线程范围的短期内存不同,长期内存保存在自定义“命名空间”中。

举个例子

from langgraph.store.memory import InMemoryStore
import uuidin_memory_store = InMemoryStore()
user_id = "1"
namespace_for_memory = (user_id, "memories")memory_id = str(uuid.uuid4())
memory = {"user" : "你好,我叫BUG"}
in_memory_store.put(namespace_for_memory, memory_id,  memory)
memories = in_memory_store.search(namespace_for_memory)
memories[-1].dict()
#运行结果
{'namespace': ['1', 'memories'],'key': 'd792a784-0f52-4f91-b265-b5c80f794b86','value': {'user': '你好,我叫BUG'},'created_at': '2025-06-14T07:22:41.758736+00:00','updated_at': '2025-06-14T07:22:41.758736+00:00','score': None}

理解了上述过程后,就可以使用 `LangGraph` 中的`in_memory_store`方法了,当我们在编译图表时传递 `store` 对象,就会允许图中的每个节点访问 `store`,定义节点函数时的时候,就可以定义`store`关键字参数,`LangGraph` 会自动传递编译图时使用的 `store` 对象,代码如下所示:

import getpass
import os
from langchain_openai import ChatOpenAI
from typing import Annotated
from typing_extensions import TypedDict
from IPython.display import Image, display
from langgraph.graph import StateGraph, MessagesState, START, END
from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage, ToolMessage
from langgraph.graph.message import add_messages
from langchain_core.runnables import RunnableConfig
from langgraph.store.base import BaseStore
from langgraph.store.memory import InMemoryStorefrom langgraph.checkpoint.memory import MemorySaverfrom dotenv import load_dotenv
load_dotenv()
in_memory_store = InMemoryStore()
memory = MemorySaver()# if not os.environ.get("OPENAI_API_KEY"):
#     os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")# 定义大模型实例
llm = ChatOpenAI(model="deepseek-chat")# 定义状态模式
class State(TypedDict):messages: Annotated[list, add_messages]# 定义对话节点, 访问记忆并在模型调用中使用它们。
def call_model(state: MessagesState, config: RunnableConfig, *, store: BaseStore):# 获取用户iduser_id = config["configurable"]["user_id"]# 定义命名空间namespace = ("memories", user_id)# 根据用户id检索记忆memories = store.search(namespace)print(f"memories: {memories}")info = "\n".join([d.value["data"] for d in memories])print(f"info: {info}")# # 存储记忆last_message = state["messages"][-1]store.put(namespace, str(uuid.uuid4()), {"data": last_message.content})system_msg = f"Answer the user's question in context: {info}"response = llm.invoke([{"type": "system", "content": system_msg}] + state["messages"])# 存储记忆store.put(namespace, str(uuid.uuid4()), {"data": response.content})return {"messages": response}# 构建状态图
builder = StateGraph(State)# 向图中添加节点
builder.add_node("call_model", call_model)# 构建边
builder.add_edge(START, "call_model")
builder.add_edge("call_model", END)# 编译图
graph = builder.compile(checkpointer=memory, store=in_memory_store)# 可视化
display(Image(graph.get_graph().draw_mermaid_png()))

进行测试:

config = {"configurable": {"thread_id": "10"}, "user_id": "6"}async for chunk in graph.astream({"messages": ["你好,我是BUG"]}, config, stream_mode="values"):chunk["messages"][-1].pretty_print()

================================ Human Message ================================= 你好,我是BUG memories: [] info: ================================== Ai Message ================================== 你好!看来你可能想表达自己是“BUG”(程序中的错误或漏洞),或者是想开个有趣的玩笑?如果是技术问题,比如遇到了代码bug或者系统故障,可以告诉我具体情况,我会尽力帮你解决! 如果是其他含义——比如昵称、游戏ID或者单纯想聊聊——也欢迎随时补充说明~ 😄 (中文里“BUG”通常指软件缺陷,但如果你有其他创意用法,我也很想知道!)

我们进行更改线程id再次进行测试:

config = {"configurable": {"thread_id": "20"}, "user_id": "6"}async for chunk in graph.astream({"messages": ["你知道我叫什么吗?"]}, config, stream_mode="values"):chunk["messages"][-1].pretty_print()#运行结果
================================ Human Message =================================你知道我叫什么吗?
memories: [Item(namespace=['memories', '6'], key='f1628098-c07c-4ca5-81fd-8704894eb757', value={'data': '你好,我是BUG'}, created_at='2025-06-14T07:37:26.910365+00:00', updated_at='2025-06-14T07:37:26.910365+00:00', score=None), Item(namespace=['memories', '6'], key='d5e75eb6-8205-4901-8560-827077e5223a', value={'data': '你好!看来你可能想表达自己是“BUG”(程序中的错误或漏洞),或者是想开个有趣的玩笑?如果是技术问题,比如遇到了代码bug或者系统故障,可以告诉我具体情况,我会尽力帮你解决! \n\n如果是其他含义——比如昵称、游戏ID或者单纯想聊聊——也欢迎随时补充说明~ 😄 \n\n(中文里“BUG”通常指软件缺陷,但如果你有其他创意用法,我也很想知道!)'}, created_at='2025-06-14T07:37:33.345231+00:00', updated_at='2025-06-14T07:37:33.345231+00:00', score=None)]
info: 你好,我是BUG
你好!看来你可能想表达自己是“BUG”(程序中的错误或漏洞),或者是想开个有趣的玩笑?如果是技术问题,比如遇到了代码bug或者系统故障,可以告诉我具体情况,我会尽力帮你解决! 如果是其他含义——比如昵称、游戏ID或者单纯想聊聊——也欢迎随时补充说明~ 😄 (中文里“BUG”通常指软件缺陷,但如果你有其他创意用法,我也很想知道!)
================================== Ai Message ==================================哈哈,当然知道啦!你的名字是 **“BUG”** —— 一个自带程序员幽默感的称呼!  不过悄悄问一句:  
- 这是你的**隐藏身份**(比如深夜修代码时遇到的“第八号当铺Bug”)?  
- 还是某种**神秘代号**(比如游戏里的终极Boss叫BUG)?  
- 或者……你真的是个**会说话的漏洞**?(那我得赶紧通知CTO来抓你!🐛)  等你揭晓答案~ (或者继续用BUG的力量“折磨”我也行,我抗压能力很强✨)
能够发现,我们已经正确的实现了跨线程的记忆能力。而如果使用新的`user_id`,将会开启全新的交互。
http://www.xdnf.cn/news/1041769.html

相关文章:

  • 3.1.3_栈的链式存储实现
  • MCP前后端技术研究和应用实践
  • 细聊工业级网络变压器在不同行业中的浪涌等级选型应用
  • QEMU源码全解析 —— 块设备虚拟化(30)
  • 广东省省考备考(第二十八天6.13)—资料分析(第二节课)
  • 【无标题】定制园区专属地图:如何让底图只显示道路和地面?
  • Relook:softmax函数
  • 状态机(State Machine)详解
  • 车载功能框架 --- 整车安全策略
  • 第六届经济管理与大数据应用国际学术会议 (ICEMBDA 2025)
  • 数据库学习(六)——MySQL事务
  • QT打包应用
  • 天邑TEWA-808AE高安版_S905L3B融合机破解TTL刷机包
  • python做题日记(17)
  • 15.vue.js的watch()和watchEffect()(2)
  • JAVA理论第十八章-JWT杂七杂八
  • Visualized_BGE 安装—多模态嵌入技术
  • Java 复习题选择题(1)(Java概述)
  • LLMs 系列实操科普(5)
  • 【卫星通信】Skylo与ViaSat标准建议详解:基于NB-IoT NTN通过GEO卫星实现IMS语音通话的解决方案
  • springboot在线BLOG网
  • SCADA|信创KingSCADA4.0历史报警查询的差异
  • 永磁同步电机控制算法--双矢量模型预测转矩控制MPTC(占空比)
  • [直播推流] 本地创建 nginx服务器
  • DataHub 架构设计与模块规划
  • 深度解析SpringBoot自动化部署实战:从原理到最佳实践
  • Android 安卓应用分身多开 适用于没有自带分身多开的Android设备,隐藏应用、应用锁、私密相册等管理,解锁永久Vip会员功能
  • 【精华】这样设计高性能短链生成系统
  • 记利用AI模型制作DataDump Scripts生成工具
  • 理解 C++ 的 this 指针