Skip to content

第五章 上下文管理 — 记忆与压缩

AI Agent 面临的核心工程挑战之一:上下文窗口有限,但对话越来越长。Hermes 的解决方案是三层架构——上下文引擎(可插拔)、压缩器(三区策略)、记忆管理器(多 Provider)。

5.1 上下文引擎架构

agent/context_engine.py 定义了可插拔的上下文管理接口:

核心接口

python
class ContextEngine:
    last_prompt_tokens: int       # 上次 prompt token 数
    last_completion_tokens: int   # 上次 completion token 数
    threshold_tokens: int         # 压缩触发阈值

    def should_compress(self) -> bool:
        """是否需要压缩"""
    def compress(self, messages) -> List[Dict]:
        """执行压缩,返回压缩后的消息列表"""

插件系统允许第三方实现自定义压缩策略,只需放到 plugins/context_engine/<name>/ 目录下。

5.2 上下文压缩器 — 三区策略

agent/context_compressor.py 实现了经典的三区压缩算法:

压缩流程

结构化摘要模板

压缩后的摘要遵循固定格式:

[CONTEXT COMPACTION — REFERENCE ONLY]
## Resolved Questions
- 用户偏好 Python 而非 JavaScript
- 项目使用 uv 管理依赖

## Pending Questions
- 部署目标尚未确认

## Active Task
- 正在实现用户认证模块

## Remaining Work
- 编写测试
- 更新文档

关键设计:摘要中保留了 _prev_summary,每次压缩都在前一次摘要的基础上迭代更新,避免信息丢失。

5.3 工具结果智能摘要

不是所有工具结果都同等重要。压缩器为每种工具定制了摘要策略:

工具类型摘要内容丢弃内容
terminal退出码、输出行数、错误信息完整 stdout/stderr
file_read文件路径、大小、行数文件完整内容
file_write文件路径、写入行数写入的内容
web_search搜索查询、结果数量搜索结果详情
web_extractURL、内容大小完整网页内容
browserURL、操作类型页面完整 DOM
execute_code代码预览(前几行)、输出行数完整代码和输出

JSON 安全截断

工具参数中的大 JSON 字符串会被安全截断:

python
def _json_safe_truncate(s: str, max_chars: int) -> str:
    """尝试解析 JSON,缩小字符串值,重新序列化"""
    try:
        obj = json.loads(s)
        # 递归缩小所有字符串值
        _shrink_strings(obj, max_chars)
        return json.dumps(obj, ensure_ascii=False)
    except json.JSONDecodeError:
        return s  # 非 JSON 原样返回

5.4 会话持久化 — SessionDB

hermes_state.py 实现了基于 SQLite 的会话存储,支持全文搜索。

数据模型

关键特性

WAL 模式(Write-Ahead Logging):

python
self._conn.execute("PRAGMA journal_mode=WAL")

允许多个读者 + 一个写者并发操作,不会阻塞。

写入冲突处理

python
def _execute_with_retry(self, sql, params, max_retries=3):
    for attempt in range(max_retries):
        try:
            return self._conn.execute(sql, params)
        except sqlite3.OperationalError as e:
            if "locked" in str(e) and attempt < max_retries - 1:
                time.sleep(random.uniform(0.05, 0.2))  # 随机抖动
                continue
            raise

会话链(Session Chaining):压缩后创建新 session,通过 parent_session_id 链接,保留完整历史。

FTS5 全文搜索

sql
CREATE VIRTUAL TABLE messages_fts USING fts5(content, session_id);
-- 搜索: "工具调用" 相关的对话
SELECT session_id, snippet(messages_fts) FROM messages_fts
WHERE messages_fts MATCH '工具调用' ORDER BY rank;

5.5 记忆管理器 — 多 Provider 架构

agent/memory_manager.py 协调多个记忆 Provider:

Provider 接口

python
class MemoryProvider(ABC):
    def prefetch(self, query: str) -> str:
        """对话开始前,根据用户消息预取相关记忆"""

    def sync_turn(self, user: str, assistant: str) -> None:
        """每轮对话后,同步新信息到记忆"""

    def get_tool_schemas(self) -> List[Dict]:
        """返回记忆相关的工具 schema(如 memory_save)"""

    def handle_tool_call(self, name: str, args: Dict) -> str:
        """处理记忆工具调用"""

故障隔离

每个 Provider 独立运行,一个失败不影响其他:

python
for provider in self._providers:
    try:
        result = provider.prefetch(query)
        combined += result
    except Exception as e:
        logger.warning("Provider %s failed: %s", provider.name, e)
        # 继续尝试下一个 Provider

5.6 内置记忆 Provider

MEMORY.md — 持久化事实

存储在 ~/.hermes/memories/MEMORY.md,记录跨会话的持久事实:

markdown
# Memory

## 用户偏好
- 偏好 Python,不喜欢 JavaScript
- 喜欢用 Rich 库做终端输出
- 偏好中文交流

## 项目约定
- 使用 uv 管理依赖
- 测试用 pytest + xdist

## 纠正记录
- 不要用 simple_term_menu,tmux 下有 bug

USER.md — 用户画像

存储在 ~/.hermes/memories/USER.md

markdown
# User Profile
- 角色:后端工程师,10 年 Go 经验
- 项目:hermes-agent AI agent 开发
- 时区:UTC+8

上下文隔离

记忆通过 <memory-context> 标签注入,防止被当作用户输入:

xml
<memory-context>
这里是记忆内容,不会被视为用户发送的消息
</memory-context>

记忆使用规则

  • 只记事实,不记录任务进度或临时状态
  • 声明式格式:"用户偏好 X"而非"总是做 X"
  • 用户偏好 > 纠正 > 约定 的优先级

5.7 外部记忆集成

Honcho

Honcho 是生产级记忆后端,提供辩证式用户建模

  • 通过对话自动构建用户认知模型
  • 支持多用户、多会话隔离
  • 适合长期运行的生产环境

Mem0

基于向量检索的记忆系统:

  • 自动从对话中提取关键信息
  • 语义搜索而非关键词匹配
  • 适合需要模糊检索的场景

集成方式

config.yaml 中配置:

yaml
memory:
  provider: honcho  # 或 mem0
  honcho:
    api_key: "..."
    endpoint: "https://..."

源码导航

  • 上下文引擎 → agent/context_engine.py
  • 压缩器 → agent/context_compressor.py
  • 会话存储 → hermes_state.py
  • 记忆管理 → agent/memory_manager.pyagent/memory_provider.py

下一章:第六章 技能系统

基于 MIT 许可发布