§ 10.2 · Section

Few-shot 示例

Few-shot Prompting & In-Context Learning

"光说不如给个例子"——这句老话在提示词里成立到令人吃惊的程度。但关于"给几个例子"这件事,中文互联网上流传的答案和提出这个词的那篇论文,差了整整一个数量级。"Few-shot 就是给三五个例子"这句话你一定听过。而 GPT-3 那篇《Language Models are Few-Shot Learners》里,few-shot 的示例数原文写的是 "typically 10 to 100"——10 到 100 个。三五个是当代工程实践的建议(Anthropic 官方给的正是 3 到 5 个),跟论文的做法不是一回事。这一节要做的第一件事,就是把这两个数字彻底分开;然后讲清 in-context learning 到底是怎么回事、示例该怎么挑、以及论文自己诚实列出的失效清单。

生活场景
🥟 教人包饺子:说十遍不如包一个给他看

你要教一个从没进过厨房的人包饺子。

方式一 · 纯讲:"取一张皮,放适量馅,对折捏合,边缘要压紧,捏出褶子。"每个字他都懂,可"适量"是多少?"褶子"往哪个方向捏?捏出来的东西大概像个小笼包,也可能像个馄饨。

方式二 · 包一个给他看:你不说话,当着他的面包三个,摆在案板上。第一个是标准的,第二个馅少了一点、你顺手把它捏成月牙形补救,第三个皮破了、你演示怎么用另一张皮补。

他看完那三个,比听你讲十分钟管用得多。因为示例同时传递了三层信息:包成什么样(目标形态)、怎么包(操作过程)、遇到意外怎么处理(边缘情况)。这三层里,后两层几乎无法用语言精确描述。

Few-shot 提示就是"包几个给它看"。你不描述规则,你直接给出几对「输入 → 输出」,让模型自己从中提取规律。这一招之所以有效,是因为很多要求你自己也说不清楚,但你一眼能认出对不对。

三个词先分清:zero-shot、one-shot、few-shot

这三个词都出自 GPT-3 那篇论文,而且论文给了非常明确的定义。它们共同的前提最关键,也最常被忽略:三者都不做梯度更新、不做微调。

先把"梯度更新"这个词翻译一下。梯度更新(gradient update)说白了就是"改动模型内部的参数"——那是训练干的事,要显卡、要时间。而这三种设定全都在"模型一个参数都不改"的前提下进行,差别只在于你在提示词里放了几个示例。这一点决定了它们的性质:这不是学习,这是"看着办"。

设定论文里的定义你在提示词里放什么要不要改模型参数
zero-shot
零样本
不给任何示例,只给一段自然语言的任务说明"把下面这句英文翻译成中文:……"不改
one-shot
单样本
只给一个示例任务说明 + 一组「输入 → 输出」不改
few-shot
少样本
在上下文窗口容量允许的范围内,给尽可能多的示例任务说明 + 若干组「输入 → 输出」,论文里通常 10 到 100 个不改

注意 few-shot 那一行的定义。论文的原意不是"给少量几个",而是"在窗口装得下的前提下,能给多少给多少"。那个 "few"(少)是相对于传统机器学习来说的——传统方法要几千上万条标注数据才能学一个任务,而这里只要几十条放在提示词里就行,所以叫"少"。"少"是相对训练数据的"少",不是相对你的直觉的"少"。这是整个混淆的源头。

GPT-3 那篇论文的准确信息

既然本节要靠这篇论文立论,先把它的身份信息核准:

"in-context learning"这个词值得当场翻译。in-context 就是"在上下文里",也就是在你那段提示词里;learning 是学习。合起来就是"模型在读你这段提示词的过程中,临时摸清了这个任务该怎么做"——读完这次请求,它什么都不记得,下次得重新看一遍示例。

为什么论文管它叫"元学习的内循环"?元学习(meta-learning,"学习怎么学习")分两层:外循环是漫长的预训练,模型在里面见过无数种任务模式;内循环是每一次具体推理,模型在提示词里认出"哦,这是那类任务",然后调用已有的模式。打个比方:外循环是一个人上了十几年学、见过各种题型;内循环是他考试时看了两道例题,立刻明白这张卷子考什么。他不是在考场上学会了新知识,他是认出了该用哪套已有的本事。

★★ 最容易写错的一条:10 到 100,不是 3 到 5

这是本节最有价值的澄清点,值得单开一节反复说。

