Spring AI 通关秘籍:从聊天到业务落地,Java 选手再也不用馋 Python 了!

作为天天跟代码打交道的 IT 人,你是不是也有过这种崩溃时刻:想给项目加个 AI 功能,结果对着 Python 的 LangChain、LLaMAIndex 一顿猛学,回头一看自己的 Spring 项目 ------"这俩咋凑一块儿啊?"

别慌!今天咱们聊的Spring AI,就是 Java 生态给咱们准备的 "AI 开发 Buff"。它把复杂的 AI 调用、流式交互、工具整合都封装成了熟悉的 Spring 风格,不用再当 "API 缝合怪",咱们用 Java 也能轻松玩明白 AI。

1. 先唠唠:Spring AI 到底是个啥?

说直白点,Spring AI 就是AI 领域的 "Spring 框架" 。它解决了 Java 开发者对接 AI 时的 3 个核心痛点:

  • 不用记各种 AI 模型(OpenAI、阿里云通义千问、讯飞星火)的不同 API 格式,统一用ChatClient调用;
  • 不用自己写流式输出、重试、降级逻辑,Spring 帮你封装好了;
  • 能无缝整合 Spring 生态的东西(Spring Boot、Spring Cloud),跟你现有的业务系统搭班子毫无违和感。

简单讲:以前你对接 AI 要写 100 行 "胶水代码",现在用 Spring AI,10 行搞定。

2. 入门实战:用 Spring AI 搞个 "普通对话"

先从最简单的开始 ------ 让 AI 跟你聊两句。步骤简单到离谱,跟搭 Spring Boot 项目没区别。

参考官方文档中的示例代码编写:👉 Chat Client API

2.1 先搭环境(3 步走)

  1. 新建 Spring Boot 项目,在pom.xml里加依赖(以对接 OpenAI 为例):
xml 复制代码
<!-- Spring AI核心依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>1.0.0-M1</version> <!-- 用最新版就行 -->
</dependency>
<!-- Web依赖(方便测接口) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. application.properties里填 AI 密钥(去 OpenAI 官网申请,或者用国内模型的密钥):

properties

ini 复制代码
# OpenAI配置
spring.ai.openai.api-key=你的API密钥
spring.ai.openai.chat.model=gpt-3.5-turbo
  1. 写个 Controller 测试:
less 复制代码
@RestController
@RequestMapping("/ai")
public class AIChatController {

    // Spring AI自动注入ChatClient,不用自己new!
    private final ChatClient chatClient;

    public AIChatController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    // 普通对话接口:传个问题,返回AI的回答
    @GetMapping("/chat")
    public String chat(@RequestParam String question) {
        // 调用AI,一句话搞定
        return chatClient.prompt().user(question).call().content();
    }
}

2.2 跑起来试试!

启动项目,访问http://localhost:8080/ai/chat?question=用Java写个HelloWorld,AI 直接给你返回代码 ------ 就这么简单,没有任何花里胡哨的操作。

3. 进阶:搞个 "流式对话",跟 ChatGPT 一样实时输出

普通对话是 "等 AI 想完一起返回",流式对话是 "AI 想一句输出一句",体验更丝滑(比如 ChatGPT 的打字效果)。Spring AI 搞这个也很简单,核心是用Flux(响应式编程)。

3.1 写个流式接口

less 复制代码
// 流式对话接口:返回Flux<String>,支持实时输出
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String question) {
    // 用stream()方法,返回Flux<ChatResponse>
    return chatClient.prompt()
            .user(question)
            .stream() // 关键:开启流式
            .map(chatResponse -> chatResponse.getResult().getOutput().getContent());
}

3.2 测效果

用 apifox 或者浏览器访问这个接口,你会看到 AI 的回答 "一行一行蹦出来",跟你平时用 ChatGPT 一模一样。前端要做的就是监听 SSE(Server-Sent Events),把内容实时渲染出来 ------Java 后端这边,咱们已经搞定了!

1

4. 给 AI 立规矩:System 角色设定

你有没有遇到过 AI "答非所问"?比如你让它当 Java 老师,它却跟你聊 Python。这时候就需要System 角色------ 给 AI 定个 "身份" 和 "规则",让它别跑偏。

Spring AI 里设定 System 角色超简单,就在prompt()里加个system()方法:

less 复制代码
@GetMapping("/chat/teacher")
public String javaTeacherChat(@RequestParam String question) {
    // System角色:告诉AI"你是Java导师,只聊Java,用简单的话讲"
    String systemPrompt = "你是一名资深Java导师,只回答与Java相关的问题," +
                          "避免涉及其他编程语言,解释时用大白话,别甩专业术语。";
    
    return chatClient.prompt()
            .system(systemPrompt) // 加System规则
            .user(question)       // 用户问题
            .call()
            .content();
}

