☰
abtop上下文窗口计算原理:为什么cache_creation token会被重复计数,以及如何避免
2026/9/27 4:35:10 网站建设 项目流程

abtop上下文窗口计算原理:为什么cache_creation token会被重复计数,以及如何避免

【免费下载链接】abtopLike htop, but for AI coding agents. Monitor Claude Code & Codex CLI sessions, tokens, context window, rate limits, and ports in real-time.项目地址: https://gitcode.com/gh_mirrors/ab/abtop

abtop是一个面向 AI 编程智能体的实时监控系统,就像经典系统监控工具 htop 之于 CPU 和内存——它让你在一块屏幕上同时查看所有 Claude Code、Codex CLI 与 OpenCode 会话的 token 消耗、上下文窗口占用百分比、速率限制和开放端口。在它的 context 面板 中,上下文占用率只用input_tokens + cache_read_input_tokens来计算,刻意排除了 cache_creation。为什么这么做?如果天真地把三种 token 相加会发生什么?这篇指南带你彻底搞懂 abtop 上下文窗口的计算原理。

先认识 abtop:AI Agent 版的 htop

abtop 全程只读本地文件与进程状态,不需要 API 密钥,也不需要登录。启动后你会看到每个会话一行状态:模型版本、运行时长、上下文百分比、token 速率,以及每个会话独立的上下文窗口进度条。

要理解上下文计算原理,先要知道 abtop 的数据来自哪里。对 Claude Code 而言,每个会话都会把完整对话记录追加写入一个 JSONL 转录文件(格式见 AGENTS.md)。每条assistant消息里都带着一段usage统计:

字段含义
input_tokens本轮未命中缓存、按全价重新发送的输入 token
output_tokens本轮模型生成的输出 token
cache_read_input_tokens本轮命中提示缓存、直接读出的输入 token
cache_creation_input_tokens本轮新写入提示缓存的输入 token

提示缓存(prompt caching)是 Anthropic 的计费与加速机制:把冗长的系统提示、工具定义和历史对话缓存起来,下一轮直接读取,既快又省钱。上面四个字段就是 abtop 计算上下文的全部原料。

abtop 上下文窗口占用的计算公式

abtop 的核心规则只有一句话:上下文 = 最近一条 assistant 消息的 input_tokens + cache_read_input_tokens。

对应的源码在 src/collector/claude.rs:

// Context = input_tokens + cache_read (excludes cache_creation, #54) let current_context = if cr == 0 && cc > 0 { inp + cc } else { inp + cr }; result.last_context_tokens = current_context;

得到last_context_tokens后,再除以该模型的上下文窗口上限,就得到面板上那根百分比进度条:

  • 窗口上限由 context_window_for_model() 决定:默认200K;当模型名带[1m]标记或实测上下文已超过 200K 时,自动切换为1M;
  • context_percent = last_context_tokens / context_window × 100,超过 75% 会显示!、超过 90% 显示⚠警告(渲染逻辑在 src/ui/context.rs)。

为什么 cache_creation 会被"重复计数"

这是整篇文章的关键问题。先看一个正常轮次的 token 分布:

input_tokens = 2 ← 少量新增内容 cache_read_input_tokens = 11313 ← 大部分历史走缓存命中 cache_creation_input_tokens = 4350 ← 本轮新内容写入缓存

直觉上,"上下文总大小"似乎应该是三者之和。但项目维护文档 AGENTS.md 明确指出:

在compaction(上下文压缩)轮次中,同一批 token 会同时被报告为cache_creation和cache_read——旧缓存被作废旧重写,写入了新的缓存条目,同时新前缀又被命中。三项相加,这批 token 就被计了两次。

这正是 abtop 历史上 issue #54 的根源:如果简单相加,一次压缩之后上下文占用率会瞬间虚高,甚至"突破"窗口上限,你会误以为会话要爆了,其实真实占用根本没变。所以 abtop 选择只信input + cache_read这个口径——它也与 Claude Code 自带的 statusline 显示保持一致(参考 scripts/abtop-statusline.sh)。

特例:新会话为什么又要加 cache_creation?

如果永远排除 cache_creation,会漏掉另一种场景。

会话刚开始时,还没有任何缓存可命中,第一条 assistant 消息的报告通常是:cache_read = 0,而cache_creation很大(整个初始提示正在被写入缓存)。此时真正代表"当前上下文大小"的就是input_tokens + cache_creation_input_tokens,若仍按input + cache_read算,会读出接近 0% 的假象。

所以源码里那个if就是干这个的:当cache_read == 0且cache_creation > 0时,改用input + cache_creation(相关测试见 test_parse_transcript_fresh_session_uses_cache_creation_for_context)。

一句话总结这套口径:

场景缓存状态上下文取法
常规轮次有缓存命中input + cache_read
压缩轮次同一批 token 双份上报input + cache_read(不能加 cache_creation)
新会话首轮无缓存、正在写缓存input + cache_creation

如何避免重复计数:4 条实用建议

✅自己写状态行/监控时,坚持input + cache_read口径。这是与 Claude Code 官方 statusline 对齐的做法,天然免疫压缩轮次的双份上报。

✅用"断崖式下跌"识别 compaction,而不是绝对值。abtop 的判断条件是:上下文相比上一轮骤降超过 30%,且cache_read相比上轮跌至原来的 1/5 以下(旧缓存被整体作废)。单看某一项波动都可能误报,两个条件同时成立才算一次真正的压缩(检测逻辑在 src/collector/claude.rs)。压缩次数会显示在上下文栏的C2这类标记里。

✅区分"缓存命中波动"和"真实上下文变化"。普通对话中缓存命中率自然起伏,总上下文量会有正常抖动;只要没有断崖式下跌,就不该当作窗口将满的信号。

✅留意窗口上限会动态变化。同一模型在[1m]配置下上限是 1M 而非 200K,固定写死 200K 会在新会话里算出虚高的百分比。abtop 的做法是同时参考转录中的模型名与实测最大值,自动选择上限。

小结

  • abtop 的上下文占用 =input_tokens + cache_read_input_tokens÷ 模型窗口上限,cache_creation 默认不计入;
  • 重复计数发生在 compaction 轮次:同一批 token 被同时报成cache_creation与cache_read,三项相加即虚高(#54);
  • 唯一例外是新会话首轮cache_read = 0的场景,此时cache_creation才代表真实上下文大小;
  • 记住"两项之和 + 一个例外",你就能在任何 AI Agent 监控工具里算出不会骗人的上下文窗口占用。

【免费下载链接】abtopLike htop, but for AI coding agents. Monitor Claude Code & Codex CLI sessions, tokens, context window, rate limits, and ports in real-time.项目地址: https://gitcode.com/gh_mirrors/ab/abtop

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询