关于 input-token-analysis
Input Token Analysis 是用于分析 Hermes 中会话、cron 运行和工具流量输入 Token 消耗的技能。它对主要消耗项排序,指导先验证配置或提示词调整,并与基线比较效果。
主要功能
- 01汇总 Token 审计脚本
- 02按任务、模型和提供方拆分
- 03分析会话、cron 与工具流量
- 04提案前验证配置调整项
- 05基线记录与后续变化测量
适用场景
- 01调查异常偏高的输入 Token 用量
- 02找出 Token 消耗高的 cron 任务
- 03测量节省 Token 调整后的变化
- 04按消耗项和预估成本比较用量
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ moonlight-lupin/ agent-skills --skill input-token-analysis安装后在 Claude Code 中输入/input-token-analysis确认已加载。
附带文件scripts/audit.py
详细介绍
输入 Token 分析
说明输入 Token 的总消耗情况。用数字回答三个问题:Token 都消耗在哪里、哪些消耗项占主导、哪些配置或提示词改动可以减少消耗。不同于 input-token-overheads,后者审计每轮对话的系统提示词块。本技能审计跨会话、定时任务触发和工具流量的总量。
适用场景
- 月度/每周输入 Token 账单金额高且原因不明(例如“30 天内消耗了 2.4B 个 Token”)
- 应用节省 Token 的改动后,与基线对比测量变化
- 怀疑某个定时任务的 Token 消耗失控
如需检查每轮对话的上下文窗口健康状况,请使用 input-token-overheads。如需处理 API 账单争议,请使用提供商的用量仪表盘——本地遥测无法查看提供商侧的缓存情况。
快速开始
运行审计脚本(只读,仅使用标准库):
python3 ~/.hermes/skills/agent-ops/input-token-analysis/scripts/audit.py --days 30
# other profiles: --db ~/.hermes/profiles/<name>/state.db
# custom cron ledger: --cron-audit /path/to/usage_audit.jsonl --jobs /path/to/jobs.json
脚本会输出:按任务/模型/提供商统计的总量、缓存读取和缓存写入列、加权单次调用平均值(长会话和短会话下限)、高消耗会话、问题定时任务、仅统计活跃项的工具结果用量及工具占比,以及超大结果计数。所有数据均来自真实数据库记录——脚本能够测量时,切勿手动估算。
预检规范
先核实,再提出建议。凭记忆给出的建议不可接受。
- 配置项和当前值——先读取实时值:
hermes config get <key>。切勿凭记忆陈述当前值,也不要假设正在使用默认值。 - 默认值和工作机制——根据已安装的版本(
hermes_cli/config_defaults.py)或 Hermes 文档,确认配置项是否存在及其作用。如果已安装版本与文档不一致,请明确说明。 - 提供商行为——不要假设提供商会报告缓存字段、遵循某个定价层级,或以特定方式统计 Token。提出相关说法前,请实际探查或查阅其最新文档。
- 无法核实的说法——在报告中标记为“未核实”。明确标注未知情况,胜过自信地猜测。
如果提案引用了未经核实的配置项、值或机制,就不完整。请先完成预检,否则删除该提案。
解读
先按消耗量排序,再为每项匹配一个预先检查过的调节手段:
| 发现 | 信号 | 调节手段 |
|---|---|---|
| 长会话占主导 | Top 会话 >200 api_calls,输入 >40M | 首先检查提供商的缓存折扣。启用缓存后,预热会话可以低成本地重新读取历史记录;只有未缓存的冗余内容占主导时才重置。每次重置都会按全价重新支付整个前缀的费用。检查压缩是否确实触发(compact count >0) |
| background_review 占比较大 | task='background_review' >总量的 5% | 设置 auxiliary.background_review.max_input_tokens(默认值为 600000),或设置 enabled: false;手动执行 /refine 仍然有效。还可以将 auxiliary.background_review.model 路由到更便宜的模型——不同模型会重新读取精简摘要,而不是完整对话记录 |
| 单个 cron 任务占主导 | 每次触发的 avg prompt_tokens 达数百万 | 重写其提示词并设置读取预算:使用按日期限定的源数据、跳过过大的项目、缩小滚动窗口、达到上限即停止并延后处理 |
| Cron 成本已接近下限 | 每次触发的平均 token 数接近单次调用下限(25-30k) | 固定的脚手架下限乘以触发次数是成本主因:减少触发频率或合并任务,而不是缩短提示词 |
| 工具结果占据大部分上下文 | 工具字符数 >已存储活跃内容的 70%(发送量上限;脚本会打印占比) | 设置 tool_output.max_bytes(默认值为 50000)、file_read_max_chars(默认值为 100000)和溢出预算。启用提供商缓存后,节省主要来自结果首次出现的轮次以及避免压缩——通过缓存重新读取稳定结果的成本很低。过大的结果会以预览内容 + 路径的形式溢出到 $HERMES_HOME/cache/spillover/ |
| 技能重复加载 | 每个会话中,相同的技能正文加载 N 次 | 行为规则:已在上下文中的技能,切勿再次调用 skill_view。启用缓存后,直接重复读取会有折扣;真正的损害是上下文压力导致更早压缩,从而使缓存失效 |
| 短会话的单次调用下限较高 | 脚本中 <50 次调用的会话加权平均值(通常为 25-40k) | 这是固定基线(系统提示词 + 工具架构),应通过 input-token-overheads 降低,而不是通过此技能降低 |
| 子 Agent 扇出开销较大 | 大量启动 delegate_task;每个子任务都要在未缓存的情况下重新支付完整的系统提示词 + 工具架构 | 将 delegation.model 路由到更便宜的模型,以处理机械性子任务;将多次工具调用合并为一次 execute_code 调用,而不是扇出;限制并发子 Agent 数量 |
| 压缩频繁触发 | 每个会话的压缩事件较多;compression_ineffective_count >0 | 每次压缩都会将历史记录改写成新前缀 = 此后所有内容都会发生全价缓存未命中。权衡 compression.threshold 与提供商的缓存折扣;将压缩摘要器(auxiliary.compression.model)路由到便宜的模型——它会读取整个对话 |
| 某个提供商的 cache_read ≈ 0 | 提供商完全不返回缓存 token 字段(此时本地输入就是完整提示词,无法测量占比——请查看提供商的计费面板);或者提供商返回了该字段,但值为 0(缓存确实未启用:会话较短、前缀不稳定或 TTL 已过期——请调查原因) | |
| 高价模型处理低价任务流量 | 主模型上的 title_generation/approval/vision 行 | 将各个 auxiliary.<task>.model 路由到 Flash 级模型;对于频繁的小型调用,可近乎零成本地节省费用 |
| Token 排名 ≠ 成本排名 | 便宜模型消耗的 token 数是高价模型的 10 倍 | 按 billing_provider 对 estimated_cost_usd/actual_cost_usd 排名;优化时排除 billing_mode='subscription_included' 行(边际成本为零) |
操作流程
1. 建立基线
针对所需时间窗口运行脚本。记录:输入总量、各任务的细分数据、前 10 个会话、cron 问题任务统计、工具字符占比、缓存列和成本总额。将输出与计划实施的更改保存在一起。
完成标准:最终报告中的每个数字都能追溯到脚本中的对应行。
2. 预先检查每个候选优化手段
在任何优化手段纳入提案之前,都要在运行中的实例上验证:键存在(hermes config get)、当前值已知,且机制与已安装的构建版本或文档相符。提出与缓存相关的说法前,先检查提供商的报告行为。
完成标准:草案提案中的每个优化手段都有已验证的键和当前值,或者标记为 UNVERIFIED,并说明缺少什么。
3. 排序并映射
按令牌数和预估成本对使用方排序(两者的排序可能不同)。对排名前 3 的每一项,指出预先检查过的优化手段。如果某个使用方没有对应的优化手段,请明确说明,不要凭空编造。
完成标准:排名前 3 的使用方各自都有一个预先检查过的优化手段,或者明确判定为“没有本地优化手段”。
4. 提出更改
按影响从高到低提出更改,每项都包含:配置键或提示词编辑、预期节省量、回退方式。针对每个 billing_provider,应用该提供商的缓存折扣来计算预期节省量;如果提供商不报告缓存字段,请说明该估算有上限,并在提供商控制面板上核实。配置编辑必须通过 hermes config set 进行——工具已阻止直接编辑 config.yaml(已于 2026-09-02 验证)。编辑 Cron 提示词:先备份旧提示词,再进行编辑,然后验证结构({"jobs": [...], "updated_at": ...})并确认计划仍然有效。
完成标准:用户已批准每项更改,且更改已应用并通过回读验证。
5. 安排增量检查
创建一个约 30 天后运行的一次性 Cron,在提示词中包含旧基线,并重新运行此技能。内容包括:基线数值、已应用更改列表,以及每项更改的通过标准(例如,“job X avg prompt_tokens/fire >2M = 未修复”)。
完成标准:增量检查 Cron 已创建(hermes cron list 中可见),且其提示词包含基线数值、已应用更改列表和通过标准。
注意事项
- 以只读方式打开 state.db(
file:...?mode=ro,uri=True,并对路径进行 URL 编码)。数据库处于使用中,可能有数百 MB;使用写入连接可能导致锁定。 - 不同提供商的线协议对 input_tokens 的定义不同。 Anthropic 风格的线协议会将
cache_read_tokens计入输入之外(实际提示词 ≈ input + cache_read + cache_write);OpenAI 风格的prompt_tokens则将缓存令牌作为子集计入。经验判断:如果某行的 cache_read > input_tokens,该提供商的 input 不包含缓存。绝不要跨提供商比较原始 input_tokens;应按 billing_provider 计算有效提示词。缓存占比仅在同一计量口径内有意义。 - jobs.json 有两种已观察到的结构——
{"jobs": [...], "updated_at": ...}和纯列表。编辑前后都要兼容两种结构;每次写入后都要验证容器结构。 - 缓存占比为 0 并不能证明没有缓存。 有些提供商的
usage中完全不返回缓存令牌字段(已于 2026-09-02 确认有一个这样的提供商——其 usage 对象只包含 prompt/completion/total),因此本地遥测无法观测其缓存情况。另一些提供商会按调用报告缓存读取量。请查阅各提供商的文档和账单仪表板,以获取确切数据。 - **sessions.input_tokens 和 session_model_usage 的差异来自归因方式,而不只是时间:**任务行按会话累计,并根据 last_seen 归因(会将窗口开始前的开销计入窗口内);而按会话排名使用开始/活动日期。总数无法对账时,说明偏差方向;绝不要将这两种总数混在同一求和中。
- token_count 列经常为 NULL——使用 LENGTH() 衡量内容大小,并记住字符数 ≈ 令牌数/4 只能作为粗略估算。
- 压缩和不活动状态会造成存储内容偏差。 按
active=1筛选消息:压缩后的行已被摘要替换,不活动行也不会再发送。已存储的活动内容仍是已发送内容的上限(截断已在捕获时应用)。实时内容与压缩内容的拆分可以解释为什么会话的数据库大小可能超过其上下文大小。 - 一次触发就可能远超其他所有项——计算平均值前,先在 cron 台账中查找最大的 prompt_tokens;一次数百万令牌的触发就可能隐藏在看似正常的均值中。
- Cron 台账中的 prompt_tokens 定义是按次触发统计的,且文档不充分——每次触发占一行,但一次 Agent 式触发会进行多次 API 调用,并在每次调用时重新发送上下文。将每次触发的平均令牌数视为实际 cron 输入量的下限;需要精确数据时,请与该次触发的会话行核对。
- 每次调用的平均值必须加权计算——使用 SUM(input)/SUM(calls),绝不要对每会话比率取 AVG;否则,一个 200 次调用的会话和一个 10,000 次调用的会话权重相同。
验证清单
- 脚本以只读方式运行,检查了每个相关的配置文件数据库(默认配置 + 所有启用的配置)
- 已核对总数,并说明归因偏差(按 last_seen 统计的任务行与按开始/活动时间统计的会话)
- 已将每个主要消耗项对应到预先核实的调节措施,或标记为“本地无可用调节措施”
- 已预先核实每项拟议的调节措施:键存在、当前值已实时读取、作用机制已确认
- 已回读验证应用后的更改(
hermes config get,重新解析 cron jobs.json) - 已备份旧提示词/配置,并记录备份路径
- 已安排 Delta 检查 cron,并在其提示词中写明基线和通过标准