SuperAPI AI 工具集

writing-great-skills

智能体与模型

查看项目

更新于 10-16 04:06

技能介绍

用途

《Writing Great Skills》是一份关于如何编写和编辑智能体技能(agent skill)的参考文档。它的核心主张是:技能存在的意义是从一个随机性系统中争取确定性;而可预测性——即智能体每次运行都走同样的过程,而非产出同样的结果——是根本美德,文中所有手段都服务于这一点。

文中加粗的术语在 GLOSSARY.md 中有定义,可前往查阅完整含义。

何时使用

  • 编写新技能,决定如何组织结构、措辞和范围时;
  • 审查或编辑一个触发不可靠、运行不一致或已变得臃肿的现有技能时;
  • 诊断技能失败模式:智能体赶步骤、忽略参考材料,或触发了错误的技能时。

何时不使用

  • 针对一次性提示词的通用提示工程——本参考讨论的是可复用技能,目标是跨运行的可预测性;
  • 关于技能/插件打包机制的问题(目录布局、清单字段)——应查阅平台的插件文档。

调用方式

有两种选择,代价不同:

  • 模型调用技能(model-invoked skill)保留描述,因此智能体可以自主触发它,其他技能也能触达它(你仍然可以手动输入其名称)。它会带来上下文负载——描述每一轮都占据上下文窗口。机制:省略 disable-model-invocation,并撰写面向模型的描述,包含丰富的触发措辞(如“当用户想要……、提到……时使用”)。
  • 用户调用技能(user-invoked skill)将描述从智能体的可及范围中移除:只有你手动输入其名称才能调用它,其他技能也无法调用。零上下文负载,但消耗认知负载:你就是那个必须记住它存在的索引。机制:设置 disable-model-invocation: true;描述变为面向人的——一行摘要,去掉触发列表。

只有当智能体必须自行触达该技能,或另一个技能必须触达它时,才选择模型调用。如果它只会被手动触发,就做成用户调用,不付上下文负载。

当用户调用技能多到你记不住时,这种堆积的认知负载可由一个路由技能(router skill)来化解:一个用户调用技能,列出其他技能以及各自何时使用。

撰写描述

模型调用的描述承担两项工作——说明技能是什么,并列出应触发它的各个分支。每个词都会增加上下文负载,因此描述比正文更需要严格修剪:

  • 把技能的引导词前置——描述正是引导词发挥调用作用的地方。
  • 每个分支一个触发条件。重命名同一分支的同义词属于重复——“使用 TDD 构建功能……要求测试先行开发”是同一分支写了两遍。应合并它们,只保留真正不同的分支。
  • 删掉正文中已有的身份说明。描述只保留触发条件,以及任何“当另一个技能需要……”的触达子句。

信息层级

技能由两类内容构成——步骤与参考——二者可自由混合:技能可以全是步骤、全是参考,或两者兼有。核心决策是使用哪一种,以及各自在信息层级中处于什么位置。信息层级是一架按智能体对材料的即时需要程度排序的阶梯:

  • 技能内步骤(in-skill step):SKILL.md 中的有序动作,是主要层级——智能体按顺序做什么。每个步骤以一个完成标准(completion criterion)结束,即告诉智能体工作已完成的那个条件。让它可检查(智能体能否分辨完成与未完成?),并在重要处做到穷尽(“每个被修改的模型都已交代”,而非“产出一份变更列表”)——模糊的标准会招致过早完成。
  • 技能内参考(in-skill reference):SKILL.md 中的定义、规则或事实,按需查阅。它常常是一个合理的扁平同级集合(一次审查的每条规则都在同一级)——这是不错的安排,不是坏味道。本技能就全是参考。
  • 外部参考(external reference):被推出 SKILL.md 到单独文件中的参考,通过上下文指针(context pointer)触达,只在指针触发时加载。(范围从已披露参考——如 GLOSSARY.md 这样的同级文件,仍属于技能的一部分——到完全外部参考,即存在于技能系统之外、任何技能都可指向的参考。)

一个要求高的完成标准会驱动彻底的案头工作(legwork)——即智能体在工作内部所做的挖掘——无论技能是否有步骤,因为“每条规则都已应用”约束扁平参考,正如“每个步骤都已完成”约束一个序列。

推得太少,顶层会臃肿;推得太多,又会藏起智能体真正需要的材料。这种张力就是整个决策所在。