GPT-3 论文里,few-shot 的示例数原文写的是 "typically 10 to 100"——通常 10 到 100 个。这个数字受限于模型的上下文窗口能装多少。

而中文技术文章里几乎一致地写着"few-shot 就是给 3 到 5 个例子"。这句话并不是凭空编的——它来自当代工程实践,而且有权威出处:Anthropic 官方文档建议给 3 到 5 个示例

两个数字都是对的,但它们回答的是两个不同的问题。混着用,就会在两个场合同时判断失误。

GPT-3 论文(2020)当代工程实践(Anthropic 官方建议)
示例数通常 10 到 100 个3 到 5 个
要回答的问题不做任何微调,纯靠上下文,模型的能力上限在哪儿?在真实产品里,性价比最高的示例数是多少?
为什么是这个数为了把 in-context learning 的能力推到极致,窗口能塞多少塞多少够用即可。示例占 token、占钱、占窗口,而且当代模型的指令遵循能力远强于 2020 年
对示例的要求从数据集里采样,追求数量与覆盖相关、多样、有结构;贴近真实用例、覆盖边缘情况
使用场合读论文、理解基准测试设定、比较模型能力写产品提示词、控制成本

为什么工程实践能把数字降这么多?两个原因。第一,模型本身变了。2020 年的 GPT-3 是一个纯粹的"续写机器",你得用大量示例把它"扳"到任务上;今天的模型经过了指令微调和 RLHF(Reinforcement Learning from Human Feedback,"基于人类反馈的强化学习"),你直接说要求它就懂,示例只是用来消除歧义、对齐细节。第二,示例是要花钱的。每个示例都占 token,都要按输入价计费,还要挤占上下文窗口。100 个示例可能占掉几千个 token,每次请求都要重发一遍。

换成大白话:论文在实验室里测"最多能做到多好",所以不计成本地堆示例;产品里问"花最少的钱做到够好",所以三五个就收手。好比汽车极速要在专业赛道上把油门踩到底,而日常通勤没人这么开。拿赛道数据去指导日常驾驶,或者拿通勤经验去质疑赛道成绩,两种做法都不对。

论文的实测数据:从 zero 到 few 到底涨多少

光讲定义太虚,看论文给的两组具体数字。这两组都可以放心引用:

数据集指标zero-shotone-shotfew-shotzero → few 的差
CoQA(对话式问答)F181.584.085.0+3.5
TriviaQA(常识问答)准确率64.3%68.0%71.2%+6.9 个百分点

看这两行有两个值得注意的地方。

第一,从 zero 到 one 的那一跳,往往比从 one 到 few 的那一跳更大。CoQA 是 81.5 → 84.0 → 85.0,第一步涨 2.5,第二步只涨 1.0。TriviaQA 是 64.3 → 68.0 → 71.2,第一步涨 3.7,第二步涨 3.2。这个规律的实用含义很直接:如果你现在一个示例都没给,那么加第一个示例的性价比最高。好比教人认路,第一次带他走一遍效果最大,第二次第三次的边际收益就小了。

第二,涨幅是几个百分点的量级,不是翻倍。Few-shot 是有效的手段,但它不是魔法。有些文章把 few-shot 说成"能让模型能力质变",那是夸大。真正会出现质变级提升的是 §10.3 要讲的思维链——那里有一组 17.7% 到 78.7% 的数字,那才叫质变。

论文最核心的那张图讲了什么

如果只能从 GPT-3 那篇论文里记住一个结论,应该是它 Figure 1.3 表达的那件事,而不是任何一个具体分数:

Key · 核心论点

随着模型规模变大:zero-shot 的表现平稳提升,而 few-shot 的提升更快。

换句话说,模型越大,越擅长 in-context learning——大模型不只是"知道得更多",它更擅长"看几个例子就明白你要什么"。这个"从例子里领会意图"的能力,本身是随规模涌现出来的。

这个结论比任何一个分数都重要,因为它解释了一件你可能观察到的现象:同样一份带示例的提示词,在小模型上几乎没用,在大模型上效果明显。不是你的示例写得不好,是小模型"领会力"不够。这就像学徒:老师傅示范一遍就能上手的活儿,新手看十遍还是不会——不是示范得不清楚,是接收端的能力不同。

Analogy · 装修师傅看的那块样板

你家装修,要贴一面很特别的墙砖:横竖交错、每三块换一次色、边角要留特定的缝。

