少样本学习(Few-shot)
少样本学习(Few-shot Learning)是通过在 Prompt 中提供少量输入-输出示例,引导 LLM 理解任务要求和期望输出格式的技术。这是最直观、最有效的提示工程策略之一。
Zero-shot vs One-shot vs Few-shot
根据提供示例数量的不同,分为三种模式:
Zero-shot
不提供任何示例,直接给出任务描述:
将以下产品评论分类为"正面"、"负面"或"中性":
"这款手机的摄像头非常棒,电池续航也超出预期!"
适用场景:模型已经充分理解的通用任务(简单情感分析、语言翻译等)。
One-shot
提供一个示例:
将产品评论分类为"正面"、"负面"或"中性":
示例:
输入:"物流很慢,包装也破损了,很失望。"
输出:负面
请分类:
输入:"这款手机的摄像头非常棒,电池续航也超出预期!"
输出:
Few-shot
提供 3-8 个示例(经验上最优区间):
将产品评论分类为"正面"、"负面"或"中性":
示例1:
输入:"物流很慢,包装也破损了,很失望。"
输出:负面
示例2:
输入:"产品质量一般,价格也算合理,勉强还行。"
输出:中性
示例3:
输入:"超出预期!质量很好,发货也快,强烈推荐!"
输出:正面
请分类:
输入:"颜色跟图片有点差异,不过总体还能接受。"
输出:
示例选择策略
Few-shot 示例的质量比数量更重要。以下是选择高质量示例的核心原则:
多样性
示例应覆盖任务的各种情况,避免只选择"简单的正面案例":
- 覆盖不同的类别/输出类型
- 包含边界情况(如"中性"这种难以判断的评论)
- 体现任务的真实复杂性
# 差的示例集(缺乏多样性)
示例1:很好的产品 → 正面
示例2:非常满意 → 正面
示例3:超级推荐 → 正面
# 好的示例集(多样性充足)
示例1:很好的产品 → 正面
示例2:有点小问题但总体OK → 中性
示例3:质量很差,退货 → 负面
示例4:手感不错但颜色与描述不符 → 中性(边界案例)
相关性
示例应与实际输入在分布上尽可能接近:
- 领域相关:处理医疗文本时,示例也应来自医疗领域
- 风格相关:如果实际输入是口语化的,示例也应该是口语化的
- 难度相关:包含与实际问题相近难度的案例
格式一致性
所有示例必须遵循完全一致的格式,输出格式也必须统一:
- 相同的字段顺序
- 相同的标点和换行习惯
- 一致的语言风格
示例顺序对效果的影响
研究表明,Few-shot 示例的顺序会显著影响模型输出,这被称为"顺序偏差(Order Bias)":
- 放在最后的示例对模型输出影响最大(近因效应)
- 因此,最相关或最代表性的示例应放在最后
- 如果担心顺序偏差影响结果,可以用相同示例以不同顺序测试几次,取平均
建议:将最典型、最具代表性的示例放在示例列表的最后位置。
动态少样本检索(Dynamic Few-shot)
静态 Few-shot 对所有输入使用相同的示例集;动态 Few-shot 根据每个具体输入,实时检索最相关的示例。
from sentence_transformers import SentenceTransformer
import numpy as np
# 示例库(可以有数百条)
example_pool = [
{"input": "...", "output": "..."},
# 数百个示例
]
# 预计算所有示例的 embedding
encoder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
example_embeddings = encoder.encode([ex["input"] for ex in example_pool])
def get_dynamic_few_shot(query, k=4):
"""根据查询检索最相关的 k 个示例"""
query_embedding = encoder.encode([query])
# 计算余弦相似度
similarities = np.dot(example_embeddings, query_embedding.T).flatten()
# 取 Top-k 最相似的示例
top_k_indices = similarities.argsort()[-k:][::-1]
return [example_pool[i] for i in top_k_indices]
# 使用
query = "这个产品不错,但是客服态度差"
selected_examples = get_dynamic_few_shot(query, k=4)
# 将选出的示例组织为 Few-shot Prompt
动态检索的核心思想:与查询语义最相似的示例,能提供最有针对性的参考,帮助模型处理类似的输入。
示例数量的最优值
理论上,更多示例提供更多信息;实践中,示例越多也会:
- 增加 Prompt 长度,提高 API 成本
- 在长上下文中,早期示例可能被遗忘
- 某些模型在过长 Prompt 时性能下降
经验规律:
- 3-5 个示例:对大多数分类和格式化任务已经足够
- 8-10 个示例:针对需要精细示例的复杂任务
- >10 个示例:通常边际收益下降,考虑微调代替
对于每个具体任务,建议通过实验找到最优示例数(分别测试 0、1、3、5、8 个示例的效果)。
Prompt 长度与成本的权衡
Few-shot Prompt 的成本可观:
假设每个示例平均 100 token,使用 5 个示例:
额外成本 = 5 × 100 = 500 token/次请求
每月 10 万次请求:
额外输入 token = 5000 万 token
GPT-4o 成本($5/M token):$250/月 额外费用
成本控制策略:
- 精简示例文字,去掉冗余解释
- 动态 Few-shot 只针对复杂输入启用,简单输入用 Zero-shot
- 考虑将复杂格式示例微调到模型中,减少运行时 Prompt 长度
RAG 与 Few-shot 的结合
RAG(检索增强生成)和 Dynamic Few-shot 都基于相似检索,可以自然结合:
[系统提示]
你是一位专业的法律助手。
[动态检索的类似案例(Few-shot)]
案例1:[与用户问题相似的历史法律问题及答案]
案例2:[另一个相关案例]
[RAG 检索的相关知识文档]
根据《合同法》第XX条:...
[用户问题]
我和供应商签订了合同,对方违约了,我该怎么办?
这种组合利用 Few-shot 告诉模型"如何回答这类问题",利用 RAG 提供"回答问题所需的知识",两者互补。