2 minute read

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 个英文结构化节:

  1. Primary Request and Intent
  2. Key Technical Concepts
  3. Files and Code Sections
  4. Errors and fixes
  5. Problem Solving
  6. All user messages
  7. Pending Tasks
  8. Current Work
  9. 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│
│ 触发过晚      │ 工具结果清理不及时 │ 阈值判断失准      │
└───────────────┴──────────────────┴──────────────────┘

修复思路也很明确:

  1. 引入语言感知的 bytesPerToken 系数——检测到 CJK 字符占比 >50% 时,使用 ~1.0-1.5 而非 4
  2. 或者更彻底地,优先使用 API 的 countTokens 端点进行精确计数,而非本地估算

这两个改动的代码量都不大,但影响面覆盖整个上下文管理链路。


写在最后

Claude Code 无疑是一款优秀的产品,其架构设计(query loop、5 层错误恢复、4 层上下文压缩)展现了极高的工程水准。但在国际化支持方面,它目前本质上还是一个”英文优先”的工具。

对于中文用户来说,你可能会发现在长对话中更容易遇到上下文中断、压缩后信息丢失、记忆匹配不精确等问题——这些不是你的使用方式有问题,而是底层系统对中文的支持确实存在结构性差距。

希望这篇分析能帮助大家更好地理解自己使用的工具,也希望 Anthropic 团队能在未来版本中改进这些问题。


本文基于 Claude Code 源码快照(2026-03-31)的深度分析,涵盖 src/services/tokenEstimation.ts、src/services/compact/、src/memdir/ 等核心模块。

Comments