CCDV-F 备考手册 · Claude Certified Developer – Foundations
Chapter 06 · Domain 5(本章 skill 权重合计 11.3%)

LLM Fundamentals 与技术底座
tokens、context window、非确定性,与那四个被点名的 model options

这是全书第二重的一章,但它考的不是「你会不会背参数」。blueprint 把 tokens、context windows、sampling、non-determinism、next-token generation 与四个 model options 压进 TS 5.1,把「支撑 AI 应用开发的基础技术概念、与 wrap REST API 的 SDK 集成、websockets」压进 TS 5.2。两条 skill 合起来回答同一个问题:这套系统在哪些地方不像你熟悉的确定性软件,你的集成层该为此做什么准备。本章从「一次生成是怎么发生的」推起,一路推到「同样的 prompt 为什么两次不一样」,再推到四个 option 各自动的是哪个旋钮。

本章的事实纪律 — fast mode、extended thinking、adaptive thinking、effort levels 这四个是 guide 点了名但没给行为定义的机制。本章写到的每一条行为都先查了官方文档并登记(reference/verified-behaviors.md),逐条挂 vb:。查不到行为的地方,本章只说「guide 点了这个名字」,不替它编语义——这正是 ch01 P5「机制按官方职责用」对本书自己的要求。

一、一次生成是怎么发生的:从 next-token 到「两次不一样」

先把最底下那层讲清楚,因为本章后面所有判断都从它长出来。

Claude 底层是一个 autoregressive language model:预训练的目标是「给定文档中此前的上下文,预测下一个词」。官方同时点破了一件常被忽略的事——这样预训练出来的模型本身并不擅长回答问题或遵循指令,要靠 fine-tuning 与 RLHF 才变成一个可用的助手。工程含义:模型的「服从性」是被训练出来的一种倾向,不是一条被执行的规则。这句话你在 ch01 P3 那里已经见过一次,这里是它在模型层的根。

生成的单位不是字符,是 token。官方定义:token 是语言模型的最小单位,可以对应词、子词、字符甚至字节;一个 token 对应多少字符随模型与语言而变——「约 3.5 个英文字符 / token」是官方对 4.7 之前模型的说法,Claude 4.7 及之后的模型换了更新的 tokenizer,同一段文本约多 30% token。所以 3.5 只能当旧模型的量级参考,要精确数字就按目标模型调 token counting。模型每一步从一个概率分布里挑下一个 token,挑完把它接回输入,再挑下一个——「一次回应」就是这个循环跑了很多遍。

既然每一步都是从分布里挑,就有一个控制挑法的旋钮:temperature 控制生成时预测的随机性,高温更有创造性与多样性,低温更保守、更确定、倾向最可能的措辞。到这里为止都是教科书。下面这条不是。

temperature = 0 也不给你确定性
Non-determinism is a property of the system, not a bug in your code

官方原话:使用者可能在 API 上遇到 non-determinism;即使 temperature 设为 0,结果也不会完全确定,相同输入在多次 API 调用之间可能产生不同输出。这一点对 Anthropic 第一方推理服务与第三方云厂商推理同样成立。

为什么这条值得单独立一张卡 —— 它是本章撑起后面很多判断的地基。任何以「同样的 prompt 跑两次结果不同 = 我的代码有 bug / 缓存坏了 / 模型换了」为前提的排查路线,起点就错了。正确的动作是先问「这个差异是不是超出了非确定性能解释的范围」——比如它是不是系统性的(某一天起集体变化 → 走 ch01 P8 的版本轴),还是逐次抖动的(那就是这条)。

边界 — 非确定性不是「怎样都行」的挡箭牌。输出格式不稳定该修的是 schema 与校验(ch01 P7,见 ch10);这条只解释「为什么两次不会逐字相同」,不解释「为什么这次少了一个必填字段」。

口诀:逐次抖动是性质,集体漂移才是事故。

还有一层反转:在最新的模型上,采样旋钮已经不归你转了。temperature、top_p、top_k 在 Claude 4.7 及之后的模型上已 deprecated——设成非默认值返回 400;官方给的替代是「省略它们,用 prompting 引导模型行为」。SDK 层还有一个更硬的表现:Python SDK 从 v1.0 起直接把这三个参数移除了,传进去抛 TypeError。

