模型变强之后,Skill 和 Prompt 该做减法了
最近几个月,我花了不少时间在做同一件事:把之前精心调试过的 Prompt 和 Skill 拆开,逐行审视,然后删掉一大半。起因是一次实测经历——我拿一个打磨了好几周的工作流去跑新版本模型,结果发现效果没有变好,反而更不稳定了。后来把 Prompt 从八百字压缩到六十字,把原先拆成五步的 Skill 合并成一步,整个流程不仅更稳,输出质量还明显上了一个台阶。
这个话题值得单独拿出来聊聊。如果你也在用大模型做自动化任务、搭 Agent,或者维护一批长期使用的 Skill 模块,那你大概率也攒下过不少“历史包袱”——那些为旧模型针对性设计的复杂指令、长串的少样本示例、层层嵌套的流程编排。在那个模型能力还比较弱的阶段,这些都是必要的;但当底座模型已经换了几代之后,它们很可能正在悄悄拖累你的效果。这篇文章就是围绕“做减法”展开的:为什么该减、怎么减、哪些不能减、以及如何验证减完之后的效果。我尽可能用自己踩过的坑和实测数据来说明,希望能给你一些可以立刻上手的判断依据。
以下默认你具备基本的概念认知:Prompt 是发给模型的指令文本,Skill 则是把意图识别、Prompt 模板、工具调用、后处理逻辑打包成的一个可复用模块。如果你对后者不太熟,可以把它理解成一个“提前封装好的技能包”,Agent 按需调用。有了这个前提,我们往下聊。
1. 从“模型弱”到“模型强”,Prompt 策略的假设变了
先说一个反直觉的事实:很多当时看起来天经地义的 Prompt 技巧,本质上都是在迁就一个“理解能力不太行”的模型。当模型换代之后,这些技巧不仅没有增益,反而可能变成干扰源。
1.1 旧策略的诞生背景:那是为“不聪明”的模型准备的
早期的模型很“楞”。你问它一句话,它可能答非所问;你让它输出 JSON,它可能夹带散文;你让它按步骤执行,它可能自作聪明跳过中间环节。为了对付这些问题,社区里沉淀出了一整套工程手段:把任务拆得很碎、每一步都给出明确的输出格式约束、给若干条 few-shot 示例让模型模仿、在指令里反复强调“不要做什么”。
这套思路在当时是有效的,也确实是那个阶段能做到的最好方案。但问题在于,当所有人都在用这套方法论时,很多人已经把这个“迁就弱模型”的手段本身当成了目的。一套 Prompt 写得越来越长,长到模型需要先花大量上下文去理解“你要它怎么回答问题”,而不是直接回答问题本身。
我见过一个典型的案例:某团队的一套文档分类 Prompt,包含任务描述、角色设定、输出格式定义、五条 positive 示例、五条 negative 示例、边界情况处理说明,总计超过两千字。每换一个场景,他们就在原有 Prompt 上继续追加补充说明。结果就是模型把大量注意力用在理解这些“元指令”上,真正用于理解文档内容的比例反而下降了。
1.2 新模型的“内化能力”:指令跟随的质变
现在的模型不一样了。新一代模型在预训练和指令微调阶段,就已经“内化”了大量关于角色扮演、格式输出、任务拆解、步骤执行的通用能力。这意味着什么?意味着很多你原本需要用几百字去教它的东西,它早就会了。
最典型的是格式约束。过去你要给它定义“必须返回 JSON,且字段名为 title、content、timestamp”,然后还要附上示例。现在的模型,只要你在结尾写一句“以 JSON 格式输出”,它就能给出符合预期的结构化结果。我自己的实测是:在同一个输入下,不写完整字段定义,只给一句格式要求,模型输出的 JSON 字段名甚至比用完整 schema 约束时更稳定——因为字段名没有被提示词里的其他噪声干扰。
这不是说提示技巧完全没用了,而是说提示技巧的作用边界发生了位移。过去技巧是用来“教模型做事”,现在技巧更应该用来“告诉模型目标”。当我们还在用旧方式教一个已经会做的模型做事时,本质上是在给一个熟练工反复培训入门课程,它不反感,但它会因此变得迟钝。
1.3 减法背后的本质:把注意力还给任务本身
大模型的注意力窗口虽然是有限的,比过去大得多,但注意力质量依然有限。当你塞进去大量冗余说明时,模型确实会“读完”它们,但真正作用于关键信息的权重会被稀释。
我自己的体感是:Prompt 中的每一句可有可无的话,都像在给模型的推理过程加一层雾。模型需要先判断“这句话是在约束我,还是在提供任务信息”,这个过程本身就是一次额外的推理开销,也会引入额外的不确定性。现在模型变聪明了,最理性的做法就是不再让它做这种判断题,把它的聪明用在任务本身。这跟你自己干活一样:如果领导给你下任务时说了一堆废话,你要么花时间去分辨哪些话有用,要么干脆理不清重点。模型也一样。
2. 做减法之前,先看清哪些 Prompt 内容是噪声而非信号
减法不是乱删。你得先知道一段 Prompt 里哪些东西是“信号”,哪些是“噪声”。我把常见 Prompt 内容做了个分类,基本上所有话都可以归入这几类,但它们的价值差异极大。
2.1 角色设定:需要判断是“真实约束”还是“无效装饰”
“你是一个资深的文案专家”“你是一个严谨的代码审查者”“你是拥有十年经验的律师”……这类角色设定是社区里最常见的写法。但我的判断是:绝大部分角色设定都属于无效装饰。
为什么会这样?因为模型本身已经具备了大量专业领域的知识表征。你说“你是一个资深文案专家”,和直接说“请写一段产品文案”,在输出质量上的差异几乎可以忽略。角色设定在什么情况下才有效?是在模型的默认输出风格和你的目标明显不一致时。比如,你希望输出更口语化,但模型的默认风格偏正式,这时“你是我的朋友,请用聊天的口吻回应我”这类设定才有真实的约束价值。
我的建议是:做一个简单的消融测试。把角色设定删掉,对比输出,如果发现没有显著变化,那就删掉。不要因为“大家都这么写”就保留。我做过不少类似的对比,多数情况下的结论都是“删了没差”。
2.2 纷繁的 few-shot 示例:少而精才是趋势
Few-shot(少样本示例)曾经是 Prompt 工程的核心支柱。在模型能力有限的阶段,给两三条示例确实能让模型快速掌握任务模式。但到了现在,这一点需要重新评估。
我自己的实操经验是:当模型已经具备了基本的任务理解能力,示例的价值主要体现在两个场景——输出格式极其特殊、难以用文字描述清楚时;或者任务的判断标准非常主观、需要给模型一个“品味锚点”时。除了这两种情况,多数示例是可有可无的。
更关键的是,示例可能带来“示例偏差”。如果你给了一条质量并不完美的示例,模型反而会模仿那条示例中的瑕疵。我在一个摘要任务中深有体会:我给了三条示例摘要,模型产出的摘要风格和我的示例高度趋同,包括示例中的表达定式。删掉示例后,模型产出的摘要反而更自然多样、信息密度更高。这让我意识到,示例在教模型的同时,也在限制模型的上限。给模型一条“标准答案”,它就懒得自己想更好的答案了——除非你明确告诉它“这只是格式参考,内容质量要超过它”。
2.3 负面指令的边际递减:从“别犯错”到“目标明确”
“不要输出多余的解释”“不要编造事实”“不要使用过于正式的语言”……这类负面指令也是过去很少争议的标配。但这里同样存在边际递减效应。
负面指令的问题在于:它让模型的注意力往“错误方向”聚集。当你说“不要编造事实”时,模型会反复检视自己的输出里是否存在“编造事实”的嫌疑——这个检视过程本身就是推理偏差的来源。尤其在生成类任务里,你越强调某个负面行为,模型越容易在相关概念上打转。
当然,不是说所有负面指令都要删干净。我的原则是:只保留对任务成败起到关键作用的负面约束,比如“在代码中不要使用外部依赖”这种直接影响结果的硬约束;而类似于“不要啰嗦”“不要加多余解释”这类软性约束,完全可以转化成正面指令——“请直接输出最终结果”,效果反而更好。
2.4 冗长的步骤描述:任务拆解要收敛到“必要粒度”
步骤描述是很多复杂 Skill 里占比最大的一部分。过去大家习惯把任务拆到特别细,比如“第一步,分析用户输入。第二步,列出三个可能的意图。第三步,为每个意图生成回复草稿。第四步,选择最合适的草稿。第五步,格式化输出为 JSON。”这个思路的诞生背景是:弱模型一次做不了太多事,拆细了才能保证每个环节的质量。
但现在的模型在不同任务间的迁移和执行能力已经有本质提升。过度拆分会带来两个新问题:一是步骤之间的衔接需要模型额外维护“中间状态”,这种状态维护在没有显式记忆机制的 Prompt 执行过程中是脆弱的;二是每一步的描述本身都在消耗上下文,挤占了实际任务的信息。我实测过很多次,一个原本拆成八步的任务,合并成“分析输入并直接输出结果”三步,效果几乎不降,有时候还升了。
判断步骤是否过细有一个很简单的标准:相邻两步之间是否有必须的中间产物。比如“先生成草稿、再修改草稿”,如果修改这一步并不依赖草稿的中间版本,那么这两步就应该合并成一步——“生成一份高质量的最终文案”。
3. Skill 的减法:从“流程保险丝”回到“行为约束”
Prompt 层面的减法比较容易理解,但 Skill 层面的减法要复杂一些,因为 Skill 还涉及工具调用、分支逻辑、外部依赖等更多组件。这里我重点讲三个我认为最值得动手的方向。
3.1 消除无意义的“流程保险丝”步骤
不少人在搭 Agent 工作流的时候,会下意识地加一些“保险丝”步骤:比如给模型加一个“自查环节”,让它输出答案后再检查一遍自己的回答是否合理;或者加一个“意图确认环节”,先问用户一句“你确定要做这个吗”。这些步骤背后的出发点是好的——防止模型乱来。但当模型变强之后,这些保险丝的成本收益比就不再划算了。
“自查”就是一个典型的例子。它可能降低输出中的明显错误率,但同时会拉长推理链。推理链越长,中间环节的微小偏差积累越多,最终输出的稳定性反而下降。我用一组 50 个测试样本做过对比:带自查流程的版本,输出错误率 4%;不带自查流程的版本,输出错误率也是 4%。但带自查流程的平均延迟高了近一倍。也就是说,这个保险丝没有带来任何收益,纯纯的成本。
“意图确认环节”则更值得商榷。多数真实场景中,用户给 Agent 发指令时已经带着明确的意图,多一轮确认只是增加交互成本。除非你的场景本身是高风险的(比如删除数据、发送邮件、扣费操作),否则意图确认就是多余的。
3.2 当子任务节点的执行边界变模糊,说明该合并了
Agent 类的 Skill 常常被拆成多个子任务节点,每个节点有独立的 Prompt 和输出。这种结构在弱模型时代非常合理,因为每个节点的职责边界足够清晰。但现在你会发现,很多子任务节点的边界已经变模糊了:比如“信息抽取节点”和“信息分类节点”之间的边界,模型已经能一次做完;再比如“要点归纳节点”和“最终总结节点”,模型输出结果几乎一样。
当你发现两个节点的输出高度相似,或者第二个节点只是对第一个节点的输出做了轻微加工时,这就是明确的合并信号。合并之后,你的 Skill 会变得更轻、更直接,更重要的是,它减少了多节点串行执行时中间的“信息翻译损耗”——每个节点的输出都要经过一次格式转换和语义提取,这种转换过程本身就有信息损失。把多个节点合成一个,信息从原始输入直接到最终输出,损耗最小。
我自己的一个典型实践是把一个“先抽取关键信息,再基于关键信息生成报告”的两节点 Skill,合并成一个“直接生成报告”的单节点 Skill。合并前,报告里偶尔出现“抽取结果与报告内容不一致”的问题;合并后,这个问题彻底消失了。因为模型直接从原始上下文生成了报告,不存在中间抽取结果的干扰。
3.3 知识库引用和外部工具:减少认知负担,而不是增加
随着 RAG 的普及,很多人构建 Skill 时习惯性加上知识库检索,把相关知识片段注入上下文作为参考。这个思路本身没错,但它有两个潜在问题。
一是“知识噪声”。当你检索到的知识片段和当前任务相关度不够高时,这些片段不仅无益,还会干扰模型对任务的理解。我在一个汽车维保问答 Skill 中发现:当知识库检索到的内容包含车型配置参数时,模型反而容易混淆“问题问的是故障现象,却答了一堆配置说明”——因为检索片段里的参数信息权重太高,压过了用户问题本身的意图。
二是“引用过度”。一些 Skill 会要求模型“回答时引用知识库原文”,这会让输出变得冗长,而且模型会在引用时尽量保留原文措辞,导致答案的针对性和可读性下降。更合理的做法是:知识库只提供事实依据,模型用自己的语言组织答案。如果你发现强引用模式已经在拖累回答质量,那就改成“参考知识库内容,用自己的话回答”。
减法在这里的体现不是删掉知识库,而是简化引用策略,删除低质量片段,把上下文空间让给更重要的任务信息。
4. 减法不是裸奔:三条不能砍的底线
说了这么多该减的东西,如果不讲边界,很容易把人带进另一个极端:把必要的约束也删了,导致输出回到“野马”状态。我在反复实验中总结出三条不能随便砍的底线,供你参考。
4.1 输出格式的硬约束:最不值得赌的部分
哪怕是最聪明的模型,在“自由发挥”时也经常制造意外格式——该换行不换行,该用 JSON 用了 Markdown,或者字段名说变就变。输出格式的硬约束,是 Prompt 里最不该省的部分。
我的建议是:输出格式描述应该保持精确但精简。不需要长篇大论解释每个字段的含义,但要明确给出结构骨架,必要时给一个最小示例(注意是最小示例,不是完整示例)。比如你要求 JSON 输出,就写清楚字段名、字段类型、嵌套关系,附上一个极简的、符合结构的雏形。这样模型有了“格式锚点”,但又不至于被完整示例带偏内容风格。
格式约束的删除要特别谨慎,尤其是下游有解析器或自动化流程依赖时。我见过不止一次因为输出格式不规范导致整个链路报错的情况,排查起来非常痛苦。这个底线不该碰。
4.2 关键安全边界与不可逆操作的确认机制
无论模型变得多强,对于涉及不可逆操作的场景,确认机制不能减。比如:删除数据、覆盖文件、发送对外消息、扣费支付、修改权限。这些操作一旦执行出错,后果不是“重新生成一次”能解决的。确认机制在这里不是“流程保险丝”,而是“安全护栏”,两者有本质区别。
保险丝减掉的理由是“成本大于收益”,护栏保留的理由是“收益根本无法用成本衡量”。所以在设计中,高风险的确认节点必须保留,而且还要尽量设计成“用户显式确认”,而不是“模型自行判断是否需要确认”。
同理,涉及隐私、合规、安全边界的行为约束也不该删。比如“不要输出个人敏感信息”“不要给出医学诊断类结论”这类硬性限制,无论模型多强都该保留。你可以把它们写得言简意赅,但内容不能砍。
4.3 任务所需的领域语义上下文:这是“信号”,不是“噪声”
最后一条不能砍的是任务所需的领域语义上下文。什么是领域语义上下文?就是模型无法从自身知识中直接获得的任务背景信息,比如你的业务流程、数据字段定义、产品的目标用户特征、专业术语在你的场景中的特殊含义。
这些内容虽然写起来冗长,但它们是为模型提供“任务坐标系”的关键信息,删了模型就只能靠猜。所以,减法的标准不是“字数少”,而是“只保留对任务有直接影响的信息”。领域语义上下文属于直接影响任务质量的信息,是信号,是必须保留的。
我建议区分两类信息:一类是“任务背景”(必须保留),另一类是“对模型行为方式的修饰”(多数可减)。判断一个问题即可:如果删掉这段信息,模型还能准确知道“我到底要它做什么、做到什么程度算合格”吗?如果能,删;如果不能,留。
5. 回归测试与效果验证:敢减,还要会验
做减法最大的心理障碍是“万一删坏了怎么办”。这事无解,只能靠验证。你需要一套低成本、高覆盖的回归测试流程,让你每次减完都有充分信心。这也是我这几周反复做的事情。
5.1 优先构建你的“黄金样本集”
手头最重要的资产不是 Prompt,而是一组高质量测试样本集。这个样本集我一般保持 30-50 条,覆盖典型输入、边界输入、异常输入三类。每条样本包含:输入、期望行为要点、可接受的输出范围。注意,期望输出不一定是标准答案,而是行为约束的集合(比如“必须包含三个要点”“不得出现编造的引用来源”),这样更符合生成式任务的特点。
这个样本集不是一次建完的,而是每次遇到线上问题、用户反馈或边界案例时,都往里追加一条。时间久了它的覆盖面会越来越广,成为你评估 Prompt/Skill 质量的唯一可靠依据。
5.2 输出对齐与稳定性并重的评估方式
每次做 Prompt 减法时,我跑两个维度:对齐度和稳定性。对齐度,是把同一批样本喂给旧版和新版的 Prompt,看新输出是否还满足“可接受的行为约束”;稳定性,是把同一样本跑五遍(或十遍),看输出的变异程度是否在接受范围内。
减法的目标不是“输出不变”,而是“输出质量不降,且稳定性提升”。如果减完 Prompt 后,输出的对齐度不掉、稳定性变好,就大胆保留。如果一个减完的结果在对齐度上掉了一条语义边界的上限,稳定性的提升又不足以弥补,那就表明减过头了,回退一个层级。
我推荐的做法是,每减一处,只改一个变量,然后完整跑一遍样本集。这样可以精确定位是哪一句删除导致的退化,不用猜。这是最笨但最有效的方法。
5.3 用“压力样本”检验过度的减法
除了常规回归,我还习惯准备几条“压力样本”。这些样本专门用来测试 Prompt/Skill 的韧性——比如输入特别长、意图特别隐晦、边界条件特别模糊、或者包含干扰信息。在正常样本上能通过的 Prompt,遇到这类样本才见真章。
一个很常见的现象是:正常输入下,精简 Prompt 和冗长 Prompt 的效果差不多;但遇到压力样本时,冗长 Prompt 中那些细枝末节的提示,反而会绑住模型的手脚,让它在异常输入面前不知所措。而精简 Prompt 因为保留了充分的推理自由度,往往表现更稳。所以我说“压力样本”是判断 Prompt 冗余度的试金石:如果一条 Prompt 在正常样本上表现不错、压力样本上拉胯,多半是里面既有冗余约束又在关键信号上缺位——需要的是优化而非简单删减。
6. 我自己关于做减法节奏的一个复盘
最后说一点实践层面的节奏建议,这算是这一轮迭代里我个人最大的体会。
做减法不是一次性的工程,需要像“版本迭代”一样持续推进。我习惯每切换一次模型版本,就对核心 Prompt 和 Skill 做一次“瘦身评审”,删掉那些只对应旧模型的问题模式的内容。同时,任何线上稳定的 Prompt/Skill 都保持“重构不重写”的原则——先定位冗余,逐步删除,每一步都有测试支撑,而不是推倒重来。
还有一个小技巧:删除之前先做备份,把需要删除的内容记录在一个“文档区”里。别看这些内容暂时不需要了,它们仍然有价值,因为它们记录了这个场景下曾经遇到过的坑。如果未来遇到类似的问题,这些内容是很有用的调试参考。它们只是不再需要出现在 Prompt 里,不代表应该永远消失。
我自己的体会是,跟模型的配合逻辑本质上是一种协作关系。模型的能力在走强,我们这边提供给它的“工作环境”也应该跟着进化——不是越复杂越好,而是越清晰越好。把那些为了应付旧模型而堆砌的复杂度拿掉,让模型的注意力重新集中在真正重要的事情上,这大概就是“用好新模型”的正确姿势。你把手头的 Prompt 和 Skill 翻出来,挑一个最近效果不太满意的,试着删掉一半内容跑一遍——你可能会和我一样,发现结果比想象中更惊喜。