介绍:想让AI智能体像人一样"学以致用"?Spring AI Alibaba的Skills机制,通过"渐进式披露"让模型按需加载专业知识,既省Token又强能力。
步骤一:什么是Skills
Skills是可复用的指令与上下文包,智能体在遇到相关任务时会自动发现并使用。
核心设计:渐进式披露
传统方式:把所有技能说明一股脑塞进系统提示->上下文臃肿、成本高
bash
Skills方式分三步走:
- 1.清单注入:系统提示中只注入技能列表(名称+简短描述+路径)
- 2.按需加载:模型判断需要某技能时,调用read_skill(skill_name)加载完整SKILL.md
- 3.资源访问:根据技能目录下的资源(脚本、参考文档等)执行具体操作
这种方式大幅降低了初始上下文长度,让模型能够"按需学习"。
[1]Skill目录结构
每个技能都是一个独立目录,必须包含SKILL.md:
bash
skills/
├── pdf-extractor/
│ ├── SKILL.md # 必需:技能定义文件
│ ├── references/ # 可选:参考文档
│ ├── examples/ # 可选:示例
│ └── scripts/ # 可选:辅助脚本
├── code-reviewer/
│ └── SKILL.md
└── data-analyzer/
└── SKILL.md
[2]SKILL.md格式规范
bash
---
name: pdf-extractor
description: 从PDF文档中提取文本、表格和关键信息。当用户需要处理PDF文件时使用此技能。
---
# PDF提取器技能
## 功能说明
- 提取PDF中的纯文本
- 识别并提取表格数据
- 获取文档元信息
## 使用方法
1. 提供PDF文件路径
2. 指定需要提取的内容类型
3. 获得结构化结果
## 依赖工具
- Python: PyPDF2库
- Shell: pdftotext命令
必须字段:
- name:技能唯一标识(小写字母、数字、连字符,最长64字符)
- description:技能描述(会被注入系统提示,过长会被截断)
步骤二:在Agent中使用Skills
方式一:文件系统技能
适用于本地开发或生产环境挂载技能目录:
java
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.agent.hook.skills.SkillsAgentHook;
import com.alibaba.cloud.ai.graph.skills.registry.filesystem.FileSystemSkillRegistry;
// 1. 创建技能注册表(从项目目录加载)
SkillRegistry registry = FileSystemSkillRegistry.builder()
.projectSkillsDirectory(System.getProperty("user.dir") + "/skills")
.build();
// 2. 创建Skills Hook
SkillsAgentHook skillsHook = SkillsAgentHook.builder()
.skillRegistry(registry)
.build();
// 3. 构建Agent并挂载Hook
ReactAgent agent = ReactAgent.builder()
.name("skills-agent")
.model(chatModel)
.saver(new MemorySaver())
.hooks(List.of(skillsHook))
.build();
// 4. 使用
agent.call("请介绍你有哪些技能");
// 模型会先列出可用技能清单
agent.call("请帮我从这份PDF中提取文本: /path/to/doc.pdf");
// 模型会自动调用read_skill('pdf-extractor')加载完整技能说明
目录配置说明:
- userSkillsDirectory:用户级技能目录(默认~/saa/skills)
- projectSkillsDirectory:项目级技能目录(默认./skills)
- 同名技能优先级:项目级>用户级
方式二:Classpath技能
适用于技能打包在JAR中的场景:
java
SkillRegistry registry = ClasspathSkillRegistry.builder()
.classpathPath("skills") // 从src/main/resources/skills加载
.basePath("/tmp/skills") // JAR内资源复制到的临时目录(可选)
.build();
SkillsAgentHook hook = SkillsAgentHook.builder()
.skillRegistry(registry)
.build();
步骤三:集成
真实场景中,技能往往需要执行脚本(Python/Shell)来完成具体任务。下面是一个完整的集成示例:
java
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.agent.hook.skills.SkillsAgentHook;
import com.alibaba.cloud.ai.graph.agent.hook.shelltool.ShellToolAgentHook;
import com.alibaba.cloud.ai.graph.agent.tools.PythonTool;
import com.alibaba.cloud.ai.graph.agent.tools.ShellTool2;
import com.alibaba.cloud.ai.graph.skills.registry.classpath.ClasspathSkillRegistry;
// 1. 技能注册表(从classpath加载)
SkillRegistry registry = ClasspathSkillRegistry.builder()
.classpathPath("skills")
.build();
// 2. Skills Hook:提供read_skill工具 + 技能列表注入
SkillsAgentHook skillsHook = SkillsAgentHook.builder()
.skillRegistry(registry)
.build();
// 3. Shell Hook:提供Shell命令执行能力
ShellToolAgentHook shellHook = ShellToolAgentHook.builder()
.shellTool2(ShellTool2.builder(System.getProperty("user.dir")).build())
.build();
// 4. 构建Agent
ReactAgent agent = ReactAgent.builder()
.name("skills-integration-agent")
.model(chatModel)
.saver(new MemorySaver())
.tools(PythonTool.createPythonToolCallback(PythonTool.DESCRIPTION))
.hooks(List.of(skillsHook, shellHook))
.enableLogging(true)
.build();
// 5. 调用示例
String skillFilePath = "/path/to/skills/pdf-extractor/saa-roadmap.pdf";
AssistantMessage response = agent.call("请从 " + skillFilePath + " 文件中提取关键信息。");
执行流程:
- 用户请求处理PDF
- 模型发现pdf-extractor技能匹配
- 调用read_skill('pdf-extractor')加载完整技能说明
- 技能说明指示使用Python脚本
- Agent调用PythonTool执行提取逻辑
- 返回结构化结果
步骤四:高级用法
除了技能内容,你还可以让工具也跟随技能按需激活------只有当模型调用了read_skill后,该技能绑定的工具才会被注册。
java
// 定义工具
ToolCallback pdfTool = FunctionToolCallback.builder("extract_pdf", new PdfExtractor())
.description("提取PDF内容")
.build();
// 将工具绑定到技能
Map<String, List<ToolCallback>> groupedTools = Map.of(
"pdf-extractor", // 与SKILL.md中的name一致
List.of(pdfTool)
);
SkillsAgentHook hook = SkillsAgentHook.builder()
.skillRegistry(registry)
.groupedTools(groupedTools) // 技能激活后才暴露工具
.build();
优势:避免模型过早接触不相关的工具,减少工具选择的困惑。
步骤五:生产环境建议
[1]自动重载技能
开发阶段频繁修改技能时,可开启自动重载:
java
SkillsAgentHook hook = SkillsAgentHook.builder()
.skillRegistry(registry)
.autoReload(true) // 每次Agent执行前重新加载技能
.build();
[2]自定义系统提示模板
如需定制技能列表的展示格式:
java
SystemPromptTemplate customTemplate = SystemPromptTemplate.builder()
.template("## 可用技能\n{skills_list}\n\n## 加载方法\n{skills_load_instructions}")
.build();
SkillRegistry registry = FileSystemSkillRegistry.builder()
.projectSkillsDirectory("./skills")
.systemPromptTemplate(customTemplate)
.build();
模板变量:
- {skills_list}:技能名称+描述列表
- {skills_load_instructions}:加载说明(如何使用read_skill)
[3]用户级与项目级目录隔离
java
SkillRegistry registry = FileSystemSkillRegistry.builder()
.userSkillsDirectory("/home/user/saa/skills") // 通用技能
.projectSkillsDirectory("/app/project/skills") // 项目特定技能
.build();
// 同名技能:项目级覆盖用户级
步骤六:在Graph/ChatClient中使用Skills
除ReactAgent外,你也可以通过以下方式使用
java
import org.springframework.ai.chat.client.ChatClient;
import com.alibaba.cloud.ai.graph.advisors.SkillPromptAugmentAdvisor;
// 创建Advisor
SkillPromptAugmentAdvisor skillAdvisor = SkillPromptAugmentAdvisor.builder()
.projectSkillsDirectory("./skills")
.build();
// 集成到ChatClient
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(skillAdvisor)
.build();
// 调用时系统提示中会包含技能列表
String response = chatClient.prompt()
.user("请介绍你有哪些技能")
.call()
.content();
eg:这种方式下,模型无法按需加载完整SKILL.md,如需完整Skills体验(渐进式披露),请使用ReactAgent+SkillsAgentHook。
加入技术群可以获取资料,含AI资料、Spring AI中文文档等,等你加入~