Few-shot 的本质:上下文学习
大语言模型具备一种独特能力——上下文学习(In-Context Learning, ICL)。模型不需要更新参数,仅通过 Prompt 中提供的少量示例就能学会新任务。Few-shot Prompt 就是利用这一能力的技术。
核心公式:
模型输出 = f(Prompt 中的示例分布 × 输入查询)
模型并非"理解"了任务规则,而是从示例中提取了统计模式(输入-输出的映射关系、格式规范、语言风格),并在推理时应用这些模式。这意味着:示例的选择、排列、格式直接决定了模型的表现。
示例选择策略
随机选择
从示例池中随机抽取 K 个样本。最简单但效果最不稳定。
import random
examples = load_examples("data/training_set.jsonl")
selected = random.sample(examples, k=4)
问题: 随机选取可能选到不代表任务分布的示例,导致模型行为偏移。
相似性选择
基于语义相似度,选取与当前输入最接近的示例。这是最常用的策略:
from sentence_transformers import SentenceTransformer
import numpy as np
class SimilarExampleSelector:
def __init__(self, examples, model_name="all-MiniLM-L6-v2"):
self.encoder = SentenceTransformer(model_name)
self.examples = examples
self.embeddings = self.encoder.encode(
[ex["input"] for ex in examples],
normalize_embeddings=True
)
def select(self, query, k=4):
query_emb = self.encoder.encode([query], normalize_embeddings=True)
# 余弦相似度
scores = self.embeddings @ query_emb.T
top_k_idx = np.argsort(scores.flatten())[-k:][::-1]
return [self.examples[i] for i in top_k_idx]
效果: 在分类任务上,相似性选择通常比随机选择提升 3-8% 准确率。
注意: 相似性度量很关键。文本嵌入的相似性不等于任务语义相似性。在情感分析中,与查询情感极性相同的示例可能比主题相同的示例更有用。
多样性选择
确保所选示例覆盖不同类别/模式,避免同质化:
def diverse_select(query, examples, k=4, n_clusters=4):
"""先聚类,再从每个簇中选最相似的"""
from sklearn.cluster import KMeans
embeddings = encode_all(examples)
kmeans = KMeans(n_clusters=n_clusters, random_state=42).fit(embeddings)
selected = []
for cluster_id in range(n_clusters):
cluster_indices = np.where(kmeans.labels_ == cluster_id)[0]
cluster_examples = [examples[i] for i in cluster_indices]
# 从该簇中选与 query 最相似的
best = select_most_similar(query, cluster_examples)
selected.append(best)
return selected[:k]
选择策略对比
| 策略 | 实现难度 | 计算成本 | 效果稳定性 | 最佳场景 |
|---|---|---|---|---|
| 随机 | 极低 | O(1) | 低 | 基线对比、快速原型 |
| 相似性 | 中 | O(N) 检索 | 中-高 | 分类、抽取、QA |
| 多样性 | 高 | O(N) + 聚类 | 高 | 多类别任务、生成任务 |
| 混合 | 高 | 中-高 | 最高 | 生产环境 |
示例顺序的影响
一个被广泛验证的现象:示例顺序对模型输出有显著影响。
研究表明:
- 放在 Prompt 末尾的示例对模型影响最大(近因效应)
- 放在开头的示例也有较强影响(首因效应)
- 中间位置的示例影响最弱
import itertools
def find_optimal_order(examples, eval_set):
"""暴力搜索最优排列(仅适合示例数少时)"""
best_acc, best_order = 0, None
for perm in itertools.permutations(range(len(examples))):
ordered = [examples[i] for i in perm]
acc = evaluate(few_shot_prompt(ordered), eval_set)
if acc > best_acc:
best_acc, best_order = acc, perm
return best_order, best_acc
实用建议:
- 示例数 ≤ 4 时,可以尝试排列搜索
- 生产环境用固定顺序 + 评估集验证
- 将最"典型"的示例放在最后(紧邻查询)
格式设计
标准格式
输入:[示例输入1]
输出:[示例输出1]
输入:[示例输入2]
输出:[示例输出2]
输入:[实际查询]
输出:
结构化格式
{
"examples": [
{"input": "今天天气真好", "sentiment": "positive", "confidence": 0.95},
{"input": "这服务太差了", "sentiment": "negative", "confidence": 0.92}
],
"query": "产品质量还可以",
"response_format": {"sentiment": "string", "confidence": "number"}
}
对话格式
User: 判断以下句子的情感:今天天气真好
Assistant: {"sentiment": "positive", "reason": "表达了愉悦的情绪"}
User: 判断以下句子的情感:这服务太差了
Assistant: {"sentiment": "negative", "reason": "表达了不满的情绪"}
User: 判断以下句子的情感:产品质量还可以
Assistant:
格式选择原则
| 格式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 键值对 | 简单直观 | 解析需正则 | 简单分类 |
| JSON | 可靠解析 | Token 开销大 | 结构化输出 |
| 对话 | 符合模型训练分布 | 轮次混乱风险 | 指令跟随 |
| XML标签 | 清晰分隔 | Token 开销大 | 复杂嵌套结构 |
关键原则:输出格式必须在示例中 100% 一致。 一个格式不规范的示例会破坏模型对输出格式的遵守。
Few-shot vs Fine-tune:边界在哪
何时用 Few-shot
- 任务数据量小(< 1000 条)
- 需要快速迭代验证
- 任务逻辑相对简单
- 不愿承担 Fine-tune 的训练成本
- 任务经常变化
何时该 Fine-tune
- 任务数据量大(> 10,000 条)
- Few-shot 已无法装入 context window
- 推理成本成为瓶颈(Fine-tune 小模型更经济)
- 任务有大量领域特定术语/格式
- 需要稳定的、确定性的输出
成本模型对比
Few-shot 成本 = API调用次数 × (示例Token数 + 查询Token数 + 输出Token数) × 单价
Fine-tune 成本 = 训练成本(GPU) + 部署成本 + API调用次数 × (查询Token + 输出Token) × 单价
当 API 调用次数 > N 时,Fine-tune 更经济。N 的计算:
def break_even_point(examples_tokens, ft_train_cost, ft_deploy_cost_monthly,
api_price_per_1k, ft_api_price_per_1k):
"""计算 Fine-tune 的盈亏平衡点"""
monthly_savings_per_call = (examples_tokens / 1000) * (api_price_per_1k - ft_api_price_per_1k)
return (ft_train_cost + ft_deploy_cost_monthly) / max(monthly_savings_per_call, 0.001)
实战清单
- 示例质量 > 示例数量:4 个高质量示例胜过 16 个普通示例
- 覆盖任务分布:示例应覆盖正/负/边界 case
- 格式绝对一致:所有示例严格遵循同一格式模板
- 隔离示例与查询:用明确分隔符(
\n\n---\n\n)区分 - 示例数经验值:分类任务 2-4 个,抽取任务 3-5 个,生成任务 1-3 个
- 动态选择:生产环境推荐相似性 + 多样性混合策略
- 评估驱动:建立评估集,量化每次示例变更的影响
Few-shot Prompt 的本质是用示例"编程"模型行为。每一个示例都是一条隐式规则,每一次排列都是一次程序结构设计。把示例当作代码来对待——版本管理、测试覆盖、代码审查——你的 Prompt 就会从手工艺走向工程化。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
