hermes:上下文深入优化

Hermes 上下文优化实战指南

面向重度日常使用与长期项目工作的配置策略,基于 1M / 260K 窗口模型的成本与性能权衡。


一、记忆与画像预算:8000 / 4000 算浪费吗?

结论先行

在大上下文窗口(32K 以上)下,将 MEMORY.md 设为 8000 字符、画像设为 4000 字符,不算浪费,反而是一种理性的"扩容"。

关键前提:预算是字符数,不是 Token 数

Hermes 的记忆与画像预算单位是字符(characters),而非 Token。默认值为:

项目

默认上限

建议扩容值

MEMORY.md(记忆)

2,200 字符

8,000 字符

USER.md(画像)

1,375 字符

4,000 字符

扩容后合计约 12,000 字符,约合 3,000–4,000 tokens,且是每次会话固定注入的持久化信息,不会随对话增长而膨胀。

为什么重度场景下"划算"

  • 避免重复交代:项目约定、环境配置、工具怪癖被持久化。
  • 维持行为一致性:沟通偏好、工作习惯被固化。
  • 跨会话连贯性:长期项目的上下文连续性价值,远高于几千 tokens 的固定开销。

真正的上下文"黑洞"不在记忆

实测显示,Hermes 中更值得审视的开销是:

  • 技能(Skills):默认加载 121 个技能可占用 12,000–15,000 tokens
  • MCP 工具定义:可达 8,000–10,000 tokens

相比这些,记忆与画像的扩容增量并不突出。优先精简技能和 MCP 工具,比压缩记忆更有效。

唯一需要警惕的情况

若模型窗口偏小(如 8K / 16K),固定注入的 3–4K tokens 会显著挤占对话空间,更早触发压缩。此时应维持默认预算或仅适度上调。


二、1M 窗口下,压缩设置会带来更多费用吗?

结论:会,而且风险真实存在

费用增加并非压缩功能本身"更贵",而是三个机制叠加:

1. 延迟触发导致二次方成本增长(核心风险)

threshold 是相对于模型窗口的比例。在 1M 窗口下:

  • threshold: 0.5 → 第一次压缩要等到 500K tokens
  • 在此之前,每次 API 调用都携带完整且不断增长的上下文
  • 单次费用与上下文长度成正比,调用次数随会话线性增加
  • 总费用呈二次方(quadratic)增长

实测案例:436 次调用的会话,上下文从 25K 增长到峰值 456K,因未触及 500K 触发线,压缩一次都没发生,仅按列表价估算成本约 113 美元。

2. 压缩本身的辅助调用开销

压缩会调用辅助模型对中间轮次做摘要,这是一次独立的模型请求,产生额外费用。max_attempts: 10 意味着失败重试会重复调用辅助模型,费用线性叠加。

3. 对缓存命中率的破坏(隐性成本)

压缩会重写对话历史,改变后续请求的提示前缀,可能导致 prompt cache 失效。DeepSeek 等提供商的缓存命中与未命中价格差异可达上百倍。一次压缩省下的 token 空间,可能被后续缓存未命中费用抵消。

逐参数诊断

参数

你的值

问题

threshold

0.5

1M 窗口下 = 500K 才触发,太晚

target_ratio

0.1

legacy 模式才生效,需确认 tail_mode

deepseek-v4.1-flash

0.4

1M 下 = 400K,仍偏晚

Qwen3.5-27B

0.75

1M 下 = 750K,几乎不可能触发

max_attempts

10

失败重试烧钱,3 次足够


三、优雅的压缩配置

设计思路

  1. 用绝对上限(threshold_tokens)替代迟滞的比例触发
  2. 让修剪(prune)先于压缩(compress)发生
  3. 压缩任务交给廉价辅助模型

推荐配置

compression:  enabled: true  tail_mode: lean                           # 尾部预算由lean规则接管:clamp(窗口×2.5%, 10K, 25K)  threshold_tokens: 230000                  # 绝对上限:1M窗口下确保230K触发  threshold: 0.7                            # 比例触发:260K窗口下=182K,低于230K,先生效  proactive_prune_tokens: 60000             # 确定性修剪:历史超60K时清理旧工具输出  proactive_prune_min_reclaim_tokens: 8192  # 缓存保护:修剪至少回收8K才提交  max_attempts: 3  idle_compact_after_seconds: 1800          # 闲置30分钟后,下次唤醒前先压缩auxiliary:  compression:    provider: openrouter    model: google/gemini-2.5-flash-preview:free  free_only: true

双重触发保险机制

Hermes 取比例触发器与绝对上限中较低者触发压缩:

  • 1M 窗口:比例线 700K,绝对上限 230K 先生效 → 230K 触发
  • 260K 窗口:比例线 182K,低于 230K → 182K 触发

无论哪种窗口,都有明确、可预测的压缩边界,切断了二次方成本增长链条。

关键修正:target_ratio 在 lean 模式下无效

  • target_ratio 仅在 legacy 模式生效,用于计算保留的逐字尾部预算。
  • lean 模式使用独立规则:尾部预算 = clamp(窗口 × 2.5%, 下限 10K, 上限 25K)
    • 1M 窗口:2.5% = 25K,触及上限 → 实际 25K
    • 260K 窗口:2.5% = 6.5K,低于下限 → 实际 10K

