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 加什么功能?评论区聊聊~

相关推荐
自由的疯3 小时前
Java Jenkins+Docker部署jar包
java·后端·架构
37手游后端团队3 小时前
揭秘ChatGPT“打字机”效果:深入理解SSE流式传输技术
人工智能·后端
自由的疯3 小时前
Java Jenkins、Dockers和Kubernetes有什么区别
java·后端·架构
aiopencode3 小时前
tcpdump 抓包内容分析实战,快速定位到结论的工程化套路(含真机抓包)
后端
用户673398017513 小时前
Docker部署单机版NacosV3.0版本并使用Nginx代理
后端
京东零售技术3 小时前
浅析cef在win和mac上的适配
后端
Java水解3 小时前
MySQL 中 ROW_NUMBER() 函数详解
后端·mysql
赋范大模型技术圈3 小时前
OpenAI Agent Kit 全网首发深度解读与上手指南
人工智能·openai
美团技术团队3 小时前
从0到1建设美团数据库容量评估系统
后端