如何确定 Few-Shot Prompt 的示例数量,又不浪费上下文

Few-shot prompting 可以提高输出一致性、格式遵循和边界案例处理能力,但也可能悄悄占用真实用户输入与模型回答所需要的上下文空间。
真正该问的不是“Few-shot Prompt 到底应该放几个示例?”因为不存在适用于所有模型和任务的固定数字。更实用的问题是:
在保留足够生产输入和输出空间的前提下,能够通过质量测试的最小示例集合是什么?
可靠的方法是:从少量、差异明确的示例开始,统计完整请求的 Token,再只为已经确认的失败模式增加示例。本文提供一套预算公式、0/1/3/5 示例测试阶梯、压缩规则,以及可以通过 TokenTest 对目标端点进行比较的测试模板。
简短答案:从少量示例开始,让每个示例证明自己的价值
可以先按下面的顺序测试:
- 先运行没有示例的 zero-shot 版本。
- 加入一个能够展示目标格式的标准示例。
- 测试三个示例,分别覆盖常规场景、边界场景和容易混淆的场景。
- 只有当三个示例仍然存在可重复的错误时,再测试五个示例。
- 最终保留能够满足质量、延迟和 Token 预算要求的最小版本。
这是一套测试顺序,不代表所有模型都必须使用三个或五个示例。Anthropic 当前的 multishot 指南针对 Claude 提到,三个到五个示例通常可以改善结果,并建议示例保持相关、多样、清晰和结构一致。Google 的 few-shot 指南同样强调代表性示例,并指出最佳数量会随任务变化。OpenAI 的 Prompt Engineering 指南则建议使用多样的输入输出示例,让模型从 Prompt 中学习任务模式。
最终生产决策仍然应该来自你实际使用的模型、端点、语言与请求结构测试。
为什么 Few-Shot Prompt 示例很容易变贵
一个示例通常不只有“示例内容”,还会重复包含:
- role 或分隔符,
- 示例输入,
- 示例输出,
- 格式语法,
- 重复字段名,
- 解释性标签,
- 以及被复制到每个示例里的相同规则。
如果一个完整示例需要 220 个输入 Token,五个示例可能增加约 1,100 个 Token。此时还没有计算消息包装、工具定义、检索内容、真实用户请求和输出预留。
可见文字也不等于完整请求。OpenAI 的 Token Counting 指南区分了纯文本输入和包含 messages、tools、files 等结构的请求级统计。Anthropic 提供 Messages 请求的 Token Counting 接口,Gemini 也提供面向具体模型请求内容的 Token 统计方法。不同 Provider 的统计方式并不完全相同,所以字符数不能替代生产环境的 Token 预算。
不要用固定示例数量,要用完整请求预算
先使用下面的公式:
可用于示例的 Token =
上下文上限
- 固定请求 Token
- 生产输入 Token
- 检索与工具 Token
- 输出预留
- 安全余量
各部分应包含:
| 预算部分 | 需要统计的内容 |
|---|---|
| 上下文上限 | 实际模型与端点对应的限制 |
| 固定请求 Token | System Prompt、策略、响应 Schema、消息包装、稳定工具定义 |
| 生产输入 Token | 有代表性的高分位真实输入,而不是最短测试样本 |
| 检索与工具 Token | RAG 片段、函数定义、工具结果、图片或文件元数据、对话历史 |
| 输出预留 | 完整有用回答、结构化输出,以及需要考虑的 reasoning/thinking 行为 |
| 安全余量 | 多语言膨胀、超长边界输入、Tokenizer 或请求结构变化 |
只有最后剩下的空间,才属于 Few-Shot Prompt 示例。
示例预算表
假设团队为某种请求结构批准了 8,000 Token 的内部工作预算。这个数字只是工程预算示例,不是任何模型的规格。
| 组成部分 | Token |
|---|---|
| System Prompt 与 Schema | 900 |
| 生产用户输入 | 1,700 |
| 检索与工具 | 1,200 |
| 输出预留 | 2,400 |
| 安全余量 | 600 |
| 可用于示例 | 1,200 |
如果每个完整输入输出示例需要 260 Token,四个示例约为 1,040 Token,可以放入预算;五个示例约为 1,300 Token,会超出预算。结论不是“四个最好”,而是“四个是当前预算最多能容纳的数量;如果一个或三个已经通过测试,就应该保留更少的版本”。
统计每个新增示例的增量成本
不要只单独计算示例文本。应该反复统计同一个完整请求:
T0 = 0 个示例时的完整请求
T1 = 1 个示例时的完整请求
T3 = 3 个示例时的完整请求
T5 = 5 个示例时的完整请求
增量_1 = T1 - T0
增量_3 = T3 - T1
增量_5 = T5 - T3
同时记录质量和 Token:
| 版本 | 输入 Token | 任务通过率 | 格式通过率 | 边界错误 | 是否保留 |
|---|---|---|---|---|---|
| Zero-shot | 实测 | 实测 | 实测 | 记录错误 | 基线 |
| 1 个示例 | 实测 | 实测 | 实测 | 记录错误 | 有价值才保留 |
| 3 个示例 | 实测 | 实测 | 实测 | 记录错误 | 明显更好才保留 |
| 5 个示例 | 实测 | 实测 | 实测 | 记录错误 | 确有必要才保留 |
最终应该选择通过发布标准的最小版本。如果五个示例消耗更多上下文,却没有修复新的错误,就删除多余示例。
按覆盖范围选择示例,而不是追求数量
三个几乎重复的示例,通常不如三个教学目的不同的示例。
一个紧凑的示例集合可以覆盖:
- 标准场景:最常见的请求和准确的输出结构。
- 边界场景:空值、歧义、超长输入或临界分类。
- 对比场景:两个看起来相似、但应该产生不同输出的输入。
只有当第四或第五个示例代表了现有集合无法解决、且在生产中反复出现的错误时,才加入它。
增加示例前,先完成这句话:
这个示例存在的目的,是教模型如何 ________。
如果答案与另一个示例相同,就应该合并或删除。
在不丢失教学作用的情况下压缩示例
压缩的目标不是让示例变得晦涩,而是删除不负责“教行为”的 Token。
1. 删除重复指令
把共享规则统一放在示例区块之前。不要在每个示例里重复“只返回有效 JSON”或完整分类列表。
2. 缩短输入,但保留决策边界
保留真正改变答案的短语、字段或上下文,删除装饰性背景信息。
3. 直接展示生产输出格式
如果生产环境要求 JSON,就展示 JSON。不要浪费 Token 输出应用永远不会接受的解释段落。
4. 使用一致的标签和分隔符
稳定结构能减少无意变化。Anthropic 的指南也明确建议保持结构一致,并把 XML 风格标签作为区分示例的一种方式。
5. 删除模型不需要的解释
很多示例只需要正确输出,并不需要解释为什么正确。只有当推理方式本身就是任务要求时,才保留 rationale。
压缩前后对比
冗长版本:
示例 1
下面是一条客户支持消息。请分析这条消息,并从完整分类列表中确定正确类别。你必须返回一个 JSON 对象。
客户消息:同一个月度订阅被扣了两次费用,我希望退回重复扣款。
正确答案:正确类别是 billing_duplicate_charge,因为客户明确表示一个订阅发生了两次扣费。
压缩版本:
<example>
Input: 同一个月度订阅扣款两次,请退回重复扣款。
Output: {"category":"billing_duplicate_charge"}
</example>
压缩版本仍然保留了决策边界和生产输出结构,同时删除了重复策略与解释。
可直接测试的 Few-Shot Prompt 模板
使用下面的模板比较不同示例数量。每次只修改 <examples> 区块,其他请求保持一致。
请把客服消息分类为以下一个类别:
billing_duplicate_charge, billing_refund_pending, account_login, product_bug。
只返回 JSON:
{"category":"category_name"}
<examples>
<example>
Input: 同一个月度订阅扣款两次,请退回重复扣款。
Output: {"category":"billing_duplicate_charge"}
</example>
<example>
Input: 退款上周已经批准,但银行卡还没有收到。
Output: {"category":"billing_refund_pending"}
</example>
<example>
Input: 密码重置成功,但登录时新密码仍然被拒绝。
Output: {"category":"account_login"}
</example>
</examples>
Input: 仪表盘有数据,但导出按钮生成的 CSV 是空的。
Output:
建立四个版本:
- 0 个示例,
- 只保留第一个示例,
- 保留全部三个示例,
- 三个示例再加两个真实高频错误示例。
使用计划上线的模型和端点运行每个版本。在 TokenTest 中,不要只相信本地文本估算,而要对比端点返回的 usage 证据。TokenTest 当前公开产品检查包括输入 Token 单调性、总 Token 一致性、输出 Token 合理性、缓存 Token 证据,以及端点支持时的 thinking/reasoning Token 证据。TokenTest 首页也明确说明测试时输入的 API Key 不会被存储。
如果需要更完整的流程,可以继续阅读如何建立一套 Token 感知的 Prompt 审查流程和生产级 LLM 应用的上下文窗口规划开发者指南。
在增加示例前保护输出空间
Few-Shot Prompt 示例与模型回答共享容量。不要让更大的示例区块悄悄压缩任务真正需要的输出。
先定义输出预留:
- 结构化输出最多需要多少字段,
- 最长可接受回答,
- 工具调用参数或中间结果,
- 重试与修复开销,
- 以及需要纳入预算的 Provider 特定 reasoning/thinking 行为。
然后再把示例放入剩余空间。如果新增示例会占用受保护的输出空间,可以:
- 压缩现有示例,
- 用更强的示例替换较弱示例,
- 针对当前请求动态检索示例,
- 或者在端点和成本允许时提高已批准的请求预算。
中英文必须分别测试
不要假设英文示例集合与中文翻译会使用相同 Token。Tokenization 会受到模型、Tokenizer、标点、文字系统、JSON 转义和中英文混排影响。
每个本地化请求都应该单独统计和评估。为什么中文 Prompt 的 Token 预算可能和英文不同解释了为什么不能依赖一个固定换算倍数。
本地化也会改变示例质量。直译可能破坏原示例用于教学的歧义、语气或分类边界,因此需要同时重新验证 Token 和行为。
什么时候改用动态示例
静态 Few-Shot 区块简单,但每个请求都会重复发送同一组示例。以下情况更适合动态选择:
- 示例库很大,
- 用户请求来自多个不同领域,
- 每次只有少量示例真正相关,
- 长尾错误经常变化,
- 或静态示例占用了过多 Prompt Token 预算。
可以检索少量相关示例,但检索结果本身也必须纳入完整请求统计。动态选择能减少重复上下文,但错误检索也可能加入无关或相互矛盾的示例。
上线前检查清单
- [ ] 已统计 zero-shot 版本。
- [ ] 每个示例都有不同的教学目的。
- [ ] 已统计完整请求,包括工具、Schema、检索与历史。
- [ ] 增加示例前已经保护输出预留和安全余量。
- [ ] 0/1/3/5 版本使用同一测试集评估。
- [ ] 最终选择能够通过测试的最小版本。
- [ ] 中英文版本分别统计和评估。
- [ ] 本地估算已与真实端点 usage 对比。
- [ ] 模型、端点、Schema 或示例变化后会重新检查 Token。
最终原则:每个示例都必须“支付租金”
当 Few-Shot Prompt 示例能够避免明确错误时,它们就有价值;当它们重复同一经验、保留无关文字,或挤占真实输入与有效输出时,它们就是浪费。
从零开始。用一个示例教格式。用少量多样化示例覆盖已经确认的失败模式。每次统计完整请求,并保留能够通过测试的最小集合。
开始一次 TokenTest 端点评测,在下一次 Prompt 修改进入生产环境前,对比 0、1、3、5 个示例的请求结构。