找回密码
 立即注册
首页 业界区 安全 Agent Skills | Spring Ai Alibaba从零构建可扩展 AI 智 ...

Agent Skills | Spring Ai Alibaba从零构建可扩展 AI 智能体

颖顿庐 4 小时前
在当今AI应用开发领域,让AI智能体具备灵活的工具调用能力可扩展的技能体系,是落地复杂业务场景的核心挑战。Spring AI Alibaba 原生提供了完善的 Skill 技能支持,能让智能体实现「技能发现→按需加载→工具执行」的全流程自动化。
本文将从核心概念、组件解析、实战场景、最佳实践四个维度,手把手教你掌握 Spring AI Alibaba Skill 的使用方法。
一、核心概念

1.1 渐进式披露(核心设计思想)

Spring AI Alibaba Skill 采用渐进式披露机制,最大化提升模型效率:

  • 系统初始仅注入技能元数据(名称、描述、路径);
  • 模型判断需要使用某技能时,调用 read_skill(skill_name) 加载完整的 SKILL.md 文档;
  • 最后按需访问技能资源、执行绑定工具。
1.2 Skill 标准目录结构

每个技能独立为一个子目录,SKILL.md 为强制必需文件,目录结构如下:
  1. skills/                 # 技能根目录
  2. └── pdf-extractor/      # 单个技能目录(自定义命名)
  3.     ├── SKILL.md        # ✅ 必需:技能核心定义文档
  4.     ├── references/     # 可选:技能参考资料
  5.     ├── examples/       # 可选:使用示例
  6.     └── scripts/        # 可选:执行脚本
复制代码
1.3 SKILL.md 格式规范

SKILL.md 采用元数据+正文结构,元数据通过 --- 包裹,是模型识别技能的关键:
  1. ---
  2. name: pdf-extractor          # 必需:小写字母、数字、连字符,最长64字符
  3. description: 用于从PDF文档中提取文本、表格和表单数据  # 必需:简洁描述,超长会被截断
  4. ---
  5. # PDF 提取技能
  6. ## 功能说明
  7. You are a PDF extraction specialist. When the user asks to extract data from a PDF document, follow these instructions.
  8. ## 使用方法
  9. 1. **Validate Input**
  10.    - Confirm the PDF file path is provided.
  11.    - The default path for the pdf file is the current working directory.
  12.    - Use the `shell` or `read_file` tool to check if the file exists
  13.    - Verify it's a valid PDF format
  14. 2. **Extract Content**
  15.    - Execute the extraction script using the `shell` tool:
  16.      ```bash
  17.      python scripts/extract_pdf.py <pdf_file_path>
  18.      ```
  19.    - The script will output JSON format with extracted data
  20. 3. **Process Results**
  21.    - Parse the JSON output from the script
  22.    - Structure the data in a readable format
  23.    - Handle any encoding issues (UTF-8, special characters)
  24. 4. **Present Output**
  25.    - Summarize what was extracted
  26.    - Present data in the requested format (JSON, Markdown, plain text)
  27.    - Highlight any issues or limitations
  28. ## Script Location
  29. The extraction script is located at:
  30. `scripts/extract_pdf.py`
  31. ## Output Format
  32. The script returns JSON:
  33. ```json
  34. {
  35.   "success": true,
  36.   "filename": "report.pdf",
  37.   "text": "Full text content...",
  38.   "page_count": 10,
  39.   "tables": [
  40.     {
  41.       "page": 1,
  42.       "data": [["Header1", "Header2"], ["Value1", "Value2"]]
  43.     }
  44.   ],
  45.   "metadata": {
  46.     "title": "Document Title",
  47.     "author": "Author Name",
  48.     "created": "2024-01-01"
  49.   }
  50. }
  51. ```
复制代码
scripts/extract_pdf.py简介,因为目前测试脚本的执行,所以mock返回了一个json格式的解析内容。
二、核心组件解析

Spring AI Alibaba Skill 体系由四大核心组件构成,各司其职、协同工作:
2.1 对话模型(ChatModel)

对接阿里通义千问大模型,是智能体的「大脑」,负责推理决策:
  1. private static ChatModel getChatModel() {
  2.     // 构建通义千问API客户端
  3.     DashScopeApi dashScopeApi = DashScopeApi.builder()
  4.             .apiKey(System.getenv("AliQwen_API"))  // 环境变量配置API Key
  5.             .build();
  6.     // 创建对话模型
  7.     return DashScopeChatModel.builder()
  8.             .dashScopeApi(dashScopeApi)
  9.             .build();
  10. }
复制代码
2.2 技能注册中心(SkillRegistry)

负责加载、管理所有技能,Spring AI Alibaba 提供两种常用实现:

  • ClasspathSkillRegistry:从项目类路径(resources)加载技能
  • FileSystemSkillRegistry:从本地文件系统加载技能
代码示例
  1. SkillRegistry registry = ClasspathSkillRegistry.builder()
  2.         .classpathPath("skills")  // 指向resources/skills目录
  3.         .build();
复制代码
2.3 技能钩子(SkillsAgentHook)

