MemOS 获取记忆接口实战:/product/get_memory 分页查询与 /product/get_all 全量子图导出指南
【免费下载链接】MemOSSelf-evolving memory OS for LLM & AI Agents: ultra-persistent memory, hybrid-retrieval, and cross-task skill reuse, with 35.24% token savings and DeepSeek Harness support.项目地址: https://gitcode.com/gh_mirrors/memos/MemOS
本篇指南聚焦 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 相关函数):
remove_embedding_recursive:递归剔除向量字段,避免超大 embedding 数据随响应传输,实现"轻量导出";convert_graph_to_tree_forworkmem:将图结构转换为工作记忆树,采样目标节点数为200(target_node_count=200),并按自定义类型比例分配节点配额:WorkingMemory:0.20LongTermMemory:0.40UserMemory:0.40
ensure_unique_tree_ids:保证树中所有节点 ID 唯一;filter_nodes_by_tree_ids:依据树节点 ID 集合回滤原始记忆,使返回的节点与树结构严格一致;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 应用提供了一套结构化、可迁移的记忆读取方案。
【免费下载链接】MemOSSelf-evolving memory OS for LLM & AI Agents: ultra-persistent memory, hybrid-retrieval, and cross-task skill reuse, with 35.24% token savings and DeepSeek Harness support.项目地址: https://gitcode.com/gh_mirrors/memos/MemOS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考