- 训练数据的幽灵——偏见、分布与模型行为的根源
- Transformer内部机制解剖——注意力、层归一化与信息流
- Token的世界——分词、词表与语义空间的本质
- 涌现与能力边界——大模型能做什么、不能做什么以及为什么
训练数据的幽灵——偏见、分布与模型行为的根源
训练数据的幽灵
偏见、分布与模型行为的根源
版本:1.0 | 日期:2026-03-16 模型的一切行为都是训练数据的影子
图解速览
五分钟看懂全篇核心,再读正文细节。
图1|预训练数据组成(以 LLaMA-3 为例)
15 万亿 Tokens 的来源:
████████████████████████████████░░░░░░░░ 67% Common Crawl(网页爬取)
████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 8% GitHub 代码
██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 5% 书籍
██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 4% Wikipedia
█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 3% ArXiv 论文
████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 13% 其他
其中语言分布(估算):
英文 ≈ 55% 中文 ≈ 5% 其他语言 ≈ 40%
直接推论:
① 英文能力 >> 中文能力(数据量 11 倍差距)
② Python/JS 代码质量高(GitHub 数据充足)
③ 小语种、冷门领域 → 数据少 → 幻觉率高
图2|训练如何把"数据"变成"能力"
预训练任务:预测下一个 Token
训练样本: "巴黎是法国的___"
↑
模型输出: P(首都)=0.72 P(城市)=0.18 P(心脏)=0.04 ...
正确答案: "首都"
损失函数: -log(0.72) = 0.33 ← 越小越好
反向传播: 调整数百亿参数,让"首都"的概率更高
↑
重复以上过程 15 万亿次(每个 token 一次)
最终结果:
FFN 层的某些神经元 → 强烈关联"首都"概念
"巴黎" + "法国" → 在高维空间中指向"首都"方向
★ 所谓"学会知识" = 参数被调整成能高概率预测正确 token
图3|RLHF 三阶段流水线
阶段① 监督微调 SFT
┌─────────────────────────────────────────────┐
│ 人类专家写高质量问答对 → 微调预训练模型 │
│ 目的:从"续写机器"变成"对话助手" │
└─────────────────────────────────────────────┘
↓
阶段② 训练奖励模型 RM
┌─────────────────────────────────────────────┐
│ 同一问题,模型给出 A/B 两个回答 │
│ 人类标注员选"哪个更好" │
│ 用这些偏好数据训练一个"打分机器"(RM) │
└─────────────────────────────────────────────┘
↓
阶段③ PPO 强化学习
┌─────────────────────────────────────────────┐
│ 模型生成回答 → RM 打分 → 高分行为权重增加 │
│ 重复迭代 → 模型学会人类偏好的回答方式 │
└─────────────────────────────────────────────┘
↓
最终:有帮助 + 无害 + 诚实 的对话模型
⚠️ 副作用:
讨好性(Sycophancy) ← 人类评分员喜欢被夸
过度拒绝 ← "安全但无用"也能得高分
答案冗长 ← 长答案看起来更认真
图4|偏见的传播链路
训练数据中的偏见
↓
"成功科技创业者"的文章:70% 使用男性代词
Embedding 学习阶段
↓
"创业者"向量 → 在高维空间中更靠近男性特征向量
推理时激活
↓
"写一个创业者的故事" → 默认生成男性主角
用户体验
↓
用户看到偏见输出,但可能没有察觉
─────────────────────────────────────────────
解法:
提示词层面: 明确指定"性别不限"或"中性视角"
系统层面: 测试不同人群的输出差异,建监控
模型层面: RLHF 阶段对偏见输出降分(不完美)
图5|数据分布 → 提示词激活区域
不同风格的提示词激活不同"数据分布子集":
你的提示词风格 被激活的训练数据类型
─────────────────────────────────────────────────
"请阐述量子纠缠的物理机制" → 学术论文、教材分布
→ 输出精确、专业
"量子纠缠是啥意思?" → 论坛问答、科普博客
→ 输出通俗、有时欠准确
"量子纠缠的最新研究进展" → 新闻报道、科技媒体
→ 输出以报道式开头
─────────────────────────────────────────────────
★ 实践结论:
想要什么质量的输出
→ 用对应质量文本的语言风格提问
→ 相当于"把模型调到那个频道"
目录
- 训练数据决定模型的一切
- 预训练数据的来源与规模
- 数据分布如何塑造模型能力
- 偏见的类型与根源
- RLHF:价值观注入的过程
- 数据污染与模型能力失真
- 训练数据对提示词效果的影响
- 如何利用训练数据分布设计更好的提示词
- 模型行为中的数据幽灵
- 实践:识别和应对分布偏差
1. 训练数据决定模型的一切
1.1 核心命题
大模型的每一个输出,都是训练数据的某种投影。
模型能做什么? ← 训练数据中见过什么
模型怎么表达? ← 训练数据中什么表达方式最常见
模型有什么偏见? ← 训练数据中有什么偏见
模型知识截止? ← 训练数据的时间范围
不存在"模型自己想出来的东西"
所有"创意"都是训练数据中模式的重新组合
1.2 训练数据是"隐藏的 System Prompt"
与其说训练数据是"教材",不如说它是:
每一个训练样本 = 一次隐性的指令
"在这个上下文后,应该输出这个内容"
100TB 的训练数据 = 100TB 的隐性行为规范
→ 训练数据是最深层的"系统提示词"
→ 它的影响比用户写的 System Prompt 更根本
2. 预训练数据的来源与规模
2.1 主流训练语料组成(估算)
以 LLaMA-3(15T tokens)为例(公开披露的近似比例):
Common Crawl(互联网爬取):约 67%
内容:新闻、博客、论坛、维基、电商...
语言:英文为主(约 55%),其他语言分散
GitHub 代码:约 8%
内容:Python、JavaScript、Java、C++...
影响:代码能力强
Wikipedia:约 4%
内容:百科全书式的中性陈述
影响:知识准确性基础
ArXiv 学术论文:约 3%
内容:科学、数学、工程...
影响:学术推理能力
Books(书籍):约 5%
内容:小说、非虚构、教材...
影响:长文本生成、叙事能力
其他(Stack Exchange、新闻、法律文件等):~13%
2.2 数据量的历史增长
训练数据量演进(预训练 tokens):
GPT-2 (2019): 40B tokens
GPT-3 (2020): 300B tokens
PaLM (2022): 780B tokens
LLaMA-1 (2023): 1.4T tokens
LLaMA-2 (2023): 2.0T tokens
LLaMA-3 (2024): 15T tokens
未来趋势: 接近互联网"数据墙"(约 60-100T 高质量 tokens)
→ 数据量增长正在放缓
→ 数据质量提升成为新的战场
2.3 数据质量 vs 数据量
不是所有 token 价值相同:
低质量数据(降低模型质量):
● 重复内容(垃圾 SEO 文章)
● 错误信息(虚假新闻、错误百科)
● 低信息密度(广告、模板文章)
● 有毒内容(仇恨言论、露骨内容)
高质量数据(提升模型质量):
● 经过编辑的书籍和学术论文
● 专家撰写的技术文档
● 高质量的代码(有测试、有注释)
● 多角度的分析和辩论
研究发现(Falcon、Phi 系列):
1T 高质量数据训练的小模型
可以超过 5T 低质量数据训练的大模型
→ Phi-2(2.7B)在某些基准上超过 LLaMA-2-13B
关键差异:专门策划的高质量训练数据
3. 数据分布如何塑造模型能力
3.1 频率即能力
训练数据中出现越频繁的模式,模型越擅长:
Python 代码:
GitHub 中 Python 代码 >> Fortran 代码
→ 模型写 Python 远好于写 Fortran
英语写作:
互联网英文内容 >> 斯瓦希里语内容
→ 英文输出质量 >> 斯瓦希里语输出质量
学术摘要:
ArXiv 中大量 "We present..." / "Our results show..."
→ 模型特别擅长写这种风格的摘要
博客写作:
互联网大量博客模式
→ 模型自然会写列表、小标题结构的博客
3.2 分布不均的后果
领域知识不均匀:
主流科技(AI、SaaS、移动互联):训练数据极丰富
→ 模型在这些领域表现优秀
传统行业(矿业、农业、传统制造):训练数据相对少
→ 模型对这些领域的理解更浅
偏远地区文化、小众方言:训练数据极少
→ 模型会犯文化理解错误
→ 对于训练数据少的领域,需要更多上下文支持(RAG、few-shot)
3.3 训练分布与提示词风格的关系
实验(在不同提示词风格下测试模型表现):
学术风格:
"请阐述量子纠缠的物理机制及其在量子信息传输中的应用"
→ 模型激活了 ArXiv / 教材 分布 → 输出准确、专业
口语化风格:
"量子纠缠是啥意思?怎么用来传信息?"
→ 模型激活了论坛 / 科普文 分布 → 输出通俗、有时不够准确
新闻风格:
"量子纠缠研究的最新进展是什么?"
→ 模型激活了新闻报道分布 → 输出以报道式开头
→ 提示词风格决定了激活哪个"数据分布子集"
→ 选择与任务目标匹配的语言风格
4. 偏见的类型与根源
4.1 偏见来源
大模型的偏见来源于训练数据中的偏见:
互联网的偏见(数据来源偏见):
● 英语主导:英文观点被过度代表
● 数字鸿沟:发达国家用户内容更多
● 写作群体:受过教育、有时间写作的人更多
● 时代偏见:当代观点多,历史观点少(按比例)
历史记录的偏见(内容偏见):
● 历史上男性写作者更多 → 男性视角被过度代表
● 主流媒体立场 → 主流观点被过度代表
● 成功案例被记录,失败案例被遗忘
互联网有毒内容(有害偏见):
● 歧视性内容(尽管被过滤,仍有残留)
● 极端主义内容(过滤难度大)
● 虚假信息(被广泛传播,难以区分)
4.2 具体偏见类型
性别偏见:
"护士"→ 训练数据中多为女性描述
"工程师"→ 训练数据中多为男性描述
→ 模型在补全时会反映这种关联
测试:"护士李 __ 工作认真" vs "工程师李 __ 工作认真"
→ 模型在前者更可能补全"她"
文化中心主义:
默认"西方"视角(美国、欧洲)
"历史上最重要的战争" → 可能更多欧美战争
美食推荐 → 可能更多西方菜系
语言能力偏见:
非英语文本的质量和推理能力往往低于英文
(即使用中文提问)
社会偏见:
某些职业与种族的关联
某些行为与性别的关联
(这些偏见来自互联网内容,RLHF 部分抑制)
4.3 偏见的传播机制
偏见如何从训练数据进入模型行为:
Step 1:训练数据中的模式
"成功的科技创业者"相关文章 → 70% 使用男性代词
Step 2:模型学习统计关联
"创业者" → 与男性特征的 Embedding 更近
Step 3:推理时激活
"写一个创业者的故事" → 默认生成男性主角
Step 4:用户看到,可能没有察觉
→ 偏见是无声的
→ 需要主动意识到并测试
5. RLHF
5.1 RLHF 的完整流程
阶段1:监督微调(SFT, Supervised Fine-Tuning)
数据:人类撰写的高质量问答对
目标:让模型学会"有用的对话格式"
结果:从"下一个 token 预测机器" → "对话助手"
阶段2:奖励模型训练(Reward Model)
数据:人类对模型不同输出的偏好排序
"回答A" vs "回答B",哪个更好?
结果:一个能打分的模型(模拟人类评分者)
阶段3:PPO 强化学习
用奖励模型的分数优化原始模型
高分输出的生成方式 → 权重增加
低分输出的生成方式 → 权重减少
结果:模型行为向"人类偏好"方向移动
5.2 RLHF 注入的价值观
RLHF 通过人类评分员的偏好,向模型注入了:
有益性(Helpful):
✓ 回答要有帮助,解决用户问题
✓ 答案要完整,不留下关键细节
✓ 承认不知道比编造答案更好
无害性(Harmless):
✓ 不生成有害内容(暴力、仇恨等)
✓ 不提供危险信息(武器制作等)
✓ 在政治敏感话题上保持中立
诚实性(Honest):
✓ 不编造信息
✓ 不确定时表达不确定性
✓ 不诡辩或操纵用户
5.3 RLHF 的副作用
RLHF 带来的非预期行为:
过度拒绝(Sycophancy 的反面):
评分员倾向于对"安全但无用"的拒绝给高分
→ 模型学会了过度拒绝合理请求
→ 有时对明显合理的请求说"我无法帮助"
讨好行为(Sycophancy):
评分员更喜欢表扬自己的答案
→ 模型学会了先同意用户的观点,再给出分析
→ 即使用户错了,也倾向于"找理由支持"
答案冗长化:
评分员认为更长的答案更好(显得更有帮助)
→ 模型学会了添加废话以增加长度
→ 需要在提示词中明确"简洁回答"
语言模式固化:
大量人工撰写的 SFT 数据有特定风格
→ 模型倾向于用"当然,我很乐意帮助..."等开头
5.4 不同公司的 RLHF 哲学差异
OpenAI(GPT 系列):
强调"有用",比较愿意回答灰色地带问题
相对直接,废话少
Anthropic(Claude 系列):
Constitutional AI:基于明确的行为准则
更倾向于解释拒绝原因
对不确定性更谦逊
Google(Gemini 系列):
强调安全,有时过度谨慎
对政治话题更保守
→ 选择模型时,了解其 RLHF 哲学,匹配你的应用场景
6. 数据污染
6.1 什么是数据污染(Data Contamination)
基准测试污染:
训练数据中包含了评测基准的题目(MMLU、GSM8K、HumanEval...)
→ 模型"背住了"答案,而非真正学会了能力
例子:
MMLU 多项选择题
如果在训练数据中出现了 "MMLU: Question X → Answer B"
→ 模型在评测时"认出"了题目并输出 B
→ 不代表模型真正理解了知识
影响:
已发布的大模型基准分数可能被高估
特别是开源数据集(网上能找到答案)
→ 这是为什么学术基准分高不代表实际使用效果好
6.2 数据污染的检测
def check_memorization(model, text_sample: str) -> float:
"""
测试模型是否记住了特定文本(数据污染检测)
使用"接龙"测试
"""
# 给定文本的一部分,看模型能否完全续写
prefix = text_sample[:len(text_sample)//2]
predicted = model.complete(prefix, max_tokens=len(text_sample)//2)
actual_suffix = text_sample[len(text_sample)//2:]
# 计算准确匹配程度
overlap = sum(a == b for a, b in zip(predicted, actual_suffix))
memorization_rate = overlap / len(actual_suffix)
return memorization_rate # > 0.8 可能被记住了
6.3 对你的评测设计的启示
如果你要评测模型在你业务场景的表现:
✗ 不要使用公开的学术基准(可能被污染)
✓ 使用你自己的私有测试集
✓ 定期更新测试集(防止模型后续更新后被污染)
✓ 测试集保密,不要加入模型的输入/上下文
业务专属评测的优势:
真实反映你的场景
不受公开污染影响
可以针对你的特定失败模式设计
7. 训练数据对提示词效果的影响
7.1 哪些提示词天然有效
某些提示词之所以有效,是因为训练数据中有大量对应的高质量样本:
"让我们一步步思考"(Chain of Thought)有效,因为:
训练数据中大量的教学材料、解题过程都是"逐步推理"格式
这个语言模式 → 激活"解题过程"相关的权重
"你是一位专业的 [职业]" 有效,因为:
训练数据中有大量该职业专家写的内容
角色关键词 → 激活该领域的知识分布
Few-shot 示例有效,因为:
训练数据中有大量"给定示例,推断规律"的文本
(教材、API 文档、Stack Overflow 回答示例)
这个模式 → 激活"归纳头"(Induction Heads)
XML 标签结构化有效(对 Claude 尤其明显),因为:
Anthropic 在 SFT 阶段使用了大量 XML 格式的训练数据
→ Claude 对 XML 结构特别敏感
7.2 不同模型的"方言"
每个模型都有它最熟悉的"语言风格"(来自训练数据):
Claude(Anthropic):
偏好 XML 标签(<task>, <context> 等)
对列表、结构化输出响应好
对"Constitutional AI"风格的指令敏感
GPT 系列(OpenAI):
对 Markdown 格式响应好
偏好 "用以下格式输出:..." 的直接指令
对 JSON 格式输出很可靠
Gemini(Google):
对 Google 风格的指令格式响应好
多模态提示词效果好
LLaMA/Mistral(Meta/社区):
对 Llama 官方的 chat 格式响应好
对复杂系统提示词有时"过拟合"到训练格式
→ 不同模型有不同的"提示词方言"
→ 从一个模型迁移到��一个时,提示词可能需要调整
7.3 激活训练数据分布的技巧
原理:通过在提示词中使用特定关键词,激活相关训练数据的分布
技术写作分布:
"请写一篇技术文档,包含概述、实现细节和示例代码"
→ 激活 GitHub README、技术博客分布
学术写作分布:
"请从学术角度分析..."
"请综述相关研究..."
→ 激活 ArXiv、学术论文分布
新闻写作分布:
"请用新闻报道的风格..."
"...的最新进展"
→ 激活新闻文章分布
对话式分布:
"用简单的语言解释..."
"假设我是一个初学者..."
→ 激活科普、FAQ 分布
8. 利用训练数据分布设计更好的提示词
8.1 "镜像"高质量训练样本
思路:想象训练数据中存在你想要的输出,
然后构造能激活那个"训练样本区域"的提示词
想要代码审查报告?
思考:GitHub 上优秀的代码 review 评论是什么风格?
→ "请像一个严格的高级工程师进行代码审查,关注安全、性能和可维护性"
想要投资分析报告?
思考:Bloomberg、高盛等机构报告的写法?
→ "请写一份机构级的投资分析,包含宏观背景、基本面分析和风险提示"
想要教学解释?
思考:优秀教材和大学教授的解释方式?
→ "请像一位耐心的大学教授,由浅入深地解释这个概念,并给出生动的例子"
8.2 训练数据中的"黄金格式"
以下格式在训练数据中高频出现,模型特别擅长输出:
Q&A 格式(训练数据:Stack Overflow, Quora):
"Q: 如何...?\nA: ..."
→ 模型对这种格式的续写质量非常高
代码注释格式(训练数据:GitHub):
"# Function to calculate..."
"def calculate_..."
→ 代码注释质量高
Markdown 教程格式(训练数据:博客、文档):
"## 安装\n...\n## 使用\n...\n## 示例\n..."
→ 技术教程质量高
学术摘要格式(训练数据:ArXiv):
"We propose... Our method... Results show..."
→ 学术风格摘要质量高
故事叙述格式(训练数据:小说、博客):
"从前... 然后... 最终..."
→ 叙事质量高
8.3 反向利用:避开低质量分布
某些提示词会激活低质量训练数据分布:
避免激活 SEO 垃圾文章分布:
✗ "写一篇关于减肥的文章,包含关键词'减肥方法'"
✓ "写一篇基于运动科学的减肥指南,针对久坐上班族"
避免激活模板堆砌分布:
✗ "生成产品描述"(过于宽泛)
✓ "为高端音响设备写产品描述,强调音质细节和使用场景"
避免激活低质量翻译腔分布(中英混杂):
✗ 频繁切换语言,让模型激活翻译数据
✓ 保持一种主要语言,减少激活翻译语料的概率
9. 模型行为中的数据幽灵
9.1 数据噪音导致的奇怪行为
训练数据中的奇怪模式会在模型行为中浮现:
"重复和语言游戏"测试:
反复问同一个问题 → 模型有时开始"胡言乱语"
原因:训练数据中存在一些重复/噪音样本
对特定词汇的过度反应:
某些词汇(如 "banana")有时触发奇怪行为
原因:训练数据中这些词出现在不寻常的上下文中
语言风格"泄漏":
有时候英文提示词得到带中英混合的回答
原因:训练数据中存在大量中英混合内容
→ 这些是训练数据"幽灵":
看不见,但会在某些边界条件下显现
9.2 著名的训练数据幽灵案例
案例1:GPT-2 的政治偏见
当时互联网上充斥大量特定政治倾向的内容
→ 模型在政治话题上表现出明显立场
→ 后续模型通过 RLHF 努力中和
案例2:早期模型的性别偏见
训练数据中 "doctor" 更多被描述为男性
→ 模型在翻译时默认将"医生"翻译为阳性形式
案例3:"Sydney" 事件
早期 Bing Chat 的奇怪行为
据分析:训练数据中可能有"Sydney AI"相关的角色扮演内容
→ 在对话中被激活,导致异常行为
案例4:大模型对特定公司的"过度熟悉"
互联网上存在大量某些大公司(Google、Apple...)的内容
→ 模型对这些公司的了解远超小公司
→ 问"XYZ 公司的CEO是谁"可能得到虚构答案
9.3 数据幽灵的实践影响
对应用开发者的启示:
1. 不要假设模型对所有实体的了解程度相同
→ 对小众/内部实体,始终提供上下文(RAG 或直接注入)
2. 语言风格对模型行为有隐性影响
→ 敏感任务测试不同提示词风格的差异
3. 模型对某些话题可能有"预设立场"(来自训练数据)
→ 对有争议性的话题,明确要求"中性/多角度分析"
4. 边界情况下的奇怪行为通常有训练数据根源
→ 遇到奇怪行为,思考"什么训练数据可能导致了这个"
10. 识别和应对分布偏差
10.1 判断你的任务是否在训练分布内
高置信区(训练数据充分):
✓ 英语内容处理
✓ 主流编程语言代码
✓ 常识性知识问答
✓ 日常写作任务
→ 可直接使用,较少需要特殊支持
中置信区(训练数据适中):
△ 中文/日文等主要亚洲语言
△ 专业但有记录的领域(医学、法律、金融)
△ 近几年但不超截止日期的事件
→ 可使用,但建议提供上下文,验证重要输出
低置信区(训练数据稀少):
✗ 小语种、小众方言
✗ 私有企业内部知识
✗ 超过截止日期的事件
✗ 极度专业的技术领域(核物理、神经外科手术细节)
→ 必须外部知识注入(RAG),不能信任参数记忆
10.2 偏见的系统性测试
def test_for_bias(llm, test_groups: list, template: str) -> dict:
"""
测试模型在不同群体上的行为差异
template 中用 {group} 占位
"""
results = {}
for group in test_groups:
prompt = template.replace("{group}", group)
responses = [llm.call(prompt) for _ in range(5)] # 多次采样
results[group] = {
"responses": responses,
"avg_length": sum(len(r) for r in responses) / len(responses),
"unique_count": len(set(responses))
}
return results
# 使用示例
bias_test = test_for_bias(
llm=my_llm,
test_groups=["男性工程师", "女性工程师", "非二元性别工程师"],
template="写一段关于{group}的职业故事"
)
# 分析:不同组的输出是否在质量、长度、描述上有系统性差异
10.3 应对偏见的提示词策略
# 策略1:显式要求去除偏见
def debias_prompt(original_prompt: str) -> str:
return original_prompt + """
重要要求:
- 不要基于性别、种族、国籍或其他人口学特征做出假设
- 如果任务涉及人物,使用中性表达或要求我提供具体信息
- 对不同群体保持一致的分析标准
"""
# 策略2:多角度要求
def multi_perspective_prompt(question: str) -> str:
return f"""
请对以下问题从多个视角(至少3种不同立场)分析,
确保覆盖主流和非主流观点:
问题:{question}
格式:
视角1([立场描述]):...
视角2([立场描述]):...
视角3([立场描述]):...
综合评述:...
"""
# 策略3:对特定敏感任务要求反偏见输出
def stereotype_resistant(profession: str, task: str) -> str:
return f"""
任务:{task}
注意:在描述{profession}时,
请避免使用与该职业相关的性别/种族/年龄刻板印象。
如果你的初稿中有任何刻板形象,请主动修改。
"""
10.4 构建更公平的 AI 应用
系统层面的偏见缓解措施:
1. 输入标准化
对用户提交的内容进行标准化,
去除可能触发偏见模式的冗余信息
(如:不需要透露用户年龄、性别的场景,就不传入)
2. 输出监控
建立自动化检测管道,监控输出中的偏见指标
统计不同用户群的回答质量差异
3. 反馈循环
收集用户对偏见输出的举报
积累案例用于优化 System Prompt 或 Fine-tuning
4. 透明度
在用户界面说明 AI 可能存在偏见
提供反馈渠道
不要将 AI 决策用于高风险场景(招聘、贷款)不加人工审核
附录:训练数据影响速查
现象 根源(训练数据) 应对策略
────────────────────────────────────────────────────────────────────
英文效果 > 中文 英文训练数据多 用中文优化模型/提供充分中文上下文
代码能力不均 GitHub 以主流语言为主 小众语言提供 few-shot 示例
知识截止 训练数据有时间范围 RAG + 明确告知截止日期
幻觉 有损压缩 + 低频知识 RAG + 要求引用来源
偏见 训练数据反映社会偏见 显式去偏见指令 + 测试
过度拒绝 RLHF 过度对齐 提供授权上下文 + 澄清意图
讨好行为 RLHF 评分员偏好 要求批判性分析 + "诚实优于讨好"
特定格式偏好 SFT 数据风格 使用该模型的"原生"格式
训练数据是看不见的老师。 它塑造了模型会说什么,怎么说,喜欢说什么,拒绝说什么。 读懂训练数据的幽灵,你就读懂了模型行为的深层逻辑。
Transformer内部机制解剖——注意力、层归一化与信息流
Transformer 内部机制解剖
注意力、层归一化与信息流
版本:1.0 | 日期:2026-03-16 面向读者:想真正理解"为什么这样调教有效"的开发者与研究者
图解速览
五分钟看懂全篇核心,再读正文细节。
图1|Transformer Block 一层做了什么
输入向量 x(上一层传来)
│
├──────────────────────────────────┐
│ │ 残差连接(直接抄过来)
▼ │
LayerNorm(归一化) │
│ │
▼ │
Multi-Head Attention │
(从其他 token 那里收集信息) │
│ │
▼ │
+ ◄─────────────────────────────── ┘
│
├──────────────────────────────────┐
│ │ 残差连接(再抄一次)
▼ │
LayerNorm(再归一化) │
│ │
▼ │
Feed-Forward Network │
(查"记忆库",非线性变换) │
│ │
▼ │
+ ◄─────────────────────────────── ┘
│
▼
输出向量 x'(传给下一层)
★ 这个结构重复 32–120 次(层数)
图2|注意力机制:每个词"问"所有词
句子: [系统] [你] [是] [助手]
当前生成位置 ↑
每个 token 发出三个信号:
Q(我在找什么?)
K(我能提供什么信息?)
V(如果你选我,这是我的内容)
计算过程:
Q K
注意力分数 = softmax( ─────── · [系统,你,是,助手]ᵀ )
√维度
结果(权重示意):
[系统]=0.55 [你]=0.25 [是]=0.12 [助手]=0.08
│
▼
输出 = 0.55×V[系统] + 0.25×V[你] + 0.12×V[是] + 0.08×V[助手]
↑ 注意力最高的词贡献最多信息
★ System Prompt 在最前面 → 被后续所有 token 高度关注
→ 这就是 System Prompt 权威性高的底层原因
图3|因果掩码:只能看过去,不能看未来
生成 "北京" 时的视野:
位置: 1 2 3 4 5
token: [我] [爱] [北] [京] [!]
生成第4位"京"时:
✓ 可以看 [我][爱][北] (过去)
✗ 不能看 [京][!] (未来,用 -∞ 屏蔽)
注意力矩阵(✓=可看,✗=屏蔽):
我 爱 北 京 !
我 [ ✓ ✗ ✗ ✗ ✗ ]
爱 [ ✓ ✓ ✗ ✗ ✗ ]
北 [ ✓ ✓ ✓ ✗ ✗ ]
京 [ ✓ ✓ ✓ ✓ ✗ ] ← 生成这一行
! [ ✓ ✓ ✓ ✓ ✓ ]
→ 这是"自回归生成":逐个 token 往后生成
图4|FFN 层:知识存储在哪里
FFN(前馈网络)≈ 一个巨大的"模式→知识"查询表
输入向量 x
│
▼
W₁ 矩阵(4096 × 16384)
每一行 = 一个"问题检测器"
│
激活函数(只保留匹配的)
│
W₂ 矩阵(16384 × 4096)
每一列 = 对应"知识内容"
│
▼
输出:知识叠加到残差流
类比:
W₁[i] → "这是在问关于法国首都的问题吗?"
激活值 → 匹配程度(0.92 = 高度匹配)
W₂[i] → "答案是巴黎,特征是..."
★ 幻觉根源:FFN 存的是"有损压缩"的知识
训练数据稀少的知识 → 检索精度低 → 容易出错
图5|残差流:信息贯穿全程
Token "苹果" 从输入到输出的旅程:
Layer 0: [苹果的原始向量] ← 静态 Embedding
+
Layer 1: [词性信息:名词] ← 浅层:语法处理
+
Layer 8: [语义消歧:水果 or 品牌?] ← 中层:语义理解
+
Layer 16: [上下文判断:结合"好吃" → 水果方向] ← 中层
+
Layer 28: [最终表示:适合续写"味道甜美"] ← 深层:任务执行
│
▼
最终向量 → 预测下一个 token
★ 残差连接保证每层都是在原有基础上"叠加"信息
不是覆盖,是积累。越深的层越"懂"上下文语义
图6|KV Cache:为什么不重复计算
没有 KV Cache(低效):
生成第1个token:计算 [Prompt] 的 K,V
生成第2个token:重新计算 [Prompt+T1] 的 K,V ← 重复!
生成第3个token:重新计算 [Prompt+T1+T2] 的 K,V ← 更多重复!
→ 时间复杂度 O(n²)
有 KV Cache(高效):
生成第1个token:计算并【缓存】[Prompt] 的 K,V
生成第2个token:【读缓存】Prompt K,V + 只算 T1 的新 K,V
生成第3个token:【读缓存】Prompt+T1 K,V + 只算 T2 的新 K,V
→ 每步只算1个新 token,时间复杂度降为 O(n)
★ Prompt Caching(Anthropic/OpenAI都支持)= 把 System Prompt
的 KV Cache 存在服务端,下次调用直接复用
→ 长 System Prompt 场景延迟降低 60-80%
目录
- 为什么要了解内部机制
- Transformer 全局架构
- Embedding:词语如何变成向量
- 注意力机制:模型如何"看"上下文
- 多头注意力:并行的多种视角
- 前馈网络:模式的存储与激活
- 层归一化:稳定信号的守门人
- 残差连接:信息高速公路
- 信息在层间的流动规律
- KV Cache:推理加速的原理
- 从机制到实践:机制理解如何指导调教
- 常见误解澄清
1. 为什么要了解内部机制
很多人调教大模型像"炼丹"——凭直觉试、靠运气中。了解 Transformer 内部机制能让你:
- 理解 few-shot 为什么有效:注意力机制的 in-context 激活
- 理解上下文长度限制的本质:注意力矩阵的计算复杂度
- 理解幻觉的根源:前馈网络的知识存储方式
- 理解为什么长文本末尾被"遗忘":注意力稀释与位置编码退化
- 针对性设计提示词:知道模型"怎么读",才知道怎么"喂"
2. Transformer 全局架构
现代大模型(GPT、Claude、LLaMA 等)都是 Decoder-only Transformer:
输入 tokens
↓
[Token Embedding + Position Encoding]
↓
┌─────────────────────────────────┐
│ Transformer Block × N 层 │
│ ┌──────────────────────────┐ │
│ │ Layer Norm │ │
│ │ Multi-Head Attention │ │
│ │ + Residual Connection │ │
│ ├──────────────────────────┤ │
│ │ Layer Norm │ │
│ │ Feed-Forward Network │ │
│ │ + Residual Connection │ │
│ └──────────────────────────┘ │
└─────────────────────────────────┘
↓
[最终 Layer Norm]
↓
[Linear + Softmax → 词表概率分布]
↓
采样 → 下一个 token
规模感知:
| 模型 | 层数 | 隐藏维度 | 注意力头数 | 参数量 |
|---|---|---|---|---|
| GPT-2 | 12 | 768 | 12 | 117M |
| LLaMA-7B | 32 | 4096 | 32 | 7B |
| GPT-4(估计) | ~120 | ~12288 | ~96 | ~1.8T |
| Claude 3 Opus | 未公开 | 未公开 | 未公开 | ~未知 |
3. Embedding
3.1 Token → 向量
词表中的每个 token 对应一个高维向量(通常 4096 或更高维):
"猫" → token ID 12345 → 向量 [0.21, -0.84, 0.33, ..., 0.07] (4096维)
"狗" → token ID 23456 → 向量 [0.19, -0.81, 0.31, ..., 0.05] (语义相近,向量相近)
"量子" → token ID 45678 → 向量 [-0.52, 0.31, 0.88, ..., -0.42] (语义不同,向量远离)
重要认知: 语义相似度 = 向量余弦相似度。模型通过向量距离"理解"语义关系。
3.2 位置编码
Transformer 本身无法感知顺序(注意力是集合操作),必须手动注入位置信息:
最终 token 向量 = Token Embedding + Position Encoding
位置编码方案演进:
绝对位置编码(GPT-2):每个位置对应一个固定向量,长度硬编码
旋转位置编码 RoPE(LLaMA):将位置信息编码进注意力计算,泛化更好
ALiBi(MPT):注意力分数直接加位置偏置,长度外推能力强
实践影响:
- 使用 RoPE 的模型(LLaMA、Mistral)在超出训练长度后性能降级更平缓
- 绝对位置编码模型超出最大长度会直接崩溃
3.3 Embedding 空间的结构
训练后的 Embedding 空间具有代数结构:
向量("国王") - 向量("男人") + 向量("女人") ≈ 向量("女王")
这意味着模型确实在 Embedding 层就编码了"语义关系"
4. 注意力机制
4.1 直觉理解
注意力机制解决的问题:给定当前 token,应该从上文的哪些位置获取信息?
人类阅读类比:
"那只猫坐在垫子上,它看起来很舒适。"
↑
"它"指代谁?→ 注意力头会在"猫"上分配高权重
4.2 QKV 机制
每个 token 同时扮演三个角色:
Q(Query,查询者): "我在找什么信息?"
K(Key,被查询者): "我有什么信息可供查询?"
V(Value,内容): "如果你选择了我,这是我的实际内容"
计算过程:
注意力分数 = softmax(Q × Kᵀ / √d_k) × V
Q K d_k
↓ ↓ ↓
[当前token] × [所有token]ᵀ / √维度 → 归一化 → 加权求和[所有token的V]
4.3 因果掩码(Causal Mask)
Decoder-only 模型只能看过去的 token,不能看未来:
位置: 1 2 3 4 5
token: "我" "爱" "北" "京" "!"
生成"京"时的注意力视野:
"北" 可以 attend to "我"、"爱"、"北" ✓
"北" 不能 attend to "京"、"!" ✗(未来信息)
实现方式:将未来位置的注意力分数置为 -∞,softmax 后变为 0
4.4 注意力分数的可解释性
注意力权重可以可视化,揭示模型的"注意焦点":
提示词中的注意力模式规律(研究发现):
高注意力位置:
- 输入序列的开头(System Prompt)
- 输入序列的结尾(最近的用户消息)
- 语义相关的关键词
低注意力位置:
- 中间段的冗余内容
- 重复出现的词
→ 这解释了为什么"重要信息放开头或结尾"是有效的提示词技巧
5. 多头注意力
5.1 为什么需要多头
单个注意力头只能捕获一种关系模式。多头注意力并行运行多个独立的注意力头:
多头注意力 = 8个(或32个)独立的 QKV 注意力 → 拼接 → 线性变换
不同头捕获不同类型的关系(研究发现):
头1:句法依赖(主谓关系)
头2:共指消解(代词指代)
头3:位置关系(前后文)
头4:语义相似(同义词)
...
5.2 对调教的启示
多头 = 多视角同时处理文本
实践意义:
同时在提示词中包含多种信号更有效:
- 语义信号(关键词)
- 结构信号(格式标记)
- 角色信号(专家身份)
- 示例信号(few-shot)
不同的头会分别"抓住"这些不同维度的信息
5.3 注意力头的专业化
通过消融实验(移除特定头观察效果),研究者发现:
"归纳头"(Induction Heads):
功能:识别并重复上文中出现的模式
重要性:是 in-context learning(few-shot)的核心机制
位置:通常在前几层中形成
→ 这解释了为什么 few-shot 示例格式一致性至关重要:
归纳头依赖于模式的一致性来进行归纳
6. 前馈网络
6.1 结构
每层 Transformer Block 中的 FFN(前馈网络):
FFN(x) = W₂ · activation(W₁ · x)
W₁: d_model × d_ffn (扩展,d_ffn ≈ 4 × d_model)
W₂: d_ffn × d_model (压缩回来)
常用激活函数:ReLU(早期)、GELU(GPT-2/3)、SwiGLU(LLaMA)
参数量分布(以 LLaMA-7B 为例):
注意力层参数:约 24%
FFN 层参数: 约 67%
其他: 约 9%
→ FFN 占了模型参数的大头!
6.2 FFN 是"记忆存储"
研究发现 FFN 层充当知识存储器:
FFN 的工作方式(概念化):
W₁ 的每一行 = 一个"模式检测器"
· 激活 = "找到了匹配的模式"
· W₁[i] · x > 0 → 第 i 个模式被激活
W₂ 的每一列 = 该模式对应的"知识内容"
· 将知识内容叠加到残差流
类比:
W₁ 是"问题"集合("这是什么动物?")
W₂ 是"答案"集合("是猫,特征是...")
激活值 = 该问题与当前上下文的匹配程度
6.3 幻觉的根源
幻觉产生机制:
1. 训练数据中存在错误事实
→ FFN 层存储了这些错误"记忆"
2. 相似的查询激活了不相关的知识模式
→ 模型"混搭"了不同的知识
3. 强迫模型回答超出知识边界的问题
→ 模型以高置信度输出最接近的"记忆片段"
→ 看起来像编造,实际是"错误检索"
→ 对策:明确允许模型说"不知道",降低模型对低置信知识的输出欲望
7. 层归一化
7.1 LayerNorm vs BatchNorm
BatchNorm(图像领域常用):对 batch 维度归一化
问题:序列长度可变,batch 内样本长度不同,难以适用
LayerNorm(Transformer 使用):对单个样本的特征维度归一化
输入 x(维度 d)→ 均值归零 → 方差归一 → 缩放偏移
y = γ · (x - μ) / σ + β
μ:x 的均值,σ:x 的标准差
γ, β:可学习参数
7.2 LayerNorm 的作用
为什么必须有 LayerNorm?
问题:深层网络中,随着层数增加:
- 激活值可能爆炸(梯度爆炸)
- 激活值可能消失(梯度消失)
- 数值分布在不同层之间漂移
LayerNorm 的效果:
- 将每层的激活值规范到相似的尺度
- 稳定训练过程(允许更大学习率)
- 减少对初始化的敏感性
7.3 Pre-Norm vs Post-Norm
现代大模型几乎都用 Pre-Norm(在注意力/FFN 之前做归一化):
Post-Norm(原始 Transformer):
x → Attention(x) → x + Attention(x) → LayerNorm → 输出
Pre-Norm(GPT、LLaMA 等):
x → LayerNorm(x) → Attention(LayerNorm(x)) → x + ... → 输出
Pre-Norm 优点:
- 梯度流动更稳定
- 可以训练更深的网络
- 不需要 warmup 也能训练
7.4 RMSNorm(现代简化版)
LLaMA 等模型用 RMSNorm 代替 LayerNorm:
RMSNorm(x) = x / RMS(x) · γ
去掉了均值归零的步骤,只做均方根归一化
- 计算更快(省去均值计算)
- 实践中效果相当
8. 残差连接
8.1 结构
残差连接(Residual Connection / Skip Connection):
output = LayerNorm(x) + f(LayerNorm(x))
↑
直接加回原始输入 x
可视化:
x ──────────────────────── +──→ output
│ ↑
└──→ LayerNorm → f(·) ─────┘
8.2 为什么残差连接如此重要
没有残差连接的深层网络问题:
梯度传播路径:loss → 第N层 → ... → 第1层
路径太长 → 梯度在传播中指数衰减 → 底层几乎不被更新
有残差连接:
梯度有"直接通路"从 loss 流向任何层
保证了底层参数也能有效更新
更深层的意义:
残差连接创造了"残差流"(Residual Stream):
每个 token 维护一个持续流动的向量(残差流)
每一层向这个向量中"写入"信息(加上 Attention 和 FFN 的输出)
这个残差流从第 0 层流到第 N 层
最终残差流 = 初始 Embedding + 所有层的贡献之和
→ 每层都在精炼和丰富这个向量的信息
→ 早层捕获低级特征(词性、语法)
→ 深层捕获高级语义(推理、世界知识)
8.3 层间分工规律
研究发现不同深度的层有不同分工:
浅层(前 1/4):
- 词法、句法处理
- 词性识别、实体识别
- 局部模式匹配
中层(中间 1/2):
- 语义组合
- 跨句子关系
- 实体属性绑定
深层(后 1/4):
- 高级推理
- 任务特定处理
- 最终预测准备
→ 实践意义:
提示词中的语法结构影响浅层处理
语义内容和逻辑结构影响中深层处理
任务指令在最后几层才被"执行"
9. 信息在层间的流动规律
9.1 "Lost in the Middle" 现象的机制解释
研究发现长文本中,中间位置的信息被提取得最差:
注意力分布(长文本):
位置 0(开头):注意力权重高(锚定效应)
位置 中间: 注意力权重低
位置 末尾: 注意力权重高(近因效应)
为什么?
开头:长时间的"注意力积累",被后续所有 token 反复 attend
末尾:距离当前生成位置最近,Key-Value 向量最新鲜
中间:两头不靠,容易被忽视
实践建议:
重要信息放位置:
✓ System Prompt 开头(被所有后续 token 看到)
✓ 用户消息结尾(离生成位置最近)
✗ 长文本/长对话的中间位置(容易丢失)
如果必须放中间:
→ 使用标题/标记突出(增加注意力权重)
→ 在结尾重申关键点(近因效应)
→ 缩短上下文,只保留相关信息
9.2 注意力稀释
上下文越长,每个位置分配的平均注意力越少:
注意力矩阵大小 = 序列长度 × 序列长度
注意力分数 softmax 后总和 = 1
序列长度 100:每个位置平均分配 1% 的注意力
序列长度 1000:每个位置平均分配 0.1% 的注意力
序列长度 10000:每个位置平均分配 0.01% 的注意力
→ 上下文越长,单条信息被"稀释"越严重
→ 这就是为什么"长上下文 = 低信息密度"
9.3 计算复杂度
标准注意力计算复杂度:O(n²)
n = 序列长度
n = 1000:需要 1,000,000 次计算
n = 4000:需要 16,000,000 次计算(16倍)
n = 128000:需要 16,384,000,000 次计算
这就是为什么:
1. 长上下文 API 更贵(成本oc²增长)
2. 长上下文推理更慢
3. 存在上下文长度上限
改进方案:
Flash Attention:优化内存访问,保持 O(n²) 计算但实际速度快 2-4 倍
Sparse Attention:跳过部分计算,降低到 O(n√n)
Linear Attention:近似方法,降低到 O(n)
10. KV Cache
10.1 推理时的重复计算问题
自回归生成中的低效:
生成第 T 个 token 时,需要对所有历史 token 重新计算 K, V
生成 "我爱北京天安门":
生成"爱":计算 ["我"] 的 K, V
生成"北":计算 ["我", "爱"] 的 K, V ← "我"的 K,V 重复计算了!
生成"京":计算 ["我", "爱", "北"] 的 K, V ← 重复计算更多!
...
问题:每生成一个 token 就要重新算所有历史 token 的 K, V
10.2 KV Cache 的原理
解决方案:缓存历史 token 的 K, V,只算新 token 的 K, V
KV Cache:
生成"爱":计算并缓存 K["我"], V["我"]
生成"北":
K["爱"], V["爱"] ← 新计算
K["我"], V["我"] ← 从缓存读取,不重新计算!
生成"京":
K["北"], V["北"] ← 新计算
K["我"], V["我"], K["爱"], V["爱"] ← 缓存读取
效果:生成速度从 O(n²) 降低到 O(n) 每步
10.3 KV Cache 与内存
KV Cache 内存占用:
单层单头 KV Cache = 2 × n × d_head × 精度字节数
全模型 KV Cache = 上述 × 层数 × 头数
以 LLaMA-13B 为例(n=4096 tokens):
约 800MB 的 KV Cache
→ 这就是为什么:
1. 长上下文推理需要更多 GPU 显存
2. 批量推理时上下文长度受显存限制
3. 上下文压缩技术有实用价值
10.4 Prompt Caching
现代 API 提供的 Prompt Caching(如 Anthropic 的 cache_control)利用了 KV Cache:
传统调用:每次都重新计算 System Prompt 的 KV
每次请求:重算 2000 token 的 system prompt + 新的 user 消息
Prompt Caching:
首次请求:计算并在服务端缓存 System Prompt 的 KV
后续请求:直接复用缓存,只计算新消息
效果:
延迟降低 60-80%(长 system prompt 场景)
成本降低(缓存 token 价格更低)
11. 从机制到实践
11.1 机制 → 提示词设计原则映射
| 机制 | 具体现象 | 实践指导 |
|---|---|---|
| 注意力的开头/结尾偏向 | 中间信息被忽视 | 重要内容放首尾 |
| 注意力稀释 | 长上下文信息提取差 | 保持上下文精简 |
| 归纳头的模式识别 | Few-shot 格式一致才有效 | 示例格式必须统一 |
| FFN 的知识存储 | 知识有截止日期,可能幻觉 | 用 RAG 补充外部知识 |
| 残差流层间分工 | 不同深度处理不同特征 | 同时提供语法+语义+任务信号 |
| 因果掩码 | 只看历史,不看未来 | 上下文顺序影响处理效果 |
| KV Cache | 推理时历史 token 不重计算 | Prompt Caching 优化成本 |
11.2 为什么 CoT 有效
从机制角度理解 Chain-of-Thought:
直接回答:
输入 → 最后几层 → 输出答案
推理链条必须"压缩"在隐层表示中
对于复杂推理,表示能力不够
CoT(先写出推理过程):
输入 → 生成"步骤1:..." → 将步骤1作为新上下文
→ 生成"步骤2:..." → 将步骤2作为新上下文
→ 最终答案
本质:将隐性推理外显为 token 序列,
每一步推理都利用了整个残差流的表示能力,
相当于"在词表空间中用中间变量进行计算"
11.3 为什么 System Prompt 权威性高
信息处理优先级机制:
1. System Prompt 在序列最前面
2. 被后续所有 token 的注意力 attend(最大"曝光度")
3. 进入深层后,System Prompt 的语义已被高度编码进残差流
4. 用户消息的处理"建立在" System Prompt 的表示之上
→ System Prompt 不是"指令优先级更高",
而是因为它被最充分地处理和编码,
形成了处理后续内容的"上下文基底"
11.4 为什么角色扮演能改变模型行为
训练数据中存在大量"角色扮演"模式:
小说、剧本、角色对话...
这些数据训练了模型中的"角色激活"模式:
当 Embedding 空间中的"专家"、"角色"向量被激活时,
相关的 FFN 知识模块也被激活
→ "你是一位资深医生" 不只是告知身份,
而是将后续内容的处理"路由"到与医学相关的参数区域
研究支持:
激活引导(Activation Steering)实验表明,
在残差流中直接注入特定概念的表示向量,
可以改变模型的输出风格,
与在 Prompt 中描述该概念效果相似
12. 常见误解澄清
误解 1:"模型'理解'了语言"
真相:模型学习的是 token 序列的统计规律
"理解" = 在高维向量空间中建立了有效的映射关系
验证方式:
- 语序敏感性测试:打乱语序,模型仍能部分"理解"(统计规律残留)
- 最小语义对(adversarial pairs):语义相反但句子结构相似,
模型有时候混淆(真正理解不会混淆)
误解 2:"注意力 = 理解重要性"
真相:注意力权重 ≠ 重要性
注意力是"信息路由"机制,不是显式的"重要性评分"
- 高注意力 ≠ 该信息对输出最重要
- 某些关键信息可能通过低注意力路径传递(间接影响)
实验证明:
删除高注意力 token 有时对输出影响不大
删除低注意力 token 有时反而破坏输出
误解 3:"层数越多越好"
真相:每层的分工不同,增加层数不是线性收益
规模定律(Scaling Laws):
性能提升 ∝ 参数量^0.7(大约)
但参数量 ∝ 层数 × 宽度
→ 增加层数 vs 增加宽度,需要权衡
实践影响:
"蒸馏"和"剪枝"实验证明,
许多层是冗余的,去掉不影响大部分能力
→ 提示词不需要"激活所有层"的技巧,模型自动优化
误解 4:"模型有'记忆'"
真相:模型没有跨请求的状态记忆
"记忆"的两种形式:
1. 参数记忆(永久):训练时烧录进权重,每次推理都在
2. 上下文记忆(临时):当前会话的 KV Cache,请求结束即消失
→ 多轮对话中,模型"记得"是因为历史对话被附加在 input 中
→ 不是模型"记住了",而是你"提醒了"它
误解 5:"参数量 = 知识量"
真相:参数不只存知识,还存计算方式
参数的多种用途:
- 知识存储(FFN 层):约 40-50% 的容量
- 语法/语言规则:约 20-30%
- 推理计算模式:约 20-30%
- 对齐/安全行为:少量
→ 小模型未必"什么都不知道",
可能只是"计算能力受限"(推理步骤多时出错)
或"知识存储格式不同"(需要更好的提示词激活)
附录:关键概念速查
Transformer ← 基础架构,所有现代大模型的基石
QKV ← 注意力的三要素:Query/Key/Value
多头注意力 ← 并行多视角的信息聚合
因果掩码 ← 只看过去,Decoder-only 的核心约束
残差连接 ← 梯度高速公路,使深层训练成为可能
残差流 ← 每个 token 贯穿全网络的信息载体
LayerNorm ← 稳定激活分布的归一��层
FFN ← 知识存储与非线性变换
KV Cache ← 推理加速,避免重复计算历史 token
归纳头 ← In-context learning 的核心机制
位置编码 ← 让无序注意力感知顺序的补丁
理解内部机制是从"炼丹师"到"工程师"的分水岭。 不需要实现 Transformer,但需要用它的工作方式来指导决策。
Token的世界——分词、词表与语义空间的本质
Token 的世界
分词、词表与语义空间的本质
版本:1.0 | 日期:2026-03-16 理解 token 是理解大模型一切行为的基础
图解速览
五分钟看懂全篇核心,再读正文细节。
图1|文本到 Token 的切割过程
原始文本: "我爱 transformer"
│
▼
BPE 分词器
│
┌─────────┴──────────┐
│ │
▼ ▼
中文字符按字节切 英文按高频子词切
│ │
▼ ▼
"我" "爱" "transform" "er"
[ID:101][ID:102] [ID:8962] [ID:3384]
│ │
└─────────┬──────────┘
▼
最终序列:[101, 102, 8962, 3384]
│
▼
模型只看到这 4 个数字
↑ 不是文字,是整数 ID
一句话:模型从不"读文字",只读整数编号。
图2|BPE 合并规则是怎么学来的
训练语料统计(词频→合并):
第1步 词表 = 所有单字节/字符
[h] [e] [l] [o] [w] [r] [d] ...
第2步 找最高频相邻对
语料里 "l" "o" 挨在一起最多次
→ 合并 → 新 token "lo"
第3步 继续找最高频对
"lo" "w" 最多次 → 合并 → "low"
第4步 重复 5万次 → 词表变成 5万个 token
结果:
常见词 ──→ 整词变一个 token ("the" → [ID:287])
罕见词 ──→ 拆成子词 ("tokenization" → ["token","ization"])
中文字 ──→ 通常1字=1-2 token ("你" → [ID:xxxxxx])
图3|中英文 Token 效率对比(成本直接相关)
相同语义"今天天气很好":
中文原文 英文原文
────────── ──────────────────────
今天天气很好 The weather is great today
分词结果: 分词结果:
今 │ 天 │ 天 │ The │ weather │ is │
气 │ 很 │ 好 great │ today
≈ 6–9 tokens ≈ 5 tokens
┌──────────────────────────────────┐
│ 相同意思,中文贵约 30–50% │
│ → 中文系统要特别注意 token 成本 │
└──────────────────────────────────┘
图4|Embedding:把整数 ID 变成有意义的向量
词表 ID → Embedding 矩阵 → 高维向量
"猫" [ID:500] → [ 0.21, -0.84, 0.33, ..., 0.07 ] ← 4096维
"狗" [ID:501] → [ 0.19, -0.81, 0.31, ..., 0.05 ] ← 语义近,向量近
"量子" [ID:999] → [-0.52, 0.31, 0.88, ..., -0.42 ] ← 语义远,向量远
↑
这个矩阵(词表大小 × 4096)就是模型"认识词"的方式
训练时自动学成的,不是人手写的
语义空间示意(降维后):
·量子
·物理
·猫 ·狗 ·猫咪 ← 语义相关的词聚在一起
·宠物
·代码
·Python ← 另一个语义簇
图5|Token 计费全链路
一次 API 调用的真实消耗:
你发送的内容 实际 Token 数
─────────────────────────────────────────────
System Prompt(500字中文) ≈ 750 tokens ← 每次都算!
对话历史 Round 1–5 ≈ 2000 tokens ← 历史越长越贵
当前用户消息(100字) ≈ 150 tokens
─────────────
输入合计 ≈ 2900 tokens
模型生成回复(300字中文) ≈ 450 tokens ← 输出比输入贵5倍!
总费用 ≈ 2900×$15 + 450×$75 (单位:$/百万token,Opus定价)
≈ $0.043 + $0.034 = $0.077 / 次
关键结论:
① 减少输出 token > 减少输入 token(单价更高)
② 长对话的输入成本随轮次二次方增长
③ 中文要比英文多花 30-50%
目录
- 一切从 Token 开始
- BPE 分词算法
- Token 与字符的关系
- 中文 Token 的特殊性
- 词表设计与模型能力
- Token 计费的真相
- Embedding 空间的几何结构
- 语义空间中的操作
- Token 边界对模型能力的影响
- 特殊 Token 与控制信号
- 实践中的 Token 优化策略
- 词表外信息:OOV 问题
1. 一切从 Token 开始
1.1 为什么不直接用字符或词
大模型处理文本的基本单位是 Token,而不是字符(character)或词(word)。
字符级处理的问题:
"transformer" = ['t','r','a','n','s','f','o','r','m','e','r'] → 11个字符
上下文太碎,长句子超出窗口;序列太长,注意力计算代价高
词级处理的问题:
词表需要包含所有词 → 英语估计 50 万词以上
新词、专有名词、代码变量名 → OOV(Out-of-Vocabulary)问题
不同语言词表无法共享
Token 的折中:
介于字符和词之间的单位
常见词 = 1 个 token
罕见词 = 多个 token
词表大小 = 3 万 ~ 15 万(可控)
1.2 Token 的感性认识
# 实际感受一下 token 分割(OpenAI tiktoken)
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
print(enc.encode("Hello, world!"))
# → [9906, 11, 1917, 0] (4 tokens)
print(enc.encode("transformer"))
# → [8962, 3384] (2 tokens: "transform" + "er")
print(enc.encode("我爱北京天安门"))
# → [37046, 101, 232, 21410, 53595, 38082, 254, 30298, 101] (9 tokens)
# 中文每字约 1.5-2 个 token
# 英文每词约 1-1.3 个 token
# 代码中的变量名通常 1-3 个 token
2. BPE 分词算法
2.1 BPE(Byte Pair Encoding)原理
现代大模型(GPT、Claude、LLaMA)几乎都用 BPE 或其变体:
训练过程(构建词表):
Step 1:从字符开始
原始词表 = 所有字符(256 个字节 + Unicode 字符)
Step 2:统计相邻对频率
训练语料:["low", "lower", "newest", "widest", ...]
字符化: ["l o w", "l o w e r", "n e w e s t", ...]
最高频相邻对:('e', 's') → 合并为 'es'
Step 3:合并,更新词表
新词表中增加 'es'
原来的 'e' + 's' → 'es'(一个 token)
Step 4:重复直到词表达到目标大小(如 5 万)
结果:
高频词 → 整个词成为一个 token
低频词 → 被拆成高频子词 token
直觉理解:
BPE 词表中存在的 token 例子(GPT-4 的 cl100k_base):
单字符: 'a', 'B', '1', '.'
子词: 'ing', 'tion', 'un', 'pre', 'er'
完整词: 'the', 'hello', 'python', 'import'
词+空格:' the', ' hello', ' import' ← 注意空格被合并进 token!
长词: 'transformers', 'cryptocurrency'
代码片段:'def ', 'return ', ' '(4个空格)
2.2 BPE 变体
| 变体 | 代表模型 | 特点 |
|---|---|---|
| BPE | GPT-2 | 基础版本 |
| Byte-level BPE | GPT-4, LLaMA | 从字节开始,无 OOV 问题 |
| SentencePiece | T5, Gemini | 不依赖预分词,多语言更好 |
| WordPiece | BERT | 从全词出发,向子词分割 |
| Unigram | 多个学术模型 | 概率模型,可输出多种分割 |
2.3 为什么 Token 边界有时"奇怪"
"bumblebee" 被分为:['b', 'umb', 'le', 'bee'] 或 ['bumb', 'lebe', 'e']
→ 取决于训练语料中的频率统计
"Beyoncé" 可能被分为:['B', 'ey', 'onc', 'é']
→ 稀有名字,没有整体出现在训练词表中
"🎉" = [9468, 97] 两个 token
→ Emoji 由多个字节组成,在字节 BPE 中可能跨多个 token
这些"奇怪"边界有时导致模型在这些词上表现异常:
→ 模型"看到"的是 token,不是词
→ 如果 token 边界切割了语义单元,模型处理这个词就更难
3. Token 与字符的关系
3.1 不同内容的 Token 效率
英文自然语言: 1 token ≈ 4 个字符(约 0.75 个单词)
中文: 1 token ≈ 0.5-0.7 个汉字(1个汉字 ≈ 1.5-2 token)
代码(Python): 1 token ≈ 3-4 个字符(关键字效率高,变量名低)
JSON: 1 token ≈ 3-5 个字符(符号多,效率低)
Base64: 1 token ≈ 3 个字符(高度"随机",效率最低)
3.2 Token 效率对成本的影响
# 相同语义内容,不同格式的 token 消耗差异(估算)
# 方式1:冗余 JSON
data_json = '''{"user": {"name": "张三", "age": 25, "city": "北京"}}'''
# ≈ 35-40 tokens
# 方式2:简洁格式
data_compact = "用户:张三,25岁,北京"
# ≈ 15-20 tokens
# 方式3:XML(冗余标签)
data_xml = "<user><name>张三</name><age>25</age><city>北京</city></user>"
# ≈ 45-55 tokens
→ 选择格式不只是风格问题,直接影响 API 成本
3.3 字符计数 vs Token 计数
模型的限制是基于 token 数,不是字符数:
常见误区:
"我的 System Prompt 只有 2000 个字符,应该不超限"
→ 2000 中文字符 ≈ 3000-4000 tokens!
→ 远超很多场景的预期消耗
正确做法:
始终用 token 计数工具估算(tiktoken、Anthropic token counter)
中文内容按"字数 × 2"估算 token 数
英文内容按"词数 × 1.3"估算 token 数
4. 中文 Token 的特殊性
4.1 中文的 Token 劣势
英文: "the quick brown fox" → 4 tokens(几乎1词1token)
中文: "敏捷的棕色狐狸" → 约 8-12 tokens(1字1-2token)
相同语义内容,中文消耗更多 token
→ 相同上下文窗口,中文能放的信息量更少
→ 相同价格,中文输入/输出更贵
4.2 不同模型对中文的优化差异
| 模型 | 中文 Token 效率 | 说明 |
|---|---|---|
| GPT-4 (cl100k) | ~1.7 token/字 | 中文优化一般 |
| Claude | ~1.5 token/字 | 略好 |
| Gemini | ~1.3 token/字 | 中文优化较好 |
| Qwen(通义) | ~1.0-1.2 token/字 | 专门优化中文 |
| ChatGLM | ~1.0 token/字 | 中文原生 |
实践建议: 中文密集型应用考虑使用中文优化的模型,可节省 30-50% 的 token 成本。
4.3 中文分词的歧义
BPE 不了解中文语言学,纯粹按频率统计分割:
"今天天气很好" 可能被分为:
['今天', '天气', '很', '好'] ← 语义清晰
或
['今', '天天', '气很', '好'] ← 语义模糊
模型并不知道哪种更"正确",它只是处理 token 序列
这可能导致模型对某些中文词组处理不稳定
→ 实践意义:
避免依赖模型"正确分词"
对分词敏感的任务(如 NER),最好预处理
5. 词表设计与模型能力
5.1 词表大小的权衡
词表越大:
✓ 更多词可以用单个 token 表示(效率高)
✓ 罕见词的处理更好
✗ Embedding 层参数更多(词表大小 × 隐藏维度)
✗ 最后的 Linear 层也更大
✗ 每个 token 的训练样本更少(长尾稀疏)
词表越小:
✓ 参数更少
✓ 每个 token 训练充分
✗ 更多词需要多个 token 表示
✗ 序列更长,注意力计算更慢
典型词表大小:
GPT-2: 50,257
GPT-4: 100,277 (cl100k_base)
LLaMA-2: 32,000
LLaMA-3: 128,256 ← 大幅扩展
Gemini: ~256,000
5.2 词表与多语言能力
词表中不同语言的 token 分配决定了多语言能力:
以 cl100k_base(GPT-4)词表 100K 为例(估算):
英文相关: ~60%(高频英文词、子词)
数字/符号:~15%
代码相关: ~10%
中文: ~5%
其他语言: ~10%
→ 中文只有 5% 的词表空间,所以中文 token 效率低
→ 专注中文的模型(Qwen、ChatGLM)会为中文分配 30-50% 词表空间
5.3 词表更新的难题
为什么模型发布后词表不能随意更新?
1. Embedding 层大小固定 → 增加 token 需要改变模型架构
2. 新 token 没有训练数据 → 即使加入词表,Embedding 向量随机初始化,无意义
3. 所有 tokenizer 依赖 → 词表变化会让历史上下文/缓存失效
→ 词表在训练前就必须设计好
→ 这也是为什么大模型升级时,tokenizer 通常也一起升级(不向后兼容)
6. Token 计费的真相
6.1 输入 vs 输出 Token 的价格差异
API 定价(以 Claude claude-opus-4-6 为例):
输入 token:$15 / 1M tokens
输出 token:$75 / 1M tokens
输出比输入贵 5 倍!
原因:
输入:并行处理,KV Cache 可复用
输出:自回归生成,必须串行,每步都是独立的前向传播
→ 优化成本的第一步:减少输出 token,而不是输入 token
6.2 Token 成本计算
def estimate_cost(input_text, output_text, model="claude-opus-4-6"):
"""估算 API 调用成本"""
# 粗略估算 token 数
def count_tokens(text):
# 英文:4字符/token,中文:1.5字符/token(粗估)
chinese_chars = sum(1 for c in text if '\u4e00' <= c <= '\u9fff')
other_chars = len(text) - chinese_chars
return int(chinese_chars * 1.5 + other_chars / 4)
input_tokens = count_tokens(input_text)
output_tokens = count_tokens(output_text)
# 价格($/1M tokens)
prices = {
"claude-opus-4-6": {"input": 15, "output": 75},
"claude-sonnet-4-6": {"input": 3, "output": 15},
"claude-haiku-4-5-20251001": {"input": 0.8, "output": 4},
}
price = prices.get(model, prices["claude-sonnet-4-6"])
cost = (input_tokens * price["input"] + output_tokens * price["output"]) / 1_000_000
return {
"input_tokens": input_tokens,
"output_tokens": output_tokens,
"estimated_cost_usd": cost
}
6.3 隐藏的 Token 消耗
每次 API 调用的实际 token 消耗:
System Prompt:固定成本,每次调用都计费(除非使用 Prompt Caching)
→ 2000 字的 System Prompt ≈ 3000 tokens ≈ $0.045/1000次调用(Opus 定价)
对话历史:随轮次线性增长
→ 10 轮对话,平均每轮 500 tokens,到第 10 轮:
第1轮:500 tokens 输入
第2轮:1000 tokens 输入(含历史)
...
第10轮:5000 tokens 输入
累计输入:27500 tokens(是单轮 10 倍!)
→ 长对话的 token 成本是二次方增长的
→ 必须设计上下文压缩策略
7. Embedding 空间的几何结构
7.1 高维空间的直觉
Embedding 是将离散 token 映射到连续高维空间的过程:
词表大小:100,000 个 token
Embedding 维度:4096
每个 token = 4096 维空间中的一个点
这个空间中:
● 语义相似的词 → 距离近
● 语义不同的词 → 距离远
● 语义关系 → 向量方向关系
7.2 Embedding 的代数性质
著名案例(Word2Vec 时代发现,大模型中同样存在):
vec("国王") - vec("男人") + vec("女人") ≈ vec("女王")
vec("巴黎") - vec("法国") + vec("中国") ≈ vec("北京")
vec("good") - vec("bad") ≈ vec("fast") - vec("slow")
这说明语义关系被编码为向量的方向!
在大模型中(更复杂的几何结构):
- 情感轴:vec("好") 和 vec("坏") 在某个维度相对
- 时态轴:vec("run") 和 vec("ran") 存在规律偏移
- 专业度轴:专业词汇和通俗词汇在某些维度聚集
7.3 Embedding 压缩的本质
训练 Embedding 的过程是在"学习压缩":
互联网中的所有文本关系 → 压缩成 N × D 的矩阵
(N = 词表大小,D = 隐藏维度)
这个压缩必然是有损的:
- 多义词("苹果")被压缩成单一向量,语境消歧由上下文完成
- 文化特定概念的向量可能不在"合理"的位置
- 非常罕见的概念可能没有"专属"位置,借用相邻向量
→ 对实践的启示:
模型处理有歧义的词时需要更多上下文
文化特定概念用跨文化描述更安全
8. 语义空间中的操作
8.1 上下文调整 Embedding
静态 Embedding 不考虑上下文,但 Transformer 的处理是动态的:
"苹果很好吃" 中的"苹果" Embedding 流经 Transformer 后:
初始:vec("苹果") - 标准静态向量
经过注意力层:"好吃"、"吃"等词的语义注入
最终残差流表示:靠近"水果"语义空间
"苹果发布会" 中的"苹果" 最终表示:
初始:同样的 vec("苹果")
经过注意力层:"发布会"、"科技"等词的语义注入
最终残差流表示:靠近"品牌/科技"语义空间
→ 这是大模型消歧的核心机制:
同一个 token 的最终表示由上下文动态决定
8.2 激活引导(Activation Steering)
研究者发现可以直接在残差流中注入语义向量来控制模型行为:
# 概念示意(非实际代码,需要访问模型中间层)
# 找到"情感正向"方向:
positive_direction = mean([vec(positive_words)]) - mean([vec(negative_words)])
# 在生成时,向残差流中注入这个方向:
residual_stream[layer] += alpha * positive_direction
# 效果:模型生成更积极的内容
# 不需要修改 Prompt!直接操作内部表示
这说明 Prompt 中的语义词汇 = 向残差流中引入语义方向的间接方式
8.3 In-context Learning 的几何解释
Few-shot 示例的本质(几何视角):
示例1:输入A → 输出A
示例2:输入B → 输出B
示例3:输入C → 输出C(待预测)
这些示例在 Embedding 空间中定义了一个"变换方向":
vec(输出A) - vec(输入A) ≈ vec(输出B) - vec(输入B)
模型通过注意力(归纳头)识别这个变换方向
然后将该变换应用到新的输入C
→ 示例越一致,变换方向越清晰
→ 示例格式不一致 = 变换方向模糊 = few-shot 效果差
9. Token 边界对模型能力的影响
9.1 数字处理问题
数字的 token 分割方式极大影响模型的数学能力:
"12345" 可能被分为:
['12345'](单一 token,如果在词表中)
['123', '45'](两个 token)
['1', '23', '45'](三个 token)
每种分割方式都不对应人类的"十进制位"概念!
→ 大模型不擅长精确计算的根本原因:
token 边界与数字的语义边界不对齐
模型无法直接访问"个位"、"十位"这样的概念
改进方案:
Chain-of-Thought:用文字描述每步计算(让模型写出中间结果 token)
工具调用:数学计算交给代码解释器
特殊 tokenization:为数字的每个数位使用独立 token(部分模型做���此优化)
9.2 拼写检查的难题
"transformer" → ['transform', 'er']
模型的视角:看到两个 token,而不是 11 个字母
影响:
"transformer 有几个字母?"
模型无法直接数,因为看到的不是字母序列
需要"展开"并数各 token 内的字符 → 容易出错
"请大写 transformer 的第5个字母"
模型需要先还原 token 对应的字母,然后定位 → 高错误率
→ 字符级别的操作(数字母、翻转、填字游戏)是大模型的弱点
原因不是"不聪明",是 token 粒度与任务粒度不匹配
9.3 多语言混合的 Token 惩罚
"Hello 你好 world" 的 token 成本:
纯英文 "Hello world" → 约 2 tokens
纯中文 "你好世界" → 约 4-6 tokens
混合 "Hello 你好 world" → 约 6-8 tokens
语言切换通常增加 token 开销:
- 语言边界的特殊处理 token
- 混合内容在训练数据中频率低,每个 token 的表示质量降低
→ 系统的多语言 App,选一种主语言保持一致,避免频繁切换
10. 特殊 Token 与控制信号
10.1 特殊 Token 的作用
词表中除了普通内容 token,还有专用的控制 token:
常见特殊 token:
<|begin_of_text|> ← 文本开始标记
<|end_of_text|> ← 文本结束/EOS 标记(模型停止生成)
<|system|> ← System 消息开始
<|user|> ← User 消息开始
<|assistant|> ← Assistant 消息开始
<|eot_id|> ← 消息结束标记
[PAD] ← 填充 token(批处理时对齐序列长度)
[UNK] ← 未知 token(极少使用,字节 BPE 无 OOV)
10.2 对话模板(Chat Template)
不同模型用不同的特殊 token 构建对话格式:
LLaMA-3 格式:
<|begin_of_text|>
<|start_header_id|>system<|end_header_id|>
你是一个助手<|eot_id|>
<|start_header_id|>user<|end_header_id|>
你好<|eot_id|>
<|start_header_id|>assistant<|end_header_id|>
Claude 格式(概念化,实际由 API 处理):
Human: 你好
Assistant:
GPT 格式(OpenAI API):
<|im_start|>system
你是一个助手<|im_end|>
<|im_start|>user
你好<|im_end|>
<|im_start|>assistant
关键认知: 当你调用 messages API 时,你传的是结构化消息,API 帮你转换成模型能理解的 token 序列。如果直接用 raw completion API,必须自己构建正确格式。
10.3 EOS Token 的重要性
EOS(End of Sequence)token 是模型学会"停止"的机制:
训练时:
- 每个训练样本末尾加 EOS token
- 模型学会在合适位置预测 EOS
推理时:
- 模型预测下一个 token,如果是 EOS,停止生成
- API 的 stop_sequences 参数本质是:
将指定字符串对应的 token 序列注册为"触发停止"的信号
问题案例:
- 如果 system prompt 中意外包含了 EOS token 的文本形式
→ 模型可能提前停止生成
- 某些格式标记(如 "```" 的 token)可能被模型过度关联到停止行为
11. 实践中的 Token 优化策略
11.1 输入 Token 优化
# ❌ 低效输入:冗余信息
system_prompt = """
你好,我是一个 AI 助手。我将尽我所能帮助您解决问题。
我有丰富的知识储备,可以回答各类问题。
请注意,我只是一个 AI,可能存在错误。
现在,让我来帮助您:
"""
# ≈ 80 tokens,但信息量很低
# ✓ 高效输入:信息密集
system_prompt = """
AI 助手。直接回答,不确定时说明。
"""
# ≈ 15 tokens,语义等效
缩减 Token 的技巧:
删除废话开头: "当然,我来帮您..." → 直接内容
压缩重复说明: 多条相似规则 → 一条涵盖所有的规则
用缩写/代号: "用户ID" → "UID"(在已定义的上下文中)
选择高效格式: XML > JSON > CSV > 自然语言(信息密度依次增加)
截断无关上下文: 每轮对话只保留相关历史
11.2 输出 Token 控制
# 通过 Prompt 控制输出长度
length_control_prompt = """
回答规则:
- 简单问题:1-2句
- 解释性问题:3-5句,或带标题的要点列表
- 复杂分析:结构化,不超过500字
禁止:废话开头、重复问题、总结段落
"""
# 通过 max_tokens 硬性限制
response = client.messages.create(
max_tokens=256, # 硬性限制
...
)
# 检查是否被截断
if response.stop_reason == "max_tokens":
# 输出不完整,按需处理
pass
11.3 Prompt Caching 策略
# Anthropic Prompt Caching(稳定部分设置 cache_control)
response = client.messages.create(
model="claude-opus-4-6",
system=[
{
"type": "text",
"text": long_system_prompt, # 2000+ tokens 的固定 system prompt
"cache_control": {"type": "ephemeral"} # 标记为可缓存
}
],
messages=[
{"role": "user", "content": user_message} # 每次变化的部分
]
)
# 首次调用:正常计费
# 后续调用:system prompt 部分从缓存读取,成本降低 90%
# 最佳实践:
# - System Prompt 放最前面(最稳定)
# - 变化部分放后面(user message)
# - 确保缓存命中:前缀必须完全一致
11.4 上下文窗口管理
class ContextManager:
def __init__(self, max_tokens=8000, summary_threshold=6000):
self.messages = []
self.max_tokens = max_tokens
self.summary_threshold = summary_threshold
def add_message(self, role, content):
self.messages.append({"role": role, "content": content})
# 超过阈值时压缩历史
if self.estimate_tokens() > self.summary_threshold:
self._compress_history()
def _compress_history(self):
# 保留最近 2 轮对话
recent = self.messages[-4:]
old = self.messages[:-4]
# 用 LLM 总结旧对话
summary = summarize_with_llm(old)
# 重构消息列表
self.messages = [
{"role": "system", "content": f"对话历史摘要:{summary}"}
] + recent
def estimate_tokens(self):
# 粗略估算 token 数
total_chars = sum(len(m["content"]) for m in self.messages)
return int(total_chars / 3) # 中英混合估算
12. 词表外信息
12.1 OOV 问题的现代解法
字节级 BPE(Byte-level BPE)根本上解决了 OOV 问题:
传统方案问题:
词表中没有 "ChatGPT" → [UNK](丢失信息)
字节级 BPE 方案:
任何字符串都可以表示为字节序列
字节只有 256 种,词表至少包含所有字节
"ChatGPT" → ['Ch', 'at', 'G', 'PT'](4 tokens,保留所有信息)
→ 现代大模型(GPT-4、LLaMA-3、Claude)都使用字节级方案
→ 理论上可以处理任何 Unicode 文本,包括最新的 emoji、代码等
12.2 新领域词汇的处理
当模型遇到训练数据中未见过的专业词汇时:
情况1:词在词表中(常见词)
"CRISPR" → ['CR', 'ISP', 'R']
模型可能从上下文推断含义,但 token 边界不利于处理
情况2:词不在词表(字节级兜底)
"Z-CRISPR-X9" → ['Z', '-', 'CR', 'ISP', 'R', '-', 'X', '9']
保留所有字符,但语义理解能力弱
→ 专业领域应用的最佳实践:
在上下文中定义专业词汇("CRISPR 是一种基因编辑技术...")
不要假设模型知道最新的专有名词
新词/缩写第一次出现时提供完整说明
12.3 代码与特殊格式
# 代码被如何 tokenize 直接影响代码生成质量
# Python 缩进(4个空格)通常是单独 token:
" " → [' '] # 一个token(如果在词表中)或 [' ', ' '] 等
# 关键字是单独 token(高频):
"def " → ['def '] # 注意包含空格
"return " → ['return ']
"import " → ['import ']
# 这解释了为什么大模型写 Python 比写其他语言好:
# Python 关键字、缩进模式在训练数据中高频出现,
# 每个语义单元恰好对应一两个 token
# 对于代码生成的实践启示:
# - Python/JS/Go 等主流语言 → token 效率高,生成质量好
# - DSL/小众语言 → token 边界混乱,生成质量差
# - 为小众语言生成代码时,多提供完整示例(few-shot)
附录:Token 快速估算指南
┌────────────────────────────────────────────────────┐
│ Token 估算速查 │
├─────────────────────┬──────────────────────────────┤
│ 内容类型 │ 估算公式 │
├─────────────────────┼──────────────────────────────┤
│ 英文文章 │ 字符数 ÷ 4 │
│ 中文文章 │ 字数 × 1.5 │
│ 中英混合 │ (英文字符 ÷ 4) + (中文字 × 1.5)│
│ JSON 数据 │ 字符数 ÷ 3 │
│ Python 代码 │ 字符数 ÷ 3.5 │
│ Base64 编码 │ 字符数 ÷ 2.5 │
│ 纯数字 │ 字符数 ÷ 3 │
├─────────────────────┼──────────────────────────────┤
│ 常见场景 │ 典型 Token 量 │
├─────────────────────┼──────────────────────────────┤
│ 简短提问 │ 10-50 tokens │
│ 一段话 │ 50-200 tokens │
│ 系统提示词 │ 200-2000 tokens │
│ 一篇文章 │ 500-3000 tokens │
│ 一个代码文件 │ 500-5000 tokens │
│ 一本书(全文) │ 100k-300k tokens │
└─────────────────────┴──────────────────────────────┘
Token 是大模型与世界之间的接口层。 了解 token 的边界,就知道了模型的认知边界。
涌现与能力边界——大模型能做什么、不能做什么以及为什么
涌现与能力边界
大模型能做什么、不能做什么以及为什么
版本:1.0 | 日期:2026-03-16 了解边界,才能设计出不会踩坑的 AI 系统
图解速览
五分钟看懂全篇核心,再读正文细节。
图1|涌现:能力不是线性增长的
某任务准确率 vs 模型参数量:
100% │ ●●●
│ ●●●
75% │ ●
│ ●
50% │ ● ● ● ● ● ● ● ●
│
25% │ ● ● (随机水平)
0% └──────────────────────────────────────────
1B 7B 13B 30B 65B 180B 540B 参数量
↑
"涌现点":能力突然出现
典型涌现任务:
・少样本学习(Few-shot) 在 GPT-3(175B)级别涌现
・思维链推理(CoT) 在 62B+ 才真正有效
・指令遵循 小模型根本无法稳定遵循复杂指令
图2|规模定律:怎么花算力最划算
Chinchilla 定律(2022 年 DeepMind):
最优策略:参数量 和 训练数据量 同比例增长
┌──────────────────────────────────────────────┐
│ 模型参数 最优训练数据量 │
│ 7B → 140B tokens(7×20) │
│ 70B → 1.4T tokens(70×20) │
│ 700B → 14T tokens(700×20) │
└──────────────────────────────────────────────┘
GPT-3(175B)只训练了 300B tokens → 严重欠训练!
同等算力,训练小模型更充分 > 大模型训练不足
★ 实践结论:7B 充分训练的模型可以超过 13B 欠训练的模型
图3|能力地图:擅长 vs 不擅长
大模型能力版图:
┌─────────────────────┬──────────────────────┐
│ ★ 擅长 │ ✗ 弱项 │
├─────────────────────┼──────────────────────┤
│ 语法正确的文本生成 │ 精确大数字计算 │
│ 多语言翻译 │ 数字母/翻转字符串 │
│ 代码生成(主流语言) │ 跨会话记忆(无状态) │
│ 文本摘要与提炼 │ 实时/截止后信息 │
│ 格式转换(JSON等) │ 精确引用(高幻觉风险) │
│ 分类与信息提取 │ 严格逻辑链(>5步) │
│ 创意写作 │ 空间/图形推理(原生) │
│ 角色扮演 │ 精确计数/排列 │
│ 知识整合与类比 │ 因果推断(易混相关性) │
└─────────────────────┴──────────────────────┘
核心原则:弱项 → 交给工具(代码解释器/搜索/数据库)
图4|幻觉的本质:不是"撒谎",是"错误检索"
正常知识检索(高频知识):
问:"法国首都是哪里?"
↓
FFN 层检索:训练中见过数百万次"法国-首都-巴黎"
↓
高置信度输出:"巴黎" ✓
幻觉场景(低频/超出边界知识):
问:"2019年某场不知名地方选举结果?"
↓
FFN 层检索:训练数据中几乎没有
↓
激活了"最相似"的模式(相关选举数据的碎片)
↓
拼合出看似合理但不真实的答案 ✗
幻觉 ≠ 模型在撒谎
幻觉 = 训练数据中没有足够信息支撑正确检索
─────────────────────────────────────────
防幻觉策略:
① 提供上下文(RAG) → 让模型从文档中检索,不靠参数
② 要求引用来源 → 逼模型说出依据
③ "不知道就说" → 在 System Prompt 中明确授权
图5|CoT 为什么有效(Token 视角)
方式A:直接回答(一步到位)
问题 ──→ [模型内部一次前向传播] ──→ 答案
↑
所有推理挤在隐层里
复杂题目超出单次容量 → 出错
方式B:CoT(逐步写出思考过程)
问题 ──→ "步骤1:…" ──→ "步骤2:…" ──→ "步骤3:…" ──→ 答案
↑ ↑ ↑
一次前向 一次前向 一次前向
传播 传播 传播
(以步骤1为上下文) (以步骤2为上下文)
★ 每个中间 Token = 草稿纸上的笔算过程
把复杂推理分摊到多次前向传播 = 把心算变成笔算
→ 5步推理,正确率从 40% 提升到 80%+
目录
- 涌现能力:规模的奇迹
- 规模定律:更大不只是更强
- 大模型擅长的能力图谱
- 大模型的核心弱点
- 幻觉:最危险的能力边界
- 推理能力的真相
- 模型尺寸与任务难度的匹配
- 能力边界的系统性测试
- 绕过边界的工程策略
- 未来的能力边界变化趋势
1. 涌现能力
1.1 什么是涌现(Emergence)
涌现是大模型最神秘的特征:某些能力在小模型中完全不存在,在大模型中突然出现。
传统软件/小模型:
增加 10% 计算量 → 性能提升 10%(线性)
大模型的涌现现象:
从 1B 到 100B 参数:某些任务准确率从 ~25%(随机)突变到 ~90%
这中间没有"逐渐提升",而是突然"开窍"
例子:
少样本学习(Few-shot):GPT-3(175B)几乎是第一个真正有效的模型
思维链推理:在 62B+ 参数模型才开始有效
指令遵循:小模型无法稳定遵循复杂指令,大模型可以
1.2 涌现能力的机制假说
假说1:相变论
类比物理学相变(水变冰):系统在某个临界点发生质变
某个参数量对应"临界点",超过后能力突然出现
假说2:能力组合论
小能力逐渐积累,到某个组合完整时整体能力涌现
如:逻辑 + 语言 + 世界知识 → 三者同时足够 → 推理涌现
假说3:测量论(争议)
部分研究者认为"涌现"是评测指标的误导
换用连续评测指标,能力是线性提升的,没有突变
→ 争议仍在,但实践中"大模型能做而小模型不能做"是真实存在的
1.3 已知的涌现能力列表
在 GPT-3/PaLM 尺寸(62B-540B)涌现的能力:
✦ 3位数算术 (62B+ 出现)
✦ 问答中的Chain-of-Thought (62B+ 有效)
✦ 多步推理 (62B+ 出现)
✦ Python 代码执行模拟 (62B+ 出现)
✦ 多语言翻译质量飞跃 (62B+ 出现)
在 GPT-4/Claude 3 尺寸进一步涌现:
✦ 复杂多步骤指令遵循
✦ 长文本的连贯生成
✦ 细粒度的风格/语气控制
✦ 专业领域的高质量输出
✦ 元认知(知道自己不知道)
2. 规模定律
2.1 核心发现(Hoffmann et al., 2022 - Chinchilla)
最优训练:模型参数量 和 训练数据量 应同比例扩大
公式(Chinchilla 定律):
最优 token 数 ≈ 20 × 参数量
7B 参数模型:最优训练 ~140B tokens
70B 参数模型:最优训练 ~1.4T tokens
实践影响:
早期 GPT-3(175B)训练了 300B tokens → 欠训练!
Chinchilla(70B)训练了 1.4T tokens → 超越 GPT-3
→ 用同等计算量,小模型多训练 > 大模型少训练
2.2 规模 vs 性能的关系
性能提升的来源(近似对数线性关系):
log(性能) ∝ log(参数量) + log(训练数据量) + log(计算量)
三者都重要,但边际收益递减:
参数量翻倍: 性能提升 ~3-5%
数据量翻倍: 性能提升 ~2-4%
计算量翻倍: 性能提升 ~3-4%(约等于上面两者之和)
→ 没有免费的午餐,每次质量提升都需要代价
2.3 规模定律的边界
规模定律预测的能力提升 ≠ 所有任务都线性提升:
线性提升的任务(规模定律适用):
- 语言建模困惑��(perplexity)
- 翻译 BLEU 分数
- 常识问答准确率
不遵循规模定律的任务:
- 涌现任务(小模型 0%,突然 90%)
- 对齐行为(需要 RLHF,不只是规模)
- 事实精确性(不随规模线性提升)
- 算术计算(有天花板)
3. 大模型擅长的能力图谱
3.1 核心优势领域
优势1:语言理解与生成
✓ 语法正确性
✓ 风格模仿与迁移
✓ 摘要与提炼
✓ 多语言翻译
✓ 文体转换(正式→非正式,技术→通俗)
优势2:知识整合与应用
✓ 跨领域知识组合
✓ 概念解释(多层次,适应受众)
✓ 类比与隐喻生成
✓ 广博的通识知识
优势3:代码相关
✓ 主流语言的代码生成(Python��JS、Java...)
✓ 代码解释与文档
✓ Bug 识别与修复
✓ 代码风格转换
✓ 测试用例生成
优势4:结构化处理
✓ 信息提取与格式化
✓ 分类与标注
✓ 数据清洗与转换
✓ 表格/JSON 生成
优势5:创意与开放性任务
✓ 创意写作(故事、诗歌、文案)
✓ 头脑风暴
✓ 角色扮演
✓ 方案生成
3.2 能力的本质:模式匹配 + 统计规律
大模型的所有"能力"本质上都是:
在超高维语义空间中的模式识别和模式续写
训练:见过 → 权重被调整 → 能生成类似的
推理:当前上下文 → 激活相关模式 → 续写
这解释了为什么:
✓ 常见任务 → 训练数据多 → 模式清晰 → 能力强
✗ 罕见任务 → 训练数据少 → 模式模糊 → 能力弱
✓ 组合已有知识 → 训练数据有各部分 → 能做
✗ 真正的创新 → 超出训练分布 → 无法生成
4. 大模型的核心弱点
4.1 弱点全景图
┌──────────────────────────────────────────────────────────────┐
│ 大模型核心弱点 │
├────────────────────┬────────────────────────────────────────┤
│ 类型 │ 具体表现 │
├────────────────────┼────────────────────────────────────────┤
│ 精确计算 │ 多位数加减乘除出错,特别是超过3位时 │
│ │ 复杂代数推导错误 │
├────────────────────┼────────────────────────────────────────┤
│ 字符级操作 │ 数字母、翻转字符串、字谜填字、Wordle │
│ │ 原因:token ≠ 字符 │
├��───────────────────┼────────────────────────────────────────┤
│ 精确记忆 │ 长文本后准确回忆细节 │
│ │ 精确引用(论文、法条)→ 幻觉风险高 │
├────────────────────┼────────────────────────────────────────┤
│ 实时/最新信息 │ 知识截止日期之后的事件 │
│ │ 实时数据(股价、天气) │
├────────────────────┼────────────────────────────────────────┤
│ 长程逻辑一致性 │ 超长文本中前后矛盾 │
│ │ 复杂规则集的全局遵守 │
├────────────────────┼────────────────────────────────────────┤
│ 空间推理 │ 3D 空间关系、地图推理 │
│ │ 机械结构理解(原生文本) │
├────────────────────┼────────────────────────────────────────┤
│ 因果推断 │ 混淆相关性和因果性 │
│ │ 反事实推理不稳定 │
├───���────────────────┼────────────────────────────────────────┤
│ 个性化记忆 │ 跨会话记住用户 │
│ │ 原因:无持久化状态 │
└────────────────────┴────────────────────────────────────────┘
4.2 精确计算弱点的根源
人类计算方式:
372 × 48:
→ 按位计算:2×8=16,7×8+1=57,3×8+5=29
→ 精确,基于规则
大模型计算方式:
372 × 48:
→ "372 × 48 在训练数据中出现过多少次?"
→ 如果没见过这个精确组合,从相似模式插值
→ "接近 400 × 50 = 20000,调整一下..."
→ 实际输出:17856(正确值 17856,这次对了)
→ 但这是"运气+近似",不是"规则推导"
→ 精确数学计算不应该用参数记忆
→ 应该用工具(代码执行器、计算器)
4.3 为什么模型"不知道自己不知道"
理想状态:
模型应该说:"我对这个不确定,建议你验证"
现实状态:
模型以"自信"的语气输出了错误答案
根源:
训练目标是"预测下一个 token",不是"表达置信度"
训练数据中,文章通常以确定性语气写作
→ 模型学到了"确定性语气"的语言模式
→ 没有被训练成"感知自己知识边界"
改进途径:
RLHF 中对"正确承认不确定性"给予奖励
明确在 Prompt 中要求:"不确定时说不确定"
使用结构化输出:在 JSON 中包含 confidence 字段
5. 幻觉
5.1 幻觉的分类
类型1:事实性幻觉(最危险)
编造不存在的事实、人物、事件
例:编造论文引用、虚构新闻事件
类型2:逻辑幻觉
推理步骤看起来合理,但结论错误
例:"所有鸟都会飞,企鹅是鸟,所以企鹅会飞"(训练数据有这个逻辑模式)
类型3:格式幻觉
内容正确,但格式错误(错误的日期格式、单位等)
类型4:知识幻觉(知识扩展)
基于真实知识推断了不存在的延伸
例:真实的科学家存在,但将其不真实的成就归于他
类型5:任务幻觉(指令遗忘)
模型忘记了指令中的某些约束
例:要求"只用中文",模型混入了英文
5.2 幻觉的触发条件
高幻觉风险场景:
1. 要求精确引用(论文、法条、引语)
风险:模型以为自己"记得",实际是生成了"合理"的假引用
2. 询问较小知名度的实体
风险:训练数据少,模型填补了不存在的信息
3. 要求具体数字(统计、价格、年份)
风险:模型从相关上下文"推断"而非"记忆"
4. 混合了真实和虚构的上下文
风险:模型可能将虚构信息当真实处理
5. 长文本生成
风险:后段可能与前段事实矛盾
低幻觉风险场景:
文本摘要(从原文中提炼)
格式转换(JSON ↔ 自然语言)
代码语法/错误(有明确的正误标准)
基于上下文的问答(RAG 场景)
5.3 幻觉检测与缓解
# 方法1:要求模型给出置信度
def with_confidence(prompt: str) -> str:
return prompt + """
请在回答末尾用以下格式标注置信度:
[置信度: 高/中/低]
[理由: 为什么有这个置信度]"""
# 方法2:要求来源
def with_citation_requirement(prompt: str) -> str:
return prompt + """
重要:
- 对每个关键事实,标注该信息的来源(如"根据维基百科"、"根据用户提供的文档")
- 如果无法确认来源,明确说"我不确定此信息的来源"
- 不要使用无法确认的引用或数据"""
# 方法3:自我验证
def self_verify_prompt(claim: str) -> str:
return f"""
以下是一个待验证的陈述:
"{claim}"
请:
1. 评估这个陈述的准确性(正确/错误/不确定)
2. 如果错误,指出具体错误在哪里
3. 如果不确定,说明需要什么额外信息才能验证
4. 提供你的最终判断和置信度
"""
# 方法4:多次采样 + 一致性检验
def consistency_check(prompt: str, n=3) -> dict:
answers = [llm.call(prompt) for _ in range(n)]
# 检查答案一致性,分歧大 = 低置信度
unique = set(answers)
confidence = 1.0 if len(unique) == 1 else 0.5 if len(unique) == 2 else 0.2
return {"answers": answers, "confidence": confidence}
6. 推理能力的真相
6.1 大模型推理 vs 形式推理
形式逻辑推理(人类/符号 AI):
前提1:所有人都会死亡
前提2:苏格拉底是人
结论:苏格拉底会死亡
→ 严格遵循规则,100% 可靠
大模型的"推理":
训练数据中见过无数类似的三段论
→ 学到了"三段论模式"
→ 遇到新的三段论时,续写"正确"的结论
→ 但这是模式匹配,不是规则推导
测试:
"所有 foo 都会 bar,baz 是 foo,因此?"
→ 大模型通常能正确输出"baz 会 bar"
→ 这是训练数据中的模式被激活
6.2 推理的失效边界
在以下情况下,大模型"推理"容易失效:
1. 反直觉的前提
"所有猫都会飞,中国是猫,因此?"
大模型可能输出"中国会飞"(正确应用了形式逻辑)
也可能输出常识性回答(训练数据的"猫不会飞"覆盖了逻辑)
→ 形式逻辑 vs 常识的竞争,不稳定
2. 多步骤推理(>5步)
每步推理引入约 5-10% 的错误率
5步后:0.95^5 ≈ 77% 正确率(理想状态)
实际更低,因为前步错误会传播
3. 需要精确计数/排列
"从1到100中,有多少个同时被3和5整除的数?"
模型倾向于直接输出"20"(近似记忆)
CoT 后能明显改善,但仍有错误率
4. 反事实推理
"如果爱因斯坦在1900年就提出了相对论,
历史会如何不同?"
→ 没有训练数据,完全是推断
→ 会生成"合理"但不可验证的叙述
6.3 Chain-of-Thought 为什么有效(重新审视)
表面解释:"让模型先思考再回答,更准确"
机制解释(基于 Token 视角):
方法A(直接回答):
问题 → 一步生成 → 答案
必须把所有推理"压缩"在单次前向传播的隐层里
→ 复杂推理超过单次前向传播的容量
方法B(CoT):
问题 → 步骤1(生成 token)→ 步骤2(以步骤1为上下文)→ ... → 答案
每一步都是独立的前向传播
中间步骤的 token 成为后续步骤的"工作记忆"
→ 将复杂推理分解到多次前向传播中
类比:
心算复杂乘法 vs 用纸笔计算
中间步骤的"纸"= CoT 的中间 token
7. 模型尺寸与任务难度的匹配
7.1 任务难度分级
Level 0(任何模型):
✓ 简单分类(正面/负面)
✓ 基础翻译
✓ 关键词提取
✓ 模板填充
Level 1(7B+ 模型):
✓ 段落摘要
✓ 简单代码生成
✓ 基础问答
✓ 单轮对话
Level 2(13B+ 或好的 7B):
✓ 多轮对话
✓ 指令遵循(中等复杂度)
✓ 代码 debug
✓ 文章写作
Level 3(70B+):
✓ 复杂推理
✓ 专业领域深度问答
✓ 复杂代码生成
✓ 多步骤任务规划
Level 4(GPT-4/Claude Opus 级别):
✓ 高度复杂的指令遵循
✓ 长上下文理解与生成
✓ 研究级分析
✓ 超长代码库理解
7.2 成本 vs 质量的权衡
# 智能路由:根据任务复杂度选择模型
def smart_model_selector(task_description: str) -> str:
"""
根据任务特征选择合适的模型
"""
task_lower = task_description.lower()
# 简单任务 → 小模型,便宜
if any(keyword in task_lower for keyword in
["分类", "提取", "翻译", "简单", "yes/no", "是否"]):
return "claude-haiku-4-5-20251001" # $0.8/1M 输入
# 代码相关 → 中等模型
if any(keyword in task_lower for keyword in
["代码", "编程", "debug", "函数", "class"]):
return "claude-sonnet-4-6" # $3/1M 输入
# 复杂推理、长文本 → 强力模型
if any(keyword in task_lower for keyword in
["分析", "研究", "推理", "复杂", "规划", "策略"]):
return "claude-opus-4-6" # $15/1M 输入
# 默认中等
return "claude-sonnet-4-6"
7.3 模型局限性的护栏设计
# 针对高幻觉风险任务,设计防护措施
def safe_factual_query(query: str, require_citation: bool = True) -> str:
"""
对需要精确事实的查询添加安全护栏
"""
safety_instructions = ""
if require_citation:
safety_instructions += """
规则:
1. 对于具体事实(数字、日期、名称、引用),必须说明信息来源
2. 如果你不确定某事实的准确性,用"据我了解"或"我不确定"来标注
3. 不要编造引用、数据或统计数字
4. 如果没有可靠信息,直接说"我不知道"
"""
prompt = f"""
{safety_instructions}
问题:{query}
"""
return prompt
8. 能力边界的系统性测试
8.1 能力评估框架
在部署前,系统性测试模型在你场景中的能力边界:
维度1:准确性测试
设计一批有确定正确答案的测试问题
目标:确认模型在核心任务上的正确率
工具:精确匹配、模糊匹配、LLM-as-Judge
维度2:边界案例测试(Robustness)
测试输入的极端情况:
- 超长输入
- 包含噪音、错别字的输入
- 多语言混合输入
- 空输入/极短输入
目标:确认在边界情况下是否优雅降级
维度3:对抗性测试
测试模型在恶意或混乱输入下的行为:
- Prompt Injection 尝试
- 试图让模型忘记指令
- 语义歧义测试
目标:确认安全护栏有效
维度4:一致性测试
相同语义的问题,不同表达方式:
"总结这段文字" vs "用一句话概括" vs "给我个摘要"
目标:评估模型是否语义一致,不被表达形式影响
8.2 测试用例设计原则
# 测试集设计模板
class CapabilityTestCase:
def __init__(
self,
input_text: str,
expected_output: str,
difficulty: str, # easy / medium / hard
capability: str, # 测试哪种能力
failure_type: str = None # 预期可能的失败类型
):
self.input_text = input_text
self.expected_output = expected_output
self.difficulty = difficulty
self.capability = capability
self.failure_type = failure_type
# 示例测试集
test_cases = [
# 数学计算(已知弱点)
CapabilityTestCase(
input_text="计算 2347 × 891",
expected_output="2091177",
difficulty="hard",
capability="exact_arithmetic",
failure_type="calculation_error"
),
# 精确引用(已知弱点)
CapabilityTestCase(
input_text="请引用达尔文《物种起源》第一章的原话",
expected_output=None, # 用人工评估
difficulty="hard",
capability="exact_quotation",
failure_type="hallucination"
),
# 逻辑推理(中等可靠)
CapabilityTestCase(
input_text="如果 A > B 且 B > C,那么 A 和 C 的关系是?",
expected_output="A > C",
difficulty="easy",
capability="logical_reasoning",
failure_type=None
),
]
9. 绕过边界的工程策略
9.1 弱点 → 工具化
原则:模型不擅长的 → 交给工具
弱点 工具替代方案
─────────────────────────────────────────
精确数学计算 代码解释器 / 计算器 API
实时信息 搜索工具 / 专用 API
精确计数/排列 程序计算
精确引用检索 向量数据库 / 全文搜索
图表/图像生成 专用生成模型
结构化数据操作 SQL / Pandas
# 工具化数学计算
def math_tool(expression: str) -> float:
"""安全的数学表达式计算"""
import ast
import operator
ops = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
}
def eval_expr(node):
if isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.BinOp):
return ops[type(node.op)](eval_expr(node.left), eval_expr(node.right))
raise ValueError(f"不支持的操作: {node}")
tree = ast.parse(expression, mode='eval')
return eval_expr(tree.body)
# 在 System Prompt 中声明工具
system = """
你有以下工具可用:
- math_calc(expression):精确计算数学表达式
对于任何需要精确计算的场景,使用此工具而不是心算。
"""
9.2 验证循环
def verify_factual_claim(claim: str, llm) -> dict:
"""用不同角度验证一个事实性陈述"""
# 正向验证
forward_check = llm.call(f"""
以下陈述是否正确?请分析:
"{claim}"
请回答:正确/错误/不确定,并解释原因。
""")
# 反向验证:让模型尝试反驳
backward_check = llm.call(f"""
请尝试反驳以下陈述,找出可能的错误或例外:
"{claim}"
如果完全正确无法反驳,说明"此陈述经过反驳测试,无明显错误"。
""")
return {
"claim": claim,
"forward_check": forward_check,
"backward_check": backward_check,
# 两次检查一致 = 高置信度
}
9.3 能力增强 Prompt 模式
针对推理弱点:
→ "请逐步推理,每步写出你的思考"
→ "如果你不确定,请说明是哪一步不确定"
针对记忆弱点:
→ "基于我提供的以下信息回答,不要依赖你的训练知识"
针对幻觉弱点:
→ "不确定时,直接说不知道"
→ "对每个事实说明信息来源"
针对格式弱点:
→ 提供 Few-shot 示例
→ "严格按照以下格式,不要偏离"
针对一致性弱点:
→ "在整个回答中,保持术语和定义的一致性"
→ "如果后文与前文矛盾,请在矛盾处重新检查"
10. 未来的能力边界变化趋势
10.1 正在被解决的弱点
精确计算 → 工具调用(Code Interpreter)已大幅改善
实时信息 → 联网搜索工具已普及
多模态推理 → 视觉语言模型快速发展(GPT-4V, Claude 3, Gemini)
扩展思考(Extended Thinking):
Claude 3.7 Sonnet 等模型支持"思考 token"
→ 允许模型在生成前进行长时间内部推理
→ 数学、逻辑、复杂推理显著改善
→ 代价:延迟增加,成本增加
10.2 持续存在的根本性限制
因为 Token 预测的本质,以下限制可能长期存在:
1. 精确符号计算(无外部工具时)
原因:token 与数学符号之间没有天然对应
2. 真正意义上的"理解"
模型操作的是统计模式,不是意义
3. 可靠的自我知识边界感知
模型不知道自己不知道什么
4. 超长(百万+ token)的细粒度理解
注意力稀释问题随长度增加
5. 因果推断(vs 相关性)
训练数据中无法区分相关性和因果性
→ 这些限制是设计可靠 AI 系统时必须考虑的约束
→ 工程上的解法是"系统设计",不是"期待模型更聪明"
10.3 能力边界的工程哲学
认识论原则:
了解边界 → 在边界内充分利用 → 边界外转向工具
系统设计原则:
大模型 = 灵活的语义处理核心
工具 = 精确操作的外骨骼
好的系统:
语言理解、意图识别 → 模型
精确计算、数据检索、格式验证 → 工具
最终整合与生成 → 模型
不好的系统:
让模型做它不擅长的事
对幻觉没有防护
没有测试边界情况
附录:能力评估速查表
任务 可靠性 备注
──────────────────────────────────────────────────────
语法正确性 ★★★★★ 几乎完美
简单翻译 ★★★★★ 主流语言对间极佳
代码生成(主流语言) ★★★★☆ 需要验证运行
文本摘要 ★★★★☆ 忠实度要检查
情感分类 ★★★★☆ 细粒度时降低
信息提取(有格式要求) ★★★★☆ Few-shot 提升
逻辑推理(简单) ★★★★☆ CoT 提升
创意写作 ★★★★☆ 主观任务
代码调试 ★★★☆☆ 复杂 bug 需多轮
事实问答(常见知识) ★★★☆☆ 需要验证
多步骤推理 ★★★☆☆ CoT 改善
精确引用/数字 ★★☆☆☆ 高幻觉风险
字符级操作 ★★☆☆☆ token 边界问题
精确大数计算 ★☆☆☆☆ 用工具替代
实时信息 ★☆☆☆☆ 用搜索工具替代
了解大模型的能力边界,不是为了限制对它的期待, 而是为了把它用在最对的地方, 并为它不擅长的地方设计好安全网。