Conversational Flow golden use case improvements – Anthropic total_tokens omits cache read/write tokens, undercounting cost

使用 CrewAI 的 Anthropic 原生 provider 时, total_tokens 只计算 input_tokens + output_tokens ,遗漏了 cache_read_input_tokens 和 cache_creation_input_tokens ,导致任何启用

快速结论:使用 CrewAI 的 Anthropic 原生 provider 时,total_tokens 只计算 input_tokens + output_tokens,遗漏了 cache_read_input_tokenscache_creation_input_tokens,导致任何启用 prompt cache 的请求在成本核算时严重低估。优先排查是否有代码依赖 total_tokens 做费用计算。

适用环境:crewai 1.15.10,Python 3.12,macOS(Darwin 25.1),Anthropic 原生 provider 路径(非 LiteLLM)。

最快修复方案:暂无确认的一步修复方案。Issue 中未提供已验证的 CrewAI 内修复补丁;用户侧可行做法是自行封装 Anthropic SDK 或直接使用 Anthropic 原始 usage 数据来计算费用。

注意事项:cache write 按输入价格 1.25 倍计费,cache read 按 0.1 倍计费,直接加总原始 token 数仍无法精确计算美元成本;流式响应中 cache 计数器可能只在最终 chunk 出现,需确认聚合逻辑已处理。

问题场景

用户在使用 CrewAI 构建会话式 Flow 应用时,基于 llm_call_completed 事件或 llm._token_usage 统计每次会话成本。由于 Anthropic 的 prompt cache 命中后,total_tokens 远低于实际计费 token 数,导致成本核算严重偏低。

复现步骤:先发送一个足够大且带 cache_breakpoint 的 system prompt,第二次调用相同 prompt 触发 cache read;随后对比 total_tokens 与四个计数器之和。

报错原文

call 1: reported total_tokens=   17 | prompt=   13 completion=   4 cache_write= 4509 cache_read=    0 -> actually billed=4526
call 2: reported total_tokens=   34 | prompt=   26 completion=   8 cache_write= 4509 cache_read= 4509 -> actually billed=9052

"usage": {
  "input_tokens": 2,
  "total_tokens": 42,
  "output_tokens": 40,
  "cached_prompt_tokens": 0,
  "cache_creation_tokens": 2285
}

原因分析

定位到 crewai/llms/providers/anthropic/completion.py 大约 L1971 处:

cache_read_tokens = getattr(usage, "cache_read_input_tokens", 0) or 0
cache_creation_tokens = (
    getattr(usage, "cache_creation_input_tokens", 0) or 0
)
result: dict[str, Any] = {
    "input_tokens": input_tokens,
    "output_tokens": output_tokens,
    "total_tokens": input_tokens + output_tokens,   # <-- omits both cache counters
    "cached_prompt_tokens": cache_read_tokens,
    "cache_creation_tokens": cache_creation_tokens,
}

两个 cache 计数器已正确捕获并单独输出,但未计入 total_tokens。可能原因是 CrewAI 沿用了 Anthropic SDK 原生定义(total_tokens = input + output),未考虑 cache 计费口径。另一个可能原因是 total_tokens 的语义本身不明确——部分调用方将其理解为“发送给模型的 token 数”,部分理解为“计费 token 数”。

环境排查

  • 确认 crewai 版本是否为 1.15.10 或其他受影响版本;可检查 crewai/llms/providers/anthropic/completion.py 中的 total_tokens 计算逻辑。
  • 确认是否走 Anthropic 原生 provider 路径(非 LiteLLM),因为不同 provider 实现可能不同。
  • 确认使用流式响应时,缓存计数器是否只在最终 chunk 返回;需检查日志聚合逻辑是否正确合并所有 chunk 的 usage 数据。
  • 确认是否开启 prompt caching(即 system prompt 中是否设置 cache_breakpoint)。

解决步骤

  1. 临时绕过:如果只用于成本核算,可自行包装 Anthropic SDK 或直接调用 Anthropic 原始 API,从 usage 对象中读取 cache_read_input_tokenscache_creation_input_tokens,按权重计算实际费用(cache write ×1.25,cache read ×0.1)。
  2. 如果必须继续使用 CrewAI,从 llm._token_usagellm_call_completed 事件中读取四个独立计数器(prompt_tokenscompletion_tokenscached_prompt_tokenscache_creation_tokens),自行加权求和,不依赖 total_tokens
  3. 可优先尝试:检查 CrewAI 是否有后续版本修复此问题(Issue 标注了 OSS-114 内部跟踪),升级到最新版 crewai 后重新验证 total_tokens 是否包含 cache 计数。
  4. 如果希望 CrewAI 官方修复时保留向后兼容,可在 Issue 中表达期望新增 billed_tokenscost_tokens 字段,而不是改变 total_tokens 现有语义。

验证方法

用同一 prompt 调用两次:第一次产生 cache write,第二次产生 cache read。对比 total_tokensprompt_tokens + completion_tokens + cached_prompt_tokens + cache_creation_tokens 四者之和。如果两者一致,说明修复生效;如果 total_tokens 仍只等于 input + output,则问题仍存在。测试时注意计数器是累积的,需按调用次数分别记录。

参考来源

crewAIInc/crewAI #6768

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 19203

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注