渐进式披露(progressive disclosure)就是沿阶梯下移——从 SKILL.md 移出到链接文件——以保持顶层可读。机制:技能文件夹中一个链接的 .md 文件,按其内容命名(本技能将其完整定义披露到 GLOSSARY.md)。有些技能以不止一种方式被使用,每种不同方式就是一个分支(branch)——不同运行走技能中的不同路径。分支是检验披露的最干净标准:每个分支都需要的就内联,只有部分分支会触达的就推到指针之后。上下文指针的措辞,而非其目标,决定智能体何时以及多可靠地触达该材料。

阶梯决定一块内容处于多深的位置,而共置(co-location)决定它一旦就位后旁边放什么:把一个概念的定义、规则和注意事项放在同一标题下,而非散落各处,这样读一部分就会把邻近内容一并带来。

何时拆分

粒度(granularity)是你划分技能的精细程度,每一刀都要花掉两种负载之一,所以只有当这一刀值得时才拆。有两种切法:

  • 按调用拆分:当你有一个独特的引导词应当自行触发它,或另一个技能必须触达它时,拆出一个模型调用技能。你要为新的、始终加载的描述付出上下文负载,所以这种独立触达必须值得。
  • 按序列拆分:当仍在前方的步骤(某步骤的完成后步骤)诱使智能体赶工眼前这一步(过早完成)时,拆开一串步骤。让它们不在视野内,能鼓励智能体在当前任务上做更多案头工作。

修剪

让每个含义只有一个单一事实来源(single source of truth):一个权威位置,这样改变行为只需改一处。

检查每一行是否相关:它是否仍与技能所做的事有关?

然后逐句而非逐行地猎杀无效句(no-op):对每个句子单独运行无效句测试,当一句失败时,删掉整句,而不是从中修剪字词。要激进——大多数失败的散文应当删掉,而非重写。

引导词

引导词(leading word)是一个紧凑的概念,已存在于模型的预训练中,智能体在运行技能时用它来思考(例如 lesson、fog of war、tracer bullets)。它在全文中反复出现(虽然不一定——一个强引导词可能只需出现一次),累积出一个分布式定义,并以最少的 token 锚定一整片行为区域,靠的是招募模型已持有的先验。

它在两方面服务于可预测性。在正文中它锚定执行:每当该词出现,智能体就伸手去取同样的行为。在描述中它锚定调用:当同一个词存在于你的提示词、文档和代码中时,智能体就把这种共享语言与技能联系起来,更可靠地触发它。

寻找机会把技能重构为使用引导词。一个三连词在三处拼写出来(重复),一个描述花一整句去指涉一个想法——每一段都是乞求坍缩成单个 token 的段落。示例包括:

  • “fast, deterministic, low-overhead” -> tight——一个品质在一个阶段被重述——坍缩成单个预训练词(a tight loop)。
  • “a loop you believe in” -> red——把一个模糊的门槛转成二元可观察状态(循环在 bug 上变红,或不变红)。

你赢两次:更少的 token,以及一个更锐利的钩子供智能体挂靠其思考。假设每个技能都携带着引导词可以退休的重述——去找出它们。

失败模式

用这些来诊断用户可能遇到的技能问题。

  • 过早完成(premature completion):在步骤真正完成前就结束它,注意力滑向“已完成”。防御按顺序:先锐化完成标准(便宜、局部);只有当它不可约地模糊且你观察到赶工,才通过拆分(序列切法)隐藏完成后步骤。
  • 重复(duplication):同一含义出现在不止一处。耗费维护和 token,并把一个含义在阶梯上的显著度抬高到超出其真实等级。
  • 沉积(sediment):因添加感觉安全、移除感觉冒险而沉淀下来的陈旧层。任何没有修剪纪律的技能默认的命运。
  • 蔓延(sprawl):技能单纯太长,即使每一行都是活的且独特的。伤害可读性和可维护性,浪费 token。解药是阶梯:把参考披露到指针之后,按分支或序列拆分,让每条路径只携带它需要的。
  • 无效句(no-op):模型默认已经遵守的一行,所以你付了负载却什么也没说。测试:它相对默认是否改变了行为?一个弱引导词(在智能体已经够彻底时说“要彻底”)就是无效句;修复办法是换一个更强的词(relentless),而非换一种技术。
  • 否定(negation):靠禁止来引导会适得其反:别想大象说出了大象,让它更可得,而非更不可得。要正面提示——陈述目标行为,让被禁的行为从未被说出;只在无法正面表述的硬护栏处保留禁止,即便如此也要配上该做什么。