Hermes Agent记忆系统架构与核心技术解析
📅 2026/7/22 10:19:06
👁️ 阅读次数
📝 编程学习
1. Hermes Agent 记忆系统架构概览
Hermes Agent 的记忆系统采用四层栈式设计,每一层解决不同维度的记忆需求。这种分层架构体现了"核心简洁、扩展丰富"的设计哲学,既保证了基础功能的可靠性,又为高级功能提供了灵活的扩展点。
1.1 四层记忆栈详解
Layer 1:内建文件记忆
- 实现方式:两个Markdown文件(MEMORY.md和USER.md)
- 容量限制:MEMORY.md 2200字符,USER.md 1375字符
- 特点:始终启用,不依赖外部服务,采用冻结快照机制
- 典型内容:
- MEMORY.md:环境事实、项目约定、工具特性
- USER.md:用户偏好、沟通风格、个人习惯
Layer 2:会话持久化
- 实现方式:SQLite数据库+FTS5全文索引
- 功能特点:
- 记录完整对话历史
- 支持跨会话语义检索(通过session_search工具)
- 与Layer 1的定位区分:原始过程 vs 提炼事实
Layer 3:上下文窗口管理
- 核心组件:ContextCompressor
- 触发条件:上下文窗口使用率≥50%
- 五阶段压缩流程:
- 工具输出裁剪(零成本)
- 头部保护(保留前3条消息)
- 尾部token预算(从后向前累积)
- LLM生成结构化摘要
- 迭代更新已有摘要
Layer 4:外部记忆提供者
- 设计模式:插件系统(MemoryProvider ABC)
- 当前支持:Honcho、Mem0等8种后端
- 约束条件:同一时间只允许激活一个外部provider
1.2 关键设计原则
有界性(Bounded)
- 字符硬限制防止记忆膨胀
- MEMORY.md:2200字符(约800 tokens)
- USER.md:1375字符(约500 tokens)
- 采用字符而非token计数的原因:模型无关性
策展式(Curated)
- Agent主动决定保存内容
- 保存优先级:
- 用户偏好和纠正
- 环境事实
- 流程知识
- 通过memory工具的schema嵌入行为引导
缓存友好(Cache-Friendly)
- 冻结快照模式保护提示词前缀缓存
- 写入立即持久化但下个session才生效
- 唯一例外:上下文压缩时重建系统提示词
2. 内建记忆系统核心技术
2.1 双态存储引擎
MemoryStore类实现双态管理:
class MemoryStore: def __init__(self): self.memory_entries: List[str] = [] # 活跃状态 self.user_entries: List[str] = [] # 活跃状态 self._system_prompt_snapshot = {} # 冻结快照冻结快照:
- 在load_from_disk()时捕获
- 用于系统提示词注入
- session内保持不变,保证前缀缓存稳定
活跃状态:
- 由工具调用实时修改
- 每次修改立即持久化到磁盘
- 工具响应反映活跃状态
2.2 原子写入与并发安全
写入流程:
- 创建临时文件
- 写入内容并刷盘
- 原子rename替换原文件
@staticmethod def _write_file(path: Path, entries: List[str]): tmp_path = tempfile.mkstemp(dir=path.parent, prefix=".mem_") try: with open(tmp_path, "w") as f: f.write(content) f.flush() os.fsync(f.fileno()) os.replace(tmp_path, path) # 原子操作 except: os.unlink(tmp_path) raise并发控制:
- 使用分离的.lock文件而非flock()
- 原因:避免"w"模式截断文件造成的竞态条件
- 锁文件与数据文件分离,不影响原子替换
2.3 记忆安全扫描
记忆内容被注入系统提示词,需防范:
- Prompt注入攻击
- 角色劫持
- 秘密泄露
- 持久化后门
防御措施:
- 12种正则模式检测威胁
_MEMORY_THREAT_PATTERNS = [ (r'ignore\s+previous\s+instructions', "prompt_injection"), (r'you\s+are\s+now\s+', "role_hijack"), # 其他10种模式... ] - 检测10种不可见Unicode字符
- 写入前自动扫描内容
3. 冻结快照与提示词缓存
3.1 缓存经济学
Anthropic的system_and_3缓存策略:
- 系统提示词:最高优先级缓存点
- 最近3条非系统消息:滚动窗口
- 节省约75%的token处理成本
关键洞察:系统提示词的稳定性比记忆实时性更重要。
3.2 冻结快照实现
加载时捕获快照:
def load_from_disk(self): self.memory_entries = self._read_file("MEMORY.md") self.user_entries = self._read_file("USER.md") self._system_prompt_snapshot = { # 冻结点 "memory": self._render_block("memory", self.memory_entries), "user": self._render_block("user", self.user_entries), }系统提示词注入:
- 始终使用冻结快照
- 活跃状态的修改不影响当前session的提示词
- 新写入内容在下个session生效
3.3 缓存失效策略
唯一重建时机:上下文压缩
- 压缩导致消息序列结构改变
- 缓存必然失效
- 顺带重新加载记忆快照
def _invalidate_system_prompt(self): self._cached_system_prompt = None self._memory_store.load_from_disk() # 重新加载快照4. 记忆提供者插件系统
4.1 MemoryProvider ABC
核心生命周期方法:
class MemoryProvider(ABC): @abstractmethod def initialize(self, session_id: str, **kwargs): ... @abstractmethod def prefetch(self, user_message: str) -> str: ... @abstractmethod def sync_turn(self, user_msg: str, assistant_msg: str): ... @abstractmethod def shutdown(self): ...可选钩子:
- on_turn_start:轮次计数
- on_session_end:会话摘要
- on_pre_compress:压缩前提取
- on_memory_write:内建记忆同步
- on_delegation:子Agent观察
4.2 提供者案例:Honcho
工具集:
- honcho_profile:用户画像卡片
- honcho_search:语义搜索
- honcho_context:辩证问答
- honcho_conclude:持久化结论
节流机制:
- injection_frequency:每轮/首轮
- context_cadence:上下文API调用间隔
- dialectic_cadence:辩证API调用间隔
- reasoning_level_cap:推理级别上限
4.3 提供者案例:Holographic
纯本地特性:
- SQLite存储事实
- 可选HRR(Holographic Reduced Representations)代数
- 无外部API依赖
特色工具:
- probe:实体召回
- related:结构邻接
- reason:组合查询
- contradict:矛盾检测
5. 上下文窗口管理
5.1 压缩触发条件
双重检测机制:
- 预检(preflight):
- 基于消息长度的粗略估算
- 快速判断是否需要压缩
- 精确检测:
- 使用实际tokenizer
- 阈值:context_length × 50%
5.2 五阶段压缩算法
工具输出裁剪:
- 目标:旧的大体积tool消息
- 替换为"[Old tool output cleared]"
- 零成本操作
头部保护:
- 保留前3条消息(系统提示+初始交互)
- 建立对话基本上下文
尾部token预算:
def _find_tail_cut_by_tokens(messages, budget): for i in range(len(messages)-1, head_end-1, -1): msg_tokens = estimate_tokens(messages[i]) if accumulated + msg_tokens > budget: break accumulated += msg_tokensLLM结构化摘要:
- 模板包含:
- Goal/Progress/Key Decisions
- Next Steps/Critical Context
- 增量更新已有摘要
- 模板包含:
迭代更新:
- 保留前次摘要作为基础
- 只补充新内容
- 避免信息衰减
5.3 记忆冲刷机制
流程:
- 注入系统消息: "[System: The session is being compressed...]"
- 单次API调用:
- 仅memory工具可用
- Agent决定保存内容
- 执行memory工具调用
- 清理冲刷相关消息
设计要点:
- 使用唯一哨兵标记定位清理范围
- 优先使用辅助LLM客户端(更便宜模型)
- 冲刷的memory调用会同步到外部provider
6. 生产环境实践建议
6.1 容量规划
MEMORY.md:
- 2200字符 ≈ 800 tokens(英文)
- 中文等语言token效率更高
- 使用率提示:[67% — 1,474/2,200 chars]
优化策略:
- 定期清理过时条目
- 合并相关事实
- 用缩写替代完整短语
6.2 安全配置
必做检查:
- 启用内存扫描
memory: security_scan: true - 限制记忆工具调用权限
- 审计MEMORY.md变更历史
高级防护:
- 自定义威胁模式
CUSTOM_THREATS = [ (r'company\-specific\-threat', "custom_threat") ] - 定期轮换存储路径
6.3 性能调优
缓存优化:
- 保持系统提示词稳定
- 减少不必要的压缩
- 适当增大压缩阈值
外部provider选择:
- 低延迟场景:Holographic(纯本地)
- 复杂查询场景:Honcho(辩证推理)
- 存储敏感场景:RetainDB(Delta压缩)
6.4 监控指标
关键metric:
- 记忆写入频率
- 压缩触发次数
- 外部provider延迟
- 缓存命中率
- 安全扫描拦截次数
日志示例:
[memory] flush_memories saved 3 entries [compressor] reduced ctx from 12k→4k tokens [honcho] prefetch latency=142ms7. 架构演进与边界案例
7.1 设计决策验证
字符vs Token限制:
- 问题:不同模型tokenizer不同
- 验证:跨模型测试(Claude vs GPT-4)
- 结论:字符计数确保一致性
双文件分离:
- 问题:为何不合并?
- 验证:多用户场景测试
- 结论:支持独立配置/隔离
7.2 已知边界案例
中文处理:
- 现象:字符限制下中文信息密度更高
- 建议:动态调整字符限制
def adjust_for_cjk(limit): return int(limit * 1.3) # CJK补偿系数
长会话稳定性:
- 现象:50+轮次后压缩质量下降
- 方案:引入会话分段
if turn_count > 50: self._segment_session()
7.3 演进路线
短期规划:
- 记忆版本控制
- 差分同步外部provider
- 基于信任评分的自动清理
长期方向:
- 分层记忆生命周期
- 联合压缩策略
- 神经记忆索引
编程学习
技术分享
实战经验