MemOS 获取记忆接口实战:/product/get_memory 分页查询与 /product/get_all 全量子图导出指南

原创2026-09-23 16:33:19476 阅读
文章标签:人工智能大模型Agent 记忆AI AgentRAG知识图谱dsh-plugin

MemOS 获取记忆接口实战:/product/get_memory 分页查询与 /product/get_all 全量子图导出指南

本篇指南聚焦 MemOS 开源仓库中"获取记忆(Get Memories)"这一核心 API 能力,讲解 POST /product/get_memory 分页查询与 POST /product/get_all 全量/子图导出两个接口的设计动机、请求参数、响应结构,并结合仓库源码剖析其底层实现原理。读完本文,你将能够独立完成记忆资产的前端分页展示、按类型全量导出以及基于查询语句提取相关记忆子图三类典型任务。

1. 接口总览:两种记忆集合访问模式

在 MemOS 中,用户的记忆资产以 MemCube 为组织单元存储,其中既包含系统自动生成的原始记忆片段,也包括用户偏好和工具使用记录。为了满足"轻量展示"与"批量处理"两类差异极大的使用场景,开源版通过 MemoryHandler 提供了两条独立的集合访问通道,路由均挂在 /product 前缀之下(定义见 server_router.py):

接口路径 方法 设计定位 核心能力
/product/get_memory POST 前端 UI 列表分页展示 支持 page/page_size 分页,默认附带偏好记忆,支持细粒度类型开关与元数据过滤
/product/get_all POST 数据迁移、复杂关系分析、全量导出 支持按 memory_type 导出全量数据,或传入 search_query 召回并返回相关记忆子图(Subgraph)

配套的还有按 ID 精确获取的 POST /product/get_memory/{memory_id} 与 POST /product/get_memory_by_ids,它们与本文两个接口共同构成完整的记忆读取体系,相关说明可参考同目录文档 get_memory_by_id.md。

2. 核心机理:分页 vs 全量导出

两个接口虽然都是"读记忆",但底层处理链路完全不同,理解其设计差异有助于选对接口:

  • 业务分页模式(/get_memory):为前端列表设计,强调"轻量"。请求模型 GetMemoryRequest(见 product_models.py)默认开启偏好记忆、工具记忆与技能记忆的附带返回,并允许通过 filter 对元数据做条件过滤。它返回的 data 是按记忆类别分组的四元结构,方便前端直接渲染。
  • 全量导出模式(/get_all):为数据迁移或关系分析设计,强调"完整"。当携带 search_query 时,服务端会执行一次语义检索,把命中的记忆节点及其关联关系整理成树形子图返回;当不携带查询词时,则按 memory_type 导出某一类记忆的全量数据。

从源码看,/get_all 的两个分支分别落到两个独立 handler:

  • 有 search_query → handle_get_subgraph:调用 naive_mem_cube.text_mem.get_relevant_subgraph(...) 获取相关子图;
  • 无 search_query → handle_get_all_memories:调用 naive_mem_cube.text_mem.get_all(...) 获取指定类型全量数据。

两者随后走同一条"图 → 树"格式化链路(详见第 6 节)。

3. 关键接口参数详解

3.1 分页查询参数(/get_memory)

按文档定义,/get_memory 的核心参数如下:

参数名 类型 必填 说明
mem_cube_id str 是 目标 MemCube ID。
user_id str 否 用户唯一标识符。
page int 否 页码(从 1 开始)。若设为 None 则尝试全量导出。
page_size int 否 每页条目数。
include_preference bool 否 是否包含偏好记忆。

对照源码中的 GetMemoryRequest,实际请求模型还提供了两个文档未展开但非常实用的扩展参数:

  • include_tool_memory(默认 True):是否返回工具记忆(ToolSchemaMemory、ToolTrajectoryMemory);
  • include_skill_memory(默认 True):是否返回技能记忆(SkillMemory);
  • filter:可选元数据过滤条件,支持嵌套的 and/or 结构以及 gt 等比较运算符,例如 {"and": [{"id": "uuid-xxx"}, {"created_at": {"gt": "2024-01-01"}}]}。

设置 page=None(或 page_size=None)时接口会退化为不带分页的全量拉取,这与 /get_all 的定位在语义上互补:前者返回分组后的结构化结果,后者返回树形子图/类型化全量数据。

