Damn AgentBeta

Token 与上下文窗口

Token 计量、上下文窗口、成本估算,以及 Agent 系统中的压缩与预算策略。

上下文窗口是 Agent 系统最常碰到的硬约束。它不是“尽量多塞一点历史”,而是要在目标、证据、工具结果和推理链之间做预算分配。

Token 是什么

Token 是模型处理文本的最小单位,不等于“一个字”或“一个单词”。英文常按子词切分,中文通常一个字或一个词片段对应一个或多个 Token。同一段内容在不同模型、不同分词器下的 Token 数可能不同。

工程上应遵守三条规则:

  1. 不要凭直觉估长度,用 provider 的 tokenizer 或官方计数 API。
  2. 工具结果往往比用户输入更长,读文件、跑测试、抓网页都会快速吃掉预算。
  3. 系统提示、工具定义、历史消息都占窗口,不是只有用户说的话算 Token。

上下文窗口的分工

区域典型内容管理要点
系统层角色、规则、安全边界、输出格式保持稳定,避免频繁变动导致缓存失效
任务层当前目标、约束、计划、待办随任务阶段更新,必要时单独摘要
证据层文件片段、检索结果、工具输出截断、引用、分层加载,不要整包灌入
历史层过往对话、决策、失败记录压缩、选择性回放、结构化存档
预留层模型回复和下一轮工具参数为输出和 tool call 留出安全边际

《Claude Code Harness Engineering》指出,活跃编码 Agent 每轮可能消耗数千 Token,复杂重构会很快逼近上限,因此需要压缩、记忆和缓存协同工作。来源:《Claude Code Harness Engineering:从入门到实战》,pp. 88-95。

成本与性能

Token 同时影响延迟

  • 输入 Token 越多,首 Token 延迟通常越高。
  • 输出 Token 越多,总耗时和费用越高。
  • 工具定义如果冗长且不稳定,会重复消耗预算并破坏提示缓存。

Agent 产品应至少记录:

  • 每轮 input_tokensoutput_tokenscached_tokens(如果 provider 支持)。
  • 工具调用前后的窗口占用变化。
  • 压缩或截断发生时的触发原因。

常见预算策略

  1. 分层加载:先给目录、签名、摘要,确认需要后再读全文。
  2. 结果截断:工具输出设最大字符或最大 Token,保留头尾和错误信息。
  3. 摘要压缩:长会话折叠成结构化状态,而不是原文堆叠。
  4. 引用而非复制:用文件路径、行号、chunk id 指向证据,减少重复文本。
  5. 工具定义瘦身:描述清楚即可,避免把教程塞进 schema。

估算上下文预算

实际项目里不需要手算每个 token,但需要在设计阶段保留预算意识。一个简化估算方式是:

预算项示例内容设计建议
固定开销system prompt、developer instructions、工具 schema尽量稳定,避免每轮重复塞大段说明
会话状态计划、已完成步骤、失败记录、用户偏好用结构化摘要替代完整聊天历史
当前证据文件片段、检索结果、日志、网页按相关性分层加载,并保留来源定位
输出预留模型回答、tool arguments、解释文本任务开始前预留,不要把输入塞满

如果上下文窗口是 window,输入最好不要长期逼近 window。Agent 还需要为模型输出、工具调用参数、错误重试和压缩摘要留出空间。

压缩不是总结一段话

上下文压缩应该保留任务继续执行所需的状态,而不是把历史对话压成文学摘要。常见压缩结构可以是:

目标:
- 当前要完成的可验证结果。

已完成:
- 文件、命令、决策和证据链接。

未完成:
- 下一步动作、阻塞点、风险。

约束:
- 用户明确要求、禁止事项、格式要求。

可丢弃:
- 已经验证无关的尝试、重复日志、过长原文。

这样压缩后的内容可以被下一轮 Agent 直接接手;单纯写“我们讨论了很多上下文工程问题”没有工程价值。

失败模式

现象常见原因系统层应对
模型“忘记”早期约束窗口被历史挤占把关键约束提升到系统层或任务摘要
工具结果丢失细节过度截断分级截断,保留错误栈和关键字段
成本突然飙升大文件反复注入去重、缓存读取结果、限制重试
回答变短或变敷衍接近窗口上限主动压缩或拆分子任务

可观测指标

生产系统至少要记录这些上下文指标:

  • input_tokensoutput_tokenscached_tokens 和总费用。
  • 每个工具返回被截断前后的长度。
  • 压缩触发时间、压缩前后 token 数、压缩摘要版本。
  • 任务成功率与上下文占用的关系,尤其是长任务尾部失败。
  • 因窗口不足导致的重试、降级、人工接管次数。

这些指标能帮助你判断问题是“模型不够强”,还是上下文装配策略把模型逼到了错误状态。

与 Agent 设计的关系

记忆不是“把所有东西塞进 prompt”。记忆是原材料,上下文工程是装配方式。详见 工具调用与记忆上下文工程

检查清单

  • 是否给输出和工具参数预留了 token,而不是把输入填满。
  • 是否对大文件、大日志和网页结果做了截断策略。
  • 是否能从 trace 里看见哪一轮触发了压缩。
  • 是否区分长期记忆、会话摘要和当前证据。
  • 是否在成本异常时能定位到具体工具或上下文层。

延伸阅读

参考来源

On this page