测试一下:问 "Python 怎么写循环?",AI 会说 "我只聊 Java 哦,Java 的循环有 for 和 while 两种......"------ 规矩立住了!

5. 给 AI 加 "插件":Advisors 功能增强

下图展示了,在与大模型交互过程中,Advisors的执行流程:

Advisors 是 Spring AI 的 "增强器",能在 AI 调用的前、中、后插逻辑,比如日志记录、权限校验、参数修改。举个最实用的例子:记录每次 AI 调用的 "问题" 和 "回答"。

5.1 自定义一个日志 Advisor

java 复制代码
// 实现Advisor接口,重写before和after方法
@Component
public class AILogAdvisor implements Advisor {

    private static final Logger log = LoggerFactory.getLogger(AILogAdvisor.class);

    // AI调用前:记录用户的问题
    @Override
    public void before(Prompt prompt) {
        String userQuestion = prompt.getMessages().stream()
                .filter(msg -> msg.getRole() == Message.Role.USER)
                .findFirst()
                .map(Message::getContent)
                .orElse("无用户问题");
        
        log.info("AI调用开始,用户问题:{}", userQuestion);
    }

    // AI调用后:记录AI的回答
    @Override
    public void after(Response response) {
        String aiAnswer = response.getResult().getOutput().getContent();
        log.info("AI调用结束,AI回答:{}", aiAnswer);
    }
}

5.2 用 Advisor 增强 ChatClient

只需要在注入ChatClient时,用ChatClient.builder()把 Advisor 加进去:

kotlin 复制代码
@Configuration
public class AIClientConfig {

    @Value("${spring.ai.openai.api-key}")
    private String apiKey;

    @Bean
    public ChatClient chatClient(AILogAdvisor aiLogAdvisor) {
        // 构建ChatClient,加入日志Advisor
        return OpenAiChatClient.builder()
                .apiKey(apiKey)
                .model("gpt-3.5-turbo")
                .advisor(aiLogAdvisor) // 加增强器
                .build();
    }
}

这样一来,每次调用 AI,日志里都会自动记录 "用户问了啥""AI 答了啥"------ 排查问题、统计用量都方便!

6. 关键一步:Tool Calling 对接业务系统

AI 光会聊天没用,得能调用咱们业务系统的接口(比如查订单、查库存),这就是Tool Calling。Spring AI 把这个流程封装成了 3 步:定义工具、让 AI 选工具、执行工具并返回结果。

6.1 第一步:定义业务工具(比如 "查订单")

先写个 "订单查询服务",模拟业务系统:

typescript 复制代码
// 模拟业务系统:订单服务
@Service
public class OrderService {
    // 根据订单号查订单
    public String getOrderInfo(String orderId) {
        // 实际项目里这里会查数据库/调用微服务
        return "订单ID:" + orderId + ",状态:已付款,金额:99元,商品:Java编程思想";
    }
}

然后把这个服务包装成 AI 能调用的 "Tool":

typescript 复制代码
// 定义AI工具:订单查询工具
@Component
public class OrderQueryTool implements Tool {

    private final OrderService orderService;

    public OrderQueryTool(OrderService orderService) {
        this.orderService = orderService;
    }

    // 工具名称:AI会用这个名字调用
    @Override
    public String getName() {
        return "orderQueryTool";
    }

    // 工具描述:告诉AI"这个工具是干嘛的,怎么用"
    @Override
    public String getDescription() {
        return "用于查询用户的订单信息,需要传入订单号(orderId)作为参数," +
               "参数格式:{"orderId":"用户的订单号"}";
    }

    // 工具执行逻辑:AI调用时会触发这个方法
    @Override
    public Object call(Map<String, Object> parameters) {
        String orderId = (String) parameters.get("orderId");
        return orderService.getOrderInfo(orderId);
    }
}

6.2 第二步:让 AI 调用工具

Spring AI 提供了ToolCallingChatClient,能自动判断 "要不要调用工具":

less 复制代码
@RestController
@RequestMapping("/ai/tool")
public class AIToolController {

    private final ToolCallingChatClient toolChatClient;

    // 注入工具和ChatClient,构建ToolCallingChatClient
    public AIToolController(OrderQueryTool orderQueryTool, ChatClient chatClient) {
        this.toolChatClient = ToolCallingChatClient.builder(chatClient)
                .withTools(orderQueryTool) // 把订单工具加进去
                .build();
    }

    // 调用工具的接口
    @GetMapping("/queryOrder")
    public String queryOrder(@RequestParam String question) {
        // 比如用户问:"查一下我的订单号12345的信息"
        return toolChatClient.prompt().user(question).call().content();
    }
}

