📚 首页 / 05-prompting-structured-output / README.md

模块 05 — 提示工程与结构化输出 (Prompt Engineering & Structured Outputs)

定位:把「会聊天」的 Claude 变成「能接进系统」的组件。本模块覆盖三件事:提示工程 (Prompt Engineering) 的官方原则、结构化输出 (Structured Output) 与 JSON schema 校验、few-shot 示例 (Few-shot Examples),以及 extended thinking 的当前官方说法(2026 年已发生重大变化,见 Part D)。
📘 重要英语词汇:模块 05 词汇表

0. 学习目标

🎯 学习重点:先建立「软提示、硬约束、语义校验」三层边界,这是本模块所有考题的总框架。

读完本模块你应能:

  1. 按官方最佳实践写出清晰、可维护的 prompt(含 XML 结构、role、few-shot)。
  2. 解释 结构化输出 (Structured Output) 的两个互补特性:JSON outputs(output_config.format)与 strict tool use(strict: true),以及它们为什么比「求模型输出 JSON」可靠。
  3. 设计「生成 → 校验 → 重试/修复」的容错管线,并知道哪些错误类型能被 constrained decoding 消灭、哪些不能。
  4. 说清 extended thinking 与 adaptive thinking 的演进(截至 2026-08-30 官方状态)。
  5. 在「prompt 调整 / 更大上下文 / 更好检索 / 换模型」之间做正确的第一反应(为模块 07 铺垫)。

1. 提示工程原则(以官方文档为准)

🎯 学习重点:高频考点是 eval-first、长文档在前/查询在后、XML 分区,以及正向指令优于否定式指令。

官方入口是 Prompt engineering overview,其中明确:所有提示技巧的「活参考」是 Prompting best practices 一页(来源:https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/overview,访问于 2026-08-30)。

官方还强调「先有评估再做提示工程」:动手改 prompt 前,先有 ① 明确的成功标准 ② 能实证测试的方法 ③ 一版草稿 prompt。没有评估,你无法知道改动是变好还是变坏(来源:同上 overview,访问于 2026-08-30)。

🔪 犀利细节|别把所有失败都归咎于 prompt:若失败来自缺证据,应先修检索;来自上下文塞不下,应重做切块/压缩;来自契约不稳定,应上 schema。反模式是不断追加「务必、绝对、再次强调」,正解是先按失败类型路由,再用固定评估集验证单一变量的改动。

1.1 核心原则速览(均出自 Prompting best practices,访问于 2026-08-30)

原则要点反例 → 正例
清晰直接 (Be clear and direct)把 Claude 当作「聪明但没有上下文的新同事」;想要什么就明说。黄金法则:把 prompt 给一个不了解任务的同事看,他若会困惑,Claude 也会「做个分析仪表盘」→「做个分析仪表盘,包含尽可能多的相关功能和交互,做完整实现」
给指令加背景 (Add context)解释「为什么」要这样,模型能从中泛化「永远别用省略号」→「你的回复会被 TTS 引擎朗读,省略号无法发音,所以不要用」
正向表述告诉模型做什么,而不是不做什么「不要用 markdown」→「用流畅的散文段落作答」
XML 标签结构化 (Structure prompts with XML tags)指令、上下文、示例、变量输入分标签包裹,减少歧义;标签命名保持一致混在一大段文字 → <instructions>…</instructions><context>…</context><input>…</input>
角色设定 (Give Claude a role)system prompt 里一句角色定位即可显著聚焦行为与语气无角色 → "You are a helpful coding assistant specializing in Python."
长上下文排布 (Long context prompting)长文档放 prompt 顶部,查询/指令放末尾;多文档用 <document index="n"> 包裹并带 <source> 元数据官方测试中「查询放末尾」最多带来 30% 的质量提升

1.2 让回答「先引用再作答」(grounding 技巧)

处理长文档时,官方建议先让 Claude 把相关原文引用放进 <quotes> 标签,再基于引用作答。这迫使模型「贴着证据走」,也是模块 07 RAG 中 groundedness 思想在提示层的雏形(来源:https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices,访问于 2026-08-30)。

1.3 Prefill 已被淘汰(重要架构变化)

预填充 (Prefill)——在最后的 assistant 消息里塞半截话让模型续写——自 Claude 4.6 系列与 Claude Mythos Preview 起不再支持,请求会返回 400 错误。官方给出的迁移路径(来源:同上,访问于 2026-08-30):

