技能
技能是写给智能体看的操作说明,教它用已有的能力完成某一类事情,比如怎样设计一栋房子、怎样打末影龙、怎样驯服和照顾女仆。技能不给智能体新的能力,它只教智能体把已有的 Lua API 组合起来用好。如果你还不确定该写技能还是插件,请先阅读架构概览。
技能的格式参照了 Agent Skills,写过智能体技能的人可以很快上手。
技能是怎样被加载的
一份详细的操作说明往往很长,如果把所有技能都塞进系统提示词,模型的上下文很快就会被占满。所以言出法随按需分三级加载技能。
- 索引。每一轮对话,模型都能在系统提示词里看到所有技能的名字和一句话描述。
- 正文。当模型判断手头的任务和某个技能对得上,它会调用
skill工具,把这个技能的正文加载进对话。 - 附属文件。正文里可以用相对路径提到其他文件,模型读到需要的时候,再单独加载它们。
以内置的 building_design 为例,它的正文只讲通用的设计流程,巴洛克、中式古典、赛博朋克等二十多种风格各放在一个附属文件里,要盖哪种风格才读哪一个。
目录结构
一个技能就是一个文件夹,里面必须有一个 SKILL.md,其余文件都是可选的。
taming_maid/
├── SKILL.md 必需,技能的名字、描述和正文
└── references/ 可选,正文里引用的附属文件
└── maid_types.md编写 SKILL.md
SKILL.md 由两部分组成,开头用两行 --- 包起来的是元信息,后面是正文。
---
name: taming_maid
description: 驯服野生的车万女仆。主人想要女仆、或者让你去驯服女仆时加载。
---
# 驯服女仆
野生女仆用蛋糕驯服,先确认背包里有蛋糕,没有就先去做一个。
找到一只野生女仆,走到她身边,手持蛋糕右键她:
~~~lua
-- 列出身边 16 格内的友好生物(女仆属于这一类),由近到远排好
local mobs = numen.scan.entities("passive", {radius = 16})
-- 逐个检查,找到第一只还没有主人的女仆
local maid = nil
for _, e in ipairs(mobs) do
-- type 是实体的 id,owner 为空说明她还是野生的
if e.type == "touhou_little_maid:maid" and e.owner == nil then
maid = e
break
end
end
-- 附近一只野生女仆都没有,就到此为止
if maid == nil then
return "附近没有野生女仆"
end
-- 走到她身边 2 格以内
numen.move.to(maid, {arrive = "near", range = 2})
-- 手持背包里的蛋糕右键她
numen.use.entity(maid, {item = "minecraft:cake"})
~~~
驯服成功后会收到 `maid_tamed` 事件。别人的女仆用蛋糕驯服不了,不要反复尝试。元信息只有两项。
| 字段 | 说明 |
|---|---|
name | 技能的名字,也是模型加载它时用的名字。言出法随按这个名字识别技能,和文件夹叫什么无关,不过建议两者保持一致。 |
description | 一句话描述这个技能管什么、什么时候该用。没有描述的技能不会出现在索引里,模型看不到它,也就不会用它。 |
元信息只支持单行的 key: value,不支持多行或嵌套的 YAML 写法。
写好一个技能
描述决定技能会不会被用上。 模型只凭索引里的描述判断要不要加载技能,所以描述要同时写清"管什么"和"什么时候用"。例如 building_design 的描述最后一句是"Load BEFORE designing or building any non-trivial structure",明确告诉模型在动手建造之前就该加载它。
多给可以照抄的代码。 模型最擅长的是照着例子改,与其用文字描述"先扫描再移动",不如直接给一段带注释的 Lua 代码。
写清楚失败时怎么办。 比如上面的例子写明了"别人的女仆驯服不了,不要反复尝试",这能省下模型很多次无用的重试。
长篇的参考资料拆成附属文件。 正文只写在什么情况下去读哪个文件,比如"要盖中式建筑时,先读 references/chinese_classical.md"。附属文件只能是文本,单个不超过 256KB,路径不能指到技能文件夹之外。
当然了以上都是个人经验,不一定具备普适性,我们完全可以来拿评测说话,你的方案跑分高,OK那我跪了,听你的嘛。
安装技能
把技能文件夹放进游戏目录下的 config/numen/skills/,然后按 F3 + T 重新加载资源,或者重启游戏,新技能就会生效。修改已有技能的正文后也一样。
模组也可以通过插件自带技能,见插件。
覆盖规则。如果玩家的 config/numen/skills/ 里有和模组技能同名的技能,以玩家的为准。玩家可以借此按自己的需要改写模组自带的技能。