测试一下:用户问 "查一下订单号 12345 的信息",AI 会自动调用orderQueryTool,返回订单详情 ------ 这就把 AI 和你的业务系统打通了!

7. 终极优化:RAG 检索增强,让 AI "有记忆"

AI 有个毛病:"记不住" 你公司的私有数据(比如产品文档、内部规则)。这时候就需要RAG(检索增强生成) ------ 先从你的知识库(比如 MySQL、Elasticsearch)里查相关信息,再把信息传给 AI,让 AI 基于这些信息回答。

Spring AI 整合 RAG 很简单,核心是 "检索器(Retriever)+ Prompt"。

7.1 第一步:搞个简单的知识库(用 List 模拟)

typescript 复制代码
// 模拟知识库:比如公司的产品文档
@Component
public class ProductDocRetriever implements Retriever<String> {

    // 模拟知识库数据
    private final List<String> productDocs = Arrays.asList(
            "产品名称:Java云原生框架,版本:V2.0,支持Spring Boot 3.0+,不支持Spring Boot 2.x",
            "产品名称:Python数据分析工具,版本:V1.5,支持Python 3.9+,需要安装pandas库"
    );

    // 检索逻辑:根据用户问题,从知识库找相关内容
    @Override
    public List<String> retrieve(String query) {
        // 实际项目里这里会用Elasticsearch做全文检索
        return productDocs.stream()
                .filter(doc -> doc.contains(query.split(" ")[1])) // 简单匹配产品名
                .collect(Collectors.toList());
    }
}

7.2 第二步:整合 RAG 到 AI 调用

kotlin 复制代码
@RestController
@RequestMapping("/ai/rag")
public class AIRagController {

    private final ChatClient chatClient;
    private final ProductDocRetriever docRetriever;

    public AIRagController(ChatClient chatClient, ProductDocRetriever docRetriever) {
        this.chatClient = chatClient;
        this.docRetriever = docRetriever;
    }

    @GetMapping("/queryProduct")
    public String queryProduct(@RequestParam String question) {
        // 1. 从知识库检索相关信息(比如用户问"Java云原生框架支持哪些版本?")
        List<String> relatedDocs = docRetriever.retrieve(question);
        String context = String.join("\n", relatedDocs);

        // 2. 把检索到的信息传给AI,让AI基于这些信息回答
        String prompt = "根据以下产品文档内容,回答用户问题:\n" +
                       "文档内容:" + context + "\n" +
                       "用户问题:" + question;

        return chatClient.prompt().user(prompt).call().content();
    }
}

测试一下:用户问 "Java 云原生框架支持 Spring Boot 2.x 吗?",AI 会从知识库查到 "不支持 Spring Boot 2.x",然后准确回答 ------ 这就是 RAG 的魔力,让 AI 能 "读懂" 你的私有数据!

总结:Spring AI 让 Java 开发者玩 AI 更丝滑

从普通聊天到流式交互,从角色设定到工具整合,再到 RAG 检索增强 ------Spring AI 把 AI 开发变成了 "Java 开发者熟悉的样子",不用再羡慕 Python 生态的各种 AI 库。

接下来你可以试试:把 RAG 的知识库换成 Elasticsearch,让 Tool Calling 对接更多业务接口(比如查库存、生成报表),甚至用 Spring Cloud 把 AI 服务做成微服务 ------ 玩法还有很多!

最后留个问题:你在项目里想给 AI 加什么功能?评论区聊聊~

相关推荐
码事漫谈1 天前
C++死锁深度解析:从成因到预防与避免
后端
码事漫谈1 天前
智能体颠覆教育行业:现状、应用与未来展望调研报告
后端
蓝-萧1 天前
【玩转全栈】----Django基本配置和介绍
java·后端
priority_key1 天前
排序算法:堆排序、快速排序、归并排序
java·后端·算法·排序算法·归并排序·堆排序·快速排序
韩立学长1 天前
基于Springboot的旧时月历史论坛4099k6s9(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
葡萄城技术团队1 天前
迎接下一代 React 框架:Next.js 16 核心能力解读
javascript·spring·react.js
汤姆yu1 天前
基于SpringBoot的动漫周边商场系统的设计与开发
java·spring boot·后端
灰小猿1 天前
Spring前后端分离项目时间格式转换问题全局配置解决
java·前端·后端·spring·spring cloud
RedJACK~1 天前
Go Ebiten小游戏开发:扫雷
开发语言·后端·golang
老夫的码又出BUG了1 天前
分布式Web应用场景下存在的Session问题
前端·分布式·后端