spring ai简单使用skills

1、简述

在 Spring AI 2.0 中,Skills 通过 SkillsTool 将本地 SKILL.md 文件注册为工具,让 Agent 按预设流程工作,而不是依赖临场发挥的 Prompt 。核心路径是:定义 Skill 文件 → 用 SkillsTool 加载 → 注册为 ToolCallback → 通过 ChatClient.tools() 让模型调用。

2、代码

设计三个实用的 Skills查天气翻译写作

添加依赖

复制代码
 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.1.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ybw</groupId>
<artifactId>skills-ai-demo</artifactId>
<version>1.0.0</version>
<name>skills-ai-demo</name>
<description>skills-ai-demo</description>
<modules>
    <module>quick-start</module>
</modules>
<packaging>pom</packaging>

<properties>
    <java.version>21</java.version>
    <spring-ai.version>2.0.0</spring-ai.version>
    <mybatis-plus.version>3.5.15</mybatis-plus.version>
    <fastjson2.version>2.0.62</fastjson2.version>
    <hutool-all.version>5.8.36</hutool-all.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc</artifactId>
    </dependency>
    <!--AI start-->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-ollama</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springaicommunity</groupId>
        <artifactId>spring-ai-agent-utils</artifactId>
    </dependency>
    <!--AI end-->

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--工具-->
    <!-- Source: https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
    <dependency>
        <groupId>com.alibaba.fastjson2</groupId>
        <artifactId>fastjson2</artifactId>
        <version>${fastjson2.version}</version>
    </dependency>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>${hutool-all.version}</version>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springaicommunity</groupId>
            <artifactId>spring-ai-agent-utils-bom</artifactId>
            <version>0.10.0</version> <!-- 请检查并使用最新稳定版本 -->
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

天气查询 Skill

SKILL.md 文件

位置:src/main/resources/skills/weather-skill/SKILL.md

复制代码
---
name: weather-skill
description: 查询任意城市的实时天气信息,支持摄氏度/华氏度切换。当用户询问天气、气温、降水、风速等信息时使用。
---

# Weather Query Skill

## 工作流程
1. **解析城市**:从用户输入中提取城市名称(支持中英文)。
2. **确定单位**:默认摄氏度(℃),用户明确说"华氏度"时才切换。
3. **调用工具**:执行 `getWeather` 工具获取数据。
4. **输出格式**:
   - 当前温度、体感温度
   - 天气状况(晴/多云/雨等)
   - 湿度、风速
   - 简短穿衣建议

## 边界
- 仅支持中国主要城市(北京、上海、广州等),小城市返回"暂不支持"。
- 信息来自公开 API,仅作参考,不保证 100% 准确。

Java 工具实现

复制代码
package com.example.demo.tool;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.Map;

@Component
public class WeatherTools {

    // 模拟天气 API(实际可用高德、OpenWeatherMap 等)
    private static final Map<String, Map<String, Object>> WEATHER_DB = Map.of(
        "北京", Map.of("temp", 28, "condition", "晴", "humidity", 45, "wind", 12),
        "上海", Map.of("temp", 32, "condition", "多云", "humidity", 70, "wind", 8),
        "广州", Map.of("temp", 35, "condition", "雷阵雨", "humidity", 85, "wind", 15)
    );

    @Tool(description = "查询城市天气,返回 JSON 格式数据")
    public String getWeather(String city) {
        if (city == null || city.isBlank()) {
            return "{\"error\": \"请提供城市名称\"}";
        }

        // 去除空格,支持 "北京 " -> "北京"
        city = city.trim();

        if (!WEATHER_DB.containsKey(city)) {
            return String.format("{\"error\": \"暂不支持城市:%s\"}", city);
        }

        Map<String, Object> data = WEATHER_DB.get(city);
        return String.format("""
            {
                "city": "%s",
                "temperature": %d,
                "condition": "%s",
                "humidity": %d,
                "wind_speed": %d
            }""", city, data.get("temp"), data.get("condition"), 
               data.get("humidity"), data.get("wind"));
    }
}

翻译 Skill

SKILL.md 文件

位置:src/main/resources/skills/translate-skill/SKILL.md

复制代码
---
name: translate-skill
description: 多语言翻译工具,支持中英日韩法德互译。当用户要求翻译、translate、把某段文字译成某语言时使用。
---

# Translation Skill