做题信号 — 题干里出现「我们把 temperature 调到 0 来保证一致性」,先看它跑在什么模型上。在 4.7 及之后的模型上,这句话有两个错:一是它做不到(vb-nondeterminism-o81),二是它现在会直接 400(vb-sampling-deprecated-o82)。这是本章最容易出成陷阱的一处。

二、token 是计量单位:数不准,成本与容量都会算错

token 同时是三样东西的计量单位:context window 的容量、计费的基准、rate limit 的口径。所以「数得准不准」不是细节。

官方提供了一个专门的端点来数:token counting 端点接受与创建 message 相同的结构化输入(含 system、tools、images、PDFs),响应给出输入 token 总数。三条性质要记住:

为什么会咬人:Claude 4.7 及之后的模型使用更新的 tokenizer,同一段输入文本产生的 token 数比更早的模型约多 30%,具体增幅依内容与负载形态而定。官方给的动作很直接:按你准备使用的那个模型重新计数,不要复用在更早模型上测得的计数。迁移场景下这条同时意味着成本估算与 context 容量估算都要重做——同一份 prompt 没改一个字,账单和占用都变了。模型选型与价格的完整讨论在 ch07。

三、context window:它是 working memory,不是仓库

官方定义:context window 指模型生成回应时能够引用的全部文本,包括回应本身;它不同于模型训练用的语料,而是模型的一块 working memory。紧跟着是一句本章最该抄进笔记的话——更大的 context window 让模型能处理更复杂更长的 prompt,但更多 context 并不自动更好:随着 token 数增长,准确率与召回会退化,这个现象叫 context rot。

这正是 ch01 P9「上下文是预算,不是仓库」的官方依据。塞进去要付两笔账:token 的钱,和注意力的稀释——第二笔在这里有了名字。

那么什么算进这个预算?官方的清单是「请求里的一切」:system prompt、messages 里的每一条消息(含 tool result、图片、文档)、以及你的 tool 定义。本轮生成的输出、包括它的 extended thinking,也算。开了缓存时输入计数被拆成 input_tokens / cache_read_input_tokens / cache_creation_input_tokens 三个字段,三者都计入窗口。

再补一条最容易想反的:被缓存的 prompt 前缀仍然占用 context window——prompt caching 改变的是这些 token 的计费方式,不是它们算不算数。「开了缓存所以窗口更宽裕了」是错的。

问题官方答案
历史是怎么增长的每条 user 消息与 assistant 回应都在窗口里累积,此前各轮被完整保留
每轮输入包含什么全部此前历史 + 当前 user 消息;本轮输出成为下一轮输入的一部分
输入本身就超窗所有模型返回 400 invalid_request_error("prompt is too long")
输入 + max_tokens 超窗Claude 4.5 及更新模型上请求被接受;生成触到上限时以 stop_reason: "model_context_window_exceeded" 停止

最后一行是集成层的一个真实分叉:同样是「太长了」,一个是请求被拒(4xx,你的重试逻辑会看到异常),一个是请求成功但输出被截断(2xx,你的解析器会看到半截 JSON)。后者要靠读 stop_reason 才发现,这与 ch02 讲的「先读 stop_reason 再读 content」是同一条纪律。

四、model option 之一:thinking 的两种模式

guide 在同一行里点了 extended thinking 与 adaptive thinking 两个名字。它们不是同义词,也不是新旧两个说法——是两种配置形态,行为差异比语法差异大得多。

adaptive thinking:由模型决定要不要想、想多深

在 Claude Opus 5.5、Opus 5、Sonnet 5.5、Sonnet 5、Fable 5.1、Mythos 5.1、Fable 5、Mythos 5、Mythos Preview 与 Haiku 5.5 上,thinking 已经开着,无需配置;在 Claude Opus 4.8 / 4.7 / 4.6 与 Sonnet 4.6 上,thinking 关着,要设 thinking: {type: "adaptive"} 才开,之后由 Claude 自行决定何时思考、思考多深。

