思维标记(Thinking Tokens)在你的日志中隐身,但在账单上却震耳欲聋
第一个注意到你推理模型回退的人,几乎永远不会是工程团队的成员。而是财务分析师,在周二下午联系你的经理,因为上个月的 Anthropic 账单比前一个月高了 2.4 倍,而且“我们并没有发布任何会导致这种结果的东西”。你打开仪表板,查看请求量——平稳。p99 延迟——平稳。每个响应的输出标记——平稳。错误率——平稳。你六个月前配置的每一个面板都显示系统运行健康。财务人员看的是另一个数字,而且他们是对的。
他们看的数字是推理标记(reasoning tokens),而大多数可观测性栈是在这个领域出现之前构建的。
当推理模型回答问题时,它向你计费的输出包含两部分:最终出现在应用程序响应字段中的可见响应,以及在生成该响应之前运行的思维链(chain-of-thought)。在 Claude 的扩展思维 API 上,该思维链出现在一个单独的 thinking 内容块中;在 OpenAI 的 Responses API 上,它被隐藏在 usage.output_tokens_details.reasoning_tokens 下。两者的计费标准与输出标记相同。如果你的日志 记录器只是读取 choices[0].message.content 并计算字符数,这两者都不会显示出来。
你记录的内容与你支付的费用之间的差距,就是惊喜所在。在开启扩展思维的情况下,对 Claude Opus 的复杂查询在发出 500 个可见标记之前,可能会消耗 20,000 到 40,000 个推理标记。按照 Opus 4.7 每百万标记 25 美元的输出费率计算,每次调用会有 0.5 到 1 美元的隐形成本。再乘以流量。你的仪表板报告与账单上显示的数字之间存在数量级的差异,这并不是计费系统错误——而是你的埋点(instrumentation)抓取了错误的字段。
为什么大多数可观测性栈都遗漏了它
这种差距之所以存在,是有历史原因的。当团队在 2023 年和 2024 年对其首次 LLM 调用进行埋点时,输出标记意味着一件事:响应体中返回的标记。心理模型——“输入进去,输出回来,两者都算”——与 API 返回的内容相匹配。OpenAI 的 usage 对象有 completion_tokens,Anthropic 的 usage 对象有 output_tokens,这就是全部的故事。
推理模型打破了这个模型。当 OpenAI 发布 o 系列,Anthropic 发布扩展思维时,两家供应商都增加了一个新的子字段——OpenAI 的 reasoning_tokens,Claude 的 thinking 内容块——并悄悄地将这些标记计入输出标记总数以进行计费。总计费输出是可见输出加上推理标记的总和。你的日志记录器使用了两年的可见输出字段仍然有效,仍然能读取,仍然会产生一个数字——但那 个数字不再是你账单上的数字。
OpenTelemetry GenAI 语义约定已经跟进了。现在有一个定义的属性 gen_ai.usage.reasoning.output_tokens,它映射到 usage.output_tokens_details.reasoning_tokens。opentelemetry-instrumentation-openai-v2 包会发出这个属性。大多数供应商提供的 Python 和 TypeScript SDK 也都公开了它。数据就在那里。大多数生产技术栈中缺失的是连接——必须有人编写一行埋点代码,从响应中提取出 reasoning_tokens 并将其附加到与 input_tokens 和 output_tokens 相同的 span 上。在此之前,span 看起来是完整的,仪表板看起来是健康的,而回退就隐藏在差距之中。
让财务部门措手不及的三种失败模式
这种模式重复出现的频率很高,值得为它们命名。团队被推理标记支出打得措手不及有三种截然不同的方式,每一种都需要不同的防御措施。
第一种是隐性提示词回退。工程师调整系统提示词——添加新指令、更改响应格式、收紧 schema。可见的输出标记没有变化。延迟几乎没有差别。但这一改变恰好诱导模型进入了更长的推理链,每次调用的思考标记从 1,800 增加到了 5,400。评估分数看起来不错,可见输出仪表板看起来也没问题,但单次调用的成本却翻了三倍。更改被合并了。财务部门在 30 天后发现了。
第二种是模型迁移悬崖。你的团队从非推理模型升级到推理模型——例如从 Sonnet 升级到开启思维功能的 Opus,或者从 GPT-4o 升级到推理强度设置为中等的 GPT-5。迁移测试计划检查正确性、延迟和可见输出长度。它不会检查思考标记的消耗,因为之前的模型根本没有这个概念。你在周五发布了升级。到下周一,原本团队预算只增加了 1.5 倍的工作负载,单次调用的支出实际上却增加了 8 倍。
第三种是智能体循环爆炸。一个智能体进行了五轮工具调用。每一轮都调用一个推理模型。每一轮调用的推理标记单独看并不多——也许每轮 1,200 个标记——但前一轮的推理内容会被重新追加到下一轮的上下文中。到第五轮时,你正在为“推理的推理”付费。一个看起来像是“五次小调用”的工作流,实际上是一次调用的输入量加上二次方累积的思考量。账单令人震惊;而对各轮次取平均值的单次调用仪表板,则掩盖了这种趋势。
- https://platform.claude.com/docs/en/build-with-claude/extended-thinking
- https://developers.openai.com/api/docs/guides/reasoning
- https://openrouter.ai/docs/guides/best-practices/reasoning-tokens
- https://opentelemetry.io/docs/specs/semconv/gen-ai/openai/
- https://opentelemetry.io/blog/2024/otel-generative-ai/
- https://www.traceloop.com/blog/granular-llm-monitoring-for-tracking-token-usage-and-latency-per-user-and-feature
- https://langfuse.com/docs/observability/features/token-and-cost-tracking
- https://uptrace.dev/blog/opentelemetry-ai-systems
- https://openreview.net/forum?id=Epd2N9b76r
