Lab 05 — 提示工程与结构化输出
预计 60–90 分钟。标注 ✅ 的步骤无需 API key;🔑 需要 ANTHROPIC_API_KEY。
Lab A:无 key 跑通「校验 + 修复式重试」回路 ✅
- 运行
python3 examples/validate_retry_harness.py,观察三次模拟输出如何从「围栏 + 脏值」被逐层修复。
- 修改
FAKE_LLM_OUTPUTS,把第三条也改坏(如删掉 severity),确认最终抛出 RuntimeError —— 这就是「重试耗尽 → 升级人审/降级」路径。
- 思考:如果
topic 字段的值抽错了(格式全对但内容错),这条回路能发现吗?(答:不能——语义错误不属于 schema 校验职责。)
Lab B:few-shot 构造与多样性检查 ✅
- 运行
python3 examples/few_shot_builder.py。
- 故意把 4 个示例全改成
refund 类,重跑,观察 diversity_report 的 label_distribution 如何报警。
- 把其中两个示例改为完全相同的输入,验证
duplicate_inputs 变 True。
- 用
builder.build() 的输出对照官方排布原则:指令在前、<input> 在最后。
Lab C:结构化输出实战 🔑
- `export ANTHROPIC_API_KEY=***
- 运行
python3 examples/structured_output_api.py,确认输出 JSON 通过 json.loads 且 severity 已归一化。
- 实验 schema 限制:
- 给
severity 加 "minimum": 0 之类数值约束 → 预期 400(不支持数值约束)。
- 把一个字段从
required 移除 → 观察它变成输出末尾的 optional 属性(required 属性排前面的官方行为)。
- 把
enum 改成 ["Low", "low"](仅大小写不同)→ 理解为什么官方禁止这么设计。
- (可选)把 schema 换成 Pydantic 模型,改用
client.messages.parse(),对比 parsed_output 与手工 json.loads 的差异。
Lab D:thinking 行为对比 🔑(可选)
- 对 4.5/4.6 模型:发一个
thinking={"type": "enabled", "budget_tokens": 1024} 的请求,再发 budget_tokens: 20000 的同一请求,对比 usage.output_tokens_details.thinking_tokens 与延迟。
- 对 4.6+ 模型:改
thinking={"type": "adaptive"}, output_config={"effort": "high"},重复对比。
- 连发两次相同请求(同 budget)观察
cache_read_input_tokens;再改 budget 重发,观察缓存失效(cache_creation 重新出现)。
完成标准
- ☐Lab A/B 全部通过断言
- ☐能口述:格式错误 vs 语义错误的处置差异
- ☐能口述:required-first 属性排序、enum 大小写坑、24 可选参数上限
- ☐能口述:extended thinking 弃用时间线(4.6 弃用 → 4.7+ 拒绝)与 adaptive thinking 迁移
📚 目录