2.4. Prompt Builder 实现了一套轻量级 RAG 管理系统

Prompt Builder 实现了一套轻量级 RAG 管理系统

现象与背景:为什么上下文管理成了 Agent 的“隐形天花板”

如果你在 2025 年底问 Agent 开发者最头疼的问题是什么,多数人会给出同一个答案:上下文窗口。长对话中,推理链、工具调用记录、中间摘要不断累积,很快就能把一个 200K token 的窗口撑爆。更糟糕的是,简单的截断(truncation)经常导致模型“放弃”复杂任务——因为承载长期目标的记忆片段恰好落在了被丢弃的窗口之外。

Hermes Agent 的开发者很早就意识到,这个问题无法通过无限扩展窗口容量来解决,而必须靠一套精巧的上下文压缩与缓存机制。截至 2026 年 4 月,Hermes 在 0.x 系列版本(如 v0.16.0) 中已经形成了完整的上下文管理方案:Prompt Builder 内部实现了一套轻量级 RAG(检索增强生成)管理系统,它不同于传统基于向量数据库的 RAG,而是通过对历史消息做摘要、缓存稳定前缀、按需检索相关记忆,来在有限的上下文窗口内维持长期对话的连贯性。

这套 RAG 管理系统有三个核心维度:

  • 摘要压缩:从简单滑动窗口进化为层次化摘要,动态决定哪些历史要保留原始文本,哪些压缩为摘要。
  • 上下文缓存与模板实例化:通过缓存稳定前缀(系统提示、工具定义)和已渲染的模板,大幅减少重复推理计算。
  • 历史消息的按需检索:避免全量注入,而是通过 memory_tool 根据当前任务动态查询相关历史片段。

下面我们逐一拆解这三个维度。


核心维度分析

1. 摘要压缩:从滑动窗口到层次化摘要

传统的滑动窗口(Sliding Window)只保留最近 N 轮对话,其余全部丢弃。这种做法的最大问题是:一旦窗口滚动,早期的重要决策(比如“用户要求最终生成一份 PDF”)就再也找不回来。模型会在对话中途突然忘记目标,表现得像是在执行一个独立的新任务。

Hermes 的做法是引入双层压缩系统,模拟了经典 RAG 中的“检索 + 压缩”流程:

  • 第一层:修剪(Truncation) —— 当 prompt 的 token 总数达到预设阈值(默认为窗口容量的 50%)时,自动触发。这一层会移除重复的工具调用日志、中间推理片段以及已完成的系统动作,只保留决策路径的关键节点。它就像 RAG 中的粗筛,丢掉明显的噪音。
  • 第二层:摘要(Summarization) —— 当修剪后仍然超出安全水位,压缩器会将早期对话轮次转换为精炼的摘要文本,并插入到当前上下文的开头,代替原始消息。摘要中刻意保留了任务目标、已完成步骤、未决待办三项结构化信息,确保模型在任何阶段都能“捡回”长期上下文。

下面这张对比表展示了不同上下文压缩策略对推理质量的影响:

策略 机制 长期记忆保持 计算开销 适用场景 作者的结论
滑动窗口 只保留最近 k 轮 极低 简单问答、无状态对话 不适用于任何需要多步规划的 Agent 任务
全量摘要 将所有旧消息总结为一段文本 中等,但信息容易模糊 中等 摘要模型质量极高的情况 实践中容易丢失细节,且摘要自身的计算成本不可忽略
层次化摘要(Hermes 默认) 混合修剪与摘要,按优先级压缩 强,关键节点保留原始文本 可控,通过阈值触发 多步推理、工具调用密集的任务 当前最优解,平衡了上下文占用与细节保留

从当前调研资料看,Hermes 的双层压缩触发条件可通过 compression.threshold 调整,默认 50% 是一个经过实际场景验证的平衡点——过低会频繁触发压缩,影响响应速度;过高则可能来不及在窗口溢出前完成压缩,导致 API 报错。

2. 上下文缓存与模板实例化

很多 Agent 框架都有“Prompt Builder”模块,但 Hermes 的 Prompt Builder 不止是拼接字符串,它还内建了缓存热机的思维:将一次 prompt 构建拆分为稳定部分和可变部分,对稳定部分进行缓存复用。

在 Hermes 的实现中,每一次 LLM 调用的最终 prompt 由以下片段按序拼接而成:

  1. 系统提示(System Prompt) —— 描述 Agent 角色、约束、输出格式等,在整个会话中保持不变
  2. 工具定义(Tool Definitions) —— JSON schema 列表,多数情况下在一次会话中不变
  3. 注入的上下文块(Injected Context Blocks) —— 来自各种插件、记忆检索结果等,随使用场景变化
  4. 历史消息窗口(History Window) —— 经过压缩处理后的最近消息,每个轮次都会变化

稳定前缀(1 和 2)被单独缓存,Hermes 会利用底层模型(如 Anthropic Claude)提供的 Prompt Caching API,设置 cache_control 断点。具体的缓存策略采用了官方推荐的 system_and_3 模式:

  • 断点 1:系统提示末尾。
  • 断点 2:工具定义末尾。
  • 断点 3:从下往上数第 3 条非系统历史消息的末尾。