做法一 · 写规范书:你熬夜写了两千字的施工说明,画了示意图,标了尺寸。师傅读完,皱着眉说"我大概明白了"——然后贴出来的东西跟你想的不一样。因为"错缝要错多少""换色的节奏从哪块开始"这些事,文字怎么写都有歧义。

做法二 · 贴一块样板:你自己在角落贴出 1 平米,让他照着来。他看两眼就懂了,连你没说出口的"哦原来横向要对齐"都一起懂了。

做法三 · 贴三块样板:一块标准区、一块阴角处怎么收边、一块遇到插座怎么绕。这三块把典型情况和麻烦情况都覆盖了,师傅贴一整面墙都不会来问你。

这就是 few-shot 的全部道理。做法一是纯指令,做法二是 one-shot,做法三是精心策展的 few-shot。注意做法三的关键不是"多",而是三块样板各自负责一类情况——这正是 Anthropic 说的"相关、多样、有结构"。而如果你贴的三块样板全是标准区,那第二块第三块就是白贴,这也解释了为什么示例的多样性比数量重要。

★ 示例怎么挑:官方给的三个词

Anthropic 官方文档对示例的要求浓缩成三个词:相关(relevant)、多样(diverse)、有结构(structured)。加上两条补充要求:贴近你真实的用例,以及覆盖边缘情况

要求说白了是什么意思反例(常见错误)
相关示例和你真正要处理的输入长得像——同样的领域、同样的句式、同样的数据形态你要处理的是客服聊天记录,示例却是正式的书面公文
多样几个示例之间不重复,各自覆盖一类不同情况给了五个例子,全是"正面评价 → 好评"这一种,模型学不到怎么处理负面和中性
有结构每个示例的输入和输出边界清楚、格式统一,最好用标签包裹示例和指令混在一堆文字里,模型分不清哪段是示例、哪段是要它做的事
贴近真实用例直接从你的真实数据里挑,不要自己编"干净漂亮"的假例子示例都是格式规整的短句,实际输入却是带错别字、带表情、带换行的真实用户留言
覆盖边缘情况把那几种"最容易出错"的情形各放一个进去只给了正常情况,模型遇到空输入、超长输入、多种意图混在一起时就乱了

关于"有结构",官方明确建议<example> 标签把每个示例包裹起来。这个做法看着琐碎,收益很实在——它让"示例区"和"指令区""待处理数据区"之间有了明确的墙。§10.4 会把这套标签体系讲透,这里先看它长什么样:

请把用户反馈归入四类之一:功能缺陷 / 体验问题 / 功能建议 / 无效反馈。

<examples>
<example>
输入:点进去就闪退,我都装了三遍了
输出:功能缺陷
</example>

<example>
输入:这个按钮藏太深了吧,找了半天
输出:体验问题
</example>

<example>
输入:希望能支持导出 Excel
输出:功能建议
</example>

<example>
输入:啊啊啊啊
输出:无效反馈
</example>

<example>
输入:闪退问题什么时候修?另外能不能加个夜间模式
输出:功能缺陷
备注:一条反馈含多个意图时,取更严重的那一类
</example>
</examples>

现在请处理这一条:
输入:更新完之后字变得特别小,看不清

数一下这里给了几个示例:五个,正好在 3 到 5 个这个建议区间的上限。而且这五个不是随便挑的——前四个各占一类(多样),第五个专门处理"一条反馈含多个意图"这种边缘情况,还顺手用"备注"字段把规则明确写了出来。这个"备注"是个好技巧:当示例本身可能引起疑问时,在示例内部把判断依据写清,比在指令区加一条抽象规则更有效。

★ 不要堆砌边缘情况:官方明确反对的做法

刚说完"要覆盖边缘情况",紧接着必须补一条反向的警告,否则很容易过头。

Anthropic 官方对此有一句非常直白的表态:团队常常会把一长串边缘情况(a laundry list of edge cases)塞进提示词里——"We do not recommend this."(我们不推荐这样做。)

官方给出的替代方案是:策展一组多样的、典型的(canonical)示例canonical 这个词值得翻译一下——它指"最标准、最能代表一类情况的那一个"。也就是说,与其列举二十种可能出错的情形,不如挑出五种最有代表性的,各给一个示例。

为什么堆砌边缘情况反而不好?三个原因

