🚀深挖50万行源码:Claude Code上下文管理对中文的支持到底差在哪?Token 估算的致命偏差
Claude Code 是 Anthropic 推出的 AI 编程 CLI 工具,堪称当前最强的 AI 编程助手之一。它的源码规模惊人——约 1,900 个文件、512,000+ 行 TypeScript 代码。
今天我对这份源码进行了深度分析,专注于一个很少有人关注的问题:Claude Code 的上下文管理和记忆系统,对英文和中文的支持程度是否一样?
结论先行:英文是原生优化的一等公民,中文存在系统性偏差。
一、核心问题:Token 估算的致命偏差
整个上下文管理系统的决策基础是一个叫 roughTokenCountEstimation() 的函数,源码位于 src/services/tokenEstimation.ts 第 203-208 行:
export function roughTokenCountEstimation(
content: string,
bytesPerToken: number = 4,
): number {
return Math.round(content.length / bytesPerToken)
}
逻辑很简单:用 JavaScript 的 string.length(UTF-16 code unit 数量)除以 4 来估算 token 数。
这个假设完全是为英文设计的。
在英文中,1 个 token 大约对应 4 个字符,所以 string.length / 4 是一个合理的近似。但在中文里:
| 文本 | string.length | 估算 tokens | 实际 tokens | 偏差 |
|---|---|---|---|---|
| “hello world” | 11 | ~3 | ~2 | 1.5x 高估(安全) |
| “你好世界” | 4 | 1 | 4-6 | 4-6x 低估(危险) |
| 400字中文段落 | 400 | 100 | 400-800 | 4-8x 低估 |
每个中文字在 JavaScript 里只占 1 个 string.length 单位,但在 Claude 的 BPE 分词器中通常需要 1-2 个 token。 除以 4 之后,中文的 token 数被低估了 4 到 8 倍。
更关键的是,代码中完全没有语言感知的调整——唯一存在的调整是针对 JSON 文件类型(bytesPerToken = 2),而不是针对语言。
二、连锁反应:Auto-Compact 触发失效
这个 token 低估不是孤立的问题,它直接影响了上下文自动压缩(auto-compact)的触发时机。
Claude Code 的 auto-compact 触发逻辑定义在 src/services/compact/autoCompact.ts:
- 触发阈值:当前 token 数 >
effectiveContextWindow - 13,000 - 当前 token 数的计算依赖
tokenCountWithEstimation(),而这个函数底层就是roughTokenCountEstimation()
英文对话: 估算值接近真实值,auto-compact 在上下文窗口用到 ~93% 时准时触发,平稳压缩。
中文对话: 估算值只有真实值的 12.5%-25%。系统认为上下文才用了 25%,实际已经 100% 满了。结果是 auto-compact 永远触发不了,直到 API 返回 413 Prompt Too Long 错误,才由反应式压缩(reactive compact)兜底。
这意味着中文用户会经历更多的”上下文突然中断”,而英文用户几乎不会遇到这个问题。
三、压缩总结:英文提示 + 中文内容 = 语言混杂
当上下文压缩确实被触发后(无论是主动还是被动),系统会调用一个 LLM 来生成结构化摘要。
摘要提示词定义在 src/services/compact/prompt.ts,包含 9 个英文结构化节:
- Primary Request and Intent
- Key Technical Concepts
- Files and Code Sections
- Errors and fixes
- Problem Solving
- All user messages
- Pending Tasks
- Current Work
- Optional Next Step
没有中文变体,没有语言适配指令。
虽然系统提示中有一条 "Always respond in {language}" 指令会传递给压缩子代理,但压缩专用提示本身完全是英文的。这导致:
- 英文对话 → 英文提示 + 英文内容 = 完美一致
- 中文对话 → 英文提示 + 中文内容 = 模型可能产生中英混杂的摘要
此外,摘要的最大输出限制是 20,000 tokens。由于中文字符的 token 密度更高(每个字 1-2 tokens vs 英文每个词 1 token),同样 20K tokens 的预算下,中文摘要能承载的信息量更少。
四、记忆系统:跨语言匹配的隐性降级
Claude Code 有一个精巧的记忆系统(src/memdir/),能从最多 200 个记忆文件中选出 5 个最相关的,注入到当前对话上下文。
选择器使用 Sonnet 模型,接收用户查询和记忆文件清单(文件名 + 描述),返回最匹配的文件名。
关键点:选择器的系统提示是纯英文的。
"You are selecting memories that will be useful to Claude Code
as it processes a user's query..."
当英文用户查询 “Fix the auth middleware” 匹配英文描述 “Auth middleware gotchas” 时,这是直接的关键词对应。
当中文用户查询 “修复认证中间件的问题” 匹配同一个英文描述时,Sonnet 需要做跨语言语义推理——”认证” ↔ “auth”,”中间件” ↔ “middleware”。虽然现代 LLM 有很好的多语言理解能力,但跨语言匹配的精度和可靠性不可避免地低于同语言匹配。
五、语音输入:中文完全缺席
这是最直观的差距。
src/hooks/useVoice.ts 中定义了 16 种支持的 STT(语音转文字)语言:
en, es, fr, ja, de, pt, it, ko, hi, id, ru, pl, tr, nl, uk, el, cs, da, sv, no
日语和韩语都有,唯独没有中文(zh)。
作为全球使用人数最多的语言之一,中文在语音输入中的缺席是一个明显的功能空白。
六、唯一的亮点:终端渲染
公平地说,Claude Code 在终端显示层面对中文的支持是合格的。
src/ink/stringWidth.ts 使用了 east-asian-width 库和 Intl.Segmenter 进行字素分割,CJK 全角字符被正确地视为宽度 2。这意味着中文文本在终端界面中的布局和换行是准确的。
但终端渲染只是”展示层”,它不影响上下文管理的核心决策。
七、全维度评分
| 维度 | English | 中文 | 差距等级 |
|---|---|---|---|
| Token 估算准确度 | 90% | 15% | 严重 |
| Auto-Compact 触发时机 | 92% | 12% | 严重 |
| 压缩总结质量 | 95% | 55% | 中等 |
| 记忆召回匹配 | 88% | 62% | 轻-中 |
| 语音输入 | 100% | 0% | 完全缺失 |
| 终端渲染 | 95% | 93% | 无差距 |
综合评级:English A / 中文 C-
八、根因分析
这些问题不是零散的 bug,而是同一个根因的连锁反应。
roughTokenCountEstimation() 中 string.length / 4 这个假设是为英文字符密度设计的。这个偏差通过调用链向上传播:
roughTokenCountEstimation() ← 根因:CJK 低估 4-8x
↓
tokenCountWithEstimation() ← 上下文大小的权威函数
↓
┌───────────────┬──────────────────┬──────────────────┐
│ autoCompact │ microCompact │ shouldAutoCompact│
│ 触发过晚 │ 工具结果清理不及时 │ 阈值判断失准 │
└───────────────┴──────────────────┴──────────────────┘
修复思路也很明确:
- 引入语言感知的
bytesPerToken系数——检测到 CJK 字符占比 >50% 时,使用 ~1.0-1.5 而非 4 - 或者更彻底地,优先使用 API 的
countTokens端点进行精确计数,而非本地估算
这两个改动的代码量都不大,但影响面覆盖整个上下文管理链路。
写在最后
Claude Code 无疑是一款优秀的产品,其架构设计(query loop、5 层错误恢复、4 层上下文压缩)展现了极高的工程水准。但在国际化支持方面,它目前本质上还是一个”英文优先”的工具。
对于中文用户来说,你可能会发现在长对话中更容易遇到上下文中断、压缩后信息丢失、记忆匹配不精确等问题——这些不是你的使用方式有问题,而是底层系统对中文的支持确实存在结构性差距。
希望这篇分析能帮助大家更好地理解自己使用的工具,也希望 Anthropic 团队能在未来版本中改进这些问题。
本文基于 Claude Code 源码快照(2026-03-31)的深度分析,涵盖 src/services/tokenEstimation.ts、src/services/compact/、src/memdir/ 等核心模块。
Comments