配置上的 display 字段控制思考内容是否被返回:"summarized" 返回摘要,"omitted"(许多型号上的默认值,包括上面 thinking 默认开着的那一批)返回 thinking 字段为空的 thinking block。两种情况下计费相同、多轮回传方式也相同——所以「我没看到 thinking 文本,说明它没思考、没花钱」是错的。thinking token 按 output token 计费,即使文本没返回给你也计费,并与回应文本一起占 max_tokens。

extended thinking(manual 模式):由你给一个预算

manual 模式用 thinking: {type: "enabled", budget_tokens: N} 给每个请求设一个思考 token 预算,Claude 在开始最终回答前对着这个预算思考。官方给它保留的适用场景很具体:当负载要求可预测的延迟、或对思考成本的精确控制时,manual 模式仍然有用。

预算有三条硬规则:至少 1,024(更小的值被 API 拒绝);必须小于 max_tokens(interleaved thinking 是唯一例外);而且——这条最容易记反——它是目标而不是硬上限:实际用量随任务变化,Claude 可能远未用完就停止推理,max_tokens 才是总输出的硬天花板。

可用性是有时限的 — thinking.type: "enabled" 配 budget_tokens 在 Claude 4.6 各模型上已 deprecated(请求仍然成功);Claude 4.7 及之后的模型不支持它,会以 400 拒绝。反过来,在 Claude 4.5 及更早支持 thinking 的模型上,extended thinking 是唯一可用的 thinking 模式——Claude Haiku 4.5 就属于这一类,对它传 type: "adaptive" 返回 400。两个方向的 400 都存在,方向取决于模型代次。

迁移时最该防的不是语法:官方说映射很小——去掉 budget_tokens、设 thinking: {type: "adaptive"}、改用 output_config: {effort: ...} 控制推理深度。但紧接着提醒要预期的是行为差异而不只是语法差异:固定预算下 Claude 每个请求都思考;adaptive 下由 Claude 自行决定要不要思考、思考多少,低 effort 时在简单输入上可能完全跳过思考。一个按「每次都会有 thinking block」写死的下游解析器,会在迁移后的某个简单请求上直接崩掉。

五、model option 之二:effort levels

官方定义:effort 参数让你控制 Claude 回应请求时花多少 token,在「回应的周密程度」与「token 效率」之间用同一个模型做取舍;顶层 effort 参数在所有受支持模型上都可用,无需 beta header(per-message effort 另算,仍是 beta,见下文)。

档位官方描述
max无 token 约束的最高能力
xhigh面向长时程工作的扩展能力
high除 Claude Opus 5.5 与 Claude Haiku 5.5 外,所有支持 effort 的模型的默认档
medium有节制的平衡档;Claude Opus 5.5 与 Claude Haiku 5.5 的默认档
low最省;显著节省 token,能力有所下降

默认档随模型而定:官方原话是把 effort 设成该模型的默认档(Opus 5.5 与 Haiku 5.5 上是 "medium",其他模型是 "high")与完全不设这个参数行为相同。所以「不设 effort 就等于 high」只在 Opus 5.5 与 Haiku 5.5 以外成立,迁移到这两个型号时要重新核对默认工作量。

三条性质决定了它在题目里怎么被考。

其一,它管的是响应里的所有 token。官方列的清单是:文本回应与解释、tool call 与函数参数、以及 thinking(当 thinking 在起作用时)。由此得到两个官方点名的结论——因为它作用于每一个 output token,无论是否开启 thinking 都起作用;以及它影响包括 tool call 在内的全部 token 支出,「更低的 effort 也意味着更少、更简短的 tool call」。所以在 agent 场景里,调 effort 改变的不只是话多话少,是行动的密度。

其二,它是软引导,不是预算。官方原话是 Effort is a behavioral signal, not a strict token budget:低 effort 下 Claude 遇到足够难的问题仍然会思考,只是在同一问题上比高 effort 时想得少。硬天花板不在 effort 这条轴上——官方对 max_tokens 的定性是它 remains the hard ceiling on total output。题干说「必须保证单次调用不超过 N token」时,答案永远不是调 effort。

