第 1 节 / 共 12 节

序章:一次 API 调用里发生了什么

在把模型内部拆开之前,先看一遍从"调 API"到"拿到回复"这条链路上,模型到底做了几件事。有了这张全景图,后面的章节就是往这七步里各自填肉。

let reply = await llm.chat(prompt: "今天天气怎么样?")

按下回车之后,大概会有七步:

  1. Tokenizer 分词:把字符串切成一串 token(子词)。"今天天气怎么样?"大约切成 6–8 个 token。字节数变整数 ID,模型只认整数。
  2. Embedding 查表:每个 token ID 到一个大矩阵里查出对应的向量(比如 4096 维浮点数)。文字从此变成数字。
  3. 加位置编码:向量本身不带顺序信息,用 RoPE 或正弦编码把"你排第几位"这条信息注入进去。
  4. 过 N 层 Transformer Block:每层做两件事——Self-Attention(每个词看上下文更新自己)+ FFN(非线性特征提取)。堆 32、64、甚至 100 多层。
  5. Softmax + 采样:最后一层输出一个"下一个 token 是什么"的概率分布。用某种采样策略(贪心 / Top-k / Temperature)从里面选一个。
  6. 自回归循环:把刚采出的这个 token 拼回输入尾巴,回到第 3 步继续算,一个词一个词吐。直到吐出 <EOS> 或达到 max_tokens。
  7. De-tokenize:把生成的 token ID 序列还原成人看得懂的字符串,返回给客户端。

两个阶段影响你能感知到的两个指标:

  • Prefill(第 1–4 步一次性处理完整个输入)→ 决定 TTFT(首字延迟)
  • Decode(第 5–6 步一个个吐 token)→ 决定 TPS(吐字速度)

这两个阶段的瓶颈完全不同,后面第六章会详细讲。

关于 Sampling 和 Temperature:第 5 步里选下一个 token 的方式,就是你在 API 里能调的旋钮。temperature=0 通常接近每次选概率最高的候选,但不同服务端实现、数值精度和并发路径仍可能带来差异;温度升高会把概率分布拉平,让低概率候选更容易被选中。翻译、代码补全这类要稳的场景通常用低温,写故事、头脑风暴可以适当提高。

上面讲的是"用"——推理时这 7 步怎么串起来。下一节讲"造"——这堆参数到底是怎么学出来的。


读完继续 用互动实验验证上面的内容
00 · 互动实验 调用全景

分别观察 TTFT 和总耗时由哪一段工作推高。

100%