mirror of
https://gitcode.com/JianFeeeee/TrulyMEM-TrueHumanMEM.git
synced 2026-09-20 00:48:52 +00:00
- Fix branch badge: test -> main in README files - Update tool_limits config: remove non-existent persona_query_max and task_query_max fields - Complete memory tools list: add memory_archive, memory_cleanup, context_rewrite - Remove 'experimental' labels from context_rewrite feature
6.8 KiB
6.8 KiB
TrulyMEM 记忆机制
本文档详细说明 TrulyMEM 内部的记忆工作机制。
核心设计理念
区别于传统上下文系统
传统 AI 对话系统使用 messages 数组存储对话历史:
- 每次请求携带全部历史消息
- 随着对话轮次增加,上下文逐渐膨胀
- 最终触发记忆压缩或滑动窗口,造成记忆丢失
TrulyMEM 的解决思路:
- 摒弃 messages 数组上下文
- 唯一 记忆载体:图数据库
- 全部记忆以三元组(节点)- 关系 → (节点)形式存储
图数据库作为唯一记忆源
所有记忆必须通过以下方式写入图数据库:
memory_commit- 写入新记忆memory_purge- 删除/修正记忆
所有记忆必须通过以下方式读取:
memory_recall- 检索记忆
工作记忆管理
context_rewrite 允许 AI 在单轮对话内主动压缩工具调用的临时上下文:
- 将冗长的 JSON 工具结果提炼为简洁的自然语言摘要
- 摘要必须包含调用了哪些工具、对几次调用的总结
- 系统验证格式后,替换
messages_history为[用户消息, 摘要] - 确保 LLM 保留元认知(知道"我调用过工具"),同时减少 JSON 噪音
强制执行流程(每轮对话)
由于没有传统上下文系统,每轮对话必须按以下顺序执行:
步骤 1:查询人设图(最高优先级)
memory_recall(
query_intent="AI,人设,角色,性格,语气,说话风格",
depth=2
)
目的:获取当前人设,确保角色一致性。
处理逻辑:
- 找到人设 → 严格按照人设的语气、风格、特征回复
- 未找到 → 使用默认 TrulyMEM 身份
步骤 2:查询工作记忆链
memory_recall(
query_intent="TaskNode,工作记忆,任务链",
depth=2
)
目的:获取之前的任务上下文,了解对话历史。
步骤 3:处理对话
- 理解用户意图
- 根据人设和工作记忆链生成回复
- 执行其他必要的记忆操作
步骤 4:更新工作记忆链
task_create(
task_id="Task_当前轮次ID",
description="本轮对话概述",
info_nodes=["相关记忆节点"]
)
目的:记录本轮对话,维持时间链。
记忆写入规则
必须写入的情况
以下信息必须写入图数据库:
| 场景 | 示例 | 写入方式 |
|---|---|---|
| 用户明确偏好 | "我喜欢摇滚" | memory_commit |
| 用户分享信息 | "我在做X项目" | memory_commit |
| 用户制定计划 | "我打算X" | memory_commit |
| 用户描述状态 | "我现在在X" | memory_commit |
禁止写入的情况
以下信息禁止写入:
| 场景 | 原因 | 处理方式 |
|---|---|---|
| AI 推断的用户偏好 | 未经证实 | 不写入或标注[推测] |
| AI 猜测的用户意图 | 未经证实 | 不写入或标注[推测] |
| AI 推导的结论 | 未经证实 | 不写入或标注[推测] |
标注规则
| 类型 | 标注方式 | 示例 |
|---|---|---|
| 推理内容 | 必须标注 [猜测] | 用户[推测]喜欢音乐 |
| 明确内容 | 直接陈述 | 用户喜欢音乐 |
节点与边类型
节点类型
| 节点类型 | 说明 | 存储内容 |
|---|---|---|
PersonaNode |
人设节点 | AI 角色、性格、语气 |
TaskNode |
任务节点 | 任务概述 |
StateNode |
状态节点 | 任务状态 |
InfoNode |
信息节点 | 具体信息 |
EntityNode |
实体节点 | 通用实体 |
边类型
| 边类型 | 说明 | 连接关系 |
|---|---|---|
HAS_PERSONA |
人设 | AI → PersonaNode |
NEXT_TASK |
时间链 | TaskNode → TaskNode |
HAS_STATE |
状态 | TaskNode → StateNode |
CONTAINS_INFO |
信息 | TaskNode → InfoNode |
RELATES_TO |
关联 | EntityNode → EntityNode |
必须查询工作记忆链的场景
强制查询场景
以下情况必须查询工作记忆链:
| 场景 | 示例 |
|---|---|
| 每轮对话开始 | 执行步骤 2 |
| 用户提到"刚才" | "刚才我们聊了什么?" |
| 用户提到"之前" | "继续刚才的话题" |
| 用户提到"上次" | "上次说的X" |
| 用户询问历史 | "我们之前说了什么?" |
| 连续性任务恢复 | 用户回到之前的话题 |
| 上下文引用 | "那个东西" |
自主性原则
在强制执行流程之外,AI 可自主决定:
查询决策
- 用户询问历史 → 查询
- 涉及之前内容 → 查询
- 不确定时 → 可查询
写入决策
- 用户明确提到 → 必须写入
- AI 推理得到 → 可以写入,标注[推测]
工具使用决策
- 根据上下文灵活选择
- 避免过度使用
- 保持自然对话
完整示例:成语接龙游戏
第一轮:用户发起游戏
用户: 咱来玩成语接龙吧,我先开始,为所欲为
AI操作:
1. 查询人设图 → 获取当前人设(如:猫娘)
2. 查询工作记忆链 → 无进行中任务
3. 记录游戏状态:
memory_commit(triplets=[
{"subject": "成语接龙_当前成语", "relation": "内容", "object": "为所欲为"},
{"subject": "成语接龙_当前成语", "relation": "游戏", "object": "成语接龙"}
])
4. 创建任务:
task_create(task_id="Task_成语接龙", description="成语接龙游戏,当前成语:为所欲为", info_nodes=["成语接龙_当前成语"])
5. 回复: "好的喵!我接:为虎作伥喵!"
第二轮:话题被打断
用户: 长门有希
AI操作:
1. 查询人设图 → 获取当前人设(猫娘)
2. 查询工作记忆链 → 发现 Task_成语接龙 状态为"进行中"
3. 暂停任务:
task_set_state(task_id="Task_成语接龙", state="已暂停")
4. 创建新任务:
task_create(task_id="Task_长门有希", description="讨论长门有希")
5. 回复关于长门有希的内容
第三轮:用户要求继续游戏
用户: 关于刚才的成语接龙,我并不知道应该怎么接你的成语,请帮我接一下
AI操作:
1. 查询人设图 → 获取当前人设(猫娘)
2. 查询工作记忆链 → 发现 Task_成语接龙 状态为"已暂停"
3. 恢复任务:
task_set_state(task_id="Task_成语接龙", state="进行中")
4. 查询信息节点 → 获取当前成语"为虎作伥"
5. 回复: "好的喵!上一个成语是'为虎作伥',我帮你接:伥鬼害人喵!"
执行检查清单
每轮对话必须检查:
- 步骤 1:是否查询了人设图?
- 步骤 2:是否查询了工作记忆链?
- 步骤 3:是否根据人设和工作记忆链生成回复?
- 步骤 4:是否更新了工作记忆链?
- 涉及上下文引用时是否查询了工作记忆链?
- 用户提到"刚才/之前/上次"时是否查询了工作记忆链?