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

简介: 本文详细讲解 Spring AI Alibaba Skill 技能体系,从核心概念、组件解析到实战开发,手把手教你基于 ReAct 智能体实现技能发现、工具调用与 PDF 信息提取,助你快速构建可扩展、可插拔的企业级 AI 智能体应用。

在当今AI应用开发领域,让AI智能体具备灵活的工具调用能力可扩展的技能体系,是落地复杂业务场景的核心挑战。Spring AI Alibaba 原生提供了完善的 Skill 技能支持,能让智能体实现「技能发现→按需加载→工具执行」的全流程自动化。

本文将从核心概念、组件解析、实战场景、最佳实践四个维度,手把手教你掌握 Spring AI Alibaba Skill 的使用方法。


一、核心概念

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

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

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

1.2 Skill 标准目录结构

每个技能独立为一个子目录,SKILL.md 为强制必需文件,目录结构如下:

skills/                 # 技能根目录
└── pdf-extractor/      # 单个技能目录(自定义命名)
    ├── SKILL.md        # ✅ 必需:技能核心定义文档
    ├── references/     # 可选:技能参考资料
    ├── examples/       # 可选:使用示例
    └── scripts/        # 可选:执行脚本

1.3 SKILL.md 格式规范

SKILL.md 采用元数据+正文结构,元数据通过 --- 包裹,是模型识别技能的关键:

---
name: pdf-extractor          # 必需:小写字母、数字、连字符,最长64字符
description: 用于从PDF文档中提取文本、表格和表单数据  # 必需:简洁描述,超长会被截断
---

# PDF 提取技能
## 功能说明
You are a PDF extraction specialist. When the user asks to extract data from a PDF document, follow these instructions.
## 使用方法
1. **Validate Input**
   - Confirm the PDF file path is provided.
   - The default path for the pdf file is the current working directory.
   - Use the `shell` or `read_file` tool to check if the file exists
   - Verify it's a valid PDF format

2. **Extract Content**
   - Execute the extraction script using the `shell` tool:
     ```bash
     python scripts/extract_pdf.py <pdf_file_path>
     ```
   - The script will output JSON format with extracted data

3. **Process Results**
   - Parse the JSON output from the script
   - Structure the data in a readable format
   - Handle any encoding issues (UTF-8, special characters)

4. **Present Output**
   - Summarize what was extracted
   - Present data in the requested format (JSON, Markdown, plain text)
   - Highlight any issues or limitations

## Script Location

The extraction script is located at:
`scripts/extract_pdf.py`

## Output Format

The script returns JSON:
```json
{
  "success": true,
  "filename": "report.pdf",
  "text": "Full text content...",
  "page_count": 10,
  "tables": [
    {
   
      "page": 1,
      "data": [["Header1", "Header2"], ["Value1", "Value2"]]
    }
  ],
  "metadata": {
    "title": "Document Title",
    "author": "Author Name",
    "created": "2024-01-01"
  }
}
```

scripts/extract_pdf.py简介,因为目前测试脚本的执行,所以mock返回了一个json格式的解析内容。

二、核心组件解析

Spring AI Alibaba Skill 体系由四大核心组件构成,各司其职、协同工作:

2.1 对话模型(ChatModel)

对接阿里通义千问大模型,是智能体的「大脑」,负责推理决策:

private static ChatModel getChatModel() {
   
    // 构建通义千问API客户端
    DashScopeApi dashScopeApi = DashScopeApi.builder()
            .apiKey(System.getenv("AliQwen_API"))  // 环境变量配置API Key
            .build();

    // 创建对话模型
    return DashScopeChatModel.builder()
            .dashScopeApi(dashScopeApi)
            .build();
}

2.2 技能注册中心(SkillRegistry)

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

  • ClasspathSkillRegistry:从项目类路径(resources)加载技能
  • FileSystemSkillRegistry:从本地文件系统加载技能

代码示例

SkillRegistry registry = ClasspathSkillRegistry.builder()
        .classpathPath("skills")  // 指向resources/skills目录
        .build();

2.3 技能钩子(SkillsAgentHook)