这条原则和 §10.4 要讲的"正确的高度"(right altitude)是同一件事的两面:提示词既不该是硬编码的规则堆,也不该是笼统到没有信号的空话。而官方特别强调的一句是——"minimal 不等于 short"(精简不等于短)。精简是指"没有冗余、没有互相打架的规则",不是指字数少。一份三千字但每一段都在提供不同信号的提示词,比一份五百字但反复强调同一件事的提示词更"精简"。

★ 论文诚实列出的失效清单

这一段能显著提升你对 few-shot 的判断力,因为它来自论文自己的坦白。

GPT-3 那篇论文明确列出了 few-shot 效果不佳的任务类别

任务类别代表数据集这类任务在考什么
自然语言推理ANLI判断两句话之间是"蕴含 / 矛盾 / 无关"。要的是逻辑关系判断,不是知识
阅读理解RACEQuAC读一段较长的文章后回答问题,常需要跨句子整合和多步推理

这份清单的价值在于它划出了 few-shot 的能力边界。Few-shot 擅长的是"教会模型输出格式和判断口味",不擅长的是"给模型它本来不具备的推理能力"。

换成大白话:你给几个例子,能让它明白"哦,你要的是这种风格、这种格式、这种粒度的判断";但如果这道题本身需要它做三步逻辑推演而它做不到,那给一百个例子也变不出来。好比你给学生看三道解得漂亮的证明题,他能学会答题的书写格式和排版,但如果他压根不掌握那个定理,例题再多也证不出新题。

顺带说,这也解释了为什么 CoT(思维链)在 few-shot 之后才被发现是个大突破——因为它攻的正是 few-shot 攻不下的那块阵地:让模型把推理过程一步步写出来。这是下一节的主题。

论文愿意把自己方法的失效场景写进去,这件事本身值得学。在技术判断上,一个方法的边界比它的战绩更有用——战绩告诉你它能干什么,边界告诉你什么时候别用它、该换别的招。

示例的顺序、数量、格式:几个实操细节

下面这些是工程实践里反复被验证的经验,不是论文结论,如实标注为经验做法:

什么时候该用 few-shot,什么时候不必

给一张判断表。因为示例是要花钱的,不该无条件加。

情形建议理由
输出格式复杂、用文字很难描述清楚强烈建议用示例是描述格式最高效的手段,一个例子胜过三段说明
判断标准带主观口味(什么算"重要"、什么算"合格")强烈建议用口味没法定义,只能示范。这是 few-shot 最不可替代的场景
要做批量分类、抽取,且类别边界模糊建议用示例能把边界钉住,尤其是那几个容易混的类别之间
任务本身极其常见(翻译、摘要、改写)可以先不用模型见过海量此类数据,zero-shot 通常够好。先测再决定要不要加
需要的是深度多步推理不要指望 few-shot论文自己列了 ANLI、RACE、QuAC 这类的失效情况。该用 CoT(§10.3)
上下文预算非常紧张谨慎用,先算账示例每次请求都要重发。如果示例固定不变,把它放提示词最前面吃前缀缓存折扣(见 §8.1)
已经有几千条标注数据考虑微调数据量到了这个级别,微调的效果和长期成本通常都优于把示例塞进每次请求

最后一行值得多说一句。Few-shot 和微调是同一个坡上的两个位置。示例三五个,用 few-shot;标注数据几千条,用微调。中间那一大段灰色区域,判断依据是这份提示词要被调用多少次——调用一万次,那几千个示例 token 就被付了一万遍,微调的一次性成本反而便宜。好比租房和买房:住三个月租,住十年买,中间那几年得算账。

Few-shot 到底"学"到了什么:一个值得警惕的细节

这一段稍微深一点,但它能让你对示例的作用有个更准的判断。

直觉上我们会以为:模型从示例里"学到了任务的规则"。但更贴近实情的说法可能是——示例主要在做三件事:告清任务是哪一类、钉住输出的格式、划定标签的取值范围。至于"每一条输入到输出的映射关系",模型很大程度上是靠预训练里已有的能力去补的。

这件事的实用含义:如果一个任务是模型压根没见过、也无法从常识推导的(比如你们公司内部一套自创的编码规则),那么给三五个示例往往不够,模型会"照着格式套,但内容全靠猜"。这种时候更该做的是把规则明确写出来,而不是指望示例把规则传递过去。

