Hermes 内存层与缓存效率 | AI生成和翻译
以下是您所需的Markdown内容简体中文翻译,已遵循所有格式与翻译规则:
这里深入探讨Hermes中记忆系统的工作原理,以及它如何在效率与有效性之间取得平衡。
架构:三层记忆系统
Hermes拥有分层记忆系统,每一层服务于不同的持久化/检索权衡:
第一层:策展记忆(MEMORY.md + USER.md)
核心系统。两个位于 ~/.hermes/memories/ 的扁平文件:
- MEMORY.md — 智能代理的个人笔记(环境事实、项目约定、工具特性)
- USER.md — 用户档案(偏好、沟通风格、角色、习惯)
工作原理:
- 在会话启动时,
MemoryStore.load_from_disk()读取两个文件,按\n§\n分隔符拆分,并捕获一个冻结快照存入_system_prompt_snapshot。 - 该快照作为有界块直接注入系统提示(MEMORY:2200字符,USER:1375字符)。您可以在自己的系统提示中看到它们——
MEMORY(您的个人笔记)和USER PROFILE(用户是谁)部分。 - 会话中途的写入(通过
memory工具)会立即更新磁盘上的文件,但不会改变系统提示。这就是冻结快照模式——它使前缀缓存在整个会话期间保持稳定。快照仅在下次会话启动时刷新。
为什么这样设计? 前缀缓存。如果记忆在会话中途改变了系统提示,后续每个API调用都会错过缓存。通过冻结快照,系统提示在所有轮次中字节一致→在支持提示缓存的提供商(Anthropic、OpenAI)上实现巨大的成本节省。
写入安全性: 原子临时文件 + os.replace() + 文件锁(fcntl.LOCK_EX)。并发会话可以同时写入而不会损坏文件。
注入/窃取扫描: 每次写入都会经过 _scan_memory_content()——正则表达式模式捕获提示注入尝试(ignore previous instructions、you are now、带 $KEY 的curl等)以及不可见的Unicode字符。由于记忆被注入系统提示,一条被污染的记条目就直接成为注入向量。
第二层:外部记忆提供商(插件系统)
一次只能激活一个外部提供商,通过config.yaml中的 memory.provider 设置。可用提供商:
| 提供商 | 类型 | 检索方式 |
|---|---|---|
| Honcho | 云端托管,辩证问答 | 语义搜索 + LLM推理 + 同行卡片 |
| Holographic | 本地SQLite + HRR向量 | 实体解析、信任评分、组合查询 |
| Mem0 | 云端托管 | 语义搜索 |
| Supermemory | 云端托管 | 语义搜索 |
| Hindsight | 云端托管 | 语义搜索 |
| RetainDB | 云端托管 | 语义搜索 |
MemoryProvider抽象基类(agent/memory_provider.py)定义了生命周期:
initialize() → 连接,创建资源,预热
system_prompt_block() → 系统提示的静态文本(指令、状态)
prefetch(query) → 每轮对话前的后台召回
sync_turn(user, asst) → 每轮对话后的异步写入
get_tool_schemas() → 公开的额外工具(如 fact_store、honcho_search)
handle_tool_call() → 派发工具调用
shutdown() → 干净退出
Honcho 最为复杂。 它有三种召回模式:
context— 预取同行上下文(摘要、表征、同行卡片)到系统提示tools— 将 honcho_search / honcho_reasoning / honcho_profile 作为工具公开,由智能代理决定何时查询hybrid— 两者兼顾(默认)
Honcho 还执行辩证问答——它使用自己的LLM推理对累积的观测结果进行综合,以形成对用户的理解。通过 dialecticCadence 和 dialecticDepth 配置,您可以控制该过程运行的频率和深度(成本与新鲜度的权衡)。
第三层:会话搜索(FTS5)
session_search 工具——本身不是记忆,但却是回忆临时信息的主要方式。基于SQLite FTS5,同时使用 unicode61 分词器(单词级别)和 trigram 分词器(CJK子串支持)。搜索所有过去会话的消息。
这是效率杠杆——智能代理被指示使用 session_search 来获取任务进度、会话结果和已完成的工作日志,而不是把所有东西都塞进记忆。记忆仅保留那些在数周后仍然重要的持久事实。
如何让智能代理记住某些事
三种方法:
-
直接请求: 说“记住这个”或“别再这样做了”——智能代理的系统提示指示它在检测到这些信号时,主动通过
memory工具进行保存。 -
后台审查: 每轮对话后,
spawn_background_review()可以启动一个守护线程,该线程派生智能代理、回放对话并询问“是否有任何内容需要保存?”。此过程使用仅限于memory和skills工具的白名单。写入直接到磁盘;主对话不受影响。 -
手动记忆工具: 智能代理可以随时调用
memory(action="add", target="user", content="...")或memory(action="add", target="memory", content="...")。该工具强制执行字符数限制和去重。
什么内容放哪里:
target="user"→ 用户是谁(偏好、角色、风格)——限制1375字符target="memory"→ 智能代理学到了什么(环境事实、约定、特性)——限制2200字符
效率与有效性:平衡机制
1. 有界字符限制(而非令牌限制)
记忆使用字符计数,而非令牌计数。这与模型无关——2200字符无论分词器如何都大约相当于550个令牌。当达到限制时,您必须替换或删除条目。这迫使进行策展:每个条目都必须证明自己存在的价值。
2. 冻结快照 + 前缀缓存
系统提示在所有轮次中保持稳定。记忆写入更新磁盘但不更新提示。这意味着:
- 每轮对话的缓存失效成本为零
- 记忆是“最终一致性”的——新条目将在下次会话中可见
3. 预取模式(外部提供商)
外部提供商实现 prefetch(query)——在每次API调用前被调用。关键设计规则:实现应该快——真正的召回应使用后台线程,此处返回缓存的结果。
Honcho 通过以下方式实现:
- 每轮对话后
queue_prefetch(query)→ 启动一个后台线程 - 下一轮对话的
prefetch(query)→ 返回缓存结果(非阻塞) context_cadence— 上下文API调用之间的最小轮次数(默认为1)dialectic_cadence— 昂贵LLM推理调用之间的最小轮次数
4. 三层召回策略
系统提示明确指示智能代理:
- 记忆(MEMORY.md/USER.md):始终注入,每轮对话,零成本
- 外部提供商预取:如果可用则注入,受节奏控制
- session_search:按需调用,仅在智能代理需要回忆过去对话时使用
这形成了一个自然的效率层级:
- 热路径: 系统提示中的策展记忆(免费,始终存在)
- 温路径: 提供商预取(缓存,受节奏控制)
- 冷路径: session_search(FTS5查询,仅在需要时)
5. 记忆与技能分离
系统提示划出了一条清晰的分界线:
- 记忆 = 用户是谁、环境事实、稳定的约定
- 技能 = 如何做事情、程序性知识、工作流程
如果您发现一种新的做事方式,它应归入技能(SKILL.md),而非记忆。技能通过 skill_view() 按需加载,而非每轮对话注入。这防止了记忆变成一个包罗万象的垃圾桶。
6. 安全:注入扫描
由于记忆被注入系统提示,每次写入都会扫描以下内容:
- 提示注入模式(
ignore previous instructions、角色劫持) - 数据窃取尝试(带
$KEY的curl、读取.env) - 不可见的Unicode字符
- SSH后门模式
OpenClaw → Hermes
OpenClaw 是前身。迁移技能(hermes claw migrate)将 ~/.openclaw/ 中的 MEMORY.md、USER.md、SOUL.md 以及命令白名单导入到 ~/.hermes/ 中。记忆格式相同(以 § 分隔的条目),因此迁移基本上是机械式的。
TL;DR: Hermes 的记忆是一个经过策展、有界、基于文件存储的、以冻结系统提示快照(保留前缀缓存)形式注入的存储。外部提供商通过节奏控制的预取增加了语义召回能力。会话搜索处理临时性回忆。智能代理被指示要有所选择——记忆用于持久事实,session_search 用于其他一切。