其三,顶层 effort 是请求级设置,改它会炸缓存。顶层 output_config.effort 作用于整个请求;因为它会被渲染进 prompt,请求之间改它不保留此前轮次的缓存前缀。官方给的操作建议是:依赖长会话缓存命中、而模型又不支持 per-message effort 时,在开头选定一档并保持不变。在 Claude Fable 5.1、Mythos 5.1、Opus 5.5、Opus 5、Sonnet 5.5 与 Haiku 5.5 上(Claude API / Google Cloud;Amazon Bedrock 上的支持范围更窄,以官方列表为准)还有第二条路:per-message effort(beta,需 mid-conversation-output-config-2026-07-01 header)在对话中途换档且保留 prompt cache;其他模型只能在下一个请求改顶层值,缓存从头开始。同一条机制也适用于 thinking 配置——thinking 配置与解析后的 effort 档位都被渲染进 prompt 本身,在 adaptive / enabled / disabled 之间切换、改 budget_tokens、在请求间改顶层 effort 值,都会让此前的缓存前缀失效;per-message effort 是例外——在支持它的型号上,用 messages 里的 role: "system" 消息换档,已缓存的前缀保持不变。

两个控制别混用 — thinking 管「Claude 回答前要不要在 thinking block 里思考」,effort 管「Claude 在整个回应上投入多少工作量」(adaptive 模式下包括思考的频率与深度)。官方专门写了一句警告:不要把 adaptive 当成 effort 值传——adaptive 是一种 thinking mode,不是 effort 档位。这句话本身就是一道现成的干扰项模板。

六、model option 之三:fast mode

fast mode 在 premium pricing 下为受支持的 Claude Opus 模型提供最高 2.5 倍的每秒输出 token;开启方式是在请求上设 speed: "fast"。准入条件分型号:Opus 5.5 上不再需要 fast-mode-2026-02-01 beta header 或申请权限(仍带 header 的请求照常可用);Opus 5 与 Opus 4.8 上它仍是 research preview,要申请权限并带这个 beta header。

这个 option 最重要的一条是「它不改变什么」:fast mode 跑的是同一个模型、同一份权重,只是换了更快的推理配置,智能与能力没有变化;而且提速集中在 output tokens per second(OTPS),不在 time to first token(TTFT)。两句话各自砍掉一整类干扰项:想提质量的不该来这儿,想压首字延迟的也不该来这儿。

维度官方说明
支持的模型Claude Opus 5.5、Claude Opus 5 与 Claude Opus 4.8
可用平台三个型号都可在 Claude API(含 Claude Managed Agents)上用;Opus 5.5 另可用于 Azure 托管的 Claude in Microsoft Foundry 部署,Anthropic 托管的 Foundry 部署不可用
怎么确认真的用上了响应 usage.speed 取值 "fast" 或 "standard"
对不支持的模型请求 fast返回错误;超出 fast mode 限额或容量也会(429 或 529)。但官方点名了一个例外:claude-opus-4-6 带 speed: "fast" 与 beta header 的请求不报错,却按标准速度执行,usage.speed 报 "standard"——所以「没报错」不等于「用上了 fast」,要看 usage.speed
与缓存在 fast 与 standard 之间切换让 prompt cache 失效,不同 speed 不共享缓存前缀
不能同用的Batch API、Priority Tier commitment

把三个 option 并排看,判断轴就出来了:要「想得更周到」调 effort;要「明确控制思考成本与延迟」用 manual 的 budget_tokens(在还支持它的模型上);要「同样的答案更快吐完」用 fast mode。三者动的是三个不同的变量,任何把它们当同义替换的选项都可以先按 ch01 D2 无关杠杆 处理。

七、TS 5.2 的技术底座:SDK 与它包着的那个 REST API

blueprint 在 TS 5.2 里写的是「与 wrap REST API 的 SDK 集成」——这个措辞本身就是考点:SDK 不是另一个产品,它是 HTTP 之上的一层。

官方 client SDK 是面向 Messages API 的通用客户端,覆盖 Python、TypeScript、C#、Go、Java、PHP、Ruby 七种语言;每个 SDK 提供符合该语言习惯的接口、类型安全,以及对 streaming、retries、error handling 的内建支持。文档另外把「libraries and integrations」单列出来并划清了界线:它们把 Claude 暴露在别的框架的 API 表面上,不是通用的 Messages API 客户端。

