一个被忽视的关键矛盾

如果你在 AI 工程领域待过一阵子,大概率收集过一堆零碎的"经验法则"——Chain of Thought 能提升推理能力、prompt 不能太长否则模型会忽视关键信息、few-shot 例子要风格一致、长对话里模型会"性格漂移"、模型有时会自信地编造事实。这些现象看起来彼此独立,各自有各自的成因,各自有各自的应对方法。

但事实并非如此。这五件事——以及它在工程实践中的更多变种——背后是同一个机制在不同侧面的体现。一旦你理解了这个机制,这些零散的经验法则会突然连成一张清晰的图。本文要做的事情就是把这把"万能钥匙"递给你,然后带你用它打开五扇门。

这把钥匙的核心,是一个我称之为"模型内心与嘴的不对等"的现象。让我先用最少的篇幅把它建立起来。

钥匙的形状:Hidden State 与 Token 的带宽鸿沟

当模型处理一句话时,它内部的"思考"完全发生在一个高维向量空间里。具体来说,每一层 Transformer 在每个位置都维护着一个叫 hidden state 的向量,典型维度是 4096 或 8192。这个向量是模型"内心"的真实载体——它包含了对当前位置的全部理解,包括语义、上下文、潜在选项、风格倾向、置信度等等所有交织在一起的信息。

如果我们粗略估算一下,一个 4096 维的 hidden state 向量,即使每个维度只用 8 比特表达,也是 32768 比特的信息容量。这相当于一张 64×64 的灰度小缩略图能承载的全部像素信息。这是模型"内心"的真实带宽。

现在看模型的"嘴"。当模型要输出一个 token 时,它必须从词表中选一个。如果词表大小是 12 万,那么这个选择的信息量是 log₂(120000) ≈ 17 比特——大约相当于猜中一个 5 位数密码所需要的信息量。

把这两个数字放在一起,你会看到一个惊人的事实:模型内心的带宽是 32768 比特量级,模型嘴的带宽是 17 比特量级,两者相差接近 2000 倍。每生成一个 token,模型都要把它内部那张高保真"小缩略图",压缩成一个低分辨率的"5 位密码"再发出去。

这就是 LLM 工程的核心戏剧冲突——模型的内心是高维丰富的,模型的嘴是低维狭窄的,而当前架构让所有思考都必须经过嘴这个瓶颈来传递。一旦你拿到这把钥匙,LLM 工程里许多看似神秘的现象都会显出它们的真面目。让我们开始开门。

第一扇门:Chain of Thought 为什么有效

Chain of Thought(简称 CoT)是 prompt engineering 领域最著名的技巧之一。做法非常简单:不让模型直接给答案,而是让它先输出推理过程再给答案。在很多任务上,准确率会显著提升——有时候提升幅度大到 20 个百分点。

但请你停下来想一想这件事的奇怪之处。模型本身的能力没有任何变化——参数没动、架构没动、训练没动。只是 prompt 里加了一句"让我们一步一步思考",准确率就大幅提升。它的"额外能力"是从哪里冒出来的?

如果你只用直觉回答,可能会说"因为让模型先写出推理过程,它就能想得更清楚"。这个回答不算错,但它把 CoT 当作了一个魔法,没有解释清楚机制。用我们的钥匙,可以给出一个深刻得多的解释。

当模型直接给答案时,它必须在一次完整的 forward pass 内完成所有推理——也就是说,要在 80 层 Transformer 这固定的计算预算里,既理解问题、又做完算术、还要直接吐出答案。如果问题简单,这没问题;但如果问题需要多步推理,这点计算量根本不够。

而当模型先输出 CoT 时,神奇的事情发生了。生成"让我们先列出已知条件"这句话用了一次完整的 forward pass,生成"基于这些条件可以推出"用了另一次完整的 forward pass,依此类推。如果整个 CoT 输出了 100 个 token,模型实际上经历了 100 次完整的 forward pass,总计算量是单次直答的 100 倍。

所以 CoT 真正做的事情,不是教会模型"如何思考",而是给模型提供了远超单次 forward pass 的总计算预算。它让模型可以把一个复杂问题拆成多步,每步用一次完整的 forward pass 处理。每一步虽然要经过 token 这个 17 比特窄口,但因为有几十几百次步骤累积,总信息量足以解决复杂问题。

