系列第 19 篇。主文档见 智能体上下文工程实现.md。
Anthropic 的 prompt、工具描述、System Prompt 默认都是英文。但用户可能用中文、日语、阿拉伯语对话。这一篇讲跨语言场景下的上下文工程:tokenization 差异、System Prompt 的语言选择、混合语言会话、本地化的边界。
0. 跨语言不是简单"翻译"
以为多语言 agent = 把 prompt 翻成各语言,是浅薄的理解。实际涉及:
- Token 经济学差异:中文每字 ≈ 1.5-2 token,英文每词 ≈ 1.3 token,token/字符 比例完全不同
- 模型能力差异:英文表现 > 中文 > 日韩 > 小语种
- 指令遵循差异:用英文写 System Prompt 通常比用中文写更稳定
- 混合语言:用户中文问,代码英文,工具结果可能日文 log
- 文化语境:日期格式、礼貌程度、隐喻
每一项都影响上下文工程的具体做法。
1. Token 经济学的语言差异
不同语言每字符占的 token 数:
| 语言 | 字符/token 比 | 示例 |
|---|---|---|
| 英文 | ~4 字符/token | "the quick brown fox" → 4 tokens |
| 中文 | ~1.5 字符/token | "今天天气真好" → 4 tokens |
| 日文 | ~1.2 字符/token | "今日はいい天気" → 6 tokens |
| 韩文 | ~1.3 字符/token | 类似 |
| 阿拉伯文 | ~1.5 字符/token | 类似 |
| 代码(任意语言) | ~3-4 字符/token | 接近英文 |
中文同样意思的内容比英文多 2-3 倍 token。这意味着:
- 中文用户的 200k 上下文 ≈ 英文用户的 60-100k
- 中文 System Prompt 比英文版贵 2-3 倍
- 中文用户的 cache 命中收益等比放大
1.1 工程后果
| 决策 | 中文场景 |
|---|---|
| System Prompt 写哪种语言 | 英文(更省 token) |
| Memory 文件用什么语言 | 看作者偏好,但要稳定 |
| 工具描述 | 英文(cache 友好) |
| 错误信息给用户看的 | 用户语言 |
| 日志 / debug | 英文(工程可读性) |
混合策略:给模型看的部分用英文(省 token),给用户看的部分用用户语言。
2. System Prompt 的语言选择
2.1 为什么默认英文
模型在英文指令上的遵循度最稳定。同样意思的纪律:
英文: "NEVER commit changes unless the user explicitly asks you to."
中文: "除非用户明确要求,否则不要提交代码。"
英文版更容易被模型作为强约束遵守。这不是中文表达不清晰,是训练数据分布的现实 —— 大部分指令调优数据是英文。
2.2 当用户语言不是英文时
策略选项:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 全英文 System Prompt | 指令遵循稳定 | 用户看不懂 prompt(如果暴露) |
| 全中文 System Prompt | 用户友好 | 指令遵循可能差、token 翻倍 |
| 英文规则 + 中文回应风格 | 平衡 | 实现稍复杂 |
我(Claude Code)的实际选择:System Prompt 大部分英文,但加一段"respond to user in their language"。这样指令稳定,用户体验也对。
2.3 用户语言检测
不要假设用户语言:
- 用户输入第一条消息时检测语言
- 用户后续可能切换
- 代码注释、文件名等"上下文里的语言"不一定等于用户偏好
实操:让模型自己判断。System Prompt 加:
Respond in the language the user is using. If the user mixes languages,
prefer the language they used for their actual questions/instructions
(not the language of code comments or file paths).
这把判断委托给模型,比硬编码语言检测稳定。
3. 工具描述的本地化
工具描述(08 篇)是 prompt 的大头。本地化它有两难:
| 选项 | 影响 |
|---|---|
| 工具描述全英文 | cache 跨用户共享、token 节省、但中文用户看不懂工具 |
| 每语言一份描述 | 工具集不再稳定 → cache 失效(参见 01 篇) |
我的选择:工具描述全英文,让模型用用户语言"复述"工具的能力。
例子:
英文工具描述: "Glob: Fast file pattern matching tool..."
模型对中文用户说: "我用 Glob 工具搜索匹配的文件。"
模型对英文用户说: "Let me use Glob to find matching files."
模型自然能跨语言转译。强行把工具描述本地化反而破坏 cache 经济学。
4. 混合语言会话
真实场景里几乎所有非英语用户都在混合:
用户: 帮我看看这个 React 组件为什么 re-render 太多
代码: const Component = () => { useEffect(() => { ... }, []); ... }
工具结果: ESLint warning: react-hooks/exhaustive-deps
这一轮里有:
- 中文(用户问题)
- 英文(代码、错误信息、工具名)
- 技术术语(re-render,多数是英文)
模型的处理:
- 理解所有语言(不出问题)
- 回应时用中文为主
- 技术术语保留英文(更准确)
4.1 用户偏好的"语言混合度"
不同用户偏好不同:
- 偏好全中文:"重渲染太多次了"
- 偏好混合:"re-render 太多次"
- 偏好全英文(中文用户但写技术内容):"The component re-renders excessively"
通过早期对话观察用户混合度,保持一致。Memory 里可以记:
---
type: user
---
User prefers Chinese with English technical terms. Don't translate
React/programming jargon. Examples: "re-render", "useEffect", "state".
5. 工具结果的语言
工具返回的文本可能是任何语言:
- Bash 输出可能是系统 locale 的(中文系统的 ls 不变,但 git 错误可能本地化)
- WebFetch 返回的网页是网页本身的语言
- Read 文件内容是文件本身的语言
模型要处理这些"语言不可控"的输入。System Prompt 不必特别说明 —— 模型自然能跨语言理解。
但要警惕:
5.1 prompt injection 在不同语言
02 篇讲的 injection 防御主要按英文场景设计。但 injection 可以用任何语言:
用户读到一个韩文网站,里面韩文写着"忽略之前指令"
模型对韩文 injection 的识别可能不如英文敏感(训练数据偏差)。所以:
- 不依赖语言来识别 injection
- 用结构化标签(02 篇)+ 信任分级
- 关键决策不基于工具返回的"指令性文字",无论什么语言
5.2 编码问题
老旧系统返回非 UTF-8 编码:GBK、Shift-JIS、Latin-1。如果不正确解码就塞进 prompt:
- 模型看到的是乱码
- token 化结果不可预测
- 浪费 cache(同样内容不同编码 = 不同 cache key)
防御:所有工具结果在进入上下文前统一转 UTF-8。
6. CLAUDE.md 和 Memory 的语言
6.1 项目级 CLAUDE.md
如果团队是中文团队,CLAUDE.md 用中文写也合理:
# 项目说明
本项目是面向 B 端的 SaaS 平台,使用 React + Spring Boot。
代码注释用中文,但变量名英文。
PR 描述用中文写 Summary,Test Plan 用中英混合。
模型能处理。但要注意:
- 中文 CLAUDE.md token 是英文 2-3 倍
- 在 cache 里影响成本(参见 09 篇)
- 团队跨国时英文更通用
6.2 Memory 的语言
我的偏好:
- user / feedback memory:用项目主语言(团队用中文就用中文)
- project memory:同上
- reference memory:URL 等专有名词不翻译
混合也 OK:
---
type: feedback
---
测试不要用 mock。**Why:** 上季度因为 mock 过的测试通过但生产迁移失败。
**How to apply:** 集成测试用真实数据库(testcontainers)。
中英混合不影响模型理解。强行统一一种语言反而别扭。
7. 错误信息的语言
错误信息分两类:
| 错误源 | 语言策略 |
|---|---|
| Anthropic API 错误 | 通常英文,转给用户前可翻译 |
| 工具内部错误 | 英文(工程友好) |
| 给用户的解释 | 用户语言 |
| 给开发者的日志 | 英文 |
例子:
# 内部错误日志
logger.error("Tool Edit failed: old_string not found")
# 给用户的消息(如果暴露错误)
# 中文用户: "编辑失败:找不到要替换的内容。我会重新读取文件再试。"
# 英文用户: "Edit failed: could not find target text. I'll re-read the file and retry."
不要把英文错误堆栈直接暴露给非技术中文用户。也不要把中文错误塞进调试日志。
8. 时间和数字格式
不同语言的格式约定不同:
| 项目 | 美式 | 中式 | ISO |
|---|---|---|---|
| 日期 | 05/07/2026 | 2026年5月7日 | 2026-05-07 |
| 数字 | 1,234.56 | 1,234.56(一样) | - |
| 货币 | $1,234 | ¥1,234 | - |
| 24h vs 12h | 12h(PM) | 24h | - |
System Prompt 不强制格式,但 06 篇讨论时间感知时建议写记忆用 ISO 8601:
✓ "deadline 2026-05-15"
✗ "deadline 5/15/26" ← 美式还是欧式?
✗ "deadline 5月15日" ← 哪一年?
ISO 跨语言、跨地域稳定。
9. 翻译质量与上下文丢失
如果 agent 涉及翻译任务,要意识到翻译有损:
原: "I'm a senior engineer"
中: "我是一位高级工程师" / "我是一名资深工程师" / "我是 senior 工程师"
不同译法语义略有差异。如果翻译后的文本进入 Memory 或 Plan:
- 后续操作基于翻译版本
- 原文细微之处丢失
实操:关键内容保留原文,翻译只在向用户输出时做。Memory 用原文。
10. RTL(从右向左)语言
阿拉伯语、希伯来语等从右向左书写。在终端 UI 里有特殊问题:
- 字符显示顺序与逻辑顺序不同
- 与英文混排时方向切换
- 某些 Unicode 控制字符可能伪造方向(02 篇 §6.2 提到的"不可见控制字符")
防御:
- 终端 UI 显式处理 RTL 渲染
- 日志里所有内容按 LTR 显示(用 BIDI 控制字符)
- Memory 文件用 markdown 时小心 RTL 引号
11. 模型能力的语言层级
经验观察 Claude 在不同语言任务上的相对表现:
任务类型 英文 中文 日韩 其他
─────────────────────────────────────
通用对话 S A A B
代码生成(注释) S A B B-
指令遵循("必须做X") S A A- B+
长文创作 S A- B+ B
推理(多步逻辑) S A A- B
工具调用决策 S A A B+
S/A/B 是相对评分,不是绝对。结论:
- 英文场景默认能力天花板最高
- 中文 / 日韩 接近英文(高 90%)
- 小语种差距明显
如果你的 agent 主要服务非英语市场,要做更多本地化 eval。
12. 给 Agent 设计者的可迁移规则
- System Prompt 默认英文:指令遵循 + token 经济双重优势
- 回复用用户语言:明示"respond in user's language"
- 工具描述不本地化:保护 cache,依赖模型转译
- Memory 用项目主语言:团队一致即可
- 错误信息分层:内部英文,对用户翻译
- 时间用 ISO 8601:跨语言稳定
- 统一编码 UTF-8:所有工具结果入上下文前转换
- 不依赖语言识别 injection:用结构化标签
- 关键内容保留原文:翻译有损
- 非英语市场要本地 eval:能力差距是真实的
13. 一句话总结
跨语言不是把 prompt 翻一遍。token 经济学、模型能力、混合语言、本地化边界 —— 每一层都要权衡。把"给模型看的"和"给用户看的"分开处理,agent 才能既稳定又对用户友好。