【LangGraph】langgraph.store.memory.InMemoryStore 类:基于内存的键值存储

langgraph.store.memory.InMemoryStore 详解

langgraph.store.memory.InMemoryStore 是 LangGraph 框架中的一个核心类,继承自 langgraph.store.base.BaseStore,提供了一个基于内存的键值存储,用于管理代理的状态和长时记忆。它适合开发和测试场景,因数据不持久化,生产环境建议使用其他存储(如 PostgresStore)。本文详细介绍其功能、参数、方法、使用方法、实际应用及注意事项。

1. 概述

1.1 什么是 InMemoryStore

InMemoryStorelanggraph.store.memory 模块中的类,基于 Python 字典实现了一个高效的内存键值存储。它支持层次命名空间、批量操作和可选的语义搜索,适用于快速迭代和临时数据存储。由于数据存储在内存中,程序重启后数据会丢失,因此主要用于开发、测试或短期记忆场景。

该类在 langchain-core 0.2.14 版本中引入,是 LangGraph 存储系统的一部分,提供了轻量级的存储解决方案。相关信息可参考 LangGraph 存储文档InMemoryStore API 参考

1.2 核心功能

  • 内存存储:基于 Python 字典,读写操作高效,适合快速访问。
  • 层次命名空间:支持结构化数据组织,如 ("users", "123", "messages"),确保数据隔离。
  • 语义搜索:通过配置嵌入模型支持语义查询(默认禁用,需显式启用)。
  • 批量操作:提供 batchabatch 方法,支持高效的批量读写和删除。
  • 异步操作:支持异步方法(如 agetaput),适合非阻塞场景。
  • 分页与过滤:支持查询结果的分页(limitoffset)和条件过滤(filter)。
  • 版本要求:需 langchain-core>=0.2.14,推荐使用最新版本。

2. 定义与结构

2.1 类定义

InMemoryStore 继承自 BaseStore,定义如下(简化表示):

from langgraph.store.base import BaseStore
from typing import Dict, Any, Optional, List, Tuple, Union, Literal
from langchain_core.embeddings import Embeddings

class InMemoryStore(BaseStore):
    def __init__(self, index: Optional[Dict[str, Any]] = None):
        self.store: Dict[Tuple[Tuple[str, ...], str], Any] = {}
        self.index_config = index
        self.supports_ttl = False
        self.supports_index = bool(index)

2.2 初始化参数

参数类型默认值描述
indexOptional[Dict[str, Any]]None可选,嵌入索引配置,包含 dims(嵌入维度)和 embed(嵌入函数)。若提供,则启用语义搜索。

2.3 关键属性

属性类型默认值描述
supports_ttlboolFalse是否支持 TTL(时间到活),InMemoryStore 默认禁用。
supports_indexboolFalse是否支持语义搜索索引,取决于是否提供 index 参数。
storeDict{}内部字典,存储键值对,键为 (namespace, key),值为 Item
index_configDictNone嵌入索引配置,若提供则用于语义搜索。

2.4 核心方法

InMemoryStore 实现 BaseStore 的所有方法,以下是主要方法:

方法描述参数返回值异步
__init__(index=None)初始化内存存储,可选配置嵌入索引。index: Optional[Dict[str, Any]]NoneNo
put(namespace, key, value, index=None, ttl=None)存储键值对,可选设置索引(用于语义搜索)。namespace: Tuple[str, ...], key: str, value: Dict[str, Any], index: Optional[Union[Literal[False], List[str]]], ttl: Optional[float]NoneNo
get(namespace, key, refresh_ttl=None)获取指定键值。namespace: Tuple[str, ...], key: str, refresh_ttl: Optional[bool]Optional[Item]No
delete(namespace, key)删除指定键值。namespace: Tuple[str, ...], key: strNoneNo
search(namespace_prefix, query=None, filter=None, limit=10, offset=0, refresh_ttl=None)搜索匹配项,支持语义查询、过滤和分页。namespace_prefix: Tuple[str, ...], query: Optional[str], filter: Optional[Dict[str, Any]], limit: int, offset: int, refresh_ttl: Optional[bool]List[SearchItem]No
list_namespaces(prefix=None, suffix=None, max_depth=None, limit=100, offset=0)列出匹配前缀、后缀和深度的命名空间,分页控制。prefix: Optional[Tuple[str, ...]], suffix: Optional[Tuple[str, ...]], max_depth: Optional[int], limit: int, offset: intList[Tuple[str, ...]]No
batch(ops)批量执行存储操作(获取、存储、删除)。ops: Iterable[Op] (操作列表)List[Result]No
abatch(ops)异步批量执行存储操作。ops: Iterable[Op] (操作列表)List[Result]Yes
aget(namespace, key)异步获取值。namespace: Tuple[str, ...], key: strOptional[Item]Yes
aput(namespace, key, value, index=None, ttl=None)异步存储键值对。namespace: Tuple[str, ...], key: str, value: Dict[str, Any], index: Optional[Union[Literal[False], List[str]]], ttl: Optional[float]NoneYes
adelete(namespace, key)异步删除值。namespace: Tuple[str, ...], key: strNoneYes
asearch(...)异步搜索匹配项,参数与 search 一致。searchList[SearchItem]Yes
alist_namespaces(...)异步列出命名空间,参数与 list_namespaces 一致。list_namespacesList[Tuple[str, ...]]Yes

默认值

  • searchasearchlimit 默认 10,offset 默认 0。
  • list_namespacesalist_namespaceslimit 默认 100,offset 默认 0。
  • TTL 默认禁用(supports_ttl=False)。

3. 使用方法

