SpringAI智能助手案例

接下来,我们就利用SpringAI发起与大模型的第一次对话。

Java 领域 实现大模型开发(LLM),有两个非常重要的框架

SpringAI LangChain4J (4 four for)

SpringAI 最低支持的 jdk 版本是 17

LangChain4J 最低支持的版本是 8

1.1.快速入门

1.1.1.创建工程

创建一个新的SpringBoot工程,勾选Web、MySQL驱动即可:

1.1.2.引入依赖

SpringAI完全适配了SpringBoot的自动装配功能,而且给不同的大模型提供了不同的starter,比如:

|--------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| 模型/平台 | starter |
| Anthropic | <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-anthropic-spring-boot-starter</artifactId> </dependency> |
| Azure OpenAI | <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId> </dependency> |
| DeepSeek | <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> |
| Hugging Face | <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-huggingface-spring-boot-starter</artifactId> </dependency> |
| Ollama | <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> </dependency> |
| OpenAI | <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> |

我们可以根据自己选择的平台来选择引入不同的依赖。这里我们先以 OpenAI 为例。

首先,在项目pom.xml中添加spring-ai的版本信息:

<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>

然后,添加spring-ai的依赖管理项:

XML 复制代码
<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>
    </dependencies>
</dependencyManagement>

最后,引入spring-ai-openai 的依赖:

ollama 是一个软件,可以在ollama 下载各种大模型

XML 复制代码
<dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

为了方便后续开发,我们再手动引入一个Lombok依赖:

XML 复制代码
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
</dependency>

注意: 千万不要用start.spring.io提供的lombok,有bug!!

全部的完整的 pom 文件如下:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ruangong</groupId>
    <artifactId>SpringAIDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringAIDemo</name>
    <description>SpringAIDemo</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
        <spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>
    </properties>
    <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>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
1.1.3.配置模型信息

接下来,我们还要在配置文件中配置模型的参数信息。

以 openai 为例,我们将application.properties修改为application.yaml,然后添加下面的内容:

介绍一个网站,叫做硅基流动 https://www.siliconflow.cn/

接着需要实名认证(登录 注册)

充值,购买 API 的 key

选择一个适合自己的大模型

硅基流动:就是大模型的商店,里面有各种正在售卖的大模型可以被调用

将 application.properties 修改为 application.yml ,复制以下配置

复制代码
spring:
  application:
    name: ai-demo
  # Spring AI配置
  ai:
    openai:
      api-key: sk-qramtwqoiatggvuqzeihfesuxpaoeguqwprzdtgtaceajnfd
      base-url: https://api.siliconflow.cn
      chat:
        options:
          model: deepseek-ai/DeepSeek-V3
          temperature: 0.7
        completions-path: /v1/chat/completions
1.1.4.ChatClient

ChatClient中封装了与AI大模型对话的各种API,同时支持同步式或响应式交互。

不过,在使用之前,首先我们需要声明一个ChatClient

com.ruangong.ai.config包下新建一个CommonConfiguration

java 复制代码
package com.ruangong.springai.config;



import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CommonConfiguration {

    

    /**
     * 配置 ChatClient - OpenAI兼容的聊天客户端
     *
     * Spring AI 会自动扫描带有 @Tool 注解的方法,无需手动注册
     *
     * @param openAiChatModel OpenAI Chat模型(由Spring AI自动配置)
     * @param chatMemory 会话记忆存储
     * @return ChatClient 实例
     */
    @Bean("open-ai")
    public ChatClient openAIChatClient(
            OpenAiChatModel openAiChatModel,
            ChatMemory chatMemory) {
        return ChatClient.builder(openAiChatModel)
                .build();
    }
}

代码解读:

  • ChatClient.builder:会得到一个ChatClient.Builder工厂对象,利用它可以自由选择模型、添加各种自定义配置
  • OpenAiChatModel:如果你引入了 openai 的starter,这里就可以自动注入OpenAiChatModel对象。
1.1.5.同步调用

接下来,我们定义一个Controller,在其中接收用户发送的提示词,然后把提示词发送给大模型,交给大模型处理,拿到结果后返回

java 复制代码
package com.ruangong.springai.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class ChatController {

    private final ChatClient chatClient;
    // 请求方式和路径不要改动,将来要与前端联调
    @RequestMapping("/chat")
    public String chat(@RequestParam(defaultValue = "讲个笑话") String prompt) {
        return chatClient
                .prompt(prompt) // 传入user提示词
                .call() // 同步请求,会等待AI全部输出完才返回结果
                .content(); //返回响应内容
    }
}

请求地址:http://localhost:8080/ai/chat

注意,基于call()方法的调用属于同步调用,需要所有响应结果全部返回后才能返回给前端。

启动项目,在浏览器中访问:http://localhost:8080/ai/chat?prompt=你好

1.1.6.流式调用

同步调用需要等待很长时间页面才能看到结果,用户体验不好。为了解决这个问题,我们可以改进调用方式为流式调用。

在SpringAI中使用了WebFlux技术实现流式调用。

ChatController中添加chat2 方法

java 复制代码
// 注意看返回值,是Flux<String>,也就是流式结果,另外需要设定响应类型和编码,不然前端会乱码
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2(@RequestParam(defaultValue = "讲个笑话") String prompt) {
    return chatClient
    .prompt(prompt)
    .stream() // 流式调用
    .content();
}

重启测试,再次访问,会一点点生成数据展示在页面上。

1.1.7.System设定

