课程大纲 › 领域 4:提示工程与结构化输出
4.2 应用 few-shot 提示,提升输出一致性与质量
タスクステートメント4.2:出力の一貫性と品質を高めるためにfew-shotプロンプティングを適用する
官方大纲原文(日文):知识 4 条 · 技能 5 条
需要掌握的知识
- 詳細な指示だけでは一貫しない結果になる場合に、一貫した形式で実用的な出力を得るための最も効果的な手法としてのfew-shotの例
- 曖昧なケースの扱い方を示すうえでのfew-shotの例の役割(例:曖昧なリクエストに対するツール選択、ブランチレベルのテストカバレッジの不足)
- few-shotの例によって、モデルが事前に指定されたケースにのみ一致させるのではなく、新しいパターンに判断を一般化できるようになる仕組み
- 抽出タスクにおけるハルシネーションの低減に対するfew-shotの例の有効性(例:非公式な計量表現や多様な文書構造の処理)
需要能做到的事
- 曖昧なシナリオ向けに、妥当と思われる代替案ではなくあるアクションが選ばれた理由の推論を示す、的を絞ったfew-shotの例を2-4個作成する
- 一貫性を実現するために、求める具体的な出力形式(場所、問題、重大度、修正案)を示すfew-shotの例を含める
- 許容されるコードパターンと真の問題を区別するfew-shotの例を提示し、一般化を可能にしながら誤検知を減らす
- few-shotの例を使用して、多様な文書構造(インライン引用と参考文献リスト、方法論のセクションと本文に埋め込まれた詳細)の正しい扱い方を示す
- 多様な形式の文書からの正しい抽出を示すfew-shotの例を追加し、必須フィールドが空またはnullで抽出される問題に対処する
课程讲解 · AI 草稿,未经人工审核 以官方文档为准
这一条考什么
考你能否用 few-shot 示例让输出稳定、可用:当详细指令仍然得到不一致的结果时,用 2–4 个有针对性的示例展示期望的格式和判断方式;用示例说明模糊情况该怎么处理并解释为何选 A 而不选看似合理的 B;用示例区分可接受模式与真问题以减少误报;以及在抽取任务中用示例覆盖多样的文档结构和非正式表达,降低幻觉与空字段。
核心概念
few-shot 是稳定格式和判断的最有效手段
指令再详细,模型对“标准格式”“合适粒度”的理解仍可能每次不同。few-shot 示例直接展示“输入长这样时,输出就该长这样”,比文字规则更具约束力。例如材料字段有时输出“cotton blend”、有时输出“Cotton/Polyester mix”、有时干脆漏掉,加 2–3 个完整的输入输出对展示标准化写法,一致性会明显提升;把 temperature 调成 0 或换更大的模型并不能解决“标准不明确”的问题。
示例要能演示模糊情况的推理
最有价值的示例不是简单情况,而是模糊情况,并且写出为什么这样选:
示例 1
用户请求:“帮我看看订单 8812 怎么还没到”
选择工具:get_shipping_status
理由:用户关心的是物流进度,不是订单内容或退款。虽然 lookup_order 也能返回订单信息,
但只有 get_shipping_status 提供承运商轨迹,能直接回答“为什么没到”。
示例 2
用户请求:“订单 8812 不想要了”
选择工具:lookup_order
理由:“不想要”可能是取消(未发货)或退货(已签收),先查订单状态再决定,
不能直接调用 process_refund。同理,在代码审查中,可以用示例展示“分支级别的测试覆盖缺口”:函数有测试,但 except 分支从未被执行,应该怎样描述这一问题。
few-shot 促进泛化,而不是只匹配列举过的情况
写一份“所有不应标记的模式”的完整清单,模型只会机械比对清单;遇到清单之外的新写法仍会误报。示例则展示了判断的依据——为什么这个模式可接受、为什么那个是真问题——模型能把这种推理迁移到没见过的代码上。
示例:可接受
代码:user = repo.find(id) ?: return NotFound
判断:不报告。Elvis 早返回是本项目处理缺失值的约定,控制流清晰。
示例:真问题
代码:user = repo.find(id)!!
sendEmail(user.email)
判断:报告(major)。find 可能返回 null,强制解包会在用户不存在时崩溃,且调用方未做前置检查。指定输出格式:位置、问题、严重级别、修复建议
示例同时也是格式模板。每个示例都用相同结构输出,模型的输出就会对齐:
位置:src/orders/service.py:88
问题:在循环内对每个订单单独查询客户,导致 N+1 查询
严重级别:major
修复建议:循环前用 customer_ids 批量查询并构建字典抽取任务:减少幻觉和空字段
抽取任务中,文档结构多样是空字段和幻觉的主因:
- 引用有时是正文内联(作者, 年份),有时集中在文末参考文献列表;
- 方法论有时有独立章节,有时散落在引言里;
- 菜谱里写“一小撮”“少许”“a splash”这类非正式计量。
只说“抽取引用和方法论”,模型遇到非常规结构时要么留空,要么编造。few-shot 示例覆盖这些结构,演示正确做法:
示例(方法论嵌在引言中)
原文片段:“……为此,我们在 2021–2023 年对 412 名护士进行了半结构化访谈……”
抽取:methodology = "半结构化访谈,412 名护士,2021–2023"
示例(非正式计量)
原文:“加一小撮盐”
抽取:{"ingredient": "盐", "quantity": null, "unit": null, "raw_text": "一小撮"}
说明:不把“一小撮”换算成具体克数,保留原文,数量置 null。关键是示例要包含“信息确实不存在时如何表示”(null + 原文)以及“信息存在但位置不寻常时如何找到”,两者共同减少编造和遗漏。
正确做法与反模式
- 正确:为模糊场景写 2–4 个有针对性的示例,并写明为何选这个动作而非另一个看似合理的动作。反模式:只放简单、典型的示例,或一次塞几十个示例。
- 正确:示例统一展示“位置、问题、严重级别、修复建议”的输出格式。反模式:只用文字描述格式,期望模型每次都对齐。
- 正确:用对比示例区分可接受模式与真问题,让模型能泛化到新代码。反模式:写一份详尽的“不准标记”清单,或用关键词后处理过滤。
- 正确:用示例覆盖内联引用与参考文献、独立方法论章节与嵌入式描述等多种结构。反模式:失败时简单重试,或把必填字段改成可选、转人工处理。
- 正确:用示例展示非正式计量的正确处理方式。反模式:直接拿纠错数据去微调,或只加一个 enum 字段而不示范用法。
常见陷阱
- “temperature 设为 0 / 换更强模型”:解决的是随机性或能力,而问题在于标准不明确,few-shot 才对症。
- “遇到空字段就自动重试”:同样的提示重试同样的结构,大概率还是空。
- “正则后处理补抽取”:脆弱且覆盖不了多样表达,不如让模型通过示例学会识别。
- “写一份完整的不应标记模式规范”:无法泛化到未列举的新模式;题干出现“泛化到没见过的代码模式”时选 few-shot。
- “加约束:最多 10–20 条、每条一个”:硬性数量约束不解决“什么算明确提及”的判断问题,示例更有效。
- 注意边界:如果问题是“模型漏掉某类检查步骤”,有时明确要求它逐项列举(如列出所有分支再逐个核对)比加示例更直接;读题时分清是“判断/格式不一致”还是“流程缺步骤”。
实操练习
目标:在抽取任务中加入 few-shot 示例,比较加入前后对非正式计量和空字段的处理。
- 准备 3 段菜谱文本,其中包含“一小撮”“适量”“a splash of”以及缺失计量的配料。
- 先用零样本提示抽取,记录被编造数量的配料和空字段。
- 加入 2–3 个 few-shot 示例(包含非正式计量和完全缺失计量的情况),再次运行。
- 对比两次输出:是否还出现编造的克数?
raw_text是否保留?
import anthropic, json
client = anthropic.Anthropic()
FEW_SHOT = """把配料抽取为 JSON 数组,字段:ingredient, quantity, unit, raw_text。
信息不存在时用 null,绝不换算或猜测。
示例输入:加入 200 克面粉和一小撮盐
示例输出:[{"ingredient":"面粉","quantity":200,"unit":"克","raw_text":"200 克"},
{"ingredient":"盐","quantity":null,"unit":null,"raw_text":"一小撮"}]
示例输入:淋上 a splash of 柠檬汁,最后撒葱花
示例输出:[{"ingredient":"柠檬汁","quantity":null,"unit":null,"raw_text":"a splash of"},
{"ingredient":"葱花","quantity":null,"unit":null,"raw_text":null}]
"""
text = "取两个鸡蛋打散,加适量糖和少许香草精,倒入 150 毫升牛奶。"
for name, system in [("zero-shot", "把配料抽取为 JSON 数组,字段:ingredient, quantity, unit, raw_text。"),
("few-shot", FEW_SHOT)]:
msg = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=600,
system=system,
messages=[{"role": "user", "content": f"输入:{text}\n只输出 JSON。"}],
)
print(f"===== {name} =====")
print(msg.content[0].text)检查结果:few-shot 版本中“适量糖”“少许香草精”的 quantity 应为 null 且 raw_text 保留原文,“两个鸡蛋”“150 毫升牛奶”被正确数值化;零样本版本可能出现“糖 10 克”之类的编造值。生产环境中可再结合 tool use 的 JSON Schema 保证结构合法。
自测清单
- 什么情况下 few-shot 比继续细化文字指令更有效?
- 为模糊场景写示例时,为什么要写出“为什么选它而不是另一个”的理由?
- few-shot 示例为何比“不允许标记的模式清单”更能泛化到新代码?
- 一个能统一审查输出格式的示例应包含哪四个要素?
- 抽取任务中,示例应覆盖哪些文档结构差异来减少空字段和幻觉?
- 遇到“一小撮”“少许”这类表达,示例应如何示范正确处理?
对应题目(6)
题目归类由 AI 判断,仅供参考。
练习这 6 道题