因此选择 lean 模式后,应删除 target_ratio,避免无效参数造成误解。


四、参数详解

proactive_prune_tokens: 60000

含义:当历史上下文(主要是工具输出)超过 60K tokens 时,后台启动确定性修剪,不调用任何 LLM。

清理对象:终端上万行日志、读取的文件全内容、网页提取的大量文本。

动作:去重相同结果、摘要过大旧输出、截断冗长工具参数,并保护最近消息。

价值:完全免费,在上下文远未触及 230K 压缩线时提前清除"死重",减少每轮重发 token 量。

官方建议从 48,000 起试,60K 稍保守但合理。

proactive_prune_min_reclaim_tokens: 8192

含义:一次修剪至少能回收 8,192 tokens 才真正提交生效,否则放弃。

原因:提交修剪会改写已发送历史,导致 prompt cache 前缀失效,后续请求可能按更贵的缓存未命中价格计费。

作用:只为了足够大的收益才承担缓存失效代价,让缓存失效成为偶发的、值得的"大扫除",而非每轮的小动作。默认 4096,设为 8192 是更保守的选择。

idle_compact_after_seconds: 1800

含义:30 分钟无活动后,下次唤醒前先压缩。默认关闭。

价值:长会话挂起后重新接入时,避免为过时的大体积历史持续支付缓存读取费用。

max_attempts: 3

含义:压缩失败重试次数。压缩失败会重复调用辅助模型,10 次重试既不太可能在第 8 次成功,又会让费用线性叠加。3 次够用且可控。


五、辅助压缩模型的免费方案

OpenRouter 上的免费选项

模型 ID

是否免费

说明

google/gemini-2.5-flash

❌ 付费

输入 $0.30/1M,输出 $2.50/1M,需 ≥$5 余额

google/gemini-2.5-flash-preview:free

✅ 免费

无需信用卡,速率限制更严格,高峰需排队

配置步骤

  1. 注册:前往 openrouter.ai,用 Google/GitHub/邮箱登录,创建账号无需信用卡。
  2. 创建 API Key:在 openrouter.ai/keys 点击 "Create Key",格式 sk-or-v1-...。
  3. 设置环境变量:在 Hermes 运行环境中配置 OPENROUTER_API_KEY。
  4. 强制免费:配置 free_only: true,将回退逻辑限制在 :free SKU 上。

替代方案

若不想注册 OpenRouter,可使用主模型提供商自身的廉价层级(如 DeepSeek 的 flash/lite 版本),费用计入已有账单。

硬约束:辅助模型的上下文窗口必须 ≥ 主模型窗口,否则压缩调用会因超限失败,中间轮次被静默丢弃。


六、target_ratio 的真实计算逻辑

常见误解

误以为 target_ratio 基于总上下文窗口计算(如 1M × 10% = 100K)。

实际逻辑

target_ratio 基于 threshold_tokens 计算:

尾部预算 = threshold_tokens × target_ratio

配置文档原文:target_ratio 控制 "How much of threshold to keep as tail"。

示例

threshold_tokens

target_ratio

尾部预算

200,000

0.10

20,000

200,000

0.20

40,000

230,000

0.15

34,500

注意事项

  • 没有 target_tokens 参数。需要通过 threshold_tokens × target_ratio 倒推。
  • target_ratio 仅在 legacy 模式生效。lean 模式下尾部由 clamp(窗口×2.5%, 10K, 25K) 决定,该参数被忽略。

七、最终配置清单

# ============ 记忆与画像 ============memory_char_limit: 8000        # 记忆预算(字符)user_char_limit: 4000          # 画像预算(字符)# ============ 上下文压缩 ============compression:  enabled: true  tail_mode: lean                           # 尾部:clamp(窗口×2.5%, 10K, 25K)  threshold_tokens: 230000                  # 绝对上限锚点  threshold: 0.7                            # 比例触发(260K窗口下=182K先生效)  proactive_prune_tokens: 60000             # 前置修剪:超60K清理工具输出  proactive_prune_min_reclaim_tokens: 8192  # 缓存保护:回收≥8K才提交  max_attempts: 3  idle_compact_after_seconds: 1800# ============ 辅助压缩模型 ============auxiliary:  compression:    provider: openrouter    model: google/gemini-2.5-flash-preview:free  free_only: true

配置哲学总结

层次

机制

作用

第一道防线

proactive_prune_tokens

免费、确定性清理工具输出垃圾

第二道防线

threshold_tokens / threshold

强制在合理时机触发 LLM 压缩

第三道防线

idle_compact_after_seconds

闲置时低成本压缩过时历史

成本控制

auxiliary 廉价模型 + max_attempts: 3

压低压缩边际成本与失败开销

缓存保护

proactive_prune_min_reclaim_tokens: 8192

避免频繁破坏 prompt cache

核心原则:用绝对数值锚定触发点,用前置修剪减少压缩频率,用廉价模型承担摘要任务。


文档基于 Hermes 上下文管理机制整理,配置参数以官方文档为准。