一、先破一个幻觉:AI 不是想好再回答

大部分人对大模型有个默认想象:你提问,它在"脑子里"思考、组织语言、打腹稿,然后一口气把答案说出来。

错。而且错得很离谱。

真相是:大模型在任何时刻只干一件事——猜下一个字。

你输入"今天天气真",它做的事和文字接龙里的你一模一样:基于前面的所有内容,猜下一个 token 是什么。猜出"好",把"好"接到句尾,然后基于"今天天气真好"再猜下一个……如此循环,直到它认为"话说完了"。

没错,那个能帮你写代码、改简历、装成苏格拉底跟你辩论的东西,底层就是一个极限版文字接龙大师。

这个认知落差,是理解一切大模型行为的起点。后面你会反复看到:LLM 的所有优点和所有毛病,全都是从"接龙"这个设定里长出来的。

二、文字接龙:祖传手艺,但练了万亿遍

"猜下一个字"听起来简单到侮辱智商。凭什么这个游戏能玩出 ChatGPT?

差别在两件事:练了多少次,猜错了之后怎么处理。

文字接龙你输了会怎样?朋友笑你一下,接着往下玩,什么都不会改变。而大模型的"接龙训练"是这样的:把互联网上几乎所有的文本喂进去,然后拿这些文本反复出填空题——随便挑一段,盖住其中任意一处(一个 token),只让模型看被盖住之前的内容,让它猜盖住的是什么。猜完揭开答案对一下,猜错了就调整内部参数,让它下次在同样的地方猜得更准。一段文本里每个 token 都能被盖住一次,这样的题它做了数万亿遍。

相当于一个人从出生起只玩文字接龙,玩到这个量级,而且每次接错都有人纠正。玩到最后,它对"什么内容后面通常接什么"建立了极其精细的统计直觉:

  • "今天天气真"后面接"好"的概率很高,接"热"也不低,接"抽象"的概率就骤降
  • "public static void"后面接"main"的概率高到几乎必然——它读过太多 Java 代码
  • "1 + 1 ="后面接"2"的概率接近 100%

注意这个措辞:概率。模型不是"知道"1+1=2,而是它见过海量"1+1=2",于是"2"成了压倒性的高概率选项。这个区别现在看着像抬杠,讲到幻觉的时候(第 04 篇)你会回来给它上香。

三、Token:模型眼里的"字"不是你的字

接龙的最小单位是什么?你以为是"字"或"词"。

不是。是 token——一个介于"字符"和"单词"之间的碎片。

模型在训练前会用分词器(比如 BPE 算法)把所有文本切成 token。切法遵循一条朴素的经济学原则:常用的切细,不常用的切块。

用英文看最直观:

  • 常用词 “the”、“hello” → 整词一个 token
  • 生僻词 “tokenization” → 可能拆成 “token” + “ization” 两个 token
  • 中文通常一个字一个 token,部分高频词(如"我们")会被合并

这个设计解释了很多灵异现象,最著名的就是**“数不清 strawberry 里有几个 r”**:

模型看到 “strawberry” 时,收到的不是 s-t-r-a-w-b-e-r-r-y 九个字母,而是 “straw” + “berry” 两个 token。分词这一步做完,字母就没了——模型手里只有这两块,你问它里面有几个 r,它没法拆开来数。早期模型答错字母,是分词这一步造成的,跟它聪不聪明没关系。(2026 年的新模型大多已经通过字符级增强训练修复了这类问题,但机理值得知道——面试时能讲出"为什么错",比背出"现在对了"更能说明你懂。)

Token 还有一个工程上的重要身份:计费单位。API 按 token 收费、上下文窗口按 token 计算,所以你迟早需要建立"一段文本 ≈ 多少 token"的直觉:英文大约 1 token ≈ 0.75 个单词,中文大约 1 字 ≈ 1~2 token。写代码预算成本时,这个直觉就是钱。

四、temperature 和 top-p:给接龙选手调性格

模型猜下一个 token 时,输出的不是单个答案,而是一张概率表:词表里每个 token 都有一个"接下来是我"的分数。比如"今天天气真"之后:

候选 token原始分数(logit)
好8.2
热7.1
冷6.5
抽象1.3
量子-0.4

表里这些分数还不是概率,正负都有、加起来也不等于 1。中间要过一道 softmax,把每个分数换算成 0 到 1 之间、全表加起来正好 100% 的概率。temperature 作用在 softmax 之前(直接改分数差距),top-p 作用在之后(在概率上圈候选)。