3.2 全量/子图导出参数(/get_all)

参数名 类型 必填 说明
user_id str 是 用户 ID。
memory_type str 是 记忆类型:text_mem、act_mem、para_mem。
mem_cube_ids list 否 待导出的 Cube ID 列表。
search_query str 否 若提供,将基于此查询召回并返回相关的记忆子图。

对照源码 GetMemoryPlaygroundRequest(见 product_models.py),实际还包含两个值得注意的细节:

  • memory_type 的完整字面量集合为 ["text_mem", "act_mem", "param_mem", "para_mem"],其中 param_mem 是文档表中未列出的第四个取值;
  • 额外提供了 search_type 参数(默认 fulltext),可选 embedding 或 fulltext,用于指定子图召回的检索方式——即走向量语义检索还是全文检索。

同时需要说明一个实现现状:在 handle_get_all_memories 中,当前仅 text_mem 分支具备完整实现,act_mem 与 para_mem 分支会记录 "Activity memory retrieval not implemented yet" / "Parameter memory retrieval not implemented yet" 的 warning 日志。若你的需求是文本记忆(事实记忆),可放心使用;其余类型建议先确认服务端版本的实际支持情况。

4. 快速上手示例

4.1 前端分页展示(SDK 调用)

# 获取第一页,每页 10 条记忆
res = client.get_memory(
    user_id="sde_dev_01",
    mem_cube_id="cube_research_01",
    page=1,
    page_size=10
)

for mem in res.data:
    print(f"[{mem['type']}] {mem['memory_value']}")

如果不经过 SDK、直接以 HTTP JSON 形式调用,对应的请求体应贴合 GetMemoryRequest 模型:

{
  "user_id": "sde_dev_01",
  "mem_cube_id": "cube_research_01",
  "page": 1,
  "page_size": 10,
  "include_preference": true,
  "include_tool_memory": true,
  "include_skill_memory": true
}

include_preference 默认为 True,意味着默认返回结果中会附带用户的偏好记忆;若只想看正文记忆,可显式置为 false。另外,仓库中的 Python 客户端 src/memos/api/client.py 的 get_memory 方法对单次拉取条数做了 size <= 50 的校验(见 client.py),批量导大数据时建议配合分页循环或直接使用 /get_all。

4.2 导出特定的事实记忆子图

# 提取与“R 语言”相关的全部事实记忆
res = client.get_all(
    user_id="sde_dev_01",
    memory_type="text_mem",
    search_query="R language visualization"
)

该请求在服务端的实际处理路径为:server_router.get_all_memories 检测到 search_query 非空后,会以 top_k=200 的召回规模调用 handle_get_subgraph。mem_cube_ids 为空时,mem_cube_id 会回退为 user_id 本身(见 server_router.py),因此即使只传 user_id 也能正常工作。

5. 响应结构说明

两个接口均返回标准的业务响应封装(BaseResponse),外层包含 message、code、data 三个字段,差异主要体现在 data 的组织方式上。

5.1 /get_memory 的响应 data

data 是一个按记忆类别分组的字典,最多包含四个键,每个键对应一个组,每组内含 cube_id、memories 与 total_nodes(节点总数,可用于前端分页控件):

{
  "text_mem": [
    {
      "cube_id": "cube_research_01",
      "memories": [ { "id": "...", "memory_value": "...", "tags": [] } ],
      "total_nodes": 120
    }
  ],
  "pref_mem": [ { "cube_id": "...", "memories": [], "total_nodes": 8 } ],
  "tool_mem": [ { "cube_id": "...", "memories": [], "total_nodes": 3 } ],
  "skill_mem": [ { "cube_id": "...", "memories": [], "total_nodes": 2 } ]
}

该结构由 handle_get_memories 拼装:正文记忆固定返回(涵盖 WorkingMemory、LongTermMemory、UserMemory、OuterMemory 四种类型),其余三类受对应 include_* 开关控制。

5.2 /get_all 的响应 data

data 是列表结构,每项对应一个 Cube,包含 cube_id、memories 与 memory_statistics。与分页接口不同,这里的 memories 内嵌了 tree_structure 树形字段,用于描述记忆节点间的层次关系:

