1. 从“能跑就行”到“稳定复用”:SKILL 设计模式到底在解决什么问题
很多人第一次接触 Anthropic 的 SKILL 体系时,脑子里想的都是“我写个提示词,让模型照着干不就行了”。结果真上手之后才发现,一个能跑通的 SKILL 和一个能长期稳定复用的 SKILL,中间隔着的不是几行文字,而是一整套设计思路。我自己最早做 SKILL 的时候也踩过这个坑:同一个任务,今天跑出来结果不错,明天换个输入就崩了,排查半天发现不是模型能力问题,而是 SKILL 本身的结构太松散,缺少明确的约束和示例锚点。
Anthropic 官方在 SKILL 最佳实践里反复强调一个观点:SKILL 不是一段随手写的指令,而是一个有明确输入输出边界、有可预期行为的设计单元。这个定位一旦立住,你就会自然地去思考它的结构该怎么组织、边界该怎么划定、异常该怎么处理。而官方给出的两种“设计模式”——模板模式和示例模式——本质上就是在回答“如何让 SKILL 的行为可预期”这个问题。
模板模式的核心思路是用结构约束行为。你给 SKILL 一个固定的输出骨架,模型在这个骨架里填内容,自由度被限制在可控范围内。示例模式的核心思路是用样例锚定行为。你给 SKILL 几个高质量的输入输出对,模型通过类比来理解你要什么,而不是靠抽象描述去猜。这两种模式不是互斥的,实际项目中经常混用,但理解它们各自的适用场景和边界,是写出高质量 SKILL 的前提。
这篇文章我会从实际项目经验出发,把这两种设计模式的原理、适用场景、具体写法、常见坑点全部拆开讲一遍。不管你是刚接触 SKILL 的新手,还是已经写过一些但总觉得不够稳的老手,应该都能从中找到可以直接用的东西。
2. 模板模式:用输出骨架把模型的自由度关进笼子
2.1 模板模式的本质是“先定容器再填内容”
模板模式最直白的理解方式就是:你先告诉模型“输出必须长什么样”,再让它去填。这就像你给一个实习生布置任务,不是跟他说“帮我分析一下这个数据”,而是给他一张已经画好表头的表格,告诉他每一列填什么、格式是什么、哪些字段必填哪些可选。后者出错的概率会低很多。
在 SKILL 里,模板模式通常表现为一段明确的输出格式定义。比如你要做一个代码审查的 SKILL,模板模式会要求输出必须包含“问题严重等级”“问题所在行号”“问题描述”“修复建议”这四个字段,每个字段的格式都有明确规定。模型拿到这个模板后,它的任务从“自由发挥”变成了“按格式填充”,行为空间被大幅压缩。
我自己的经验是,模板模式特别适合那些输出结构固定、字段可枚举的任务。比如结构化信息抽取、格式化报告生成、标准化代码审查、固定流程的诊断分析等。这类任务的共同特点是:你知道好的输出长什么样,而且这种“好”是可以被结构化描述的。
2.2 模板的粒度控制:太粗没用,太细会僵
模板模式最容易踩的坑是粒度控制。模板太粗,比如只写“请输出一段分析”,那跟没有模板差不多,模型该飘还是飘。模板太细,比如把每个句子的句式都规定死,那模型就变成了填空机器,遇到模板没覆盖的情况直接卡死。
我的经验法则是:模板约束“信息结构”,不约束“表达方式”。什么意思?你可以规定输出必须包含哪些信息块、每个信息块的作用是什么、信息块之间的顺序关系是什么,但不要规定每个信息块里具体用什么句式、用什么词。比如代码审查 SKILL 的模板可以规定“先输出问题等级,再输出行号,再输出描述,最后给修复建议”,但不要规定“描述必须用‘该行代码存在……问题’的句式”。
另一个经验是:模板里要留“逃生舱”。所谓逃生舱,就是当模型遇到模板无法覆盖的情况时,有一个合法的输出路径。比如你可以加一个“其他说明”字段,允许模型在这里补充模板没覆盖到的信息。没有逃生舱的模板,遇到边界情况时模型要么硬填导致输出质量下降,要么直接忽略模板自由发挥,两种结果都不好。
2.3 一个完整的模板模式 SKILL 拆解
我拿一个实际项目里用过的“API 文档生成 SKILL”来举例。这个 SKILL 的输入是一段后端代码,输出是标准化的 API 文档。用模板模式写的话,结构大概是这样:
## 输出模板 请严格按照以下结构输出 API 文档: ### 接口名称 [从代码中提取的函数名或路由名] ### 请求方法 [GET/POST/PUT/DELETE 之一] ### 请求路径 [完整的路径字符串] ### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ... | ... | ... | ... | ### 响应结构 [JSON 示例或字段说明] ### 异常情况 [列出代码中显式处理的异常分支] ### 补充说明 [模板未覆盖但需要说明的信息,如无则填“无”]这个模板的好处是:每个字段都有明确的语义,模型不需要猜“我该写什么”,只需要从代码里提取对应信息填入即可。同时“补充说明”字段就是逃生舱,遇到模板没覆盖的情况有地方放。
实测下来,加了模板之后,同一个 SKILL 在不同代码上的输出一致性提升了非常明显。之前没有模板的时候,模型有时候输出一大段散文式的描述,有时候又只给几个关键词,格式完全不统一。加了模板之后,至少结构是稳定的,后续做自动化解析也方便很多。
2.4 模板模式的边界:什么时候不该用
模板模式不是万能的。有两类任务我强烈不建议用模板模式:
第一类是创造性任务。比如让 SKILL 写一段营销文案、生成一个故事大纲、设计一个方案框架。这类任务的“好”很难被结构化描述,硬套模板只会让输出变得僵硬死板。你见过哪个好文案是填表格填出来的?
第二类是探索性任务。比如让 SKILL 分析一个复杂问题、排查一个未知故障、评估一个方案的可行性。这类任务的特点是输出结构取决于输入内容,你事先不知道会遇到什么情况,自然也没法预先定义模板。强行定义模板的结果就是模型为了填模板而忽略实际情况。
判断标准很简单:如果你能事先画出输出的表格,那就用模板模式;如果你画不出来,或者画出来之后发现表格里很多格子只能填“视情况而定”,那就别用模板模式。
3. 示例模式:用高质量样例替代抽象描述
3.1 示例模式的底层逻辑是“类比学习”
示例模式的思路跟模板模式完全不同。模板模式是“我告诉你输出长什么样”,示例模式是“我给你看几个输出长什么样的例子,你自己体会”。这背后的逻辑是:对于很多任务来说,展示比描述更有效。
你想想自己学做菜的过程。如果只看菜谱上写“盐适量、火候适中、翻炒至断生”,你大概率做不出来。但如果有人给你演示一遍,或者你看几个做菜的短视频,你就知道“适量”大概是多少、“断生”大概是什么状态。示例模式就是给模型看“做菜视频”。
Anthropic 官方在最佳实践里特别强调:示例的质量比数量重要得多。给三个精心设计的示例,效果远好于给十个随手写的示例。因为模型会从示例中提取模式,如果示例本身质量参差不齐,模型提取到的模式也是混乱的。
3.2 示例的选取:覆盖典型场景和边界情况
选示例的时候,很多人只选“正常情况”的示例,这是不够的。一个好的示例集应该覆盖三类场景:
- 典型场景:最常见、最标准的输入输出对,让模型知道“一般情况下该怎么做”
- 边界场景:输入处于临界值或特殊情况的示例,让模型知道“遇到这种情况该怎么处理”
- 异常场景:输入有问题或不符合预期时的示例,让模型知道“出错时该怎么响应”
我做一个“用户反馈分类 SKILL”的时候,示例集里除了正常的“功能建议”“bug 反馈”“咨询提问”之外,还特意加了两个异常示例:一个是反馈内容完全无关的(比如一段乱码),一个是反馈内容同时涉及多个类别的。这两个异常示例让模型学会了在边界情况下输出“无法分类”和“多类别标注”,而不是硬塞进某个类别里。
3.3 示例的写法:输入输出对要完整且一致
示例的写法有几个硬性要求:
第一,输入输出必须完整。不要只给输入的片段或输出的片段,要给完整的输入和完整的输出。模型需要看到完整的上下文才能理解输入输出之间的映射关系。
第二,格式必须一致。所有示例的输入格式要统一,输出格式也要统一。如果第一个示例的输出是 JSON,第二个示例的输出是 Markdown 表格,模型就会困惑“到底该用哪种格式”。
第三,示例之间要有差异性。如果所有示例都长得差不多,模型只能学到一种模式,遇到稍微不同的输入就不知道怎么处理了。示例之间应该在内容上有差异,但在结构上保持一致。
我通常会在 SKILL 里用这样的格式来组织示例:
## 示例 ### 示例 1:典型场景 **输入:** [完整的输入内容] **输出:** [完整的输出内容] ### 示例 2:边界场景 **输入:** [完整的输入内容] **输出:** [完整的输出内容] ### 示例 3:异常场景 **输入:** [完整的输入内容] **输出:** [完整的输出内容]这种格式的好处是清晰、一致、易于扩展。加新示例的时候直接照着格式写就行,不会破坏整体结构。
3.4 示例模式的坑:示例污染和过度拟合
示例模式最大的坑是示例污染。所谓示例污染,就是示例本身包含了错误或偏差,模型把这个错误或偏差学去了。比如你写一个代码审查 SKILL,示例里有一个“变量命名不规范”的问题,但你自己在示例里把变量名写错了,模型就会学到“这种变量名是不规范的”,哪怕它其实没问题。
另一个坑是过度拟合。如果示例太具体,模型可能会过度依赖示例的表面特征,而不是理解背后的逻辑。比如你给了一个“把英文翻译成中文”的示例,示例里的英文句子都是科技类的,模型可能会学到“只翻译科技类英文”,遇到文学类英文就不知道怎么处理了。
避免这两个坑的方法是一样的:示例要经过严格审核,确保正确性;示例要有多样性,避免单一模式。我自己的习惯是,写完示例之后会自己先跑一遍,看看模型能不能从示例中正确泛化到新输入。如果泛化效果不好,就调整示例。
4. 两种模式怎么选:一张决策表和一个混合策略
4.1 选择依据:任务的可结构化程度
模板模式和示例模式的选择,核心依据是任务的可结构化程度。我整理了一个决策表,你可以对照自己的任务来判断:
| 判断维度 | 倾向模板模式 | 倾向示例模式 |
|---|---|---|
| 输出结构是否固定 | 固定,字段可枚举 | 不固定,随输入变化 |
| 任务类型 | 信息抽取、格式转换、标准化报告 | 内容生成、风格模仿、复杂判断 |
| 评价标准 | 结构完整性、字段准确性 | 内容质量、风格一致性 |
| 输入多样性 | 输入格式统一 | 输入格式多样 |
| 边界情况 | 边界情况少且可枚举 | 边界情况多且难枚举 |
这张表不是绝对的,只是一个参考。实际项目中,很多任务处于中间地带,既不是完全结构化,也不是完全自由。这时候就需要混合策略。
4.2 混合策略:模板定骨架,示例定风格
混合策略的核心思路是:用模板模式定义输出的结构骨架,用示例模式定义输出的风格和内容质量。这样既保证了结构的一致性,又保证了内容的灵活性。
我做一个“技术方案评审 SKILL”的时候用的就是混合策略。模板部分定义了输出必须包含“方案概述”“技术选型分析”“风险点”“改进建议”四个部分,每个部分的顺序和基本格式都固定。示例部分则给了三个完整的评审报告示例,展示了每个部分应该写到什么深度、用什么语气、怎么组织论据。
实测下来,混合策略的效果比单用任何一种模式都好。纯模板模式的话,输出结构没问题但内容干巴巴的;纯示例模式的话,内容质量不错但结构有时候会飘。混合之后,结构和内容都稳了。
4.3 一个容易忽略的点:模式选择要考虑维护成本
选模式的时候还要考虑维护成本。模板模式的维护成本主要在模板本身,改模板的时候要确保所有依赖这个模板的地方都同步更新。示例模式的维护成本主要在示例集,加新示例的时候要确保新示例和旧示例风格一致、不冲突。
从我的经验来看,模板模式的长期维护成本更低,因为模板是显式的、可枚举的,改了什么一目了然。示例模式的维护成本更高,因为示例是隐式的、需要整体感受的,加一个新示例可能会微妙地改变模型的整体行为。
所以如果你的 SKILL 需要长期维护、频繁迭代,我建议优先考虑模板模式,或者混合策略里以模板为主。如果是一次性任务或者变化不大的任务,示例模式更省事。
5. 从零写一个 SKILL:完整流程和实操细节
5.1 第一步:明确 SKILL 的输入输出边界
写 SKILL 之前,先花时间把输入输出边界想清楚。这一步看起来简单,但实际做的时候很容易含糊。我见过太多 SKILL 失败的原因就是边界不清:模型不知道什么该做什么不该做,用户不知道什么能指望什么不能指望。
具体要明确的东西包括:
- 输入是什么:输入的格式、范围、典型长度、可能的异常情况
- 输出是什么:输出的格式、必须包含的字段、可选字段、异常情况的输出
- 不做什么:明确排除掉那些看起来相关但实际不该由这个 SKILL 处理的事情
我自己的习惯是,在 SKILL 的开头用一段简短的说明把边界写清楚。比如“本 SKILL 用于将后端代码转换为 API 文档,输入为 Python 或 Java 的后端代码片段,输出为 Markdown 格式的 API 文档。不处理前端代码、不处理数据库 schema、不处理配置文件。”
5.2 第二步:选择设计模式并搭建骨架
边界明确之后,根据任务特点选择模板模式、示例模式或混合策略。选好之后先搭骨架,不要一上来就写细节。
搭骨架的意思是:先把 SKILL 的整体结构定下来,包括有哪些部分、每个部分的作用是什么、部分之间的顺序关系是什么。比如一个混合策略的 SKILL 骨架可能是:
## 角色定义 [这个 SKILL 扮演什么角色] ## 任务说明 [这个 SKILL 要完成什么任务] ## 输出模板 [输出的结构定义] ## 示例 [输入输出示例] ## 注意事项 [需要特别注意的点]骨架搭好之后,再往每个部分里填内容。这样写出来的 SKILL 结构清晰,后续修改也方便。
5.3 第三步:填充内容并做第一轮测试
填充内容的时候,有几个细节要注意:
用词要精确。不要用“尽量”“大概”“适当”这种模糊词,要用“必须”“不得”“至少”“最多”这种明确词。模型对模糊词的理解跟人不一样,你觉得“尽量简洁”是 100 字以内,模型可能理解成 500 字。
约束要可验证。你写的每一条约束,都要能通过某种方式验证是否被遵守了。比如“输出必须包含三个部分”是可验证的,“输出要有逻辑”是不可验证的。不可验证的约束等于没写。
留出调试空间。第一版 SKILL 不要写得太满,留一些可以调整的空间。比如模板里的字段先写核心的,跑通了再考虑加扩展字段。
填充完之后,用一批有代表性的输入做第一轮测试。测试的时候不要只看“能不能跑通”,要看“输出是否符合预期”。如果不符合,先判断是 SKILL 的问题还是模型的问题,再针对性调整。
5.4 第四步:迭代优化和版本管理
SKILL 不是一次写完就完事的,需要持续迭代。迭代的时候有几个经验:
每次只改一个地方。如果你同时改了模板和示例,测试结果变好了,你也不知道是哪个改动起了作用。每次只改一个变量,才能准确判断改动效果。
保留版本记录。SKILL 的每次修改都要有记录,包括改了什么、为什么改、改完之后效果如何。这样出问题的时候可以回溯,也可以对比不同版本的效果。
定期做回归测试。SKILL 改多了之后,可能会出现“改好了 A 场景但改坏了 B 场景”的情况。定期用一批固定输入做回归测试,确保没有引入新的问题。
6. 实战中踩过的坑和对应的解法
6.1 坑一:模板太死导致模型“硬填”
我早期做一个“会议纪要生成 SKILL”的时候,模板里规定了“决议事项”字段必须填写。结果遇到一些没有明确决议的会议,模型就硬编了一个决议出来。这就是典型的模板太死导致的“硬填”问题。
解法是在模板里加“不适用”选项。比如“决议事项”字段可以填“本次会议无明确决议”。同时要在 SKILL 里明确说明:如果某个字段确实不适用,填“不适用”比硬编内容更好。这个说明很重要,因为模型的默认倾向是“填满所有字段”,你不明确说可以留空,它就会硬填。
6.2 坑二:示例太少导致模型“过拟合”
另一个项目里,我做一个“邮件分类 SKILL”,只给了三个示例,而且三个示例都是“工作邮件”的分类。结果模型遇到“私人邮件”的时候,也硬往工作邮件的类别里塞。这就是示例太少、覆盖不全导致的过拟合。
解法是增加示例的多样性,确保每个可能的类别都有示例覆盖。同时要加一个“其他”类别,让模型遇到无法归类的邮件时有地方放。这个“其他”类别就是分类任务里的逃生舱。
6.3 坑三:约束冲突导致模型“左右为难”
有时候 SKILL 里会不小心写出互相冲突的约束。比如一处写“输出要简洁,不超过 200 字”,另一处写“输出要详细,包含所有必要信息”。模型遇到这种冲突时,行为会变得不可预测,有时候偏简洁有时候偏详细。
解法是写完 SKILL 之后做一次“冲突检查”,把所有约束列出来,看看有没有互相矛盾的。如果有,要么合并成一个约束,要么明确优先级(比如“在不超过 200 字的前提下,尽可能包含必要信息”)。
6.4 坑四:忽略异常处理导致模型“卡死”
很多 SKILL 只定义了正常情况的处理逻辑,没有定义异常情况的处理逻辑。结果遇到异常输入时,模型要么输出一堆无意义的内容,要么直接拒绝响应。
解法是在 SKILL 里显式定义异常处理逻辑。比如“如果输入为空,输出‘输入为空,无法处理’”“如果输入格式不符合要求,输出‘输入格式错误,请检查后重试’”。这些异常处理逻辑看起来简单,但能大幅提升 SKILL 的健壮性。
7. 一些让 SKILL 更稳的细节技巧
7.1 用“角色定义”锚定模型的行为基调
SKILL 开头的角色定义不是装饰,它会影响模型的整体行为基调。如果你写“你是一个严谨的技术文档工程师”,模型的输出会偏向严谨、结构化。如果你写“你是一个友好的客服助手”,模型的输出会偏向亲切、口语化。
我的经验是,角色定义要跟任务性质匹配。技术类任务用技术角色,创意类任务用创意角色,分析类任务用分析角色。不要小看这一句话,它会影响后续所有输出的风格。
7.2 用“反面示例”明确边界
除了正面示例,有时候加一两个反面示例也很有用。反面示例就是“不该这样做”的示例,让模型明确知道哪些行为是不被接受的。
比如在代码审查 SKILL 里,可以加一个反面示例,展示“只指出问题但不给修复建议”的输出,并标注“这是不正确的输出方式”。这样模型就会知道,光指出问题是不够的,必须给修复建议。
7.3 用“自检清单”让模型自己把关
在 SKILL 的末尾加一个自检清单,让模型在输出之前自己检查一遍。比如:
## 输出前自检 - 输出是否包含所有必填字段? - 每个字段的内容是否符合格式要求? - 是否有字段被硬填了不适当的内容? - 异常情况是否被正确处理?这个自检清单不需要模型真的输出检查结果,但它会引导模型在生成输出时关注这些点。实测下来,加了自检清单之后,输出的合规性有明显提升。
7.4 控制 SKILL 的长度:太长会稀释重点
SKILL 不是越长越好。太长的 SKILL 会让模型抓不住重点,而且会增加 token 消耗。我的经验是,一个 SKILL 的核心内容控制在 500 到 1500 字之间比较合适,超过 2000 字就要考虑拆分了。
如果任务确实复杂,需要很长的 SKILL,可以考虑拆成多个子 SKILL,每个子 SKILL 负责一个子任务,然后用一个主 SKILL 来调度。这样每个 SKILL 都能保持精简,整体逻辑也更清晰。
8. 关于 SKILL 设计模式的一些个人体会
写了这么多 SKILL 之后,我最大的体会是:设计模式不是目的,而是手段。模板模式和示例模式都是为了解决“如何让 SKILL 行为可预期”这个问题,但具体用哪种、怎么用,取决于你的任务特点和实际需求。
我见过一些人把设计模式当成教条,非要往模板模式或示例模式里套,结果套出来的 SKILL 反而不好用。也见过一些人完全不管设计模式,凭感觉写,写出来的 SKILL 时好时坏。我的建议是:先理解这两种模式的原理和适用场景,然后在实际项目中灵活运用,该用模板的时候用模板,该用示例的时候用示例,该混合的时候混合。
另外一个体会是:SKILL 的质量取决于你对任务的理解深度。如果你对任务本身理解不深,不知道好的输出长什么样、不知道边界在哪里、不知道异常情况怎么处理,那不管用什么设计模式,写出来的 SKILL 都好不到哪里去。所以写 SKILL 之前,先花时间把任务本身吃透,这比研究设计模式更重要。
最后分享一个我自己的习惯:每次写完一个 SKILL,我会自己扮演“最挑剔的用户”,故意用各种奇怪的输入去测试它,看看它在边界情况下的表现。这个过程往往能发现很多正常测试发现不了的问题。虽然费时间,但值得。