第一道:temperature(温度)——把分数之间的差距拉大或压小。

  • temperature → 0:所有分数先除以温度,温度越小,差距拉得越开。"好"和"热"原本只差 1.1 分,温度调到 0.1 就变成差 11 分,"好"的概率被推到接近 100%,模型变得极其稳定保守——每次都选最稳的
  • temperature → 1 以上:温度大于 1,除以它反而把差距压小。温度取 2 时,"好"和"量子"原本差 8.6 分,只剩 4.3 分,冷门选项有了出头机会,模型变得发散有创意

打个比方:temperature 是给员工调性格的旋钮。调到 0,你得到一个一丝不苟、每次输出一模一样的实习生——写代码、按固定格式返回 JSON、算账,用他。调到 1.2,你得到一个才华横溢但偶尔飘走的文案——写广告语、起标题,用他。用错场景的 temperature,是新手最常见的翻车点之一。

第二道:top-p(核采样)——设置候选池门槛。

它说:把候选按概率从高到低排好,从最高的开始把概率一个个累加,累计值达到或超过 p 就停,只留下参与累加的这几个。p 是个比例,不是个数。p = 0.9 的意思是"这些候选的概率加起来占到九成"。拿上面那张表算:“好” 0.66 加"热" 0.22 是 0.88,还不到 0.9;再加"冷" 0.12,累计 0.99,超过 0.9,停——候选池就是这三个,后面的"抽象""量子"进不来。这是给发散度上的第二道保险:temperature 调高之后,靠它拦下"量子"这种离谱候选。

两个旋钮通常只调一个:它们都在管输出有多发散,同时改,效果会叠在一起,出了问题分不清是哪个参数造成的,也复现不出来。

顺带一个工程坑:temperature 调 0 也不保证 100% 复现(机理本篇思考题 1 会问,先留个悬念)。要靠"完全可复现"跑回归测试的,得在应用层加缓存或固定种子,别指望模型参数。

完整采样流程一张图:

模型输出全部 token 的分数
(logits)

temperature 调制
分数除以 T,差距拉大或压小

softmax
分数变成合法概率分布

top-p 过滤
砍掉累计概率之外的尾部候选

按概率抽样
抽出下一个 token

五、生成循环:从你的提问到

现在把所有零件装回去,看一次完整的回答是怎么生成的:

否

是

你的 Prompt
(被切成 token 序列)

拼进上下文窗口

模型基于全部上下文
输出概率表

采样出下一个 token

是结束符
(eos)吗?

把新 token 追加到序列尾部

输出完成

⚠️ 上下文窗口塞满
就会触发截断/遗忘

用伪代码表达,就是不起眼的三层:

tokens = tokenize(your_prompt)          # 你的输入
while not done:
    probs = model(tokens)               # 对全序列预测下一个 token 的分布
    next_token = sample(probs, T, p)    # 按 temperature / top-p 采样
    tokens.append(next_token)           # 追加到尾部
    if next_token == EOS:               # 模型认为话说完了
        done = True
return detokenize(tokens)

三个值得注意的细节:

  1. 每生成一个 token,都要把整个序列重新喂一遍。"今天天气真好"生成到第 5 个字时,前 4 个字也在参与计算。序列越长计算越贵——这就是为什么长输出更费钱、为什么上下文越长响应越慢(工程上有 KV Cache 缓解,详见第 02 篇)。
  2. 结束符(eos)也是"猜"出来的。模型什么时候闭嘴,同样是概率行为。所以偶尔会出现回答到一半戛然而止,或者该停的时候强行加戏——都是 eos 采样没踩准。
  3. 最大 token 数是硬保险丝。max_tokens 到了不管模型想没想完,直接掐断。这就是有些回答"说到一半被砍"的真相。

六、逐字输出的真相:Streaming 不是特效

最后一个日常现象:网页上 AI 的回答是逐字蹦出来的,像有人实时打字。

现在你知道了:它本来就是逐字生成的。所谓"流式输出",只是服务端每生成一个 token 就推一条消息给前端,不攒着。你看到的"打字机效果"不是 UI 特效,是生成过程本身的实时直播。

反过来,那个"转圈圈等回答"的场景(比如某些 API 调用),则是客户端选择等全部生成完再一次性返回。同一个生成过程,两种呈现,差别只在一点:是一个一个往外发,还是攒够了再一起发。

