这些术语中的“shot”指的是示例。零样本提示词没有示例,单样本提示词有一个,少样本提示词有几个。在它们之间选择,是在提示词长度与你能多精确地约束输出之间做取舍。
零样本提示词
零样本提示词只给出指令和输入,别无其他。
Classify the support ticket as billing, bug, or feature request.
Return only the label.
<ticket>
{{ticket}}
</ticket>
现代模型用这种方式就能处理大量任务。零样本是正确的默认选择,因为它最短、最便宜、最容易维护。只有在清晰的指令没能产生你想要的结果时,才去求助于示例。
单样本提示词
单样本提示词只增加一个示例。一个示例非常擅长固定回答的格式,却不擅长传授判断。
Write a changelog entry for the commit below.
Example:
Commit: "fix: retry webhook delivery on 5xx"
Entry: "Fixed: webhooks are now retried when your server returns a 5xx error."
Commit: "{{commit_message}}"
Entry:
风险在于过度模仿。只有一个示例时,模型可能会照抄它的长度、开头用词或主题。
少样本提示词
少样本提示词提供几个示例,通常是二到五个,让模型从它们的共同点中推断出规律。
Rate the urgency of each message as low, medium, or high.
Message: "The export button is slightly misaligned." -> low
Message: "Checkout fails for all customers since 09:00." -> high
Message: "Can you add dark mode at some point?" -> low
Message: "Invoices for March show the wrong tax rate." -> medium
Message: "{{message}}" ->
少样本提示词在以下情况下最有用:
- 类别的边界模糊,难以用规则描述。
- 你需要特定的语气、风格或详细程度。
- 输出采用的是模型不常见的自定义格式。
如何挑选好的示例
覆盖全部范围。 每个标签或情形至少包含一次。如果所有示例都是“high”,模型就会偏向“high”。
包含困难的情形。 明显情形的示例教不了多少东西。像上面税率那条消息这样的临界情形,才决定了界线在哪里。
变换表面形式。 使用不同的长度、主题和措辞,让示例唯一共有的就是你关心的那个规律。
保持格式一致。 每个示例使用相同的分隔符、相同的顺序、相同的间距。格式不一致本身就是一种规律,模型会学到它。
使用真实数据。 取自真实输入的示例,与提示词将面对的分布相吻合。
用多少个示例
从两三个开始。只有测试显示输出有改善时才增加。每个示例每次调用都要消耗 token,所以一个带十个示例、运行一百万次的提示词,会成为账单上实实在在的一笔。对于从不改变的长示例集,服务商的提示词缓存可以降低这项成本。参阅 token 优化。
示例何时适得其反
- 顺序效应。 模型可能更看重靠后的示例。如果结果偏向最后一个标签,就打乱示例顺序。
- 标签失衡。 三个正面示例和一个负面示例,会让输出偏向正面。
- 内容泄漏。 模型在回答中重复使用示例里的名字或事实。告诉它示例只用于格式,或者使用明显是占位的内容。
- 与指令矛盾的示例。 如果规则说“一句话”,而某个示例有两句,通常是示例胜出。
零样本还是少样本:一条决策规则
| 情形 | 从哪种开始 |
|---|---|
| 常见任务,规则清晰 | 零样本 |
| 输出格式总是跑偏 | 单样本,或使用 schema |
| 标签取决于判断 | 少样本 |
| 需要特定的写作风格 | 少样本 |
| 重推理的问题 | 零样本加推理技巧 |
对于严格的格式,schema 比示例更可靠。参阅结构化输出提示词。对于推理类任务,只给答案的示例,不如展示推理过程有帮助,这正是思维链提示词背后的思路。
把示例与输入分开
用不同的分隔符分别包裹示例和真实输入,这样模型就不会把它们混淆,用户的文字也无法冒充示例。
<examples>
...
</examples>
<input>
{{message}}
</input>
PromptFlowEngine 提示词分析器会标出未加分隔的模板变量,这正是少样本模板中最常见的错误。