想象你走进一家只做试吃套餐的私房菜馆。主厨端上来的每一道小菜,都不只是一道菜——它们用味道暗示你的舌头:这家店偏什么口味、下一道菜该怎么期待。大模型推理时也是这样一位食客:你喂给它的几个「示例」,就是给它准备的试吃小碟。这些小碟不会改变它的记忆(模型参数),却能在当下这一餐里,悄悄左右它输出的方向。 这顿饭吃得对不对味,取决于几件事:菜怎么摆(示例格式)、上几道(示例数量)、荤素冷热怎么搭(示例多样性)、先上哪道后上哪道(示例顺序);还要看主厨会不会看人下菜(动态检索选择),以及菜单上的名字和端上来的菜是否名副其实(标签空间一致)。本文就用这一桌菜的故事,把 In-context 示例(即 Few-shot 示范样例)的设计与选择策略讲清楚。
掌握 In-context 示例的设计与选择策略,是 Prompt 工程师和 AI 应用开发者在不微调大模型的前提下,用最低成本换取更准确、更稳定输出的核心技能。
可视化演示
动态演示In-context示例设计的核心机制,通过架构/数据/状态/性能四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
In-context示例设计:Inco In-context示例的格式 示例数量与多样性的权衡策略 核心机制可视化 In-context示例设计整体架构与关键组件
示例格式设计
私房菜主厨摆盘,会先把所有餐盘统一成同一规格:白瓷圆盘、主菜居中、酱汁画线。试想第一道菜用西餐盘、第二道用深汤碗、第三道直接上木砧板,食客再会吃也会手忙脚乱。示例的格式,就是提示词里的「餐具」。大模型在推理时看到的只是一串字符,它需要从这串字符里归纳出「原来这是在做分类题」的规律。
统一的格式等于给模型画好了一张答题卡。业界常见的做法是「键值对模板」:每条示例写成「输入:……\n输出:……」的固定结构。研究表明,结构一致的示例比混用叙述句的示例更能稳定提升效果;而乱换标点、乱加解释性废话,就像在答题卡上涂鸦,反而干扰模型抓取规律。
从概率角度看,In-context 学习可以这样描述:模型在已知示例集 S 和当前输入 x 的条件下,逐 token 生成输出 y 的联合概率:
所以,给模型上菜前要先把每一道菜摆在同样规格的盘子里——统一模板不是形式主义,而是在降低模型理解任务的成本。这也是为什么优秀 Prompt 工程师会反复打磨示例格式,做到「一个模板走天下」。
- 示例集合 S$S = \{(x_1, y_1), (x_2, y_2), \cdots, (x_k, y_k)\}$ 表示 k 条成对的示例,每条示例都是一组「输入-输出」的示范,相当于主厨备好的小菜。
- 条件概率 P(y|x,S)竖线右侧是「已知条件」,意思是模型在看过示例集 S 和当前输入 x 之后,输出 y 的概率有多大。
- 连乘号 ∏从第 1 个 token 一直乘到第 |y| 个 token,把每个位置生成某个字符的概率相乘,得到整段输出出现的总概率。
- 历史 y_{<t}生成第 t 个字符时,模型还能看到前面已经生成的内容,这让输出像上菜一样按顺序逐道推进。
示例数量权衡
主厨端上两道开胃菜,食客立刻明白餐厅的风格;但要是连上二十道菜,食客不仅吃撑,还可能忘了第一道菜的味道。大模型的「胃容量」就是上下文窗口——它是有限的,塞进去的示例越多,留给当前输入和思考输出的空间就越少。
Few-shot 中的 K 值(示例条数)经典经验是:K=0 属于零样本,模型全凭本能发挥;K=1 到 2 就能建立任务模式;2 到 8 个示例通常已经到达收益拐点。再往上加,准确率的提升会变得非常缓慢,只把提示词撑得又长又贵。
实验数据拟合出来的规律近似如下:准确率随 K 的增长不是线性的,而是「对数式」的慢速爬升。
至于「到底上几道菜」,答案是少而精。先准备 3 到 5 条高质示例,观察效果后再慢慢加量;如果 K 超过 8 收益仍不明显,问题通常不在数量,而在示例的质量或选择方式上。
- Acc(k) 准确率表示放入 k 个示例后模型的回答正确率,是衡量示例效果的核心指标。
- log₂(k+1) 对数收益以 2 为底取对数,加 1 是为了让 k=0 时也有意义(对应零样本基线)。
- 常数 a 与 ba 表示零样本时模型的底线水平,b 表示示例的「增益斜率」——b 越大说明示例越管用,而模型本身越强大,b 往往越小。
示例多样性
连续上四道红烧肉,食客再爱也会腻。一份好的试吃菜单讲究荤素、冷热、浓淡的搭配,让食客从不同维度理解主厨的手艺。示例的多样性也有三个维度:类别覆盖、难度梯度和分布均衡。
类别覆盖指每个输出标签(比如「正向/负向」)至少出现一次,让模型知道答案的取值范围;难度梯度指示例里既有简单直白的,也有模棱两可的,帮助模型建立判别边界;分布均衡则要求各类别示例数量大致相当,避免模型被某一类「带节奏」。
多样性的高低可以用信息熵来量化,熵越大说明示例集越「百花齐放」:
设计示例时,不妨像配菜那样列一张「搭配表」:先保证每个标签都有代表,再按难度从易到难挑几道,最后把各类数量调整到接近相等。这样的示例集才能让模型全面理解任务,而不是被单一模式带偏。
- C 个类别示例集中输出标签的总种类数,比如「正向、负向」两类,C=2。
- pᵢ 类别占比第 i 类示例在全部示例中所占的比例,例如 8 条示例中 6 条正向,则 p≈0.75。
- 负号求和对每个类别求 pᵢ·log₂pᵢ 再加负号,得到熵值;占比越均匀,熵越高,说明菜单越丰富。
示例顺序排列
私房菜讲究上菜顺序:先清淡开胃,再浓烈主菜,最后甜品收尾。主厨要是先上甜品再上开胃菜,食客的味蕾会完全错乱。大模型对示例顺序也极其敏感——因为它是自回归模型,也就是一个字符一个字符地「边看边写」,先看到的示例会形成先入为主的印象,后看到的示例则离最终输出更近、影响更直接。
这种现象被称为「近因效应」:越靠近生成位置的示例,权重越高。同时开头的示例也不是毫无作用,它往往承担着「任务定义」的功能,让模型明白这是在做什么题。研究还发现,把与当前输入最相似的示例放在最后,效果通常比放在开头更好——就好比把最对口味的那道菜放在食客正式开动前。
我们可以给每个位置的示例分配一个指数衰减的权重,模拟这种「越近越重要」的影响模式:
理解了这一点,你就明白为什么示例不是「装进篮子就行」,而是要像排菜单一样排顺序:把最关键、最相似的示例放在接近查询的位置,把任务定义性的示例放在开头,能显著改善输出质量。
- 位置索引 i示例在提示词中的排列位置,i=1 是最前面那条,i=k 是最后那条。
- 距离 k−i该示例离「最新位置」的距离,最后一条距离为 0,最前面一条距离为 k−1。
- 指数衰减 e^(−α·距离)距离越远权重越小,衰减速度由 α 决定;这量化了「近因效应」的强度。
动态检索选择
迎宾员记下食客「不吃辣、爱清淡」,主厨便从后厨几十道备选菜里,挑出最对胃口的几道作为试吃小碟。动态检索式示例选择就是这个思路:不再用一套固定的示例模板对付所有输入,而是针对每一条查询,从示例池中选出最相似的那几条。
具体做法分三步:第一步,把候选示例和当前查询都编码成「嵌入向量」——可以把它理解成把一句话压缩成一个高维坐标;第二步,用余弦相似度计算查询与每个候选的语义距离;第三步,取前 K 个最相似的示例,组装进提示词。这本质上是一种最近邻检索,也是向量数据库的典型用法。
两个向量的余弦相似度定义为它们夹角的余弦值,公式如下:
动态检索让每个食客都能吃到「量身定制」的示范菜。实践中,这套方法在客服分类、代码生成、问答系统等场景里,都比随机挑选示例稳定高出 10 到 20 个百分点,是当前 ICL 应用中最值得投入的优化方向之一。
- 向量 q 与 dq 是查询输入的嵌入向量,d 是某个候选示例的嵌入向量,二者都产自同一个嵌入模型。
- 点积 q·d对应维度相乘再求和,值越大说明两个向量在方向上重合越多。
- 模长归一化分母把两个向量的长度除掉,使相似度落在 [-1,1] 区间,避免长文本天然占便宜。
标签空间一致
菜单上印着「宫保鸡丁」,端上来的就必须是鸡丁而不是豆腐。食客会根据示例的标签分布建立预期:如果 8 条示例里 7 条是「正向」,模型就会觉得这家店专出好评菜,遇到模糊输入时不由自主地往「正向」靠。
标签空间一致性包含两层含义。第一层是答案格式统一:所有示例都用同一套标签词汇,比如统一用「正向/负向」,不要混用「正/负/好/不好」;否则模型会在标签之间犹豫。第二层是标签分布均匀:各标签的示例数量尽量接近,避免模型把「频率」当成「先验概率」。
我们可以用一个偏差量来度量示例标签分布与理想均匀分布的差距:
只有菜单与出品一致,食客才会对这家店建立稳定信任。设计示例时,务必检查标签词汇是否统一、各类数量是否均衡——这是最容易忽视、却对输出偏差影响极大的环节。
- 实际比例 n_c/k示例集中类别 c 的条数 n_c 除以总条数 k,得到该类出现的经验频率。
- 理想比例 1/|C|目标分布为均匀时,每个类别应占的比例,比如 3 个类别各占 1/3。
- 绝对值求和对每个类别求两个比例之差的绝对值再累加,Δ=0 表示完全均匀,Δ 越大表示越偏斜。
AI 应用场景
电商客服工单自动分类
阶段:Prompt 工程与推理优化
解决的问题:传统做法把任务描述写死在系统提示词里,遇到表述千奇百怪的工单,模型分类准确率波动大。利用历史已标注工单作为示例池,针对每条新工单动态检索最相似的 3-5 条示例,能显著提升分类稳定性。
具体案例:某电商平台积累 10 万条历史工单。新工单进入时,系统先用嵌入模型将工单向量化,在向量库中召回最相似的 5 条,统一拼成「输入:……\n输出:退款/物流/售后……」的示例序列,再交给大模型分类。上线后准确率从 82% 提升到 94%,且无需微调。
法律问答中的示例引导
阶段:检索增强生成(RAG)
解决的问题:法律咨询答案讲究依据和格式,泛泛而答容易出错或表述不规范。从判例库中检索与当前案情相似的判例作为 ICL 示例,模型会模仿示例的「结论+法条依据」结构作答。
具体案例:某法律科技公司将裁判文书按「案情简述-判决结果」整理为示例池。用户提问「试用期被辞退有赔偿吗」时,系统检索出 3 条相似判例示例,模型参照示例格式输出「结论:……依据:《劳动合同法》第……条」,答案规范性大幅提升。
模型评测集的均衡抽样
阶段:模型评估与数据工程
解决的问题:评测大模型时,如果使用的 Few-shot 示例标签偏斜,会高估或低估模型能力。用「标签均匀 + 类别覆盖 + 难度梯度」的原则构造评测示例,才能得到可信的分数。
具体案例:某评测平台在评估情感分类能力时,从样本库中按类别等量抽样,并混合简单与困难样本,构造 8 条示例。对比发现,标签均衡的示例集比偏斜示例集的评测分数更能反映模型真实水平,避免了「虚高」的榜单成绩。
Python 演示
# -*- coding: utf-8 -*-"""检索式 In-context 示例选择从示例池中检索与查询最相似的 K 个示例并组装统一格式的提示词"""import heapqimport mathimport re POOL = [ ("这部电影情节紧凑, 非常精彩。", "正向"), ("画面很美, 但剧情十分无聊。", "负向"), ("演员演技在线, 结局感人。", "正向"), ("节奏太慢, 看得人昏昏欲睡。", "负向"), ("故事立意深刻, 值得二刷。", "正向"), ("逻辑混乱, 完全不知所云。", "负向"),] QUERY = "剧情平淡, 还好结尾比较感人。" def tokenize(text): """以单个汉字为单位切分, 模拟简单分词""" return [ch for ch in text if "\u4e00" <= ch <= "\u9fff"] def count_features(text): """统计每个汉字的出现次数, 得到稀疏特征向量""" freq = {} for ch in tokenize(text): freq[ch] = freq.get(ch, 0) + 1 return freq def cosine_sim(vec_a, vec_b): """计算两个特征向量的余弦相似度""" shared = set(vec_a) & set(vec_b) dot = sum(vec_a[ch] * vec_b[ch] for ch in shared) norm_a = math.sqrt(sum(v * v for v in vec_a.values())) norm_b = math.sqrt(sum(v * v for v in vec_b.values())) if norm_a == 0 or norm_b == 0: return 0.0 return dot / (norm_a * norm_b) def retrieve_top_k(pool, query, k): """动态检索: 对候选示例打分, 取相似度最高的 K 个""" scored = [(cosine_sim(count_features(ex), count_features(query)), ex, lbl) for ex, lbl in pool] return [(ex, lbl, score) for score, ex, lbl in heapq.nlargest(k, scored)] def build_prompt(examples, query): """按统一模板组装 ICL 提示词: 输入: ... 输出: ...""" lines = [] for ex, lbl in examples: lines.append("输入: " + ex) lines.append("输出: " + lbl) lines.append("输入: " + query) lines.append("输出: ") return "\n".join(lines) if __name__ == "__main__": k = 3 picked = retrieve_top_k(POOL, QUERY, k) print("== 检索到的最相似 %d 个示例 ==" % k) for ex, lbl, score in picked: print("[%.3f] %s -> %s" % (score, ex, lbl)) print("\n== 组装出的 Few-shot 提示词 ==") prompt = build_prompt([(ex, lbl) for ex, lbl, _ in picked], QUERY) print(prompt)
count_features(text)把一句话转成「汉字→次数」的稀疏向量,模拟嵌入表示的雏形。cosine_sim(vec_a, vec_b)实现余弦相似度公式,分数越高说明两句语义越接近。scored = [(cosine_sim(...), ex, lbl) for ex, lbl in pool]对示例池中每一条候选示例打分。heapq.nlargest(k, scored)取出相似度最高的 K 个示例,对应「最近邻检索」。lines.append("输入: " + ex)用统一的键值对模板拼接示例,保证格式一致。if __name__ == "__main__":程序入口;运行后会打印选出的示例和最终的提示词。
常见误区
误区初学者觉得多放一些示例总不会错,于是把几十上百条示例全部塞进提示词,认为「喂得越多学得越多」。
正解准确率随 K 的增长是边际递减的(对数式增长),示例过多不仅挤占有限的上下文窗口,还会把不相关示例的噪声带进来,稀释模型对当前输入的注意力。就像餐桌上菜太多,食客反而记不住每一道菜的味道。一般 3 到 8 条高质量示例就足够。
为何常见:直觉上「量变引起质变」深入人心,忽略了上下文窗口容量和注意力资源的硬约束。
误区认为示例只是并列的信息,谁先谁后都一样,于是随机打乱顺序就提交。
正解模型是自回归结构,先看到的示例相当于「先入为主」的任务锚点,后看到的示例因为离生成位置更近而有更强的近因影响。评测中交换示例顺序常导致 5 到 10 个百分点的准确率波动。
为何常见:人类习惯把示例看成无序集合,忽略了 Transformer 逐 token 生成时的位置敏感特性。
误区从示例池里随机抓几个例子,觉得只要格式对,效果就差不多,不值得花时间检索。
正解与当前输入语义相近的示例能提供更贴合的解题示范。用嵌入相似度检索选出的示例,通常比随机采样高出 10 到 20 个百分点的效果。就像给不吃辣的顾客上一桌川菜示范,示范得再标准也不对症。
为何常见:因为示例看起来都是「同一类任务」,忽视了任务内部不同输入之间的模式差异。
误区觉得只要每个标签类别都在示例里出现过,分布是否均匀无所谓。
正解模型会统计示例中的标签频率并产生先验倾向,若 8 条示例里 7 条是「正向」,遇到模糊输入时模型会偏向输出「正向」。保持标签均匀分布,相当于告诉模型「各类概率相等」,减少诱导偏差。
为何常见:把「类别存在」误解为「类别均衡」,没意识到语言模型对频率分布极其敏感。
误区示例里一会儿 JSON、一会儿自然语言、一会儿加各种表情符号,觉得形式多样能展示模型「见多识广」。
正解不一致的格式会让模型难以归纳统一规律,甚至在不同格式之间切换时出错。统一模板(如「输入:……\n输出:……」)等于给模型画好了解题答题卡,省去它猜测结构的心思。
为何常见:把提示词当作文案展示,忽略了模型真正需要的是稳定、可预期的规律。
面试题
Q1. 关于 In-context 示例的格式,以下哪项说法正确?
- A.示例格式越复杂模型学得越快
- B.示例格式需要保持统一一致← 正确答案
- C.示例格式与任务效果完全无关
- D.示例格式必须使用 JSON 语法
答案:B。统一格式相当于给模型画好答题卡,能降低它理解任务的成本;格式复杂、与任务无关或强制 JSON 都不是必要条件。就像餐具统一食客才不会手忙脚乱。
Q2. Few-shot 中 K 值通常如何选择?
- A.K 值取得越大模型效果越好
- B.K 值必须大于训练数据总量
- C.K 值通常选择 2 到 8 个即可← 正确答案
- D.K 值固定为 100 个以上才有效
答案:C。K 值带来的收益是边际递减的,2 到 8 个示例通常已到收益拐点,过多示例挤占上下文窗口。上菜上了二十道,食客反而记不住味道。
Q3. 关于示例顺序的影响,哪项描述正确?
- A.示例顺序对输出没有任何影响
- B.靠近输出的示例影响往往更大← 正确答案
- C.靠近开头的示例永远影响更大
- D.示例顺序只影响速度不影响质量
答案:B。由于自回归生成机制,靠近生成位置的示例具有更强的近因效应,影响更大;开头示例也有任务定义作用,但「永远更大」或「毫无影响」都过于绝对。
Q4. 检索式示例选择通常使用哪种度量?
- A.计算字符串的长度编辑距离
- B.统计词频出现的总次数
- C.计算嵌入向量的余弦相似度← 正确答案
- D.统计词语的笔画数总和
答案:C。动态检索一般把文本编码成嵌入向量,再用余弦相似度衡量语义方向是否一致。编辑距离侧重字面差异,词频和笔画数无法刻画语义相似。
Q5. 关于示例多样性,正确说法是?
- A.多样性越高模型效果一定越差
- B.重复同一个示例效果最好
- C.覆盖不同类别与难度更佳← 正确答案
- D.多样性只对视觉模型有效
答案:C。多样性包括类别覆盖、难度梯度与分布均衡,能帮助模型建立全面的判别边界。全是同一类示例会让模型产生偏见,就像连续上四道红烧肉一样腻。
Q6. 示例标签分布严重偏斜时会发生什么?
- A.模型更倾向输出高频标签← 正确答案
- B.模型会自动均衡标签分布
- C.模型会完全忽略标签信息
- D.模型输出速度会显著加快
答案:A。模型会从示例中统计标签频率并形成先验倾向,高频标签被过度偏爱。模型不会自动均衡,也不会忽略标签,更与速度无关。「菜单」偏了,「出品」自然跟着偏。
Q7. 在 ICL 条件概率公式 P(y|x,S) 中,S 代表什么?
- A.模型的全部训练参数集合
- B.一条完整的提示词模板
- C.事先给出的示例集合← 正确答案
- D.输入文本的字符长度
答案:C。S 是 Few-shot 示例集合,即若干条「输入-输出」示范对,作为已知条件参与生成。训练参数是 θ 的部分,模板只是载体,字符长度与 S 无关。
Q8. 设计高质量 ICL 示例应遵循哪些原则?
- A.保持模板结构统一← 正确答案
- B.示例数量尽量越多越好
- C.覆盖不同的类别与难度← 正确答案
- D.检索与输入相似的示例← 正确答案
答案:ACD。统一格式、多样均衡、按需检索都是提升示例质量的关键。示例数量并非越多越好,边际递减和上下文限制决定了「少而精」更优。
Q9. 关于示例顺序的近因效应,说法正确的有哪些?
- A.模型更关注靠近输出的示例← 正确答案
- B.所有位置的影响完全相同
- C.开头的示例也会留下印象← 正确答案
- D.交换顺序结果绝对不变
答案:AC。越靠近输出的示例影响越大(近因效应),开头示例则起到任务锚定作用。不同位置影响不同,交换顺序往往引起结果波动,故 B、D 错误。
Q10. 哪些因素会影响 ICL 示例的实际效果?
- A.示例的格式与模板结构← 正确答案
- B.示例的数量与排列顺序← 正确答案
- C.示例的多样性与标签分布← 正确答案
- D.示例文字的颜色与字体
答案:ABC。格式、数量、顺序、多样性、标签分布都是影响 ICL 效果的关键因素;而文字颜色、字体等在纯文本提示词中根本不存在,属于干扰项。