连接智能体技能系统的桥梁,负责注入技能上下文、提供工具调用能力:

SkillsAgentHook hook = SkillsAgentHook.builder()
        .skillRegistry(registry)  // 绑定技能注册中心
        .build();

2.4 ReAct 智能体(ReactAgent)

基于 ReAct(推理+执行) 模式的智能体,自主完成「思考→选技能→执行任务」的全流程:

ReactAgent agent = ReactAgent.builder()
        .name("skills-agent")          // 智能体名称
        .model(chatModel)              // 绑定大模型
        .saver(new MemorySaver())      // 内存记忆(保存对话上下文)
        .hooks(List.of(hook))          // 绑定技能钩子
        .build();

三、实战场景

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

让AI智能体主动披露自身具备的所有技能,验证技能加载是否成功。

核心代码

private static void findSkills() throws GraphRunnerException {
   
    // 1. 初始化核心组件
    ChatModel chatModel = getChatModel();
    SkillsAgentHook hook = getSkillsAgentHook();

    // 2. 构建技能智能体
    ReactAgent agent = ReactAgent.builder()
            .name("skills-agent")
            .model(chatModel)
            .saver(new MemorySaver())
            .hooks(List.of(hook))
            .build();

    // 3. 执行对话:查询技能
    AssistantMessage resp = agent.call("请介绍你有哪些技能");
    System.out.println(resp.getText());
}

执行结果

11:29:36.067 [main] INFO com.alibaba.cloud.ai.graph.skills.registry.classpath.ClasspathSkillRegistry -- Loaded 1 skills from classpath: skills
我目前拥有的技能包括:

- **pdf-extractor**: 用于从 PDF 文档中提取文本、表格和表单数据,适用于分析和处理 PDF 文件。当用户需要提取、解析或分析 PDF 文件时可使用此技能。

如需了解某项技能的详细说明(例如具体操作步骤、支持的文件类型、使用示例等),我可以为您读取其完整的技能文档(`SKILL.md`)。您也可以告诉我您的具体需求(例如:“请帮我从一份PDF中提取所有表格”),我会判断是否适用某项技能并执行相应操作。

是否需要我为您详细展开某一项技能?

场景二:技能使用(PDF 信息提取)

结合技能系统 + Python 执行工具 + Shell 工具,实现多工具协作,完成 PDF 文本/表格提取。

步骤1:自定义 Python 执行工具(GraalVM 支持)

依赖如下

<!-- GraalVM Polyglot for Python execution -->
<dependency>
    <groupId>org.graalvm.polyglot</groupId>
    <artifactId>polyglot</artifactId>
    <version>24.2.1</version>
</dependency>
<dependency>
    <groupId>org.graalvm.polyglot</groupId>
    <artifactId>python-community</artifactId>
    <version>24.2.1</version>
    <type>pom</type>
</dependency>

用于执行 Python 脚本完成 PDF 解析,工具代码如下:

package com.jcq.springaialibabaagent.tools;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;

import java.util.function.BiFunction;

/**
 * GraalVM 沙箱环境执行 Python 代码的工具
 * 安全沙箱:禁用文件IO、进程创建、本地访问
 */
public class PythonTool implements BiFunction<PythonTool.PythonRequest, ToolContext, String> {
   

    public static final String DESCRIPTION = """
            Executes Python code and returns the result.
            - 代码必须为合法Python语法
            - 沙箱执行,安全无风险
            - 支持返回数字、字符串、数组、执行结果
            """;
    private static final Logger log = LoggerFactory.getLogger(PythonTool.class);
    private final Engine engine;

    public PythonTool() {
   
        this.engine = Engine.newBuilder()
                .option("engine.WarnInterpreterOnly", "false")
                .build();
    }

    /** 构建Spring AI 标准工具回调 */
    public static ToolCallback createPythonToolCallback(String description) {
   
        return FunctionToolCallback.builder("python_tool", new PythonTool())
                .description(description)
                .inputType(PythonRequest.class)
                .build();
    }

