前言
在构建复杂的AI应用时,数据持久化和检索是至关重要的。LangGraph提供了强大的存储功能,可以帮助我们管理各种类型的数据,包括文本、向量和复杂数据结构。本文将深入探讨LangGraph的存储模块,通过实际示例展示如何有效地使用这些功能。
什么是 LangGraph 存储模块?
LangGraph的存储模块是一个灵活的数据持久化系统,专为AI应用设计。它提供了统一的接口来存储、检索和管理数据,支持:
- 键值存储操作
- 层次化命名空间管理
- 向量嵌入存储与搜索
- 自定义数据序列化
- 支持多种存储后端
在本文中,我们将通过实用示例,学习如何使用LangGraph的存储模块实现基本的数据管理功能。
示例功能概述
我们将创建一个用户消息管理系统,展示LangGraph存储模块的核心功能:
- 创建和管理内存存储实例
- 向存储中添加、获取和更新项目
- 使用命名空间组织数据
- 处理复杂数据结构
完整代码实现
让我们先来看完整的代码实现:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""LangGraph 存储功能基础操作示例
本示例展示了 LangGraph 存储模块的基本用法,包括:
1. 创建一个基础内存存储实例
2. 向存储中添加项目(Put 操作)
3. 从存储中获取项目(Get 操作)
4. 更新存储中的项目
注意:此示例是基于 LangGraph 0.6.3 版本修改的正确实现。
"""
from langgraph.store.memory import InMemoryStore
from langgraph.store.base import Item
import datetime
def basic_store_operations():
"""演示 LangGraph 存储的基本操作"""
# 创建一个内存存储实例
# InMemoryStore 是一个基于内存的存储实现
store = InMemoryStore()
# 准备要存储的项目数据
# Item 代表一个存储的项目,包含以下必需字段:
# - value: 存储的数据(字典形式,键可用于过滤)
# - key: 命名空间内的唯一标识符
# - namespace: 定义项目所属集合的层次路径(元组形式)
# - created_at: 创建时间戳
# - updated_at: 最后更新时间戳
item1 = Item(
value={"text": "这是第一条消息", "priority": "high"},
key="message_1",
namespace=("users", "user123", "messages"),
created_at=datetime.datetime.now(),
updated_at=datetime.datetime.now()
)
item2 = Item(
value={"text": "这是第二条消息", "priority": "medium"},
key="message_2",
namespace=("users", "user123", "messages"),
created_at=datetime.datetime.now(),
updated_at=datetime.datetime.now()
)
item3 = Item(
value={"title": "项目计划", "content": "每周会议安排"},
key="doc_1",
namespace=("users", "user123", "documents"),
created_at=datetime.datetime.now(),
updated_at=datetime.datetime.now()
)
# 执行 Put 操作,将项目添加到存储中
store.put(key=item1.key, value=item1.value, namespace=item1.namespace)
store.put(key=item2.key, value=item2.value, namespace=item2.namespace)
store.put(key=item3.key, value=item3.value, namespace=item3.namespace)
print("已成功添加 3 个项目到存储中")
print()
# 执行 Get 操作,通过命名空间和键获取特定项目
print("获取的项目:")
# 获取第一条消息
message_1 = store.get(key='message_1', namespace=('users', 'user123', 'messages'))
if message_1 is not None:
print(f"- 键: message_1, 值: {message_1}")
else:
print("- 找不到消息: message_1")
print()
# 获取文档
doc_1 = store.get(key='doc_1', namespace=('users', 'user123', 'documents'))
if doc_1 is not None:
print(f"- 键: doc_1, 值: {doc_1}")
else:
print("- 找不到文档: doc_1")
print()
# 执行 ListNamespaces 操作,列出存储中的命名空间
print("尝试列出命名空间:")
list_namespaces_result = store.list_namespaces()
for ns in list_namespaces_result:
print(f"- 命名空间: {ns}")
print()
# 执行 Search 操作,搜索存储中的项目
print("尝试搜索用户 'user123' 的消息:")
# 尝试直接传入namespace参数
search_result = store.search(('users', 'user123', 'messages'))
print(f"搜索结果: {search_result} size={len(search_result)}")
print()
# 更新一个项目
updated_item1 = Item(
value={"text": "这是更新后的第一条消息", "priority": "high", "status": "read"},
key="message_1",
namespace=("users", "user123", "messages"),
created_at=item1.created_at, # 保留原始创建时间
updated_at=datetime.datetime.now() # 更新时间戳
)
# 更新一个项目
# 直接调用put方法更新项目
store.put(key=updated_item1.key, value=updated_item1.value, namespace=updated_item1.namespace)
# 验证更新是否成功
updated_message_1 = store.get(key='message_1', namespace=('users', 'user123', 'messages'))
print("更新后的项目:")
print(f"- 键: message_1, 值: {updated_message_1.value}")
print(f"- 创建时间: {updated_message_1.created_at}")
print(f"- 更新时间: {updated_message_1.updated_at}")
if __name__ == "__main__":
basic_store_operations()
代码解析
1. 导入必要的模块
from langgraph.store.memory import InMemoryStore
from langgraph.store.base import Item
import datetime
在这个示例中,我们导入了:
InMemoryStore:一个基于内存的存储实现Item:表示存储中的一个项目datetime:用于处理时间戳
2. 创建存储实例
# 创建一个内存存储实例
store = InMemoryStore()
这行代码创建了一个InMemoryStore实例,它将数据存储在内存中。在实际应用中,你也可以使用其他存储后端,如SQLite或PostgreSQL。
3. 准备存储项目
item1 = Item(
value={"text": "这是第一条消息", "priority": "high"},
key="message_1",
namespace=("users", "user123", "messages"),
created_at=datetime.datetime.now(),
updated_at=datetime.datetime.now()
)
我们创建了一个Item对象,它包含以下关键字段:
value:要存储的数据,可以是任何可序列化的字典key:在命名空间内唯一的标识符namespace:层次化的命名空间,用于组织数据created_at和updated_at:时间戳,记录项目的创建和更新时间
4. 添加项目到存储
store.put(key=item1.key, value=item1.value, namespace=item1.namespace)
store.put(key=item2.key, value=item2.value, namespace=item2.namespace)
store.put(key=item3.key, value=item3.value, namespace=item3.namespace)
我们使用put方法将项目添加到存储中,指定了键、值和命名空间。
5. 从存储中获取项目
message_1 = store.get(key='message_1', namespace=('users', 'user123', 'messages'))
我们使用get方法从存储中检索项目,需要提供键和命名空间。
6. 更新存储中的项目
# 创建更新后的项目
updated_item1 = Item(
value={"text": "这是更新后的第一条消息", "priority": "high", "status": "read"},
key="message_1",
namespace=("users", "user123", "messages"),
created_at=item1.created_at, # 保留原始创建时间
updated_at=datetime.datetime.now() # 更新时间戳
)
# 执行更新操作
store.put(key=updated_item1.key, value=updated_item1.value, namespace=updated_item1.namespace)
更新操作与添加操作类似,只需使用相同的键和命名空间,但提供新的值。
执行结果分析
执行上述代码,你会看到类似以下的输出:
已成功添加 3 个项目到存储中
获取的项目:
- 键: message_1, 值: Item(namespace=['users', 'user123', 'messages'], key='message_1', value={'text': '这是第一条消息', 'priority': 'high'}, created_at='2025-09-08T06:55:32.824577+00:00', updated_at='2025-09-08T06:55:32.824577+00:00')
- 键: doc_1, 值: Item(namespace=['users', 'user123', 'documents'], key='doc_1', value={'title': '项目计划', 'content': '每周会议安排'}, created_at='2025-09-08T06:55:32.824577+00:00', updated_at='2025-09-08T06:55:32.824577+00:00')
尝试列出命名空间:
- 命名空间: ('users', 'user123', 'documents')
- 命名空间: ('users', 'user123', 'messages')
尝试搜索用户 'user123' 的消息:
搜索结果: [Item(namespace=['users', 'user123', 'messages'], key='message_1', value={'text': '这是第一条消息', 'priority': 'high'}, created_at='2025-09-08T06:55:32.824577+00:00', updated_at='2025-09-08T06:55:32.824577+00:00', score=None), Item(namespace=['users', 'user123', 'messages'], key='message_2', value={'text': '这是第二条消息', 'priority': 'medium'},
created_at='2025-09-08T06:55:32.824577+00:00', updated_at='2025-09-08T06:55:32.824577+00:00', score=None)] size=2
更新后的项目:
- 键: message_1, 值: {'text': '这是更新后的第一条消息', 'priority': 'high', 'status': 'read'}
- 创建时间: 2025-09-08 06:55:32.826575+00:00
- 更新时间: 2025-09-08 06:55:32.826575+00:00
这个输出展示了存储模块的核心特性:
- 数据持久化:数据可以被成功添加到存储中
- 数据检索:可以通过键和命名空间检索数据
- 数据更新:可以更新已存储的数据
- 命名空间组织:可以使用命名空间层次结构组织数据
存储模块的优势
通过上面的示例,我们可以看到LangGraph存储模块的几个主要优势:
- 统一的接口:提供了一致的API来管理不同类型的数据
- 层次化命名空间:通过命名空间提供了结构化的数据组织方式
- 灵活的数据模型:支持存储各种类型的数据
- 多后端支持:可以根据需要选择不同的存储后端
- 时间戳管理:自动记录项目的创建和更新时间
优化
使用持久化存储:对于生产环境,应该使用更持久的存储,如SQLite或PostgreSQL
from langgraph.store.sqlite import SqliteStore
# 使用SQLite存储
store = SqliteStore.from_conn_string(":memory:") # 或使用文件路径
考虑数据序列化:对于复杂的数据结构,确保正确处理序列化和反序列化
import json
# 序列化复杂数据
complex_data = {"nested": {"array": [1, 2, 3]}}
serialized_data = json.dumps(complex_data)
# 存储序列化后的数据
store.put(key='complex_data', value={'serialized': serialized_data}, namespace=('data', 'complex'))
# 获取并反序列化数据
result = store.get(key='complex_data', namespace=('data', 'complex'))
if result is not None:
deserialized_data = json.loads(result.value['serialized'])
实际应用场景
LangGraph存储模块在很多实际应用场景中都非常有用:
- 用户数据管理:存储和管理用户相关的各种数据
- 会话历史存储:保存聊天机器人的对话历史
- 文档管理系统:组织和检索各种类型的文档
- 向量数据库:存储和搜索嵌入向量
- 应用状态管理:保存应用的配置和状态信息
总结
LangGraph的存储模块提供了强大而灵活的数据持久化功能,可以帮助我们构建更复杂和可靠的AI应用。在本文中,我们通过一个简单的用户消息管理系统示例,学习了如何使用InMemoryStore进行基本的数据管理操作。
在接下来的文章中,我们将深入探讨更多存储模块的高级用法。
如果你觉得这篇文章对你有帮助,请点赞、收藏并关注我,以获取更多关于LangGraph的教程和技巧!