← 返回信息流
Agent SkillLINUX DO · AI·1 小时前

Claude Desktop大量max_tokens=1请求的解决方案

原标题:关于claude desktop 出现大量max token =1 请求的解决办法

速览

Claude Desktop在使用ccswitch路由模式时,因刷新信息时count_tokens接口未正确透传,导致桌面端回退到max_tokens=1请求,占比超91%。通过修改forwarder.rs,对count_tokens端点进行特殊处理,避免媒体剥离和格式转换,从而解决该问题。

AI 深度解读

背景

Claude Desktop 在使用 ccswitch 路由模式时,出现了大量异常的 API 调用。每个请求中 max_tokens 参数都被设置为 1,而非正常的 2048 或 64000。通过数据统计,在一个样本 session(ID: c78005f4-b8a5-494b-abba-39d0c96d3841)的 194 条 /v1/messages 请求中,max_tokens=1 的请求占 91.24%(177 条),而 max_tokens=64000 仅占 8.25%,max_tokens=2048 占 0.52%。按输入 token 量计算,这些异常请求仅占 7.51% 的 token 消耗,但数量上却占绝大多数。

核心内容

问题原因

Claude Desktop 桌面端有一个“刷新上下文 token 数量”的功能。每次刷新时,客户端会向服务端发送请求获取当前会话的 token 计数。理想情况下,桌面端应该调用 /v1/messages/count_tokens 这个专用接口(由 Anthropic 提供的计数 API)。然而,ccswitch 路由模式默认没有透传 count_tokens 相关接口(如 /v1/messages/count_tokens),导致桌面端无法获取 token 计数,从而 fallback 到一种降级策略:发送 max_tokens=1 的普通 /v1/messages 请求,通过返回结果中的 token 信息来间接获取计数。

解决方案

核心思路是让 ccswitch 正确透传 count_tokens 请求,避免 fallback。具体做法是修改 ccswitch 源码,让路由代理识别并特殊处理 count_tokens 端点。作者提供了一个基于新版 ccswitch 的 patch,主要改动点如下:

  1. 识别 count_tokens 端点:新增 is_count_tokens_endpoint 函数,判断请求路径是否为 /v1/messages/count_tokens 及其变体(如 /claude/v1/messages/count_tokens/claude-desktop/v1/messages/count_tokens,或任何以 /messages/count_tokens 结尾的路径)。

  2. 透传 body 不做转换:当请求是 count_tokens 时,禁止对 body 进行任何格式转换(例如从 Anthropic 格式转为 OpenAI/Gemini 格式),也禁止执行媒体剥离(media prevention),因为计数请求的 body 结构本身就是用于计数的输入,不能改动。

  3. URL 改写:当用户配置的 baseURL 是完整 URL 且指向 /v1/messages 端点时(例如 https://api.anthropic.com/v1/messages),需要将 count_tokens 请求的 URL 改写为 .../v1/messages/count_tokens,避免将计数请求误发到 messages 端点。

  4. Provider 兼容性:patch 中提到,不同 Provider 的 CountTokens 实现方式不同,需要通过统一入口 /v1/messages/count_tokens 路由到各 Provider 的对应实现:

    • Claude:向上游发送 POST {baseURL}/v1/messages/count_tokens?beta=true,使用真 Anthropic 计数,处理 cache_control/beta/OAuth。
    • Gemini / Vertex / AI Studio:调用 models/{model}:countTokens
    • Antigravity:向上游发送真实请求,带 token 和 baseURL 回退。
    • xAI:本地用 cl100k 编码数 body,不消耗 grok 额度。
    • Codex:本地按模型选 tokenizer 估算,不打 ChatGPT 上游。
    • OpenAI-compat / Kimi:视实现,多为本地或兼容路径。

实现细节

patch 在 src-tauri/src/proxy/forwarder.rs 中增加了一系列逻辑:在请求处理流程的早期判断是否为 count_tokens 请求,如果是,则跳过后续的格式转换、媒体处理、thinking 改写等步骤,并确保 URL 正确转向 count_tokens 端点。同时,修改 pnpm-workspace.yaml 允许 esbuildmsw 的构建(可能为修复构建依赖)。

关键要点

  • 问题根源:Claude Desktop 的 token 计数刷新功能需要 count_tokens 接口,但 ccswitch 路由模式未透传该接口,导致桌面端 fallback 到 max_tokens=1 的普通请求。
  • 异常表现:大量 max_tokens=1 请求,占请求总数 91% 以上,虽然消耗 token 少,但增加不必要的网络负载和延迟。
  • 核心修复:在 ccswitch 代理中增加 count_tokens 端点识别,并保证透传 body 不做任何转换或媒体剥离。
  • 关键函数:is_count_tokens_endpoint 判断路径,rewrite_full_messages_url_to_count_tokens 将 full URL 改写为正确的计数端点。
  • 不同 Provider 的计数实现差异:部分 Provider 上游有真计数接口,部分需本地估算(如 xAI 用 cl100k,Codex 用本地 tokenizer)。
  • 修复后效果:Claude Desktop 能正常调用 count_tokens 接口获取 token 数,不再产生大量 max_tokens=1 的异常请求。

意义与影响

  • 性能优化:消除大量无用请求,减少网络流量和服务器压力,提升 Claude Desktop 的响应速度和稳定性。
  • 功能正确性:确保 token 计数的准确性,避免因 fallback 带来的计数偏差(例如媒体剥离后 token 计数系统性偏低),使对话上下文管理更可靠。
  • 架构设计启发:展示了代理路由在处理非标准 API 扩展时的常见陷阱——忽略客户端特有的诊断/辅助接口会导致 fallback 行为。正确的做法是完整透传所有标准端点,或明确映射到 provider 的对应实现。
  • 社区贡献:该 patch 为 ccswitch 项目的其他用户提供了可复用的修复方案,尤其对使用 Claude Desktop 配合第三方路由的用户有直接帮助。
  • 跨 Provider 兼容性:统一将 count_tokens 请求路由到各 Provider 的对应实现,使得 ccswitch 可以支持更多后端(Anthropic、Gemini、xAI、Codex 等),同时保持计数逻辑的一致性。
查看原文 →linux.do