{
  "data": [
    {
      "cube_id": "cube_research_01",
      "memories": [
        {
          "tree_structure": { "children": [ ... ] },
          "nodes": [ ... ]
        }
      ],
      "memory_statistics": { "WorkingMemory": 40, "LongTermMemory": 80 }
    }
  ]
}

5.3 单条记忆的核心字段

data 中的记忆对象通常包含以下核心字段:

  • id:记忆唯一标识,可用于后续的 获取记忆详情 或 删除记忆 操作;
  • memory_value:经过算法加工后的记忆文本;
  • tags:关联的自定义标签。

开发者提示:如果您已知记忆 ID 并希望查看其完整的元数据(如 confidence 或 usage 记录),请使用 获取记忆详情(Get_memory_by_id)接口,其实现为 handle_get_memory,统一从 text_mem(含偏好记忆)中按 ID 精确读取,未命中时返回 "Memory with ID xxx not found" 消息。

6. 底层实现原理:从图数据库到树形结构

/get_all 之所以能返回"子图",是因为 MemOS 的记忆本体存储在图数据库中,节点之间天然存在关联边。为了把图结构变成前端易于渲染、LLM 易于消费的树,两个全量导出 handler 复用了一条完整的格式化链路(见 format_utils.py 相关函数):

  1. remove_embedding_recursive:递归剔除向量字段,避免超大 embedding 数据随响应传输,实现"轻量导出";
  2. convert_graph_to_tree_forworkmem:将图结构转换为工作记忆树,采样目标节点数为 200(target_node_count=200),并按自定义类型比例分配节点配额:
    • WorkingMemory:0.20
    • LongTermMemory:0.40
    • UserMemory:0.40
  3. ensure_unique_tree_ids:保证树中所有节点 ID 唯一;
  4. filter_nodes_by_tree_ids:依据树节点 ID 集合回滤原始记忆,使返回的节点与树结构严格一致;
  5. sort_children_by_memory_type:按记忆类型对子节点排序,保证同类记忆在树中相邻呈现。

同时 convert_graph_to_tree_forworkmem 会产出各类型的节点计数(node_type_count),最终作为 memory_statistics 随响应返回,可用于前端图表统计或导出校验。这一整套逻辑在 text_mem 与子图两条路径中完全复用,保证了分页/导出两种模式下数据口径的一致性。

7. 与其他记忆接口的协作

获取记忆接口通常不是孤立使用的,实践中常见的组合方式如下:

  • 列表 + 详情:先用 /get_memory 分页拿到记忆 ID 列表,前端点击某条后调用 /get_memory/{memory_id} 获取完整元数据;
  • 检索定位 + 子图导出:先用 search_memory 接口做关键词/向量检索,再用 /get_all 携带 search_query 拉取命中记忆的完整关系子图,用于复杂关系分析;
  • 导出备份 + 删除清理:用 /get_all 全量导出后进行数据迁移,配合 delete_memory 接口(支持按 memory_ids、file_ids 或 filter 三种模式删除)完成清理或重建;
  • 新增回写:写入侧使用 add_memory 接口,读写闭环即构成一套完整的记忆资产管理链路。

8. 注意事项与最佳实践

  • 分页参数置 None 的含义:/get_memory 的 page/page_size 均为可选,缺省为 None,此时接口会一次性返回全部数据(不分页),与 /get_all 的导出定位接近,适合小规模 Cube 的场景;
  • 大 Cube 优先走 /get_all:/get_all 内部有节点采样(200 节点上限)与树形化处理,结构更紧凑,适合迁移与关系分析;前端列表仍应优先使用 /get_memory 的 total_nodes 做分页;
  • search_type 的选择:默认 fulltext 适合精确关键词;涉及语义相近表述时可选 embedding 走向量召回,两者都经由 get_relevant_subgraph 统一返回子图;
  • 类型支持现状:当前 text_mem 是完整实现的导出类型,act_mem/para_mem 仅保留入口,调用前请确认部署版本;
  • 敏感数据与向量字段:导出结果默认已剔除 embedding 向量,若业务上需要原始向量,需另行定制或绕过 remove_embedding_recursive 处理。

综上,/product/get_memory 与 /product/get_all 分别承担了"分页展示"与"全量子图导出"两种互补职责,配合 MemOS 的图存储与树形化格式化链路,为上层 Agent 应用提供了一套结构化、可迁移的记忆读取方案。

登录后查看全文
MemOS