    @Override
    public String apply(PythonRequest request, ToolContext toolContext) {
   
        if (request.code == null || request.code.trim().isEmpty()) {
   
            return "Error:Python代码不能为空";
        }

        // 沙箱环境执行Python
        try (Context context = Context.newBuilder("python")
                .engine(engine)
                .allowAllAccess(false)
                .allowIO(false)
                .allowNativeAccess(false)
                .allowCreateProcess(false)
                .allowHostAccess(true)
                .build()) {
   

            log.debug("执行Python代码:{}", request.code);
            Value result = context.eval("python", request.code);

            // 结果类型转换
            if (result.isNull()) return "执行完成,无返回值";
            if (result.isString()) return result.asString();
            if (result.isNumber() || result.isBoolean()) return result.toString();
            if (result.hasArrayElements()) {
   
                StringBuilder sb = new StringBuilder("[");
                long size = result.getArraySize();
                for (long i = 0; i < size; i++) {
   
                    if (i > 0) sb.append(", ");
                    sb.append(result.getArrayElement(i));
                }
                return sb.append("]").toString();
            }
            return result.toString();
        }
        catch (PolyglotException e) {
   
            log.error("Python执行异常", e);
            return "执行错误:" + e.getMessage();
        }
    }

    /** 工具请求参数 */
    public static class PythonRequest {
   
        @JsonProperty(required = true)
        @JsonPropertyDescription("需要执行的Python代码")
        public String code;

        public PythonRequest() {
   }
        public PythonRequest(String code) {
    this.code = code; }
    }
}

步骤2:构建多技能协作智能体

private static void useSkills() throws Exception {
   
    // 1. 初始化大模型
    ChatModel chatModel = getChatModel();

    // 2. 绑定技能钩子 + Shell工具钩子
    SkillsAgentHook skillsHook = getSkillsAgentHook();
    ShellToolAgentHook shellHook = ShellToolAgentHook.builder()
            .shellTool2(ShellTool2.builder(System.getProperty("user.dir")).build())
            .build();

    // 3. 构建智能体(绑定技能+工具+日志)
    ReactAgent agent = ReactAgent.builder()
            .name("skills-integration-agent")
            .model(chatModel)
            .saver(new MemorySaver())
            .tools(PythonTool.createPythonToolCallback(PythonTool.DESCRIPTION))  // 自定义Python工具
            .hooks(List.of(skillsHook, shellHook))  // 多钩子组合
            .enableLogging(true)  // 开启日志,便于调试
            .build();

    // 4. 执行PDF提取任务
    String pdfPath = getTestSkillsDirectory() + "/pdf-extractor/skill-test.pdf";
    AssistantMessage response = agent.call(String.format("请从 %s 文件中提取关键信息", pdfPath));

    // 5. 输出结果
    System.out.println("========== PDF提取结果 ==========");
    System.out.println(response.getText());
}

执行结果

==========
The PDF extraction was successful! Here's the key information extracted from the `skill-test.pdf` file:

## Document Metadata
- **Title**: Sample PDF Document
- **Author**: Test Author
- **Created**: 2024-01-01
- **Modified**: 2024-01-15
- **Page Count**: 5 pages

## Extracted Text
The document contains: "This is extracted text from the PDF document. It contains multiple paragraphs and sections."

## Tables Found

### Table 1 (Page 1) - Product Inventory
| Product | Price | Quantity |
|---------|-------|----------|
| Widget A | $10.00 | 100 |
| Widget B | $15.00 | 50 |

### Table 2 (Page 3) - Financial Summary
| Month | Revenue | Expenses |
|-------|---------|----------|
| January | $50,000 | $30,000 |
| February | $55,000 | $32,000 |

四、最佳实践建议

  1. 技能规范化管理

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

    • 基础能力:SkillsAgentHook(技能系统);
    • 系统操作:ShellToolAgentHook(Shell命令);
    • 自定义能力:自定义工具(Python/Java/第三方API)。
  3. 开发与调试优化

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

    • 简单技能查询:基础版通义千问;
    • 复杂工具协作/多步骤推理:高级版大模型。