为什么这个真相重要? 因为它决定了你做 AI 应用时的两个体验设计:一是首字延迟(time to first token)比总时长更影响用户感受——用户能接受看它打字,不能接受盯着转圈;二是流式模式下做内容校验,你拿到的是半句话,处理逻辑必须按"增量"设计。这两点在《拆Agent》卷三做生产化时会反复出现。

七、两条边界:它不搜索,也不打腹稿

这两条边界决定了你什么时候能信它:

  1. 它不搜索。 生成时只依赖训练时固化的参数和当前上下文。能联网查资料是应用层外挂的本事(RAG / 联网工具),那是第 08 篇的事。
  2. 它不打腹稿。 它对语言的统计规律掌握得极其精细,细到看起来像真的懂了,但它没有"想好了再说"这一步。明白这条,你就能预判它什么时候靠谱、什么时候翻车。

小结

  • 大模型每一步只做一件事:基于全部上下文,预测下一个 token 的概率分布——极限版文字接龙
  • Token 是切出来的碎片,常用切细、生僻切块;"数不清字母"的灵异现象根源在分词
  • temperature 控发散、top-p 控候选池,两个旋钮只调一个;写代码、按固定格式返回 JSON 用低温,写文案用高温
  • 生成是一个循环:预测 → 采样 → 追加 → 再预测,直到猜出结束符或撞上 max_tokens
  • 逐字输出不是特效,是生成过程的直播——做 AI 应用时首字延迟比总时长更重要

思考题

  1. 把 temperature 设为 0 之后,同一个问题连续问十次,答案仍可能有细微差别。既然不再随机抽样了,差异从哪来?(提示:softmax 要把词表里十几万个分数加总,GPU 不会一个一个顺着加,而是分块同时加、最后再合并,分成几块、按什么顺序合并每次不一定相同。浮点数换个加法顺序,末位就会变。再想想:温度接近 0 时,两个几乎并列的候选会怎样?)
  2. 模型生成到第 1000 个 token 时,第 1 个 token 的信息还在参与计算吗?这对长对话的成本曲线意味着什么?(提示:本篇第五节说了"整个序列重新喂一遍",但这句省略了一个重要的工程优化——它叫 KV Cache。)

高频面试题

Q1:LLM 的推理(inference)过程是怎样的?为什么是自回归的?

A:模型基于已有 token 序列预测下一个 token 的概率分布,采样后将其追加到序列尾部,再以同样的方式预测下一个,直到生成结束符或达到 max_tokens。因为每一步的输出都成为下一步的输入,序列自己喂着自己往前长,所以叫自回归(autoregressive)。每一步里,词表里十几万个候选是同时算出来的,这一步本身很快;但下一个 token 要用上一个的结果,步与步之间只能排队。生成 1000 个 token 就得走 1000 轮,这就是长回答延迟的下限。

Q2:temperature 和 top-p 分别控制什么?生产环境怎么选?

A:temperature 在 softmax 前对 logits 做缩放(除以 T),T 越小分布越尖锐、输出越确定;top-p 在采样前把候选池截断到累计概率 p 以内的头部 token,过滤长尾。二者都控制随机性,通常只调一个:结构化输出、代码生成、分类任务用低温(0~0.3),创意文案、头脑风暴用高温(0.7~1.2)。生产上还要加 max_tokens 兜底和重试策略。

Q3:为什么早期大模型数不对 “strawberry” 有几个 r?

A:因为模型接收的不是字符序列,而是分词器切出的 token 序列。“strawberry” 被切成 “straw”+“berry” 两个 token,字母级信息在分词时被压缩了,模型没有直接的"逐字母视图"。要答对需要模型在内部反演出拼写,这依赖训练数据中的相关文本。2026 年主流模型已通过字符级训练增强大幅改善,但根因是分词机制而非"智力"。

Q4:什么是流式输出?它对应用架构有什么影响?

A:服务端每生成一个 token 就推送一条增量消息(SSE/WebSocket),而非等全部生成完。好处是首字延迟(TTFT)大幅下降,用户感知是"秒回+打字机"。架构影响:前端按增量渲染;后端处理逻辑必须面向流(如逐段解析 JSON 时需要缓冲策略);鉴权与内容审核要在流式语义下重新设计;失败恢复也更复杂——连接中断后已生成的 token 处理策略要提前定义。

系列导航:上一篇 00《大模型从哪来》 → 下一篇 02《上下文窗口与遗忘》:一次能记多长,为什么聊得越久越忘开头

Logo

更多推荐