大模型是怎么一个字一个字"说话"的?

读完这篇,你会理解 ChatGPT / Claude 输出文字背后的核心机制。

为什么写这篇

最近在工作中深度使用 Claude Code——让 AI 直接读取 Figma 设计稿、写组件、改 Bug,协作下来效率提升很明显。

用得多了自然就好奇:它到底是怎么工作的?输出的文字是怎么一个个生成的?为什么有时候第一个字慢、后面反而越来越快?

带着这些问题研究了一下推理机制,发现核心逻辑其实非常简单——简单到可以用十几行伪代码描述清楚。写这篇就是把自己的理解整理出来,分享给同样好奇的人。


前置知识:从 AI 到 LLM

AI 是一个很大的领域,大致可以这样分层:

AI(人工智能)
└── 机器学习(Machine Learning)
      └── 深度学习(Deep Learning)
            └── 自然语言处理(NLP)
                  └── 大语言模型(LLM)
                        └── 推理(Inference)← 本文讲的

本文聚焦的是「推理(Inference)」——即模型训练完之后,你问它问题,它是怎么一步步产生回答的过程。

注意:这不涉及模型是怎么训练的(Training),只讲已经训练好的模型是怎么"用"的。

什么是大语言模型(LLM)?

LLM(Large Language Model)是一类专门处理文字的深度学习模型,代表产品有 GPT-4、Claude、Llama 等。它们的共同点是:

  • 用海量文本数据训练
  • 基于 Transformer 架构
  • 核心能力是预测下一个词

理解了"预测下一个词",就理解了 LLM 的本质——它不是在"思考",而是在做极其复杂的概率预测。


先说结论

大模型生成文字的过程,就是一个不断猜下一个字的循环:

输入 → 猜一个字 → 把这个字加回输入 → 再猜下一个字 → ...

直到猜出"我说完了"这个特殊信号为止。


用伪代码看懂它

const input = tokenize("你好,今天天气")  // 把输入切成 token(词片段)
const output = []

while (true) {
  const prob = model(input)        // 模型计算:下一个 token 的概率分布
  const token = pickToken(prob)    // 从概率中挑一个 token
  
  if (isEnd(token)) break          // 遇到结束符 <eos>,停止

  output.push(token)               // 记录输出
  input.push(token)                // 把新 token 加回输入,继续循环
}

就这么简单。没有魔法,就是一个 while 循环。


几个关键概念

Token 是什么?

模型处理的不是"字",而是 token(词片段)。

"你好世界"  →  ["你", "好", "世界"]
"ChatGPT"  →  ["Chat", "G", "PT"]

中文大概 1~2 个字一个 token,英文大概 3~4 个字母一个 token。


model(input) 做了什么?

模型拿到所有历史 token,经过几十层神经网络计算,输出一张概率表

"好"    → 32%
"的"    → 18%
"吗"    → 15%
"啊"    → 10%
...(词表里所有词都有一个概率)

这一步叫前向传播,是整个推理里最重的计算。


pickToken 怎么选?

有几种策略,影响输出的"随机性":

策略 做法 效果
贪心(Greedy) 每次选概率最高的 稳定但死板
采样(Sampling) 按概率随机选 有创意但可能乱
Top-P / Top-K 只在概率最高的几个里随机选 平衡质量和多样性

Temperature(温度) 控制随机程度:

  • temperature = 0 → 完全确定,每次输出一样
  • temperature = 1 → 正常随机
  • temperature > 1 → 更随机、更"发散"

为什么输出是"流式"的,一个字一个字出现?

因为模型本来就是一次只生成一个 token,生成完加回输入再生成下一个。

你看到的"打字机效果"不是特效,就是真实的生成过程。


一个显而易见的性能问题

第1轮:model(["你", "好"])              → 计算 2 个 token
第2轮:model(["你", "好", "世"])         → 计算 3 个 token
第3轮:model(["你", "好", "世", "界"])   → 计算 4 个 token

每轮都要重新计算所有历史 token,对话越长越慢。

解决方案:KV Cache

把每个 token 的中间计算结果缓存起来,下一轮只计算新增的那一个 token,历史的直接复用。

第1轮:计算 ["你", "好"]          → 缓存结果
第2轮:直接用缓存 + 计算 ["世"]   → 快很多
第3轮:直接用缓存 + 计算 ["界"]   → 快很多

这也是为什么:第一个字出来慢(在做大量计算),后面的字出来越来越快


整体流程图

用户输入
    ↓
Tokenize(切成 token 序列)
    ↓
┌─────────────────────────────────┐
│  while 循环                      │
│                                  │
│  model(input)                    │
│      ↓                           │
│  概率分布(整个词表)              │
│      ↓                           │
│  pickToken(贪心/采样/Top-P)     │
│      ↓                           │
│  新 token → 加回 input            │
│      ↓                           │
│  遇到 <eos> → break              │
└─────────────────────────────────┘
    ↓
输出所有 token → 拼回文字
    ↓
展示给用户(流式逐字出现)

总结

问题 答案
模型怎么生成文字? 循环猜下一个 token,直到遇到结束符
为什么是流式输出? 每次只生成一个 token,本身就是逐个产生的
为什么越说越快? KV Cache 让历史计算不用重算
Temperature 是什么? 控制随机程度,越高越"有创意",越低越"中规中矩"
Token 是字吗? 不完全是,是比字更细的词片段

理解了这个循环,你就理解了所有大模型推理的底层逻辑——无论是 GPT、Claude 还是 Llama,核心都是这个 while 循环。

posted @ 2026-05-15 10:20  HuangBingQuan  阅读(114)  评论(0)    收藏  举报