以下是 InMemoryStore 的主要使用方式,结合前文内容展示具体示例:

3.1 基本用法

初始化和基本操作:

from langgraph.store.memory import InMemoryStore

# 初始化存储
store = InMemoryStore()

# 存储键值对
namespace = ("users", "123", "profile")
key = "info"
value = {"name": "Alice", "age": 30}
store.put(namespace, key, value)

# 获取值
item = store.get(namespace, key)
print(item)  # 输出: {"name": "Alice", "age": 30}

# 删除值
store.delete(namespace, key)

3.2 启用语义搜索

配置嵌入模型以支持语义搜索:

from langchain_openai import OpenAIEmbeddings
from langgraph.store.memory import InMemoryStore

# 初始化嵌入模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# 初始化存储,启用语义搜索
store = InMemoryStore(
    index={
        "dims": 1536,  # 嵌入维度
        "embed": embeddings
    }
)

# 存储带索引的数据
store.put(
    namespace=("docs",),
    key="doc1",
    value={"title": "LangChain 简介", "content": "LangChain 是一个 LLM 框架"},
    index=["title", "content"]  # 索引字段
)

# 语义搜索
results = store.search(
    namespace_prefix=("docs",),
    query="LangChain 框架",
    limit=5
)
for result in results:
    print(result.value)  # 输出: {"title": "LangChain 简介", "content": "LangChain 是一个 LLM 框架"}

3.3 批量操作

执行批量存储和删除:

from langgraph.store.base import Op

ops = [
    Op(type="put", namespace=("users", "123", "messages"), key="msg1", value={"content": "Hello"}),
    Op(type="put", namespace=("users", "123", "messages"), key="msg2", value={"content": "World"}),
    Op(type="get", namespace=("users", "123", "messages"), key="msg1")
]
results = store.batch(ops)
print(results)  # 输出: [None, None, {"content": "Hello"}]

3.4 结合代理系统

在 LangGraph 代理中存储会话状态:

from langgraph.graph import StateGraph
from langgraph.store.memory import InMemoryStore

store = InMemoryStore()

# 定义状态
class AgentState:
    messages: List[Dict[str, Any]]

# 创建图
graph = StateGraph(AgentState)

# 定义节点,存储消息
def store_message(state: AgentState, store: InMemoryStore):
    for msg in state.messages:
        store.put(("users", "123", "messages"), msg["id"], msg)
    return state

# 添加节点
graph.add_node("store", lambda state: store_message(state, store))
# ... 配置其他节点和边 ...

# 运行图
result = graph.invoke({"messages": [{"id": "msg1", "content": "Hello"}]}, store=store)
item = store.get(("users", "123", "messages"), "msg1")
print(item)  # 输出: {"id": "msg1", "content": "Hello"}

3.5 结合检索器工具

结合前文讨论的 create_retriever_tool,存储检索索引:

from langchain_core.vectorstores import VectorStoreRetriever
from langchain_core.tools.retriever import create_retriever_tool

retriever = VectorStoreRetriever(...)  # 假设的检索器
tool = create_retriever_tool(retriever, "search_docs", "搜索相关文档")
store.put(("tools", "search"), "config", {"tool_name": "search_docs"})

# 获取工具配置
config = store.get(("tools", "search"), "config")
print(config)  # 输出: {"tool_name": "search_docs"}

4. 实际应用

InMemoryStore 在以下场景中广泛应用:

  • 开发与测试:快速迭代测试代理逻辑或工作流,无需配置数据库。
  • 临时记忆存储:存储会话状态或短期上下文数据,如对话历史。
  • 语义搜索测试:在开发环境中验证嵌入模型和语义搜索效果。
  • 原型开发:构建 LangGraph 应用的原型,验证功能逻辑。
  • 轻量级应用:适合小规模、非持久化的状态管理场景。

5. 最佳实践

  • 开发环境优先:在开发和测试阶段使用 InMemoryStore,快速验证逻辑。
  • 层次命名空间:设计结构化命名空间(如 ("users", "id", "data")),确保数据隔离。
  • 语义搜索配置:若需语义搜索,设置 index 参数,选择高效的嵌入模型(如 OpenAIEmbeddings)。
  • 批量操作优化:使用 batchabatch 执行批量操作,减少性能开销。
  • 版本检查:通过 pip install -qU langgraph 确保安装最新版本(依赖 langchain-core>=0.2.14)。
  • 调试工具:使用 LangSmith 跟踪存储操作,调试复杂工作流或搜索结果。

6. 注意事项与限制

  • 数据不持久化:程序重启后数据丢失,生产环境建议使用 PostgresStore 或其他持久化存储。
  • 内存消耗:存储大量数据可能导致高内存使用,需监控资源。
  • 语义搜索限制:默认禁用,需显式配置 index,确保嵌入模型可用。
  • TTL 不支持supports_ttl=False,无法设置数据过期。
  • 模块路径:确保正确导入 langgraph.store.memory.InMemoryStore
  • 版本依赖:功能可能受版本限制,需确保兼容最新版本。

7. 结论

langgraph.store.memory.InMemoryStore 是 LangGraph 框架中提供内存键值存储的类,继承自 BaseStore,支持层次命名空间、批量操作和可选的语义搜索。其高效的内存访问和简单配置使其成为开发和测试的理想选择,适合快速迭代、临时存储和语义搜索验证。由于其非持久化特性,生产环境需选择持久化存储(如 PostgresStore)。结合 BaseStore 接口、嵌入模型和 LangGraph 生态系统,开发者可以构建高效的代理记忆和状态管理方案。

8. 参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值