连接智能体技能系统的桥梁,负责注入技能上下文、提供工具调用能力:
  1. SkillsAgentHook hook = SkillsAgentHook.builder()
  2.         .skillRegistry(registry)  // 绑定技能注册中心
  3.         .build();
复制代码
2.4 ReAct 智能体(ReactAgent)

基于 ReAct(推理+执行) 模式的智能体,自主完成「思考→选技能→执行任务」的全流程:
  1. ReactAgent agent = ReactAgent.builder()
  2.         .name("skills-agent")          // 智能体名称
  3.         .model(chatModel)              // 绑定大模型
  4.         .saver(new MemorySaver())      // 内存记忆(保存对话上下文)
  5.         .hooks(List.of(hook))          // 绑定技能钩子
  6.         .build();
复制代码
三、实战场景

场景一:技能发现(智能体自我认知)

让AI智能体主动披露自身具备的所有技能,验证技能加载是否成功。
核心代码
  1. private static void findSkills() throws GraphRunnerException {
  2.     // 1. 初始化核心组件
  3.     ChatModel chatModel = getChatModel();
  4.     SkillsAgentHook hook = getSkillsAgentHook();
  5.    
  6.     // 2. 构建技能智能体
  7.     ReactAgent agent = ReactAgent.builder()
  8.             .name("skills-agent")
  9.             .model(chatModel)
  10.             .saver(new MemorySaver())
  11.             .hooks(List.of(hook))
  12.             .build();
  13.    
  14.     // 3. 执行对话:查询技能
  15.     AssistantMessage resp = agent.call("请介绍你有哪些技能");
  16.     System.out.println(resp.getText());
  17. }
复制代码
执行结果
  1. 11:29:36.067 [main] INFO com.alibaba.cloud.ai.graph.skills.registry.classpath.ClasspathSkillRegistry -- Loaded 1 skills from classpath: skills
  2. 我目前拥有的技能包括:
  3. - **pdf-extractor**: 用于从 PDF 文档中提取文本、表格和表单数据,适用于分析和处理 PDF 文件。当用户需要提取、解析或分析 PDF 文件时可使用此技能。
  4. 如需了解某项技能的详细说明(例如具体操作步骤、支持的文件类型、使用示例等),我可以为您读取其完整的技能文档(`SKILL.md`)。您也可以告诉我您的具体需求(例如:“请帮我从一份PDF中提取所有表格”),我会判断是否适用某项技能并执行相应操作。
  5. 是否需要我为您详细展开某一项技能?
复制代码
场景二:技能使用(PDF 信息提取)

结合技能系统 + Python 执行工具 + Shell 工具,实现多工具协作,完成 PDF 文本/表格提取。
步骤1:自定义 Python 执行工具(GraalVM 支持)

依赖如下
  1. <dependency>
  2.     <groupId>org.graalvm.polyglot</groupId>
  3.     polyglot</artifactId>
  4.     <version>24.2.1</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>org.graalvm.polyglot</groupId>
  8.     python-community</artifactId>
  9.     <version>24.2.1</version>
  10.     <type>pom</type>
  11. </dependency>
复制代码
用于执行 Python 脚本完成 PDF 解析,工具代码如下:
  1. package com.jcq.springaialibabaagent.tools;
  2. import com.fasterxml.jackson.annotation.JsonProperty;
  3. import com.fasterxml.jackson.annotation.JsonPropertyDescription;
  4. import org.graalvm.polyglot.Context;
  5. import org.graalvm.polyglot.Engine;
  6. import org.graalvm.polyglot.PolyglotException;
  7. import org.graalvm.polyglot.Value;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import org.springframework.ai.chat.model.ToolContext;
  11. import org.springframework.ai.tool.ToolCallback;
  12. import org.springframework.ai.tool.function.FunctionToolCallback;
  13. import java.util.function.BiFunction;
  14. /**
  15. * GraalVM 沙箱环境执行 Python 代码的工具
  16. * 安全沙箱:禁用文件IO、进程创建、本地访问
  17. */
  18. public class PythonTool implements BiFunction<PythonTool.PythonRequest, ToolContext, String> {
  19.         public static final String DESCRIPTION = """
  20.                         Executes Python code and returns the result.
  21.                         - 代码必须为合法Python语法
  22.                         - 沙箱执行,安全无风险
  23.                         - 支持返回数字、字符串、数组、执行结果
  24.                         """;
  25.         private static final Logger log = LoggerFactory.getLogger(PythonTool.class);
  26.         private final Engine engine;
  27.         public PythonTool() {
  28.                 this.engine = Engine.newBuilder()
  29.                                 .option("engine.WarnInterpreterOnly", "false")
  30.                                 .build();
  31.         }
  32.         /** 构建Spring AI 标准工具回调 */
  33.         public static ToolCallback createPythonToolCallback(String description) {
  34.                 return FunctionToolCallback.builder("python_tool", new PythonTool())
  35.                                 .description(description)
  36.                                 .inputType(PythonRequest.class)
  37.                                 .build();
  38.         }
  39.         @Override
  40.         public String apply(PythonRequest request, ToolContext toolContext) {
  41.                 if (request.code == null || request.code.trim().isEmpty()) {
  42.                         return "Error:Python代码不能为空";
  43.                 }
  44.                 // 沙箱环境执行Python
  45.                 try (Context context = Context.newBuilder("python")
  46.                                 .engine(engine)
  47.                                 .allowAllAccess(false)
  48.                                 .allowIO(false)
  49.                                 .allowNativeAccess(false)
  50.                                 .allowCreateProcess(false)
  51.                                 .allowHostAccess(true)
  52.                                 .build()) {
  53.                         log.debug("执行Python代码:{}", request.code);
  54.                         Value result = context.eval("python", request.code);
  55.                         // 结果类型转换
  56.                         if (result.isNull()) return "执行完成,无返回值";
  57.                         if (result.isString()) return result.asString();
  58.                         if (result.isNumber() || result.isBoolean()) return result.toString();
  59.                         if (result.hasArrayElements()) {
  60.                                 StringBuilder sb = new StringBuilder("[");
  61.                                 long size = result.getArraySize();
  62.                                 for (long i = 0; i < size; i++) {
  63.                                         if (i > 0) sb.append(", ");
  64.                                         sb.append(result.getArrayElement(i));
  65.                                 }
  66.                                 return sb.append("]").toString();
  67.                         }
  68.                         return result.toString();
  69.                 }
  70.                 catch (PolyglotException e) {
  71.                         log.error("Python执行异常", e);
  72.                         return "执行错误:" + e.getMessage();
  73.                 }
  74.         }
  75.         /** 工具请求参数 */
  76.         public static class PythonRequest {
  77.                 @JsonProperty(required = true)
  78.                 @JsonPropertyDescription("需要执行的Python代码")
  79.                 public String code;
  80.                 public PythonRequest() {}
  81.                 public PythonRequest(String code) { this.code = code; }
  82.         }
  83. }