目录
相关文章
|
前端开发 小程序 Java
uniapp上传图片 前端以及java后端代码实现
uniapp上传图片 前端以及java后端代码实现
666 0
|
17天前
|
消息中间件 人工智能 安全
【从零手写 ClaudeCode:learn-claude-code 项目实战笔记】(8)Background Tasks (后台任务)
本节详解s08后台任务机制:通过守护线程异步执行`npm install`等耗时命令,用线程安全通知队列将结果注入LLM调用前的上下文,实现“边跑边想”。含完整代码、踩坑注释与实操示例,助新手理解AI Agent并发设计核心。
655 1
|
3月前
|
人工智能 前端开发 开发工具
从 ReAct 到 Ralph Loop:AI Agent 的持续迭代范式
Ralph Loop是一种AI编程范式,通过Stop Hook拦截机制强制模型持续迭代,直至满足可验证的完成条件(如测试通过、输出特定标记),解决AI“半途而废”问题。它依赖外部状态(Git、文件系统)实现自我参照循环,支持无人值守的AFK开发,已集成于Claude Code等主流工具。
从 ReAct 到 Ralph Loop:AI Agent 的持续迭代范式
|
4天前
|
存储 人工智能 Java
吃透 Spring AI Alibaba 多智能体|四大协同模式+完整代码
本文详细讲解 Spring AI Alibaba Multi-Agent 多智能体架构,包含顺序执行、并行执行、LLM 路由、监督者四大协同模式,搭配可运行代码示例与真实业务场景,从零带你上手多智能体开发。
303 3
|
9天前
|
缓存 前端开发 网络协议
使用 CDN 给网站加速的保姆级教程:从卡顿到飞一般的体验
CDN 内容分发网络配置全攻略,从开通到生效不到 1 小时,就能让用户体验从 “卡顿” 变 “飞一般流畅”。
492 3
|
1天前
|
人工智能 自然语言处理 安全
支付宝支付集成skill首发上线魔搭,开发者三步接入支付
支付宝发布国内首个“支付集成Skill”,开发者通过自然语言即可在Vibe Coding中零代码接入支付宝收款功能,支持快速构建电商应用(如卖猫抓板)。配套升级沙箱环境,安全高效验证支付全流程。
86 16
|
1天前
|
人工智能 安全 JavaScript
Windows11 部署 OpenClaw 小龙虾 零代码快速上手
专为 Windows 11 系统优化,针对性解决 Win11 权限、Defender、中文路径、SmartScreen 等部署常见问题,双击即可一键安装,10 分钟就能上手使用!
|
27天前
|
人工智能 JavaScript API
少走90%弯路!OpenClaw阿里云/本地部署与Claude Code协同+5条最佳实践+百炼API配置及避坑指南
OpenClaw(原Clawdbot)作为开源AI Agent框架,核心优势是“自然语言驱动自动化执行”,而Claude Code凭借精准的代码生成、逻辑校验能力,成为OpenClaw的最佳搭档——两者协同,既能让OpenClaw高效执行终端命令、处理自动化任务,又能通过Claude Code优化代码逻辑、规避语法错误,大幅提升任务落地效率。但新手在实际使用中,往往陷入“部署困难、API配置出错、协同逻辑混乱”的困境,即便花费数小时,也难以发挥两者的核心价值。
1865 6
|
9天前
|
安全 Linux 网络安全
服务器遭遇 XMRig 挖矿程序入侵排查与清理全记录
服务器遭遇 XMRig 挖矿程序入侵?这份全记录教你定位高负载 xmrig 进程,排查自启动服务、定时任务等恶意配置,详解进程终止、文件删除与安全加固步骤,轻松解决 CPU 占用过高问题,筑牢 Linux 服务器安全防线。
133 2
服务器遭遇 XMRig 挖矿程序入侵排查与清理全记录
|
3天前
|
人工智能 自然语言处理 安全
Spring AI Alibaba 人工介入实战|Human-in-the-Loop 让 AI 更可靠
本文详解 Spring AI Alibaba 人工介入 Hook 实战,通过 Human-in-the-Loop 实现 AI 智能体执行暂停、人工审批与流程恢复,让 AI 应用更安全可控。
149 1

热门文章

最新文章