还有一条边界要记:CLI、client SDK 与 libraries 是「你自己调 Claude API」的工具——你发每一个请求、处理每一个响应;Claude Code、Claude Agent SDK 与 Claude Managed Agents 工作在更高的层级,提供 agent loop、工具执行与运行时。这条线在 ch08 讲 agent 架构时会再用一次。

用 SDK 换来的具体便利里,有两件事值得单独点名,因为它们是「不用 SDK 就得自己写对」的部分:每次 API 请求都必须带 anthropic-version 请求头(例如 anthropic-version: 2023-06-01),用官方 client SDK 时它被自动处理;以及重试——ch02 讲过长请求与流式的取舍,SDK 的内建 retry 就落在那条线上。

八、websockets:blueprint 点了名,但要点清楚它点的是什么

TS 5.2 的措辞里出现了 websockets。这里必须把两件事分开说,否则很容易学错。

第一,Claude 的流式传输机制官方写得很明确,是 SSE(server-sent events)而不是 websocket。事件骨架与集成写法由 ch02 第四节主讲,本章不重复;这里只需要这一句定性。本书没有查证到 Claude API 上的 websocket 端点,因此不写它有;正文与题目里凡出现「连一条 websocket 到 Claude API」的说法,都是本书自制的干扰项。

第二,websockets 作为技术底座概念仍然要会。它属于 SKELETON 说的「ch06 的非 Claude 部分」——工程共识级、可教科书回溯的内容,不需要 vb 登记,但也不得与 guide 冲突。两句话讲完差别:

Server-Sent Events (SSE)WebSocket
方向单向:服务器 → 客户端全双工
承载普通 HTTP 响应,一条长连接上的文本事件流HTTP Upgrade 后切到独立的帧协议
适合一次请求、增量返回一段结果(生成式回应正是这个形状)双方都要随时说话(协同编辑、实时游戏、双向语音)
代价沿用现有 HTTP 基建(代理、鉴权、重试)需要额外处理连接生命周期、心跳、重连与鉴权

把这张表接回本章的主线:一次 LLM 调用天然是「我说一句、你增量地回一段」,不是「双方随时插话」——这就是为什么生成式 API 普遍落在 SSE 那一列。你的应用自己的前后端之间要不要用 websocket,是另一层的架构决定,与调 Claude 用什么传输无关。

九、基础 prompting:zero-shot / single-shot / multi-shot

guide 在 TS 5.1 末尾点了这三个词。它们是通用 ML 术语,区别只在你在 prompt 里放了几个示范:零个(zero-shot,只给指令)、一个(single-shot / one-shot)、多个(multi-shot / few-shot)。

本章只讲这条谱系与它的代价:示例是要占 context 的(第三节),而且在按 token 计费(第二节)。所以往右走一格从来不是免费的准确率——它是拿预算换稳定性,而每加一个示例都会把每一轮请求的输入抬高一截。示例该怎么挑、怎么包、放几个(relevant/diverse/structured 与 3–5 个的建议量)由 ch10 主讲,本章不重复。

本章刻意没写的两类东西,说明一下边界:其一,xhigh 与 max 各自在哪些模型上可用、各模型推荐哪一档,官方文档写得很细,但那是模型选型的面(TS 5.3),归 ch07;本章只讲档位语义。其二,compaction、context editing、tool result pruning 这些「窗口不够了怎么办」的手段属 TS 6.1 的 context engineering,归 ch11;本章只讲窗口本身的性质。fine-tuning 与 RAG 在官方 glossary 里有词条,但 blueprint 未覆盖(RAG/embedding 是 CCAR-P 的 blueprint 项),本书按不考处理。

本章题组