这就是为什么 CoT 对简单问题没什么用(单次 forward pass 已经够了),但对多步推理问题效果显著(单次 forward pass 不够,需要多步接力)。这也是为什么 CoT 有一个隐性成本——它消耗大量 token,延迟和成本都更高。CoT 的本质是用 token 数量换计算量,只不过这个交换是隐式的、看起来像免费午餐而已。

理解了这一点,你看 thinking model 这一代模型的设计就清楚了。它们其实就是把 CoT 这个技巧从"prompt engineering 的可选技巧"提升成了"模型架构的内置行为"——模型自动决定要不要 thinking、thinking 多少、什么时候停止。但底层机制是同一个:通过累积多步 forward pass 来突破单步计算量的限制,代价是每一步都要通过 token 窄口接力

第二扇门:Prompt 长度的甜蜜点

你应该听过很多关于 prompt 写作的建议——要详细、要具体、要给例子、要明确角色。这些建议指向"prompt 应该长"。但同时你又会听到另一些建议——要简洁、要聚焦、不要塞太多信息。这些建议指向"prompt 应该短"。哪个对?

答案非常具体,而且能用我们的钥匙清晰解释。

当你给模型一个 prompt,模型的第一件事是把整个 prompt 通过 embedding 转换成 hidden state 序列,然后通过 attention 机制让所有位置的 hidden state 互相影响,最终在最后一个位置形成一个综合了全部 prompt 信息的 hidden state。这个最终 hidden state 决定了模型生成第一个输出 token 时的"心境"。

当 prompt 短的时候,这个最终 hidden state 容易"杂乱"——因为信息太少,模型对要做什么、用什么风格、走哪个方向不够确定,它的内部状态分散在多个可能性上。这种状态下生成的输出往往泛泛、缺乏针对性。

当 prompt 增长到合适长度时,prompt 中的具体指令、例子、约束逐渐"塑形"了模型的内部状态。最终 hidden state 变得清晰且聚焦——模型知道你要什么、不要什么、用什么调性。这种状态下生成的输出针对性强、质量高。这就是 prompt engineering 真正的工作机制——它是在通过 token 输入来雕塑模型的内部 hidden state,让那个高维向量收敛到一个能产生高质量输出的位置上。

但当 prompt 继续变长,问题就出现了。Attention 是一种守恒资源——softmax 让所有 attention 权重之和等于 1,所以上下文越长,每个 token 拿到的注意力份额就越薄。这意味着,当你在已经足够清晰的 prompt 里继续添加信息时,你不再是在让模型的内部状态更聚焦,而是在稀释每一条信息能传递给最终 hidden state 的强度。结果是,核心指令的"声音"被次要信息淹没,模型反而开始忽视一些你认为已经讲得很清楚的东西。

这就是为什么 prompt 长度有甜蜜点。短到不够塑形(模型内部状态太分散),长到过度稀释(关键信号被次要信息淹没),中间有一段最佳区间。这个区间的位置因模型、因任务而异,但寻找它的过程是 prompt engineer 的核心工作之一。

理解了这一点,你就能解释一个看似矛盾的现象——有时候删掉 prompt 里的内容,效果反而变好。这不是"模型不需要那些信息",而是"那些信息在稀释更重要的信息"。优秀的 prompt 工程不是不停加内容,而是在每一条信息和它的稀释成本之间做权衡。

第三扇门:Few-shot 例子的真正作用

继续用这把钥匙。Few-shot prompting,也就是在 prompt 里给模型几个输入-输出的例子,是另一个被广泛使用的技巧。直觉的解释是"通过例子教会模型该做什么"。但这个解释和 CoT 那个一样,虽然不算错,却没说清楚机制。

让我们用钥匙重新看这件事。当你给模型一个 few-shot 例子,例子的"输入"部分会被转换成一段 hidden state,“输出"部分也会被转换成一段 hidden state,它们之间的对应关系通过 attention 机制被模型内部"感知"到。这个对应关系不是被显式提取成"我学到了一个规则”,而是直接体现在模型对接下来类似输入的 hidden state 处理偏置上。

更具体地说,几个 example 之后,当你给出真正的输入时,模型的最终 hidden state 已经被这些 example 拉到了和 example 输出风格相近的方向。这是一种向量空间里的"锚定"——你给的例子越多、越一致,模型的输出 hidden state 就越被锚定在那个方向上,生成的内容就越像例子。