## 工作流程
1. **识别方向**:从用户指令提取源语言和目标语言(默认源语言自动检测,目标语言为中文)。
2. **提取文本**:提取需要翻译的具体内容,忽略语气词。
3. **调用工具**:执行 `translate` 工具。
4. **输出**:
   - 翻译结果
   - 保留原格式(段落、标点)
   - 必要时附上"直译"和"意译"两个版本

## 特殊规则
- 专业术语保留英文(如 API、AI、GPU)。
- 代码块、URL 不翻译,原样保留。
- 文化梗(网络用语)做适当本地化。

Java 工具实现

复制代码
package com.example.demo.tool;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
import java.util.Map;

@Component
public class TranslateTools {

    // 模拟翻译(实际可集成 DeepL、Google Translate API)
    private static final Map<String, String> MOCK_TRANSLATIONS = Map.of(
        "Hello world", "你好世界",
        "How are you", "你好吗",
        "I love programming", "我热爱编程"
    );

    @Tool(description = "翻译文本,支持中英互译")
    public String translate(String sourceLang, String targetLang, String text) {
        if (text == null || text.isBlank()) {
            return "{\"error\": \"请提供待翻译文本\"}";
        }

        // 简单模拟
        String result = MOCK_TRANSLATIONS.getOrDefault(text, 
            String.format("[模拟翻译] 从 %s 到 %s:%s", sourceLang, targetLang, text));

        return String.format("""
            {
                "source_lang": "%s",
                "target_lang": "%s",
                "original": "%s",
                "translation": "%s",
                "note": "此为模拟翻译,实际请接入翻译 API"
            }""", sourceLang, targetLang, text, result);
    }
}

写作 Skill

SKILL.md 文件

位置:src/main/resources/skills/writing-skill/SKILL.md

复制代码
---
name: writing-skill
description: 辅助写作工具,支持文章生成、润色、续写、大纲生成。当用户要求写文章、润色、生成大纲、续写时使用。
---

# Writing Assistance Skill

## 工作流程
1. **理解需求**:识别写作类型(议论文、记叙文、商业邮件、技术文档等)。
2. **收集要素**:
   - 主题、字数要求、目标读者
   - 风格偏好(正式/轻松/幽默/科技感)
3. **调用工具**:执行 `generateOutline` 和 `writeContent` 工具。
4. **输出结构**:
   - 先给大纲(让用户确认)
   - 再生成正文
   - 最后附上修改建议

## 风格指南
- 技术文档:专业、结构化、带代码示例。
- 商业邮件:简洁、礼貌、有明确行动项。
- 创意写作:生动、有画面感、避免套话。

## 边界
- 不生成违反法律法规的内容。
- 如果主题涉及医疗、法律等专业领域,声明"建议咨询专业人士"。

Java 工具实现

复制代码
package com.example.demo.tool;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
import java.util.UUID;

@Component
public class WritingTools {

    @Tool(description = "根据主题生成文章大纲,返回层级列表")
    public String generateOutline(String topic, String writingType) {
        if (topic == null || topic.isBlank()) {
            return "{\"error\": \"请提供写作主题\"}";
        }

        // 模拟大纲生成
        return String.format("""
            {
                "topic": "%s",
                "type": "%s",
                "outline": [
                    {"level": 1, "title": "引言:为什么 %s 很重要"},
                    {"level": 2, "title": "核心概念解析"},
                    {"level": 2, "title": "实际应用场景"},
                    {"level": 3, "title": "案例一:..."),
                    {"level": 3, "title": "案例二:..."),
                    {"level": 1, "title": "总结与展望"}
                ]
            }""", topic, writingType, topic);
    }

    @Tool(description = "根据主题和风格生成完整文章")
    public String writeContent(String topic, String style, int wordCount) {
        if (topic == null || topic.isBlank()) {
            return "{\"error\": \"请提供写作主题\"}";
        }

        // 模拟文章生成
        String content = String.format("""
            # %s

            ## 引言
            在当今快速发展的时代,%s 已经成为不可忽视的重要议题。
            本文将从多个维度深入探讨%s,并为读者提供有价值的见解。

            ## 主体内容
            (此处为模拟生成内容,篇幅限制,实际接入 LLM 生成完整文章)

            ## 结论
            %s 将继续深刻影响我们的生活,值得持续关注。

            ---
            **风格**:%s | **字数**:%d 字(模拟)
            """, topic, topic, topic, topic, style, wordCount);

        return String.format("""
            {
                "topic": "%s",
                "style": "%s",
                "word_count": %d,
                "content": "%s",
                "note": "此为模拟内容,实际可接入 LLM 生成"
            }""", topic, style, wordCount, content.replace("\n", "\\n"));
    }
}