复制代码
步骤2:构建多技能协作智能体
  1. private static void useSkills() throws Exception {
  2.     // 1. 初始化大模型
  3.     ChatModel chatModel = getChatModel();
  4.    
  5.     // 2. 绑定技能钩子 + Shell工具钩子
  6.     SkillsAgentHook skillsHook = getSkillsAgentHook();
  7.     ShellToolAgentHook shellHook = ShellToolAgentHook.builder()
  8.             .shellTool2(ShellTool2.builder(System.getProperty("user.dir")).build())
  9.             .build();
  10.    
  11.     // 3. 构建智能体(绑定技能+工具+日志)
  12.     ReactAgent agent = ReactAgent.builder()
  13.             .name("skills-integration-agent")
  14.             .model(chatModel)
  15.             .saver(new MemorySaver())
  16.             .tools(PythonTool.createPythonToolCallback(PythonTool.DESCRIPTION))  // 自定义Python工具
  17.             .hooks(List.of(skillsHook, shellHook))  // 多钩子组合
  18.             .enableLogging(true)  // 开启日志,便于调试
  19.             .build();
  20.    
  21.     // 4. 执行PDF提取任务
  22.     String pdfPath = getTestSkillsDirectory() + "/pdf-extractor/skill-test.pdf";
  23.     AssistantMessage response = agent.call(String.format("请从 %s 文件中提取关键信息", pdfPath));
  24.    
  25.     // 5. 输出结果
  26.     System.out.println("========== PDF提取结果 ==========");
  27.     System.out.println(response.getText());
  28. }
复制代码
执行结果
  1. ==========
  2. The PDF extraction was successful! Here's the key information extracted from the `skill-test.pdf` file:
  3. ## Document Metadata
  4. - **Title**: Sample PDF Document
  5. - **Author**: Test Author
  6. - **Created**: 2024-01-01
  7. - **Modified**: 2024-01-15
  8. - **Page Count**: 5 pages
  9. ## Extracted Text
  10. The document contains: "This is extracted text from the PDF document. It contains multiple paragraphs and sections."
  11. ## Tables Found
  12. ### Table 1 (Page 1) - Product Inventory
  13. | Product | Price | Quantity |
  14. |---------|-------|----------|
  15. | Widget A | $10.00 | 100 |
  16. | Widget B | $15.00 | 50 |
  17. ### Table 2 (Page 3) - Financial Summary
  18. | Month | Revenue | Expenses |
  19. |-------|---------|----------|
  20. | January | $50,000 | $30,000 |
  21. | February | $55,000 | $32,000 |
复制代码
四、最佳实践建议


  • 技能规范化管理

    • 所有技能统一放在 resources/skills 目录,按业务拆分子目录;
    • SKILL.md 严格遵循格式规范,保证模型准确识别。

  • 多钩子灵活组合

    • 基础能力:SkillsAgentHook(技能系统);
    • 系统操作:ShellToolAgentHook(Shell命令);
    • 自定义能力:自定义工具(Python/Java/第三方API)。

  • 开发与调试优化

    • 开发阶段开启 enableLogging(true),查看智能体推理全流程;
    • 测试使用 MemorySaver 快速验证,生产环境替换为持久化存储。

  • 模型选型策略

    • 简单技能查询:基础版通义千问;
    • 复杂工具协作/多步骤推理:高级版大模型。


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册