可以发现,当我们询问AI你是谁的时候,它回答自己是DeepSeek-R1,这是大模型底层的设定。如果我们希望AI按照新的设定工作,就需要给它设置System背景信息。

在SpringAI中,设置System信息非常方便,不需要在每次发送时封装到Message,而是创建ChatClient时指定即可。

我们修改CommonConfiguration中的代码,给ChatClient设定默认的System信息:

java 复制代码
@Bean
    public ChatClient chatClient(OpenAiChatModel model) {
        return ChatClient.builder(model) // 创建ChatClient工厂实例
                .defaultSystem("您是一家专门做非遗产品的客户聊天助手,你的名字叫小一。请以友好、乐于助人和愉快的方式解答学生的各种问题。")
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build(); // 构建ChatClient实例

    }

我们再次询问"你是谁?"

1.1.8 上下文设定

假如你问它 假如你有12个苹果分给2个人,每人分几个?,它回答完了,你再问他 [ 分给三个人呢 ?] 它不知道要分配苹果,并且也不知道是 12 个苹果,说明当前的 chatAI 不具备了解上下文的能力?怎么办?

CommonConfig 添加如下方法:

java 复制代码
public static final Integer MAX_MEMORY_MESSAGE_SIZE = 30;

    /**
     * 配置 ChatMemory - 内存存储的会话记忆
     *
     * @return ChatMemory 内存存储的会话记忆实例
     */
    @Bean
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.builder()
                .maxMessages(MAX_MEMORY_MESSAGE_SIZE) // 窗口最大消息数目,保留最近30条消息
                .build();
    }

并且调用:

java 复制代码
@Bean("open-ai")
    public ChatClient openAIChatConfig(OpenAiChatModel openAiChatModel,ChatMemory chatMemory){
        return ChatClient.
                builder(openAiChatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory()).build())
                .build();
    }

然后重试,发现可行:

1.2.日志功能

默认情况下,应用于AI的交互时不记录日志的,我们无法得知SpringAI组织的提示词到底长什么样,有没有问题。这样不方便我们调试。

1.2.1.Advisor

SpringAI基于AOP机制实现与大模型对话过程的增强、拦截、修改等功能。所有的增强通知都需要实现Advisor接口。

Spring提供了一些Advisor的默认实现,来实现一些基本的增强功能

  • SimpleLoggerAdvisor:日志记录的Advisor
  • MessageChatMemoryAdvisor:会话记忆的Advisor
  • QuestionAnswerAdvisor:实现RAG的Advisor

当然,我们也可以自定义Advisor,具体可以参考:

https://docs.spring.io/spring-ai/reference/1.0/api/advisors.html#_implementing_an_advisor

1.2.2.添加日志Advisor

首先,我们需要修改CommonConfiguration,给ChatClient添加日志Advisor:

复制代码
@Bean("open-ai")
    public ChatClient openAIChatConfig(OpenAiChatModel openAiChatModel,ChatMemory chatMemory){
        return ChatClient.
                builder(openAiChatModel)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory()).build())
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }

之前已经添加过了。

1.2.3.修改日志级别

接下来,我们在application.yaml中添加日志配置,更新日志级别:

位置要顶格写,不要写在 spring 标签的下面

复制代码
logging:
  level:
    org.springframework.ai: debug # AI对话的日志级别
    com.ruangong.springai: debug # 本项目的日志级别

重启项目,再次聊天就能看到AI对话的日志信息了~

1.3.对接前端

在浏览器通过地址访问,非常麻烦,也不够优雅。如果能有一个优美的前端页面就好了。

别着急,我提前给大家准备了一个前端页面。而且有两种不同的运行方式。

1.3.1.npm运行

在资料中给大家提供了前端的源代码:

直接 npm run dev 即可启动

1.3.3.解决CORS问题

前后端在不同域名,存在跨域问题,因此我们需要在服务端解决cors问题。在 config 包中添加一个MvcConfiguration类:

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("Content-Disposition");
    }
}

重启服务,如果你的服务端接口正确,那么应该就可以聊天了。

注意 : 前端访问服务端 的默认路径是:http://localhost:8080

聊天对话的接口是:POST /ai/chat

请确保你的服务端接口也是这样。

恭喜您,你的第一个AI对话机器人就完成了。

相关推荐
Haooog21 小时前
RAG医疗问答系统
java·大模型·项目·rag
CoderJia程序员甲1 天前
GitHub 热榜项目 - 日榜(2026-1-9)
开源·大模型·llm·github·ai教程
喜欢吃豆1 天前
深度解析:FFmpeg 远程流式解复用原理与工程实践
人工智能·架构·ffmpeg·大模型·音视频·多模态
_OP_CHEN1 天前
【Coze智能体开发】(二)从 0 到 1 精通 Coze 智能体开发:基础到实战全攻略,新手也能快速上手!
人工智能·大模型·大语言模型·模型优化·扣子平台·智能体开发·智能体调试
Haooog1 天前
Spring AI 与 LangChain4j 对比
人工智能·大模型·springai·langchain4j
MonkeyKing_sunyuhua2 天前
大模型常见的专用名词
大模型
大模型真好玩2 天前
大模型训练全流程实战指南(一)——为什么要学习大模型训练?
人工智能·pytorch·python·大模型·deep learning
悟乙己2 天前
使用TimeGPT进行时间序列预测案例解析
机器学习·大模型·llm·时间序列·预测
数据饕餮2 天前
提示词工程实训营09- 4.2 风格模仿与调整——从“千篇一律“到“风格百变“的AI魔法
大模型·提示词工程