QUESTION 01 · TS 5.1 · NON-DETERMINISM
A regression suite pins claude-sonnet-5 and asserts byte-equality against stored golden outputs for 40 classification prompts. It passes locally and fails in CI roughly 3 runs out of 10, always on a different subset of 2–4 prompts. The diffs are paraphrases: same label, different wording. Model ID, prompt files, and SDK version are identical in both environments. What is the right conclusion?
正确 C官方在 glossary 里把这条写死了:使用者可能在 API 上遇到 non-determinism,即使 temperature 设为 0,结果也不会完全确定,相同输入在多次调用之间可能产生不同输出;第一方与第三方云厂商推理同样如此。题干给的信号(随机子集、措辞级差异、标签不变)正是这条的形状,所以该改的是断言粒度而不是环境。
D2 无关杠杆违反 P6A:题干已经把环境差异排除干净了——model ID、prompt、SDK 全部相同,而失败是随机子集而非稳定集合。区域差异会产生系统性而非抖动性的差异。这一项去修一个数据已经证明运转正常的组件。
D1 凭空捏造违反 P5B:把 temperature 0 说成「移除随机性、保证逐字相同」,与官方原句直接相反。更糟的是它在这个模型上根本传不进去:temperature 在 Claude 4.7 及之后的模型上已 deprecated,设成非默认值返回 400。
D6 半对半错违反 P8D:「浮动别名会指向新 snapshot」这个担心在别的场景真实存在,但方向搞反了——从 4.6 代起,claude-sonnet-5 这样的无日期 ID 本身就是 pinned snapshot,不是 evergreen 指针。而且版本漂移会产生系统性变化,不是三成运行里随机两三条。
QUESTION 02 · TS 5.1 · SAMPLING PARAMETERS
A summarization service is migrated from claude-sonnet-4-5-20250929 to claude-opus-5. The request builder is unchanged and still sends "temperature": 0.2. Every request now fails immediately with a 400 before any tokens are generated; the team's Python service also started raising TypeError after the SDK was bumped to v1.0. What should the team do?
正确 B官方的 deprecation 表写得很直接:temperature / top_p / top_k 在 Claude 4.7 及之后的模型上 deprecated,设成非默认值返回 400,推荐替代是「省略它们,用 prompting 引导模型行为」;Python SDK v1.0 起移除这三个参数,传入抛 TypeError。两个症状同源,一个动作同时解决。
D6 半对半错违反 P5A:前半句摸到了「非默认值才报错」这条边,但后半句自拆——top_p 与 temperature 在同一张 deprecation 表的同一行上,换过去是同一个 400。
D1 凭空捏造违反 P5C:「API 只警告不拒绝」是编的。官方原文是 returns a 400 error。降级 SDK 只能让代码通过类型检查,请求照样被服务端打回——这是把编译期问题当成运行期问题修。
D4 换模型当解法违反 P1D:题干的约束是完成迁移,不是「找一个还能吃下老请求形状的模型」。回退到 Haiku 4.5 意味着放弃这次迁移的全部目标,还把一个确定性的校验失败塞进重试循环——重试一百次是同一个 400。
QUESTION 03 · TS 5.1 · EFFORT IS NOT A BUDGET
A per-seat product bills customers a fixed amount per request and must guarantee that no single Claude call can exceed 8,000 output tokens, whatever the input. An engineer proposes setting output_config.effort to "low" on every request and removing the current max_tokens, arguing that low effort already keeps responses short. Finance needs a guarantee, not a tendency. What should ship?
正确 D官方对 effort 的定性是 a behavioral signal, not a strict token budget,低 effort 下 Claude 遇到足够难的问题仍然会思考;要一个硬上限就得用 max_tokens——它才是 the hard ceiling on total output。题干要的正是 guarantee 而不是 tendency。
D1 凭空捏造违反 P5A:「effort 在服务端生成前施加、因此比客户端上限更可靠」是给一个真实参数安上了它没有的职责。官方的定性恰好相反——effort 是 a behavioral signal, not a strict token budget,而 max_tokens 才是 the hard ceiling on total output。
D6 半对半错违反 P5B:关掉 thinking 确实砍掉一类 token 支出,但 effort 影响的是响应里的所有 token,正文回应本身并没有因此获得上限。「因此不需要显式上限」这半句把一个倾向当成了保证。
D2 无关杠杆违反 P1C:batch 作用的变量是「同步还是异步、单价多少」,不是「单次响应最多能生成多少 token」。题干的约束是每次调用的输出上限,这一项一个字都没碰到它。
QUESTION 04 · TS 5.1 · EFFORT AND THE CACHE
A support agent on claude-sonnet-5 keeps a 40k-token cached prefix (tools plus a policy system prompt) across a long session. To save money the team added logic that drops effort to "low" whenever the user's message is under 20 words, and raises it back to "high" otherwise. Spend went up 30%. cache_read_input_tokens is now near zero and cache_creation_input_tokens is large on most turns. What happened?
正确 A官方两处都写了这条:effort 会被渲染进 prompt,请求之间改它不保留此前轮次的缓存前缀,依赖长会话缓存命中时应在开头选定一档并保持不变;thinking 配置与解析后的 effort 档位都被渲染进 prompt 本身,在请求间改顶层 effort 值会让此前的缓存前缀失效(per-message effort 是例外)。「省钱逻辑反而更贵」正是缓存被逐轮打掉的账。题干钉的是 Sonnet 5,它不支持 per-message effort;若换成 Opus 5.5 / Opus 5 / Fable 5.1,另一条出路是用 per-message effort 换档,它保留缓存。
D6 半对半错违反 P6B:最小可缓存长度确实是一条真实且静默的规则,但它作用于被缓存的前缀,而这里的前缀是 40k token 的 tools + system。何况题干给了 cache_creation_input_tokens 很大——写入一直在发生,长度门槛早就过了。
D1 凭空捏造违反 P5C:把失效原因安到「thinking block 数量改变了历史消息的形状」上。真实机制是配置值本身被渲染进 prompt 因而换了 hash,与这一轮实际产生了几个 thinking block 无关。
D2 无关杠杆违反 P6D:TTL 作用的变量是「同一个前缀能活多久」,而这里的前缀每轮都在变。而且缓存默认 5-minute lifetime 且每次被用到都免费刷新,一个仍在对话中的会话不该靠过期解释。
QUESTION 05 · TS 5.1 · WHAT FAST MODE DOES NOT DO
An interactive coding assistant on claude-opus-5 shows a spinner for 2.1 s before the first character appears, then streams the remaining 3,000 tokens over 9 s. Users complain about "the wait before it starts." A teammate proposes enabling fast mode. What should the reviewer say?
正确 D官方在两处强调同一件事:fast mode 的提速集中在 output tokens per second(OTPS),不在 time to first token(TTFT)。题干把两段时间分得很清楚——2.1 秒是 TTFT,9 秒是吐字阶段;fast mode 能动的是后者。
D6 半对半错违反 P1A:「更快的推理配置」这半句是官方原话,但「整条请求路径按比例变快」是加上去的。官方明说 speed benefits are focused on OTPS, not TTFT,而题干指认的变量恰恰是 TTFT。
D1 凭空捏造违反 P5B:fast mode 不是换模型。官方原句是它跑同一个模型、同一份权重,只换更快的推理配置,智能与能力没有变化。「小一号的延迟优化变体」是给一个真实机制安上了它没有的行为。
D4 换模型当解法违反 P1C:effort levels 是 blueprint 点名的 model option,而把它往上调只会让 Claude 投入更多 token、想得更久,与「更早出第一个字」方向相反。这一项动的旋钮和题干的目标背道而驰。
QUESTION 06 · TS 5.1 · THINKING MODE MIGRATION
A code-review bot has run for a year on claude-sonnet-4-5-20250929 with thinking: {"type": "enabled", "budget_tokens": 12000}. Its post-processor reads response.content[0].thinking to build an audit trail. The team moves to claude-opus-5. Every request now returns 400, and a colleague's quick patch of thinking: {"type": "adaptive"} makes the 400 go away but the post-processor starts throwing on some requests. What is the correct fix?
正确 A三个症状对应三条官方规则。400 的来源:type: "enabled" 配 budget_tokens 在 Claude 4.7 及之后的模型上不被支持、以 400 拒绝。迁移映射:去掉 budget_tokens、设 adaptive、改用 output_config: {effort: ...} 控制深度。post-processor 抛异常的原因也在同一段——adaptive 下 Claude 自行决定要不要思考,低 effort 时简单输入上可能完全跳过思考;再加上新模型上 display 默认 "omitted",不显式要 summarized 就只拿到空的 thinking 字段。
D5 错层承载违反 P5B:adaptive 是真实存在的取值,只是被放错了载体——它属于 thinking 参数,不属于 effort。这不是本书捏造,而是官方专门写过警告的一类错用:不要把 adaptive 当成 effort 值传,adaptive 是一种 thinking mode,不是 effort 档位。而且不设 display 时,Opus 5 这类 thinking 默认开的型号默认 "omitted",「像以前一样读 thinking 文本」也读不到。
D6 半对半错违反 P5C:把 400 归因成「预算超过了上限」。真实原因是这个模型代次整个不支持 type: "enabled",调小预算不会让它被接受。后半句的容错是对的,但建立在一个修不好的前提上。
D2 无关杠杆违反 P6D:把病因诊断成 thinking 被截断。题干说的是某些请求抛异常而不是所有,这与「adaptive 在简单输入上跳过思考」的形状吻合;加大 max_tokens 作用在一个题干没有指认的变量上,那个假定「必有 thinking block」的解析器一行没改。
QUESTION 07 · TS 5.1 · TWO WAYS TO BE TOO LONG
A document QA service on claude-sonnet-5 sends a 900k-token corpus plus max_tokens: 128000. Monitoring shows two distinct failure shapes: a small set of requests returns HTTP 400 with "prompt is too long", while a much larger set returns HTTP 200 whose JSON payload is truncated mid-object and whose stop_reason the client never reads. Which change addresses both?
正确 C题干给的是两类失败,正确项要两类都覆盖。第一类:仅输入就超窗时所有模型返回 400 invalid_request_error("prompt is too long")——用 token counting 端点在发送前估算可以挡住它。第二类:Claude 4.5 及更新模型上 input + max_tokens 超窗的请求会被接受,生成触到窗口上限时以 stop_reason: "model_context_window_exceeded" 停止——那正是「HTTP 200 但 JSON 半截」的来源,只有读 stop_reason 才发现。
D2 无关杠杆违反 P6A:题干已经把源头指认清楚了——一类是稳定的请求校验失败,一类是稳定的生成截断,两类都由请求形状决定,不是瞬时容量。重试作用在瞬时失败上,这里重试一百次得到同样的两类结果。
D1 凭空捏造违反 P9B:「缓存的部分不进 context 记账」与官方原句相反——被缓存的 prompt 前缀仍然占用 context window,caching 改变的是计费方式而不是它们算不算数。缓存能省钱,不能把窗口变大。
D6 半对半错违反 P7D:拿掉 max_tokens 确实能让第二类不再因 input + max_tokens 超窗而触顶,但它对第一类(输入本身就超窗的 400)毫无作用,也没让下游开始读 stop_reason——那个把截断 JSON 当完整结果吞下去的解析器一行没改。
QUESTION 08 · TS 5.2 · TRANSPORT AND THE SDK BOUNDARY
A team is building a browser chat UI. Their Node backend calls Claude and must push partial answers to the browser as they are produced. A design doc proposes: "open a persistent WebSocket from our backend to the Claude API so tokens arrive full-duplex, and a second WebSocket from backend to browser." A reviewer is asked to correct only the Claude-facing half. What is the correct correction?
正确 B官方描述的流式机制是 SSE:每个事件带一个 SSE 事件名并在 data 里带同名 type,内容块由 content_block_start / 若干 content_block_delta / content_block_stop 包住;client SDK 对 streaming、retries、error handling 有内建支持。后端与浏览器之间用什么传输是另一层的架构决定,与调 Claude 用什么无关,评审只被要求改 Claude 那一侧。
D6 半对半错违反 P5A:「全双工对这个模式没有收益」这半句判断是对的,但它保留了「与 Claude 之间要维持一条自建长连接」这个错误前提,还把方案换成了比 SSE 更差的 long polling——增量返回本来就是 SSE 直接提供的。
D1 凭空捏造违反 P5C:整项建立在「存在一条到 Claude API 的 websocket 连接」之上——本书没有查证到这样的端点,官方给出的流式机制是 SSE。这是本书自制的干扰项,无官方出处。为一个不存在的连接去做进程隔离,是典型的「名字听起来合理」型捏造。
D5 错层承载违反 P4D:batch 是给 latency-tolerant、非阻塞的离线负载用的,而题干是交互式聊天、要求边生成边推。用轮询换掉流式,等于把「增量」这个产品需求整个丢掉。