这个策略的巧妙之处在于:它不仅缓存了系统级信息,还在历史消息中“锁定”了一个相对稳定的前缀(越靠前的历史被压缩后重新生成的频率越低),从而在每次请求中都能命中大量缓存 token,将推理成本和延迟降低 30%–80%(具体收益取决于会话长度和消息结构)。

缓存与压缩的协同:压缩减少了历史消息的体积,使“可变窗口”更短,间接提高了历史前缀的缓存命中率。因此 Hermes 的 Prompt Builder 并不是两个独立功能的堆砌,而是一个反馈闭环。

缓存策略对比

缓存策略 断点设置 缓存命中率 复杂度 作者的结论
全动态(无缓存) 0% 仅适用于一次性调用
仅系统提示 1 个断点 ~20% 极低 收益有限
system_and_3(Hermes 默认) 3 个断点 50%–70% 中等,但实现一次即可复用 投入产出比最高,推荐所有长对话场景使用

3. 历史消息的按需检索

轻量级 RAG 管理系统的“Retrieval”部分并不仅体现在压缩和缓存上,更核心地体现在:Agent 不会将全部历史消息平铺进 prompt,而是像真正的 RAG 架构一样,由记忆模块根据当前任务“检索”出最相关的片段。

Hermes 中负责这一机制的是 memory_tool。当一个新的用户请求到来,Prompt Builder 会调用记忆工具,工具内部运行一个轻量级的嵌入检索(基于文本相似度),从持久化存储中返回符合 query 的历史信息。只有这些检索结果(而非整个对话日志)才会被注入到上下文中。

这样做有三个直接好处:

  • 避免上下文污染:无关的历史消息不会占用宝贵的 token 位。
  • 节能降本:每次 LLM 调用处理的 token 数减少,API 成本线性下降。
  • 支持跨会话记忆:存储可以在会话结束后保留,Agent 重启后仍能“记住”之前的用户偏好。

从调研资料中可以看到,Hermes 的配置项 prompt_caching.enabledcontext_compression.enabled 均可以独立开关,而记忆检索通过 memory_tool 的注册来实现。用户可以通过简单的命令行配置将其全部开启:

# 启用上下文压缩(自动摘要旧消息)
hermes config set context_compression.enabled true

# 启用 prompt 缓存(减少重复推理计算)
hermes config set prompt_caching.enabled true

这样一套最小化 RAG 系统,不必引入额外的向量数据库依赖,而是将检索能力直接内建于 Prompt Builder 的组装流程中,保持了 Agent 运行时的轻量化。


先给结论:轻量 RAG 管理系统是长对话 Agent 的必需品

综合以上三个维度,我们得出一个清晰结论:对于任何需要处理多轮复杂任务的 Agent,单纯依赖大上下文窗口是不可靠的,必须在 Prompt Builder 层面引入轻量级 RAG 机制——摘要压缩负责“写”,缓存负责“省”,按需检索负责“读”——三者在工程上组合起来,才能将上下文窗口的物理限制转化为可控的管理策略。

整体方案对比

方案 压缩 缓存 检索 复杂度 综合收益 作者的结论
原始上下文全量注入 极低,极易溢出 只适合玩具 demo
仅滑动窗口截断 低,长期记忆丢失 不适用于 Agent
仅摘要压缩 中,仍可能占用过多 token 缺乏缓存配合,成本偏高
Hermes 轻量 RAG 系统 ✓(双层) ✓(前缀缓存) ✓(按需检索) 高,最大化窗口利用率 当前工程最佳实践

按场景的推荐

根据不同的应用场景,你可以调整 Hermes 上下文管理的策略组合:

  • 对话式 FAQ Bot
    上下文长度天然较短,任务无状态。可以选择关闭压缩和检索,仅保留缓存来降低重复询问的成本。

  • 多步数据分析 Agent
    需要跟踪中间计算结果,建议开启全部压缩与缓存功能,并将压缩阈值调高至 60%–70%,避免在计算密集阶段频繁压缩导致核心中间数据丢失。

  • 个人助理 / 长期陪伴 Agent
    必须开启按需检索功能,并定期将重要偏好写入持久化记忆。缓存和压缩可以沿用默认配置,重点是保证跨会话记忆的连续性。

  • 成本敏感的生产环境
    建议同时开启缓存和压缩,并密切关注缓存命中率指标。如果使用 Anthropic Claude,可考虑将系统提示进一步精炼,使其更稳定,以提高缓存利用率。


在下一章《工具调度机制让同一个 Agent 服务于多个前端》中,我们将看到这些经由 Prompt Builder 精心编织的上下文,是如何被分发到不同调用方、工具和插件中去执行的。 Tool Dispatch 的设计目标正是把 Agent 的“大脑”与“手脚”彻底解耦,让同一套推理逻辑可以无缝服务于命令行、Web 界面、聊天 API 等多种交互方式。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~