好比教人用一台洗衣机:如果这机器的按钮布局符合常规,你演示一次他就全会了;但如果这台机器有个"必须先按住电源三秒才能选程序"的怪脾气,你演示十次他也未必注意到那三秒——你得直接说出来。示例传递的是"看得见的形态",说不出的怪规则得靠文字明说。

反过来也成立:凡是"你自己也说不清、但一眼能认出对不对"的要求,就必须靠示例。文案的调性、摘要的详略、代码注释的粒度、翻译里哪些词该保留英文——这些东西写成规则会变成一堆自相矛盾的形容词,给三个例子反而一目了然。说白了:能说清的用文字,说不清的用例子,两样都不省。

常见误解一次澄清

常听到的说法实际情况
"few-shot 就是 3 到 5 个,这是论文定义"混了两件事。GPT-3 论文写的是通常 10 到 100 个;3 到 5 个是当代工程实践建议(Anthropic 官方口径)
"few-shot 是一种训练/微调"不是。论文明确前提是不做梯度更新、不做微调——模型参数一个都不改,全部发生在提示词里
"示例越多越准"边际收益递减,且要花钱占窗口。论文数据显示 zero→one 那一跳最大,one→few 明显变缓
"few-shot 能解决推理题"论文自己列了失效清单:ANLI 等自然语言推理、RACE 与 QuAC 等阅读理解。推理题该用 CoT
"边缘情况列得越全越好"官方明确反对堆砌一长串边缘情况(原话 "We do not recommend this"),应改为策展一组典型示例
"精简就是写短"官方特别强调 minimal 不等于 short。精简指没有冗余与冲突,不指字数少
"GPT-3 那篇论文拿了 NeurIPS 最佳论文奖"这一点没有取得证据。可确认的是 NeurIPS 2020 收录。不要给论文加没核实的封号
"示例格式随便,模型能看懂"格式不统一会直接削弱示例作用。所有示例必须同标签、同分隔符、同字段顺序

最后一个提醒:示例是「样品」,不是「说明书」

很多人给示例时会不自觉地写成教程,一条示例后面跟三行解释。这其实搞错了示例的作用。

打个裁缝店的比方:你想做一件衬衫,最有效的办法不是给裁缝写一篇《衬衫工艺说明》,而是带一件你满意的衬衫过去,说「照这个做,领子改成立领」。样品传递的信息量,远远超过同等篇幅的文字描述。

相当于照相馆里,你说「拍得自然一点」摄影师未必懂,但你翻出一张手机里存的照片说「像这张」,他立刻就知道了。说白了——示例的价值在于它是一个可以直接比对的成品,不是一段需要理解的规则。

所以写示例时,把力气花在让示例本身足够典型上,而不是花在给示例加注释上。如果你发现必须写一大段解释才能让示例说得通,那通常说明这条示例选得不够好,该换一条,而不是该加注释。

Recap · 收束

Few-shot 就是"包几个饺子给它看"——不描述规则,直接给几对「输入 → 输出」,让它自己提取规律。三种设定的共同前提是一个模型参数都不改:zero-shot 不给示例只给说明,one-shot 给一个,few-shot 在窗口装得下的前提下尽量多给。论文管这个能力叫 in-context learning,并把它定位为元学习的内循环。

本节最该记住的澄清:GPT-3 论文里 few-shot 通常是 10 到 100 个示例;Anthropic 官方给工程实践的建议是 3 到 5 个。两个数字回答的是不同问题,混着用会两头判断失误。论文的实测数字是 CoQA 的 81.5 / 84.0 / 85.0 与 TriviaQA 的 64.3% / 68.0% / 71.2%——涨幅是几个百分点,不是翻倍,而且从零到一那一跳性价比最高。核心论点是:模型越大,越擅长从例子里领会你要什么。

挑示例要"相关、多样、有结构",用 <example> 标签包好。但不要堆砌一长串边缘情况——官方原话是"We do not recommend this",应改为策展一组典型示例;并且记住 minimal 不等于 short。最后,论文诚实列出了 few-shot 的失效清单:ANLI 等自然语言推理、RACE 与 QuAC 等阅读理解。它能教格式和口味,教不出本来不具备的推理能力。

而那块攻不下的阵地,正是下一节的主题——让模型把推理过程一步一步写出来。那里的提升幅度是从 17.7% 到 78.7%,真正的质变。顺带还要拆一个流传更广的传说:"深呼吸,一步步想"这句咒语究竟是谁想出来的。

☰ 主页
学海无涯 · 智能篇 · § 10.2