同一个模型、同一个任务,仅仅因为提示词里换了几个示例,输出的准确率可能相差二十个百分点以上,这不是夸张,而是少样本(Few-Shot)推理中真实存在的现象。大语言模型在推理阶段依赖上下文中的少量示例来理解任务意图,示例的内容、数量、排列顺序都会直接影响模型对任务的理解。很多开发者调试提示词时反复修改指令文本,却忽略了示例本身才是少样本推理的核心变量。本文围绕示例选择与排序这两个关键维度展开,分析它们影响模型性能的原因,并给出可落地的优化策略。

为什么示例的选择会显著影响模型输出
少样本推理的本质是让模型通过上下文学习(In-Context Learning)完成任务。模型并没有真正更新参数,而是根据提示词中示例呈现的模式去推断输出格式和判断逻辑。这意味着示例实际上是模型理解任务的唯一参照物。如果示例覆盖的类别不均衡,模型会继承这种偏差;如果示例的表述风格与实际输入差异过大,模型可能无法把示例中学到的模式迁移到新样本上。
一个常见的例子是情感分类任务。假设提示词中放了三个示例,其中两个是明显的正面评价,只有一个负面评价,且负面示例的措辞比较直接,那么模型在面对带有讽刺、反语等隐含负面情感的句子时,识别能力会明显下降。原因在于示例没有展示出负面情感的多样性,模型对这类输入的内部表征不够充分。
此外,示例的难度分布也很重要。全部由简单样本组成会让模型倾向于输出浅层判断,而全部是困难样本又可能让模型过度纠结细节,反而降低对常规输入的稳定性。实践中比较推荐的做法是难度混合:以常规样本为主体,穿插一两个边界样本,帮助模型建立更立体的判断标准。这一点在分类、抽取、生成等各类任务中都有体现,只是边界样本的定义因任务而异。
示例选择的常用策略与代码实现
最直接的选择策略是随机采样,也就是从示例池中随机抽取若干条固定下来。这种方式实现简单,在示例池足够大且分布均匀时效果尚可,但缺点是不稳定——换一批随机示例,效果可能波动明显。如果任务对稳定性要求高,比如线上服务,随机采样不是好选择。
更可靠的思路是基于相似度检索,也就是为每一条真实输入动态挑选与它语义最接近的示例。这需要先把示例池中的每条样本向量化,再在推理时计算输入与候选示例的相似度,取最高的若干条拼进提示词。下面的代码演示了基于余弦相似度的示例选择实现:
import numpy as np
# 假设已有示例池的向量和文本
examples = [
{"text": "这家餐厅的菜品非常出色", "label": "正面"},
{"text": "服务态度差到让人失望", "label": "负面"},
{"text": "价格公道,环境也不错", "label": "正面"},
{"text": "等了一个小时才上菜", "label": "负面"},
]
# 简化处理:实际中应调用 Embedding 接口获取向量
example_vecs = np.array([...]) # 示例向量矩阵
query_vec = np.array([...]) # 当前输入的向量
# 计算余弦相似度并取 Top-K
sims = example_vecs @ query_vec / (
np.linalg.norm(example_vecs, axis=1) * np.linalg.norm(query_vec)
)
top_k = np.argsort(sims)[::-1][:3]
selected = [examples[i] for i in top_k]
相似度检索的缺点是容易引入类别偏置:如果输入恰好与正面示例更相似,检索出的示例可能全是同一标签,模型会被带偏。改进办法是在检索后加一层类别均衡约束,保证每个标签至少出现一次。另一种思路是先对示例池做聚类,再从每个簇中各取一条代表性样本,这样既保证了多样性,也覆盖了不同的语义空间。聚类法适合一次性构建固定提示词的场景,检索法适合每条输入动态生成的场景,两者也可以结合:先聚类筛选出高质量候选,再在推理时做相似度检索。
还有一种容易被忽视的做法是基于模型自身反馈的选择,比如用验证集评估不同示例组合的表现,保留效果最好的组合。这种方式计算开销大,但在示例池规模适中、任务固定的情况下,往往能拿到比启发式方法更稳的结果,属于用算力换效果的经典套路。
示例排序的影响与重排序技巧
示例选好之后,摆放顺序同样关键。大量实验观察到一个现象:模型对提示词中靠后位置的示例记忆更强,最后一条示例对输出的影响往往最大。因此,如果任务输入与某条示例最相似,把那条示例放在靠后位置通常能获得更好的效果,这也呼应了前文提到的动态检索策略——检索到相似示例后,建议把它排在末尾。
顺序还会引发另一个问题:多数偏差。如果示例是按标签分组排列的,比如先连续三条正面再连续三条负面,模型容易在生成时延续这种排列模式,倾向于输出与末尾示例同标签的结果。打散不同标签的示例,让正负交替出现,可以有效缓解这个问题。下面是一个简单的均衡交错排序实现:
def interleave_examples(examples):
# 按标签分组
groups = {}
for ex in examples:
groups.setdefault(ex["label"], []).append(ex)
# 逐组轮转取出,保证标签交错
result = []
max_len = max(len(v) for v in groups.values())
for i in range(max_len):
for label in groups:
if i < len(groups[label]):
result.append(groups[label][i])
return result
更进一步,可以引入基于模型置信度的重排序:先用一组候选顺序分别测试,观察模型输出概率分布的熵,选择让模型预测最确定的那组顺序。这种方法在离线场景下可行,但在线场景开销太大,一般用离线实验确定一个表现稳定的默认顺序,再结合动态检索微调末位示例。
实践建议与常见坑
综合来看,做好少样本推理优化有几个经验值得参考。第一,示例格式必须与目标输出格式完全一致,包括标点、分隔符、换行,任何细微不一致都会让模型困惑。第二,示例数量并非越多越好,多数任务在三到八个示例之间收益递减,超过之后不仅增加推理成本,还可能稀释关键信息。第三,示例中应避免出现模型可能模仿的错误,因为上下文学习本质上是模式复制,示例里的错误会被忠实放大。
常见的坑还包括:示例池与真实数据分布不一致,导致检索看似合理实则偏航;不同任务混用同一批示例,格式冲突引发输出混乱;只在一小批测试样本上调优示例,过拟合到局部数据。建议建立一套固定的评估流程,每次调整示例选择或排序策略后,在完整的验证集上重新评估,用数据说话而不是凭感觉判断效果好坏。把示例选择、排序和评估流程工程化之后,少样本推理的性能波动问题就能得到有效控制,模型的真实能力也能更稳定地发挥出来。