隐藏的 Token 税:开销如何悄然榨干你的 LLM 上下文窗口
大多数团队都知道自己的用户发送了多少个 Token。但几乎没人知道,在用户开口说话之前,他们已经花掉了多少个 Token。
在一个典型的生产级 LLM 流水线中,系统提示词(system prompt)、工具 Schema、聊天历史、安全前导词和 RAG 前置上下文会在真正的用户请求到达之前,悄无声息地消耗掉你 30-60% 的上下文窗口。对于注册了几十个工具的 Agent 系统而言,仅工具定义的开销就可能占据一个 128k 窗口的 45% —— 大约 55,000 个 Token —— 而其中许多工具可能永远不会被调用。
这就是隐藏的 Token 税:它抬高了成本,拉长了延迟,削弱了模型的注意力 —— 而所有这些在任何面向用户的指标中都看不到。
一次被征税请求的解剖
要看清这种税的实际影响,不妨设想一下:当用户发送"我今天有哪些会议?"时会发 生什么。下面是和那个 8 个 Token 的查询一起发出去的真实内容:
- 系统提示词(行为规则、人设、护栏):1,500-3,000 Token
- 工具/函数定义(名称、描述、参数 Schema):5,000-55,000 Token
- 聊天历史(对话上下文中的前几轮):2,000-10,000 Token
- RAG 上下文(检索到的文档或知识库片段):1,000-5,000 Token
- 安全前导词和输出格式说明:500-1,000 Token
- 真正的用户消息:8 Token
这就是说,为一个 8 Token 的问题,你付出了超过 10,000 Token 的开销 —— 在大型工具注册表下,这个数字轻易就能突破 60,000。每一个 Token 都按输入费率计费,同时也在争抢模型有限的注意力预算。
多轮对话会让问题雪上加霜。一段 20 轮的对话会累积 5,000-10,000 Token 的历史,但通常只有最近的 500-1,000 Token 是相关的。大多数实现都会天真地在每次调用时附带完整的对话记录,于是每一轮都在为整个历史付费。
工具 Schema:最大的静默元凶
函数调用(function calling)已经成为 Agent 式 AI 的骨干,而工具定义则是最大单一的隐性 Token 开销来源。每个定义都承载着惊人的成本:
- 工具名称:5-10 Token
- 描述:50-150 Token
- 参数 Schema(类型、必填字段):100-300 Token
- 字段描述和约束:50-200 Token
- 用于可靠调用的 few-shot 示 例:200-500 Token
加起来就是 每个工具 550-1,400 Token。一个稍具规模的集成 —— 例如 GitHub、Slack 和一套监控组件 —— 就能轻松注册 50 个以上的工具。对接多个 MCP 服务器的真实 Agent 的实测数据显示了这种规模:
- GitHub(35 个工具):约 26,000 Token
- Slack(11 个工具):约 21,000 Token
- 可观测性工具:约 8,000 Token
也就是说,在开发者还没敲下第一个字符之前,一个标准的 128k 上下文窗口就已经被吃掉了 45%。无论这些工具最终是否被调用,所有 Token 都照单收费 —— 一个简单的"总结这份文档"请求,也要为每一个注册的工具 Schema 缴全额的税。
调用时成本会进一步叠加。完整的函数集合会同时附加在原始请求和响应提交上,所以 Schema 库每次工具调用会被"拖带"两次。更糟的是,工具选择的准确率会随着注册工具数量的增加而急剧下降:
- 5-10 个工具:选择准确率超过 90%
- 50 个以上工具:降至约 49% —— 已经接近抛硬币的水平
Token 更多,效果反而更差。
链式调用中的复利问题
Token 税不只影响单次调用 —— 它会在整条流水线中成倍放大。一个由三次 LLM 调用串联(意图分类、数据库查询、响应格式化)构成的 Agent 式工作流,如果每次调用都附带 20,000 Token 的开销,那么光是结构性开销就要烧掉 60,000 Token,而最终的答案可能只有 200 个 Token。
这种复利效应在 Agent 循环中尤其残酷。一个用 10 步才能完成任务的 Agent,如果每一步都携带完整的系统提示词和工具定义,那么仅仅在开销上就可能烧掉 200,000-500,000 Token。按 0.60-$1.50 —— 还没算上那些真正干活的 Token。
放到企业级规模下,这些数字就变得无法忽视。一个每天处理 10,000 个工单、注册了 40 个工具、平均对话轮次为 5 轮的客户支持系统,面临着一个非常尴尬的选择:
- 朴素实现:约 20 亿 Token/天 → 每年 219 万美元
- 优化实现:约 7,000 万 Token/天 → 每年 76,650 美元
仅仅是结构性开销上的差异,就是 30 倍的成本落差。
审计你的 Token 预算
在动手优化之前,你需要先具备可观测性。大多数团队都是在实现了细粒度的追踪之后,才发现自己的 Token 浪费有多严重。下面是审计流水线的方法:
- 测量你的开销占比。 对每一次 API 调用,计算一下输入 Token 中来自结构性开销的比例与来自用户内容的比例。如果开销持续超过 50%,那你就有一块很大的优化空间。
- 按组件剖析。 将 Token 消耗拆分为系统提示词、工具定义、聊天历史、RAG 上下文和用户内容。在大多数系统里,工具 Schema 和聊天历史都是排名前二的元凶。
- 跨流水线追踪。 如果你串起了多次 LLM 调用,要端到端地度量总 Token 消耗。一次单独看起来很高效的调用,放到 10 步的 Agent 循环里乘一下,可能就会变得惨不忍睹。
- 监控输出 Token 的浪费。 输出 Token 通常比输入 Token 贵 4-5 倍。如果你的模型在 100 Token 就足够的场景下动辄吐出 500 Token 的回复,那就是在更贵的那种 Token 上被乘了 5 倍。
削减税负的六种策略
有了度量数据之后,这里 是一些杠杆率最高的优化手段,大致按影响力排序:
动态工具选择。 不要在每次调用时注册全部工具,而是只挑与当前查询相关的那一小部分。一个轻量分类器或基于 embedding 的过滤器挑出 3-5 个最可能需要的工具,只让这些定义随请求一同发送。单这一项就能将工具相关的开销削减 85%,同时还能真正提升准确率 —— 一项基准测试显示,把工具数从 50+ 过滤到 5 个后,工具选择准确率从 49% 跃升到 74%。
提示词压缩。 毫不留情地审视你的系统提示词。大多数提示词都是自然生长出来的 —— 每一个边界情况、bug 修复和新功能都会追加一段。一段 3,000 Token 的提示词通常可以压缩到 1,000 Token,而不损失行为保真度。删除冗长的示例,使用简洁的指令句法,合并重复的约束。
对话历史管理。 不要直接拼接完整聊天历史,而要实现滑动窗口或基于摘要的压缩。把较早的轮次压缩成一块紧凑的上下文,只保留最近的 2-3 轮原文。一段消耗 10,000 Token 的 20 轮对话可以压缩到 1,500 Token,而质量几乎不受影响。
提示词缓存(prompt caching)。 目前大多数 LLM 供应商都已支持提示词缓存 —— 存储并复用静态提示词前缀的计算表示。因为你的系统提示词和工具定义在每次调用中都是一样的,缓存可以避免每次请求都重新处理它们。这不会减少你的 Token 数量,但能把缓存部分的延迟降低多达 85%,成本降低多达 90%。
语义缓存(semantic caching)。 对于高流量、查询重复度高的系统,可以按语义相似度为键缓存 LLM 响应。如果"今天天气怎么样?"和"现在外面的天气如何?"会得到相同的回答,那就直接服务缓存版本。在高重复度工作负载上,这种方 法可以带来高达 73% 的节省。
模型路由。 并不是每一次调用都需要用你最贵的模型。把简单的分类、抽取或格式化任务路由到更小、更便宜的模型,把旗舰模型留给复杂推理。
为什么 Token 税伤害的不只是成本,还有质量
Token 税不仅昂贵 —— 它还会因为吃掉模型有限的注意力预算,而实实在在地降低输出质量。
LLM 通过注意力机制处理上下文,其中每个 Token 都要对所有其他 Token 进行 attend。上下文越长,模型的注意力就越被分散。研究一致表明,模型在上下文的开头和结尾检索信息的能力最强 —— 而埋在中间的信息,准确率会下降超过 30%。
当 55,000 Token 的工具定义卡在你的系统提示词和用户真正的问题之间时,你其实是在把用户的内容推到低注意力区。模型会字面意义上地"更少关注"那个最重要的东西 —— 用户的请求 —— 因为它正在把注意力预算花在用户并没有问及的那些服务的工具 Schema 上。
这就是为什么动态工具选择不仅是成本优化,更是质量优化。更少的无关 Token 意味着更多的注意力被分配给真正重要的 Token。
构建一种"Token 意识"架构
最有效的长期方案,并不是优化每一次单独的调用 —— 而是把 Token 经济学作为一等公民纳入你的架构设计,就像你会为 CPU 或内存预算做设计那样。
把 Token 当作被管理的资源。 按请求、按用户、按功能追踪消耗。像为数据库查询或 API 速率限制设预算和告警一样,也为 Token 设预算和告警。实现细粒度追踪的团队通常会发现,他们 20-50% 的花销并没有带来多少业务价值。
为最小化上下文而设计。 上下文窗口里的每一份信息都应该挣得它的位置。在把任何东西塞进去之前,先问一下:
- 这段系统提示词真的会改变模型行为吗?
- 这个工具定义被使用的频率是否超过 1%?
- 这一轮聊天历史对当前查询还重要吗?
如果答案是否,那它就是税。
像管理基础设施一样管理和测试提示词。 系统提示词应当是有版本、有可度量性能特征的工件,而不是可以无限生长的 Wiki 页面。当你为处理某个边缘情况增加一段时,要去度量它是否真的改变了结果。如果没有,那它就是纯粹的开销。
从一个接口开始
隐藏的 Token 税从不会造成可见的故障。你的系统依然能工作,只是更慢、更贵、也略差一些而已。在生产规模下,"略差一点"乘上数以百万计的请求,就会成为一款可持续的 AI 产品和一款在静默失血的产品之间的分水岭。
挑选你流量最高的那个接口。测量它的开销占比。那个数字会让你吃惊,而这份吃惊就是你开始动刀所需的撬动力。
- https://www.gentoro.com/blog/contextual-function-calling-reducing-hidden-costs-in-function-calling-systems
- https://www.mmntm.net/articles/mcp-context-tax
- https://redis.io/blog/llm-token-optimization-speed-up-apps/
- https://dakora.io/blog/the-hidden-30-how-prompt-optimization-cuts-your-llm-costs-for-real
- https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
- https://dev.to/whoffagents/llm-context-windows-managing-tokens-in-production-ai-apps-11l