旧 prefill 用途官方迁移方案
强制 JSON/格式Structured Outputs(本模块 Part B)或带 enum 字段的工具
去掉开场白system prompt 直接指示「不要以 Here is… 开头」;或 XML 标签包裹输出
绕过误拒答新模型拒答判断已大幅改善,直接在 user 消息里说明意图
续写被打断的回答把末尾文本放进 user 消息请它继续
架构师视角:凡是你在旧教程里看到「用 prefill 保证输出格式」的设计,一律视为过时——改用 schema 约束。

2. 结构化输出 (Structured Output):从「祈祷」到「保证」

🎯 学习重点:必考 JSON outputs 与 strict tool use 的职责分工,以及 constrained decoding 只保证结构、不保证事实。

2.1 为什么需要

不用结构化输出时,即使 prompt 写得再好,仍会遇到:JSON 语法错误、缺必填字段、类型不一致、违反 schema 需要重试(来源:https://platform.claude.com/docs/en/build-with-claude/structured-outputs,访问于 2026-08-30)。

结构化输出通过 约束解码 (constrained decoding) 解决:API 把你的 JSON schema 编译成文法 (grammar),在解码时直接禁止生成不合法的 token 序列。官方承诺(同上):

2.2 两个互补特性

结构化输出 = JSON outputs + strict tool use
             (output_config.format)   (strict: true)

两者可独立使用,也可同请求组合:agent 工作流里「工具调用参数可靠 + 最终回复是结构化 JSON」。

2.3 最小示例(Python,需 ANTHROPIC_API_KEY)

import anthropic

client = anthropic.Anthropic()  # 从环境变量 ANTHROPIC_API_KEY 读取

response = client.messages.create(
    model="claude-sonnet-4-6",  # 模型名截至 2026-08-30
    max_tokens=1024,
    messages=[{"role": "user", "content":
        "Extract the key information from this email: John Smith (john@example.com) "
        "is interested in our Enterprise plan and wants to schedule a demo."}],
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "email": {"type": "string"},
                    "plan_interest": {"type": "string"},
                    "demo_requested": {"type": "boolean"},
                },
                "required": ["name", "email", "plan_interest", "demo_requested"],
                "additionalProperties": False,
            },
        }
    },
)
print(next(b.text for b in response.content if b.type == "text"))
# 输出保证是合法 JSON,且字段齐全、类型正确

