Chapter 04

自测与跨章辨析

前三章给了原语、机制、选型。这一章不教新东西——它逼你把它们调出来用。三层梯度:先回忆,再讲机制,最后在真实场景里做判别。答案集中在文末一个折叠块里,先做完再看。

怎么用这一章

  • 合上前几章,先凭记忆作答——查得到答案的测试训练不了检索
  • 三层从易到难:概念层(01)→ 原理层(02)→ 应用判别层(综合)
  • 应用判别层是重点:每题都要你在两个方案之间选一个并说理由
应用判别层 强制二选一 · 综合 01+02+03 原理层 为什么这么设计 · 对应 02 概念层 是什么 · 对应 01 迁移度 / 难度 ↑
图 4.1越往上,越靠"把概念调来用"而非"把概念背出来"。注意:顶层只有 5 道题,但它们才是检验你是否真把这套原语内化的部分——做不动顶层、却觉得底层很顺,正是起点警告里的"做题很快"错觉。

§概念层(对应 01)

  1. 一次 LLM API 调用的输入是什么、输出是什么?多轮对话里的"会话状态"由谁维护?§01.1
  2. token 是什么单位?为什么用"字符数"估算成本和上下文长度会出错?§01.2
  3. 流式(streaming)真正改善的是哪一个指标?它让生成更快了吗?§01.3
  4. 工具调用闭环里,模型返回的 tool_use 是给用户的最终答复吗?真正执行函数的是谁?§01.4
  5. JSON mode 和 strict schema 都让模型"输出 JSON",各自不保证什么?§01.5

§原理层(对应 02)

  1. 角色(system/user)为什么能让模型"听话"?把这一点和"prompt injection 为什么有效"连起来讲。§2.1
  2. strict schema 靠什么机制保证输出形状?用一句话描述"logit 掩码"那一步发生了什么。§2.2
  3. 为什么 temperature=0 仍会让两次相同请求输出不同?根因在采样随机数,还是别的层?§2.3
  4. 长上下文为什么又慢又贵?KV cache 在其中扮演什么角色?§2.4
  5. prompt caching 命中需要什么条件?为什么把"当前时间"放在 system prompt 顶部会让命中率归零?§2.4

§应用判别层(综合,强制二选一)

每题都给两个具体方案。先选一个、写下理由,再展开答案对照——重点不是选对,是理由站不站得住。

场景 1 · 原语 × 原语

任务:给 5000 条用户评论批量打情感标签(正/负/中性),结果直接写进数据库。

判别:你会重点用结构化输出还是流式?另一个为什么放弃?这个任务该不该开 reasoning 模型的高 effort?

场景 2 · 选型 × 机制 × 供应方

任务:对一份 30 万字的合同做问答;数据合规要求绝对不出公司机房。

判别:选哪类供应方(云上某家 / 自托管开源)?结构化输出要走原生 SDK 还是 OpenAI 兼容层?哪一个判断在决策树里一票定音?

场景 3 · 机制 × 机制

现象:LLM 网关账单某天暴涨约 10×,但请求数和往常一样。

判别:最常见的两个根因是什么?分别回扣哪个机制?你会先查哪一个、怎么验证?

场景 4 · 原语 × 机制

现象:客服 agent 偶尔陷入"反复调用同一个失败工具"的死循环,烧光预算。

判别:这个故障的根因属于哪个原语的失败模式?给两种止损手段,并说明它们分别拦在闭环的哪一步。

场景 5 · 机制 × 供应方

任务:下游报表系统严格依赖 {status, eta, carrier} 三个字段。为省钱你想从 GPT-5.5 换到更便宜的模型 + 网关路由。

判别:换家时必须守住的"不可让步项"是什么?哪一条请求路径绝不能走兼容层?为什么 valid-but-wrong 在这里比"贵一点"更危险?

亲手画一张图

合上教程,在纸上或 Excalidraw 里画出整套 LLM API 的概念地图——只画中心那个模型 + 5 个脚手架节点 + 箭头方向就够。画完回到起点的图 0.1 对照:你画的箭头方向对吗?"工具调用"那条,箭头是从模型指出来(它 emit 一个提议)、还是指向模型(它自己执行)?这一笔画对了,说明一句话本质真进了脑子。

§答案

全部答案(三层都做完再展开)