这个视角能解释几个 few-shot 的奇怪现象。第一,例子的多样性会削弱锚定。如果你给三个风格各异的例子,模型的 hidden state 就被往三个方向拉,最终落在某种平均位置,锚定效果反而弱。所以 few-shot 通常需要例子风格一致。第二,example 的"格式"比"内容"更重要。研究发现,即使把 few-shot 例子的输入-输出 label 随机打乱(比如把"正面情绪"和"负面情绪"的 label 互换),模型的表现下降很少。这是因为模型主要从 example 里学到的不是"哪个输入对应哪个 label",而是"输入应该是什么形态、输出应该是什么形态、它们之间应该有什么样的转换关系"——这些都是 hidden state 层面的结构信息,不依赖具体的语义对应。第三,过多的例子收益递减甚至倒挂。这又回到了 attention 稀释——例子太多时,每个例子能贡献的锚定强度反而下降。

所以 few-shot 的本质不是"教学",而是"锚定"。它是通过 token 序列在 hidden state 空间里画出一条轨迹,让模型的输出落在这条轨迹的延长线上。理解了这一点,你设计 few-shot 时就会从"我要教模型什么规则"转向"我要把模型的输出锚定到什么位置",这是一个完全不同的、更准确的操作框架。

第四扇门:模型的"性格"为什么这么难一致

继续走下去,我们来到一个更深的现象——模型的"性格一致性"。

如果你和 Claude 长时间对话,会感觉到它有一种相对稳定的人格——表达方式、价值取向、回应节奏都有某种连贯性。但你也会注意到这种连贯性有时会"破"——某个回答突然变得比平常更冷淡、或某个回答突然过度热情、或者在某些话题上 Claude 似乎变成了另一个 Claude。这种"性格漂移"很多用户都感受过。

为什么会这样?用我们的钥匙看,答案就清晰了。Claude 的"性格"不是一个被显式存储在某个地方的实体,而是 hidden state 在向量空间里的一个稳定吸引域。当对话进行时,每一轮的 hidden state 都被前面所有 token 共同塑造。如果对话内容、用户语气、讨论话题都和"Claude 的典型性格区域"一致,hidden state 就稳定停留在那个区域,Claude 的回应就感觉一致。

但如果某个 token 把 hidden state 推向了一个不寻常的方向——比如用户用极端语气、提到了某个会激活模型不寻常关联的话题、或者在 long context 里某个早期 token 开始通过 attention 反复影响后续——hidden state 就会偏离那个稳定吸引域。一旦偏离,Claude 的回应"调性"就会跟着变,有时候这种变化不大,有时候大到用户立刻觉得"这不像 Claude"。

这就是为什么"jailbreak"(让模型说出它通常不会说的话)的核心机制是精心构造一段 token 序列,把模型的 hidden state 推到训练时人类反馈没有覆盖到的区域。在那个区域里,模型仍然在正常运转,但它的输出特征不再受人类反馈塑造的"性格"约束。这也是为什么 jailbreak 的防御如此困难——你没办法穷举所有能把 hidden state 推到异常区域的 token 序列。

这个视角对作为 agent engineer 的人有非常具体的启发。当你设计 agent 系统时,你的 prompt(SOUL.md、AGENTS.md 这些)其实是在做一件事——把 agent 的 hidden state 锚定在一个稳定的人格/能力区域。你的 prompt 写得越好,这个锚定越强,agent 在长对话中"漂移"的概率就越低。但这不是 100% 可靠的,因为后续 token 总有可能把状态推走。所以 robust 的 agent 设计应该假设漂移会发生,设计监控和回归机制——比如定期注入"复盘指令"重新校准 hidden state、或者在关键决策点重新载入完整 system prompt。

第五扇门:为什么模型会幻觉

最后这扇门通向 LLM 最让工程师头疼的现象——幻觉。

幻觉是指模型自信地说出一些事实上不正确的内容——比如编造一本不存在的书、虚构一个人的履历、给出一个错误的历史日期。直觉解释通常是"模型不知道自己不知道,所以瞎编"。这个解释对一半,但漏掉了机制层面最关键的部分。

用我们的钥匙看。当你问"《XXX》这本书的作者是谁",模型会经过一个 forward pass,在最后一层产生一个 hidden state,然后从这个 hidden state 解码出输出 token。关键问题是:hidden state 空间的结构,决定了哪些输出"看起来合理"。在这个高维空间里,“作者是 A"和"作者是 B"这两个输出对应的 hidden state 通常非常接近——它们都满足"是一个人名”、“在这本书的相关上下文里出现过”、“在文学作品作者的语义簇内"等约束。