(改写自官方 Structured outputs 文档示例,来源:https://platform.claude.com/docs/en/build-with-claude/structured-outputs,访问于 2026-08-30)

Python SDK 还提供 client.messages.parse() 助手:可直接传 Pydantic 模型作为 output_format,返回 response.parsed_output 自动完成解析与校验(同上)。

历史注记(考试可能考旧名):该功能曾以 beta header structured-outputs-2025-11-13 提供、参数名为 output_format;现 GA 参数为 output_config.format。Python SDK v1.0+ 不再接受 beta.messages.create() 上的 output_format(会抛 TypeError)(同上,截至 2026-08-30)。

2.4 Schema 能力与限制(架构师必读)

支持:基本类型、enum(仅字符串/数字/布尔/null)、const、anyOf/allOf(部分)、$ref/$defs(内部)、default、required、additionalProperties(对象必须为 false)、字符串 format(date、email、uri、uuid 等)、minItems(仅 0/1)。

不支持(会返回 400):递归 schema、enum 内复杂类型、外部 $ref、数值约束(minimum/maximum)、字符串约束(minLength/maxLength)、数组约束(除 minItems 0/1)。正则支持子集——不支持反向引用、前后瞻断言、词边界(来源:同上,访问于 2026-08-30)。

复杂度硬限制(每请求合计):

限制值说明
strict 工具数20带 strict: true 的工具
可选参数24所有 strict schema 中不在 required 里的参数总数
union 类型参数16用 anyOf 或类型数组的参数总数(编译开销指数级)

超限策略(官方建议):只把关键工具标 strict;能 required 就别 optional;扁平化嵌套;拆分请求(来源:同上)。

两个隐蔽坑:

  1. 属性排序:输出中 required 属性永远排在 optional 属性前面(schema 内部顺序只在同组内保持)。
  2. enum 大小写:枚举值可能大小写不完全匹配(如 schema 是 "conversation topic 3" 却输出 "Conversation Topic 3"),且不会报错。官方建议:枚举值比较时做大小写不敏感处理,避免仅大小写不同的枚举值(来源:同上)。

合规:结构化输出下 prompt/响应按 ZDR 处理;但 JSON schema 本身会缓存最长 24 小时,且 HIPAA 场景下 schema 定义里不得包含 PHI(属性名、enum、const、pattern 里都不行)(来源:同上)。

兼容性:与 Batch(50% 折扣)、token counting、streaming 兼容;与 Citations 不兼容(返回 400)(来源:同上)。

🔪 犀利细节|硬限制要在设计期消化:20 个 strict 工具、24 个 optional 参数、16 个 union 参数都是每请求合计,不是单个 schema 各自重置。反模式是把整个工具注册表全部标 strict;正解是按当前步骤只暴露必要工具,并把真正可缺省的字段压到业务层处理。这样同时缩小 grammar 状态空间和工具误选面。

2.5 端到端架构:校验与重试仍然要留

约束解码消灭的是格式类错误;它不保证语义正确(字段值可能事实错误),也不覆盖不支持该特性的模型/平台。生产管线仍应是:

flowchart LR A[应用构造请求<br/>prompt + JSON schema] --> B[Claude API<br/>constrained decoding] B --> C{本地校验<br/>jsonschema / Pydantic} C -- 通过 --> D[下游处理] C -- 不通过/拒绝 --> E{错误类型} E -- 格式类 --> F[重试或修复式重问<br/>带错误信息] E -- 语义类 --> G[评估/人审/降级路径] F --> B

要点:

🔪 犀利细节|重试预算按错误类型花:同一请求原样重试只能利用采样波动,无法修复错误契约或缺失证据;把 validator 的精确错误反馈给修复轮才有新增信息。若 JSON 已合法但业务值错误,应停止格式重试,转业务规则、groundedness 评估或人审,避免用额外延迟和输出 token 掩盖分类错误。

3. Few-shot 示例(多示例提示, Multishot Prompting)

🎯 学习重点:记住 3–5 个、Relevant/Diverse/Structured 三原则,并能解释「schema 管形、few-shot 管神」。

官方定位:示例是「引导输出格式、语气、结构最可靠的手段之一」。几个精心构造的示例(称为 few-shot 或 multishot prompting)能提升准确性与一致性(来源:https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices,访问于 2026-08-30)。

官方对示例的三条要求:

  1. 相关 (Relevant):贴近真实用例。
  2. 多样 (Diverse):覆盖边界情况,且足够多样,避免模型学到意外模式(例如全是你偏好的答案分布)。
  3. 结构化 (Structured):用 <example> 标签包裹(多个用 <examples>),让模型分清「示例」与「指令」。

官方建议 3–5 个示例效果最好;还可以让 Claude 评估你的示例集是否足够多样、或基于初始集生成更多(同上)。

3.1 few-shot 的架构权衡

维度few-shot结构化输出
控制对象风格、语气、判断口径、格式「感觉」输出的语法合法性
保证强度软引导(大概率遵循)硬保证(文法约束)
成本示例占输入 token;配合 prompt caching 摊薄schema 编译有复杂度限制
失效模式学到示例偏差;边界漂移语义错误、枚举大小写

实践:两者叠加——schema 管「形」,few-shot 管「神」。分类任务里 schema 的 enum 限定候选集,few-shot 示例教会模型边界案例怎么分。

🔪 犀利细节|示例是持续输入税:每个示例都会进入输入 token;总增量约等于「单次示例 token × 请求次数」,缓存命中时才可摊薄重复前缀成本。反模式是为覆盖率无限堆例子;正解是保留 3–5 个区分度最高的代表样本,把其余边界案例放进离线评估集。

4. Extended Thinking:当前官方说法(重大变化,截至 2026-08-30)

🎯 学习重点:易错点是 4.6 弃用但仍可用、4.7+ 直接 400,以及 adaptive + effort 的迁移路径。
本节是该模块最需要「核验」的部分。网上大量教程仍教 thinking: {type: "enabled", budget_tokens: N}——这在最新模型上已经失效。

官方 Extended thinking 文档顶部警告(来源:https://platform.claude.com/docs/en/build-with-claude/extended-thinking,访问于 2026-08-30):

手动模式遗留规则(仍在 4.5/4.6 上运行存量系统时需要懂):

迁移配方(官方):

# 旧(≤4.6 模型):手动预算
thinking={"type": "enabled", "budget_tokens": 10000}

# 新(4.6+/4.7+ 模型):adaptive + effort
thinking={"type": "adaptive"},
output_config={"effort": "high"}   # effort 档位见官方 effort 文档

(来源:https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices 迁移示例,访问于 2026-08-30)

架构判断:什么时候要 thinking? 多步工具循环、复杂编码、长程 agent 任务收益大;简单问答开了只增加延迟与成本。adaptive 模式下可以通过提示词引导触发(例如「Thinking adds latency… When in doubt, respond directly」)(同上)。

🔪 犀利细节|thinking 不是免费准确率旋钮:思考 token 计入输出 token,且用户等待时间包含思考阶段。反模式是全流量固定高 effort;正解是按任务复杂度分流,简单抽取直接答,复杂规划再启用 adaptive,并分别观察质量、thinking tokens 与端到端延迟。

5. Bad vs Better 架构对比

🎯 学习重点:能逐项指出软格式指令、裸解析、未校验入库三种事故点,并给出对应防线。

场景:客服系统要从用户邮件里抽取工单字段(主题、紧急度、产品线),写入数据库。

Bad(三个真实事故点)

# ❌ 事故点 1:靠 prompt 求格式,无保证
prompt = "请把邮件内容总结成 JSON 返回,格式:{\"topic\": ..., \"severity\": ...}"
raw = call_llm(prompt)
# ❌ 事故点 2:裸 json.loads,坏输出直接崩
ticket = json.loads(raw)
db.insert(ticket)   # ❌ 事故点 3:类型/取值没校验就入库

失败模式:模型有时加 ``json 围栏、有时漏 severity、有时写 "高" 而不是 "high"` → 生产环境随机 500、脏数据入库。

Better

SEVERITY = {"low", "medium", "high", "urgent"}
SCHEMA = {
    "type": "object",
    "properties": {
        "topic": {"type": "string"},
        "severity": {"enum": ["low", "medium", "high", "urgent"]},
        "product_line": {"type": "string"},
    },
    "required": ["topic", "severity", "product_line"],
    "additionalProperties": False,
}

resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    messages=[{"role": "user", "content": f"<email>{email}</email>"}],
    output_config={"format": {"type": "json_schema", "schema": SCHEMA}},
)
ticket = json.loads(next(b.text for b in resp.content if b.type == "text"))
# 兜底:enum 大小写不敏感归一(官方已知行为)
ticket["severity"] = ticket["severity"].lower()
assert ticket["severity"] in SEVERITY
db.insert(ticket)

改进点:① schema 约束消灭格式错误;② enum 限定取值域;③ 已知坑(大小写)显式归一化;④ <email> XML 标签隔离用户输入,降低注入面(详见模块 11)。

若目标模型/平台不支持结构化输出:退级方案 = prompt 里贴 schema + few-shot 示例 + 本地校验 + 带错误信息的重试(见 examples/validate_retry_harness.py,本仓库可无 key 运行演示该回路)。

6. Tradeoffs 总表

🎯 学习重点:场景题要沿可靠性、token 成本、延迟、schema 复杂度四条轴做选择,而不是背单一最佳方案。
决策选项 A选项 B权衡轴
格式保证prompt 描述格式(软)结构化输出(硬)灵活性 vs 可靠性;schema 复杂度限制
可选字段尽量 required保留 optional每个 optional 翻倍文法状态空间;24 个上限
thinkingadaptive + effort 控制不开/提示词抑制质量 vs 延迟/成本;模型代次决定可选集
few-shot3–5 个精选示例零示例输入 token 成本(用 prompt caching 摊薄) vs 一致性
修复策略重试原请求把校验错误拼进 prompt「修复式重问」后者更快收敛但多一轮延迟
枚举enum 约束自由文本 + 后处理enum 硬保证取值域但需大小写归一

7. Common Mistakes(常见错误)

🎯 学习重点:重点排雷 24 optional 上限、enum 大小写、Citations 不兼容、PHI 进 schema 与旧 prefill 五类陷阱。
  1. 把「prompt 里写了格式」当「有格式保证」——软指令永远有漏网率;能上结构化输出就上。
  2. schema 塞满 optional 参数——撞 24 个可选参数上限,且文法编译指数变慢。
  3. 在 4.7+ 模型上继续传 budget_tokens——直接 400;换 adaptive thinking + effort。
  4. 长对话里频繁改 thinking 配置——prompt cache 反复失效,成本翻倍。
  5. enum 比较不做大小写归一——官方文档明示的已知行为,别当 bug 报。
  6. few-shot 示例全部同构——模型学到的是你示例的偏差,不是任务的规律。
  7. HIPAA 场景把 PHI 写进 schema(属性名/enum/pattern)——schema 缓存不走 PHI 保护。
  8. 对语义错误做无脑重试——重试只对格式类错误有效;语义错误要评估管线兜底。
  9. 还在用 prefill 强制格式——4.6+/Mythos Preview 返回 400;改结构化输出。

8. 重要英文术语

🎯 学习重点:考试需精确区分 Structured Output、Constrained Decoding、Strict Tool Use 与 Groundedness,不能混用。
英文中文一句话
Prompt Engineering提示工程通过设计与迭代 prompt 来控制系统行为
Structured Output结构化输出用 schema 约束模型输出为合法结构化数据
Constrained Decoding约束解码解码期用文法禁止非法 token,而非事后校验
JSON SchemaJSON 模式描述 JSON 结构与约束的标准
Strict Tool Use严格工具使用strict: true 保证工具名与入参过 schema
Few-shot / Multishot Prompting少样本/多样本提示在 prompt 中给示例引导输出
Zero-shot零样本不给示例直接要求任务
Prefill预填充旧技巧:预填 assistant 半句话控制输出(已淘汰)
Extended Thinking扩展思考手动 budget_tokens 思考预算(4.6 弃用,4.7+ 拒绝)
Adaptive Thinking自适应思考thinking: {type: "adaptive"},按 effort 与复杂度自动调节
Interleaved Thinking交错思考工具调用之间穿插思考块
Grounding / Groundedness有据性回答是否贴着给定证据

9. 认证相关性

🎯 学习重点:认证题常以新旧 API/模型代次混淆设陷阱,先锁定题干日期、模型和参数代次再作答。

10. 提示词版本管理:Prompt 即代码

🎯 学习重点:高频架构答案是 prompt、模型、参数、schema 联合版本化,并以金标回归作为发布门禁。
官方提示工程的第一原则是「先有评估再做提示工程」(§1,来源: https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/overview,访问于 2026-08-30)——这句话的另一面是:prompt 是随评估演进的生产资产,不是散落在代码里的字符串。本节把 prompt 当代码管理(工程实践综合,非官方专文主张;所引官方依据逐条标注)。

10.1 prompt 即代码:什么进入版本控制

生产系统里 prompt 满足「代码」的全部判据:改变生产行为、需要评审、可能引入回归、出事故要能回滚。因此:

10.2 变更评审:像对待生产代码一样对待 prompt 变更

10.3 回归评估联动(呼应模块 12)

版本化的价值一半在管理、一半在门禁:

flowchart LR A[prompt 变更 PR] --> B[金标数据集回归评估<br/>模块 12 golden dataset] B --> C{指标对比基线} C -- 不退化 --> D[合并, 生成新版本] C -- 退化 --> E[拒绝, 回到修改] D --> F[灰度/AB 上线] F -- 线上异常 --> G[回滚 = 重新指向旧版本]
🔪 犀利细节|版本号不是审计本身:只给 prompt 文件加版本号,却不记录模型、effort/thinking 和 schema,无法复现线上行为。反模式是直接覆盖 v1 文本;正解是发布不可变新版本,并保存联合配置与评估基线,让回滚成为指针切换而非紧急改字。

10.4 与 prompt caching 的交互(成本维度)

prompt cache 按前缀匹配,prompt 内容任意改动都会使缓存失效(来源: https://platform.claude.com/docs/en/build-with-claude/prompt-caching,访问于 2026-08-30)。版本管理的纪律恰好就是缓存的纪律:

10.5 Bad vs Better

BadBetter
prompt 内联在各业务代码文件里,改哪份全靠 grepprompt 集中版本化,代码按 id + version 引用
「微调了一下措辞」直接上生产变更 PR + 金标集回归 + 对比基线后才发布
只记 prompt 文本,不记模型与参数版本对象 = prompt + 模型 + 参数 + schema
出问题靠记忆手工恢复旧措辞回滚 = 重新指向不可变旧版本

11. 本模块文件

🎯 学习重点:至少亲跑无 key 的校验重试与 few-shot 多样性示例,把概念映射到可观察失败。
📚 目录