概念层

  1. 输入是"角色标注过的整段对话"(messages),输出是模型续写的下一段 assistant 内容。会话状态由你的客户端维护——服务器无状态,每次调用都要把完整历史重发。
  2. token 是模型的子词单位(BPE 切分),约 0.75 个英文词 / 1–2 个汉字。用字符数会出错,因为切分不是按字符、且各模型 tokenizer 不同;上下文上限和计费都按 token,不按字符。
  3. 改善的是首字时间(TTFT)/ 感知延迟,不是生成总速度。总时长不变,只是让第一个字更早出现。
  4. 不是最终答复,是中间步——模型只 emit 了"想调用 X(参数)"的 token。真正执行函数的是你的代码;执行完把结果喂回,模型才给最终答复。
  5. JSON mode 不保证形状(字段可能缺/错/类型不符)也不保证完整(截断成半个对象);strict schema 保形状,但代价是 schema 需可编译、部分特性(递归等)不支持。

原理层

  1. 角色是模型训练时学会服从的特殊 token(如 ChatML 定界符),生效靠训练分布而非服务端权限校验。所以模型只能从风格上区分 system 与 user,无法证明指令来源——把"忽略上面指令"塞进 user 或工具结果里,模型可能照做,这就是注入。
  2. 把 schema 编译成语法/状态机,每步用一个 logit 处理器把"违反当前语法状态"的 token 概率设为 −∞ 再采样——非法形状的 token 概率归零,所以不可能被采到。
  3. 不是随机数。根因在推理 kernel 不是 batch-invariant:请求被拼进动态 batch,浮点求和顺序随 batch 大小变化,而浮点加法不满足结合律,末位误差逐 token 放大成不同分叉。
  4. decode 每步都要看前面所有 token;KV cache 把每个 token 的 Key/Value 存下来供复用,避免重算,但它随 token 线性增长、占满显存带宽——所以长上下文又慢(带宽受限)又贵(cache 大)。
  5. 命中要求缓存的前缀逐字节相同。时间戳每秒都变,放在顶部会让整个前缀每次都不同,后面再长的固定内容也全部失效、全价重算。动态内容必须放在缓存断点之后。

应用判别层

  1. 场景 1:重点用结构化输出(标签要进数据库,必须是可靠的枚举字段,strict schema 把 label 限定在三选一)。放弃流式——批处理没有"人盯着等"的场景,TTFT 无意义,流式只增加解析复杂度;这类任务更该用 Batch API(约 5 折)。不开高 effort reasoning——情感分类是简单任务,开高 effort 纯烧 token。
  2. 场景 2:选自托管开源(vLLM + 长上下文开源模型)。结构化输出走推理引擎自带的约束解码(自托管下没有"原生 SDK vs 兼容层"问题,引擎直接管)。决策树里"数据是否不能出境"一票定音——硬合规约束先于任何能力/价格考量,直接锁进自托管支。30 万字(30 万+ token)再叠加长上下文要求。
  3. 场景 3:两个最可能根因——① prompt cache 未命中反噬(前缀被破坏,每次付 1.25× 写入却命中不了 0.1× 读取,§2.4);② 忘设 max_tokens / 输出失控导致 completion token 暴涨(§2.6)。先查缓存命中率指标和前缀是否稳定(更隐蔽、更常见),再查 max_tokens 配置。
  4. 场景 4:根因属于工具调用原语的失败模式(失败结果原样喂回 → 模型反复重试,§01.4 / §2.6)。两种止损:① 限制每轮工具调用次数(拦在"喂回—再请求"这一步,超限就跳出循环);② 工具失败时返回结构化的错误信息而非原始报错、并在若干次后把 tool_choice 复位为 auto,让模型有机会停下来给文字答复。
  5. 场景 5:不可让步项是结构化输出的形状保证——下游严格依赖三字段,少一个或类型错会让报表系统崩或算错。这条路径绝不能走兼容层:兼容层会丢掉 strict 保证(§3.2 边界),退化成"倾向"而非"保证"。valid-but-wrong 比"贵一点"危险,是因为它静默产出错误数据、下游照单全收,等发现时已污染一片;而贵只是钱的问题,可见、可控。
收尾 · 一句话自检

不看任何材料,把这套教程的"一句话本质"复述出来

如果你能脱口而出"LLM API 的一切都是围绕一个无状态、只输出 token 的函数搭的脚手架",并能就着这句话推出"工具为什么要你执行、会话为什么要你维护、结构化为什么靠掩码"——那这套原语已经是你的了。说不顺,回 起点的概念地图 再走一遍。