Hermes Agent记忆系统架构与核心技术解析

📅 2026/7/22 10:19:06 👁️ 阅读次数 📝 编程学习
Hermes Agent记忆系统架构与核心技术解析

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%
  • 五阶段压缩流程:
    1. 工具输出裁剪(零成本)
    2. 头部保护(保留前3条消息)
    3. 尾部token预算(从后向前累积)
    4. LLM生成结构化摘要
    5. 迭代更新已有摘要

Layer 4:外部记忆提供者

  • 设计模式:插件系统(MemoryProvider ABC)
  • 当前支持:Honcho、Mem0等8种后端
  • 约束条件:同一时间只允许激活一个外部provider

1.2 关键设计原则

有界性(Bounded)

  • 字符硬限制防止记忆膨胀
  • MEMORY.md:2200字符(约800 tokens)
  • USER.md:1375字符(约500 tokens)
  • 采用字符而非token计数的原因:模型无关性

策展式(Curated)

  • Agent主动决定保存内容
  • 保存优先级:
    1. 用户偏好和纠正
    2. 环境事实
    3. 流程知识
  • 通过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 原子写入与并发安全

写入流程

  1. 创建临时文件
  2. 写入内容并刷盘
  3. 原子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 缓存失效策略

唯一重建时机:上下文压缩

  1. 压缩导致消息序列结构改变
  2. 缓存必然失效
  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

工具集

  1. honcho_profile:用户画像卡片
  2. honcho_search:语义搜索
  3. honcho_context:辩证问答
  4. 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 压缩触发条件

双重检测机制

  1. 预检(preflight):
    • 基于消息长度的粗略估算
    • 快速判断是否需要压缩
  2. 精确检测:
    • 使用实际tokenizer
    • 阈值:context_length × 50%

5.2 五阶段压缩算法

  1. 工具输出裁剪

    • 目标:旧的大体积tool消息
    • 替换为"[Old tool output cleared]"
    • 零成本操作
  2. 头部保护

    • 保留前3条消息(系统提示+初始交互)
    • 建立对话基本上下文
  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_tokens
  4. LLM结构化摘要

    • 模板包含:
      • Goal/Progress/Key Decisions
      • Next Steps/Critical Context
    • 增量更新已有摘要
  5. 迭代更新

    • 保留前次摘要作为基础
    • 只补充新内容
    • 避免信息衰减

5.3 记忆冲刷机制

流程

  1. 注入系统消息: "[System: The session is being compressed...]"
  2. 单次API调用:
    • 仅memory工具可用
    • Agent决定保存内容
  3. 执行memory工具调用
  4. 清理冲刷相关消息

设计要点

  • 使用唯一哨兵标记定位清理范围
  • 优先使用辅助LLM客户端(更便宜模型)
  • 冲刷的memory调用会同步到外部provider

6. 生产环境实践建议

6.1 容量规划

MEMORY.md

  • 2200字符 ≈ 800 tokens(英文)
  • 中文等语言token效率更高
  • 使用率提示:[67% — 1,474/2,200 chars]

优化策略

  • 定期清理过时条目
  • 合并相关事实
  • 用缩写替代完整短语

6.2 安全配置

必做检查

  1. 启用内存扫描
    memory: security_scan: true
  2. 限制记忆工具调用权限
  3. 审计MEMORY.md变更历史

高级防护

  • 自定义威胁模式
    CUSTOM_THREATS = [ (r'company\-specific\-threat', "custom_threat") ]
  • 定期轮换存储路径

6.3 性能调优

缓存优化

  • 保持系统提示词稳定
  • 减少不必要的压缩
  • 适当增大压缩阈值

外部provider选择

  • 低延迟场景:Holographic(纯本地)
  • 复杂查询场景:Honcho(辩证推理)
  • 存储敏感场景:RetainDB(Delta压缩)

6.4 监控指标

关键metric

  1. 记忆写入频率
  2. 压缩触发次数
  3. 外部provider延迟
  4. 缓存命中率
  5. 安全扫描拦截次数

日志示例

[memory] flush_memories saved 3 entries [compressor] reduced ctx from 12k→4k tokens [honcho] prefetch latency=142ms

7. 架构演进与边界案例

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
  • 基于信任评分的自动清理

长期方向

  • 分层记忆生命周期
  • 联合压缩策略
  • 神经记忆索引