统一配置:注册所有 ChatClient 和 Skills

复制代码
package com.ybw.config;

import com.ybw.tool.TranslateTools;
import com.ybw.tool.WeatherTools;
import com.ybw.tool.WritingTools;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置 ChatClient
 *
 * @author ybw
 * @version V1.0
 * @className ChatClientConfig
 * @date 2026/6/29
 **/
@Configuration
public class ChatClientConfig {


    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder,
                                 ToolCallback skillsTool,
                                 WeatherTools weatherTools,
                                 TranslateTools translateTools,
                                 WritingTools writingTools) {
        return chatClientBuilder
                .defaultSystem("""
                        你是一个通用助手,可以处理以下任务:
                        1. 查天气 → 使用 Skill(command="weather-skill") + getWeather 工具
                        2. 翻译 → 使用 Skill(command="translate-skill") + translate 工具
                        3. 写作 → 使用 Skill(command="writing-skill") + generateOutline/writeContent 工具
                        
                        根据用户意图自动选择合适的 Skill,先用 Skill 加载流程,再调用对应的 Java 工具执行。
                        用中文友好回复。
                        """)
                .defaultTools(skillsTool, weatherTools, translateTools, writingTools)
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }
}

package com.ybw.config;

import org.springaicommunity.agent.tools.SkillsTool;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
public class SkillToolConfig {

    @Bean
    public ToolCallback skillsTool() {
        return SkillsTool.builder()
                .addSkillsResource(new ClassPathResource("skills"))
                .build();
    }
}

统一服务入口

复制代码
package com.ybw.service;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MultiSkillService {

    private final ChatClient chatClient;

    public String handle(String userInput) {
        return chatClient.prompt()
                .user(userInput)
                .call()
                .content();
    }
}

测试用例

复制代码
package com.ybw.service;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@Slf4j
public class MultiSkillServiceTest {

    @Resource
    private MultiSkillService service;

    @Test
    void testWeather() {
        String result = service.handle("北京今天天气怎么样?");
        System.out.println(result);
        // 输出:调用 weather-skill → getWeather("北京") → 返回天气报告
    }

    @Test
    void testTranslate() {
        String result = service.handle("把 'Hello world' 翻译成中文");
        System.out.println(result);
        // 输出:调用 translate-skill → translate("en", "zh", "Hello world")
    }

    @Test
    void testWriting() {
        String result = service.handle("帮我写一篇关于 Java 技术栈的文章,500字左右");
        System.out.println(result);
        // 输出:调用 writing-skill → generateOutline → writeContent
    }
}

核心要点总结

Skill 触发场景 关联 Tool 特殊处理
天气 "XX天气"、"温度" getWeather(city) 支持中英文城市名、单位切换
翻译 "翻译"、"translate" translate(src, tgt, text) 保留专业术语、代码块、URL
写作 "写文章"、"润色"、"大纲" generateOutline() + writeContent() 先出大纲确认,再生成正文

每个 Skill 的 SKILL.md 定义了标准作业流程 ,而 Java @Tool 负责实际执行 ,模型作为调度中心 ,根据用户意图自动选择最合适的 Skill 组合。这种设计让 AI 行为可预测、可追溯、可维护

相关推荐
闲猫1 小时前
AI夸会话混合型记忆增强框架 《MMAG: Mixed Memory-Augmented Generation》
人工智能
秦先生在广东1 小时前
Block/Buzz:用 Nostr 协议把 AI Agent 变成有密钥的真正队友
人工智能
审小匠OpenCPAi1 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
何时梦醒1 小时前
Vibe Coding 驾驭指南:别让 AI 把你的项目写成屎山
人工智能
Hrain-AI1 小时前
2026 企业 AI 编程智能体实战:Codex 与 Claude Code
开发语言·人工智能·kotlin
美狐美颜sdk1 小时前
直播APP开发实战:从直播推流到AI美颜SDK完整方案详解
人工智能·美颜sdk·直播美颜sdk·美颜api
大模型任我行1 小时前
蚂蚁:智能体安全护栏SingGuard-NSFA
人工智能·语言模型·自然语言处理·论文笔记
就是一顿骚操作1 小时前
GPT-2 from scratch with torch:用 torch 从零实现 GPT-2
人工智能·gpt·transformer·论文解读·gpt-2
Fu2067212 小时前
数据库第三次作业
数据库