如果模型训练时见过这本书的真实作者,那么对应的真实作者 hidden state 会被强化,真实作者会被生成。但如果模型没见过这本书,或见过的次数少到没有形成强信号,那么"作者是 X"这个输出会从一个有合理形态但内容是临时合成的 hidden state 解码出来。模型不是在"瞎编”,它是在生成一个符合空间结构约束的、看起来合理的输出——只是这个输出在事实层面是空的。

更深一层,模型在生成这个输出时,没有任何机制告诉它"我刚才生成的这个名字是真实记忆还是合成"——因为 hidden state 里不存在"真实性 / 合成性"这个独立维度。这是当前 Transformer 架构的一个根本盲点:它的内部状态对"事实记忆"和"合理猜测"不做区分,两者在 hidden state 空间里看起来是一样的。模型对自己输出的"自信"是基于 hidden state 的清晰度,而不是基于这个输出对应的事实是否真的在它的训练数据里。

理解了这一点,你就明白为什么"让模型自己说不确定就输出不知道"这个简单方案不够用——模型在 hidden state 层面就没有那个"我不确定"的信号。RAG(检索增强)、tool use(让模型调外部工具查事实)、grounding(给模型提供权威来源)这些技术,本质上都是绕开"模型自己分辨真假"这个不可能任务,改为外部提供事实约束。这是当前对抗幻觉最务实的做法,而且它的有效性正是因为它正确诊断了幻觉的真实机制。

把五扇门连起来

现在请你停下来,看一眼我们刚刚走过的五扇门:CoT 为什么有效、prompt 长度的甜蜜点、few-shot 的真正作用、模型性格的稳定性、幻觉的根源。这五件事在表面上是 LLM 工程的五个不同话题,但你应该已经感受到,它们背后其实是同一个机制在不同侧面的体现。

那个机制就是我们一开始建立的关键矛盾——模型的内心是 hidden state 空间里的高维丰富认知,模型的嘴是 token 这个 17 比特的低维窄口,而所有 LLM 工程实践,本质上都是在管理"内心和嘴之间的转换"这个核心瓶颈

CoT 在做的事是用多步 token 接力来累积总计算量,绕开单步 forward pass 的限制。Prompt 长度的甜蜜点是在"足够塑形 hidden state"和"不至于稀释关键信号"之间找平衡。Few-shot 是在 hidden state 空间里画轨迹做锚定。Model 性格是 hidden state 在向量空间里的稳定吸引域。幻觉是 hidden state 空间结构的副产品,因为这个空间不区分"真实"和"合理"。

这就是为什么我说,理解了那个关键矛盾,你就拿到了一把万能钥匙。当你以后在工作中遇到任何 LLM 工程问题时,第一反应应该是问自己:这个问题在 hidden state 层面发生了什么?在 token 层面发生了什么?两者之间的转换在哪里出了问题? 这个思考框架会帮你比大多数 prompt engineer 看得深一层,因为他们大多停留在 token 层面试错,而你已经能在 hidden state 层面思考了。

一个供你内化这个框架的练习

最后,我想留一个思考练习,帮你把这个框架真正变成自己的工程直觉。

回想你最近在做的 LLM 相关工作——可能是某个 agent 的 skill 设计,可能是某次 prompt 调试,可能是某个 system prompt 的修改。从中挑一个具体的设计决策或问题,然后用本文建立的"hidden state vs token"框架重新分析一遍:你做的那个决策实际上是在 hidden state 层面影响了什么?它和 token 层面的表现之间是什么关系?如果你重新设计,有没有可能从 hidden state 视角出发找到更好的方案?

这个练习的目的不是让你立刻得出新结论,而是养成用这个框架思考的习惯。几次这样的练习之后,你会发现自己看 LLM 工程问题的视角被永久地改变了。这种视角转变,可能是当今 AI engineer 最有竞争力的差异化能力之一——因为大多数从业者,即使技术 skill 不错,也很少有人能在 mechanism level 解释 LLM 行为。能做到这一点,你在技术深度上会显著领先同等经验的同行。

这把钥匙不会过时。即使未来 Transformer 架构被更先进的模型取代,只要 AI 系统还有"内部表征"和"外部接口"的区分,就会有"内心和嘴的不对等",就会有这个关键矛盾的某种变体。掌握这个思维框架,你掌握的不只是当前 LLM 的解释工具,而是 AI 工程师面对所有内部状态-外部接口分裂系统时的通用心智模型。