Skills 技能
Skills 技能,是一份写给大模型的「操作手册」:由一个 SKILL.md 入口文件,加上若干参考文档组成。例如说,订单分析的口径、客服的回复规范、某个业务的处理流程等等。
和直接写在 聊天角色 的「角色设定」里相比,技能是渐进式读取的:模型一开始只看到技能的名称和描述,需要时才读取 SKILL.md 正文,再按正文的指引读取所需的参考文档。这样,即使角色绑定了多个技能、每个技能有较多的文档,也不会一次性占满上下文。

整个功能,涉及到 2 个表:
ai_skill:AI 技能表ai_skill_file:AI 技能文件表
另外,ai_chat_role 聊天角色表的 skill_ids 字段,记录角色绑定的技能,见 《AI 对话》。
# 1. 技能表
ai_skill 表,存储技能的基本信息。
# 1.1 表结构
省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段
CREATE TABLE `ai_skill` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '技能编号',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '技能名称:小写字母、数字、中划线,租户内唯一,创建后不可修改',
`description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '技能描述:以 SKILL.md 头信息为准,保存 SKILL.md 时同步',
`version` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1.0.0' COMMENT '版本号',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '状态:0 启用,1 停用',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_tenant_name` (`tenant_id`, `name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI 技能表';
① name 字段:技能名称,例如说 order-analysis,只能使用小写字母、数字、中划线,创建时校验租户内不重名,创建后不可修改。它也是模型调用技能工具时传入的名字。
② description 字段:技能描述,是模型最先看到、也是判断「要不要使用这个技能」的唯一依据,所以要写清楚「做什么、什么时候用」。创建时填写,之后以 SKILL.md 头信息里的 description 为准,保存 SKILL.md 时自动同步。
③ status 字段:技能状态。停用后,角色不能再绑定它,已绑定的角色在对话时也会自动跳过。
version 字段:版本号,只是文本标记,方便管理员区分。
# 1.2 管理后台
前端对应 [AI 大模型 -> 控制台 -> 技能管理] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/ai/skill 目录,提供给管理员使用,管理技能。
- 列表会展示每个技能的文件数、引用它的角色。删除技能时,会同时删除它的全部文件;角色上的绑定保留,对话时自动跳过。
- 新建技能后,会自动生成
SKILL.md、scripts/、reference/三个固定节点。点击【文件管理】按钮,可以继续编辑技能文件。
它的后端 HTTP 接口,由 yudao-module-ai 模块的 skill 包的 AiSkillController 实现。
# 2. 技能文件表
ai_skill_file 表,以目录树的形式,存储技能的文件和目录。文件内容直接保存在数据库中,不会写到磁盘上。
# 2.1 表结构
省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段
CREATE TABLE `ai_skill_file` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号',
`skill_id` bigint NOT NULL COMMENT '技能编号',
`parent_id` bigint NOT NULL DEFAULT 0 COMMENT '父目录编号:0 表示技能根目录',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '名称',
`type` tinyint NOT NULL COMMENT '类型:1 目录,2 文件',
`file_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件扩展名:md、txt、json、yaml、yml、csv',
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '文件内容:单个文件不超过 256 KB',
`size` int NOT NULL DEFAULT 0 COMMENT '内容字节数:技能合计不超过 2 MB',
`locked` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否固定:SKILL.md、scripts/、reference/ 不可删除、重命名、移动',
`sort` int NOT NULL DEFAULT 0 COMMENT '同级排序',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_skill_parent` (`skill_id`, `parent_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI 技能文件表';
① skill_id 字段:所属技能,对应 ai_skill 表的 id 字段。
parent_id 字段:父目录,对应本表的 id 字段,为 0 时表示在技能根目录。同一目录下,名称不能重复。
② type 字段:类型,对应 AiSkillFileTypeEnum 枚举,目前有 1 目录、2 文件。
file_type 字段:文件扩展名,只支持 md、txt、json、yaml、yml、csv 文本文件。content、size 字段:文件内容、字节数,单个文件不超过 256 KB,一个技能的文件合计不超过 2 MB。
③ locked 字段:是否固定。SKILL.md、scripts/、reference/ 三个节点是固定的,不能删除、重命名、移动,其余文件和目录可以自由扩展。
# 2.2 SKILL.md 入口文件
SKILL.md 是技能的入口文件,开头的头信息(frontmatter)需要包含 name、description 两项。例如说:
---
name: order-analysis
description: 订单数据分析的口径与步骤。用户询问订单量、GMV、退款率等指标时使用。
---
# 订单分析
1. 先确认统计的时间范围、渠道
2. 指标口径,见 reference/metrics.md
3. 输出时,使用表格展示,并给出结论
① name 必须与技能名称一致;description 需要写在一行,不超过 1024 个字符。保存时校验不通过,会提示具体原因。
② 正文中,使用相对路径引用技能内的其它文件,例如说 reference/metrics.md,模型会按需读取。
③ scripts/ 目录下的内容,只作为文本保存,不会被执行。
# 2.3 文件管理
在 [技能管理] 菜单,点击【文件管理】按钮,进入技能的文件管理页面。左侧是文件树,支持新建文件 / 目录、重命名、删除,以及拖拽移动;右侧是编辑器,md 文件支持编辑、预览切换。如下图所示:

它的后端 HTTP 接口,由 yudao-module-ai 模块的 skill 包的 AiSkillFileController 实现。
# 3. 如何使用?
① 第一步,在角色配置时,通过「引用技能」关联技能,可多选,只能选择启用的技能。如下图所示:

[AI 对话] 的【角色仓库】中,用户创建的「我的角色」,同样可以引用技能。
② 第二步,使用该角色进行聊天,模型会在需要时读取技能,按技能的说明回答。如下图所示:

技能是通过 AI 工具 读取的,所以需要使用支持工具调用(function calling)的模型。
# 4. 实现原理
角色绑定了技能时,每次对话会做两件事:
① 在角色设定的末尾,追加「可用技能」清单:只包含启用技能的名称、描述,合计不超过 2000 字,超出的技能不再列出。
② 增加两个只读的技能工具:
| 工具 | 参数 | 说明 |
|---|---|---|
read_skill | name | 读取技能的 SKILL.md 正文,并附上技能内其它文件的路径列表 |
read_skill_file | name、path | 读取技能内的文件,path 为相对技能根目录的路径,例如说 reference/metrics.md |
模型根据「可用技能」清单判断需要哪个技能,先调用 read_skill 读取说明,再按说明调用 read_skill_file 读取所需的文件。这样,只有用到的内容才会进入上下文。
每次读取时,都会重新校验:技能仍绑定在当前角色上、仍是启用状态、文件存在;路径只允许技能内的相对路径,不能以 / 开头,也不能包含 .、..。单次返回超过 16000 字时,会截断并提示模型。
最关键的代码!
- AiSkillToolCallback:技能工具
read_skill、read_skill_file的实现,以及「可用技能」清单的拼接 - AiSkillServiceImpl 的
#getSkillToolCallbackList(...)、#readSkillFile(...)方法:获取角色的技能工具,读取并校验技能文件 - AiChatMessageServiceImpl 的
#getToolCallbackListByRoleId(...)方法:和角色的 AI 工具、MCP 工具一起,加入本次对话的工具列表