Java+AI 无缝衔接:Spring AI 聊天模型入门到精通


🔍 开发者资源导航 🔍
🏷️ 博客主页个人主页
📚 专栏订阅JavaEE全栈专栏

一、简介

Spring AI 是 Spring 官方专为 Java 开发者做 AI 项目的框架,简单、好上手,和平时写 Spring Boot 一模一样

它能干嘛

  • 快速对接各种大模型(ChatGPT、通义千问、文心一言、本地 Ollama 等)
  • 轻松实现聊天、总结、翻译、内容生成
  • 用自己的文档、知识库做智能问答(RAG)
  • 统一接口,换模型不用改大量代码
  • 完美兼容 Spring Boot、Spring Cloud 企业项目

学完能做什么

  • 做企业内部智能客服、AI 问答机器人
  • 给现有系统加 AI 功能:智能总结、自动文案、代码助手
  • 做基于私有文档的知识库 AI
  • 开发 Java 版 AI 应用、多模态小工具
  • 用 Java 栈快速进入 AI 开发,不用从头学新语言

本文将介绍Spring AI的聊天模型的使用。

参考文档:
Spring Ai官方文档https://docs.spring.io/spring-ai/reference/index.htmlSpring Ai API文档https://docs.spring.io/spring-ai/docs/智谱AI开放平台https://docs.bigmodel.cn/cn/guide/start/introduction

二、 前期准备

Spring AI支持很多家的AI,使用方法也很相似,本文将使用智谱AI来当做演示。

1. 创建Spring Boot项目

2. 配置pom文件(注意!不同平台的AI要配置的包不一样)

XML 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-model</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-zhipuai</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

3.官网申请APIKey

打开官网:智谱AI开放平台https://bigmodel.cn/usercenter/proj-mgmt/apikeys

点击右上角添加新的apikey:

4.配置application.yml文件(不同平台配置相似,但是名字不一样)

在resource目录下创建application.yml文件,填写以下以下配置:

XML 复制代码
spring:
  ai:
    zhipuai:
      api-key: 你的apikey
      chat:
        options:
          model: GLM-5 # 你要选择的模型

填写你的apikey,根据官方文档选择填写你需要的模型。

5.写一个小测试

java 复制代码
@RequestMapping("/ai")
@RestController
public class ChatController {
    @Autowired
    private ZhiPuAiChatModel chatModel;

    @GetMapping("/zp")
    public String zp(String message) {
        return chatModel.call(message);
    }
}

6.启动!访问本地链接进行测试

(注意!调用远程api反应会比较慢)

三、ChatClient

ChatClient是基于ChatModel进行的封装,相对于ChatModel来说它的使用会更加简单一些。

可以使用流式的方式来调用该类。

java 复制代码
    private final ChatClient chatClient;

    // chatClient初始化
    public ChatController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

	@GetMapping("/call")
    public String call(String message) {
        //也可以使用.prompt(message)省略user
        return chatClient
                //调用提示词
                .prompt()
                //设置用户提示词
                .user(message)
                //发起请求
                .call()
                //以文本方式返回
                .content();
    }

3.1 角色预设

将ChatClient创建的时候我们可以设置它的系统提示词,通过系统提示词可以实现模型的角色预设功能。

java 复制代码
    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory) {
        return chatClientBuilder
//不建议像我这样设置,会气死人的
                .defaultSystem("你是乐子人,不管我说什么,你都要冷嘲热讽我")
                .build();
    }

配置后我们再调用模型它就会带入我们提供的身份。

java 复制代码
    @Autowired
    private ChatClient chatClient;

    @GetMapping("/call")
    public String call(String message) {
        return chatClient.prompt().user(message).call().content();
    }

这块的可开发程度很高哦!!

3.2 结构化输出

通过 entity() ⽅法将模型输出转为⾃定义实体, 需确保输出格式符合JSON规范。

在转换的过程中AI会自动识别字段,并且塞入合适的字段当中(当然如果他不理解这个字段也会瞎填)

java 复制代码
@Data
public class Book {
    private String bookName;
    private String bookAuthor;
    private String bookISBN;
    private String result;
}
java 复制代码
    @GetMapping("/getBook")
    public String getBook() {
        return chatClient.prompt("帮我推荐一本2026年值得阅读的书籍,并告诉我原因")
                .call()
                .entity(Book.class).toString();
    }

3.3 流式输出

逐步生成,而不是一步直接出结果,这样可以提升响应时间,进而提升用户体验。

java 复制代码
    @GetMapping(value = "/stream",produces = "text/html;charset=utf-8")
    public Flux<String> stream(String message) {
        return chatClient
                .prompt()
                .user(message)
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, 1))
                .stream()
                .content();
    }

这里要设置字符类型,否则会出现乱码。

四、ChatModel

ChatModel 是Spring AI 框架中的底层接⼝, 直接与具体的⼤语⾔模型 (如通义千问、OpenAI) 交互,提供基础的 call 和 stream ⽅法, 开发者需⼿动处理提⽰词组装、参数配置和响应解析等细节,

在使⽤上相对更加灵活,但是也更复杂,上面讲过的ChatClient是基于ChatModel进行封装的。

java 复制代码
    @Autowired
    private ZhiPuAiChatModel chatModel;   

    @RequestMapping("/chatByPrompt")
    public String chatByPrompt(String message){
        Prompt prompt = new Prompt(message);
        ChatResponse response = chatModel.call(prompt);
        return response.getResult().getOutput().getText();
    }

功能相似,因此此处简要介绍一下代码。

4.1 角色预设

java 复制代码
    @GetMapping(value = "/role")
    public String role(String message) {
        SystemMessage systemMsg = new SystemMessage("你是⼀名英国⼈, 只会说英语");
        UserMessage userMsg = new UserMessage(message);
        Prompt prompt = new Prompt(List.of(systemMsg, userMsg));
        ChatResponse response = chatModel.call(prompt);
        return response.getResult().getOutput().getText();
    }

4.2 流式输出

java 复制代码
    @GetMapping(value = "/callByStream", produces = "text/html;charset=utf-8")
    public Flux<String> callByStream(String message) {
        Flux<ChatResponse> response = chatModel.stream(new Prompt(message));
        return response.map(x->x.getResult().getOutput().getText());
    }

五、ChatMemory

和模型的对话是单向无状态的,因此模型无法保存你之前的对话。

如果要实现"记忆"功能,你每次发送请求的时候需要将之前的对话记录也一并发给他,他才可以实现"记忆"。

而ChatMemory就是负责这个功能的,根据id记录并区分对话。

5.1 MessageWindowChatMemory

MessageWindowChatMemory是目前ChatMemory唯一的实现类(老版本还存在其他的)。

它会维护一个消息窗口,窗口大小不超过指定上限。当消息数量超过上限时,系统会删除较旧的消息,但会保留系统消息。默认窗口大小为 20 条消息。

java 复制代码
@Bean
public ChatMemory chatMemory() {
    MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
            .maxMessages(10)
            .build();
    return memory;
}

ChatMemory需要配置最大的消息数量,这里不建议设置太大,Token的花费容易爆炸。

常用的方法:

java 复制代码
    //添加消息
    void add(String conversationId, List<Message> messages);

    //获取该id下的所有消息
    List<Message> get(String conversationId);

    //请求该id的消息
    void clear(String conversationId);

创建成功后需要配置给ChatClient才能生效:

java 复制代码
    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory) {
        return chatClientBuilder
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
    }

在ai模型调用中,可以通过给 Advisor 传递参数,指定当前对话ID,来实现自动化存储。

java 复制代码
    @GetMapping(value = "/stream",produces = "text/html;charset=utf-8")
    public Flux<String> stream(String message) {
        return chatClient
                .prompt()
                .user(message)
                //这个1是id,实际中不要像我这样写死
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, 1))
                .stream()
                .content();
    }

5.2 存储方式

ChatMemory默认使用本地内存存储,服务器重启后信息就会丢失,ChatMemory可以配置到大多数主流的数据库当中,本文只介绍Mysql的配置方式:

引入额外的包

XML 复制代码
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>

配置ChatMemory

java 复制代码
    @Bean
    public ChatMemory chatMemory(JdbcChatMemoryRepository jdbcChatMemoryRepository) {
        MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
                .maxMessages(30)
                .chatMemoryRepository(jdbcChatMemoryRepository)
                .build();
        return memory;
    }

配置数据库信息

XML 复制代码
spring
  datasource:
    url: jdbc:mysql://localhost:3306/你的数据库?useSSL=false&serverTimezone=UTC
    username: 用户名
    password: 密码
    driver-class-name: com.mysql.cj.jdbc.Driver

手动创建数据库表

sql 复制代码
CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY (
    `conversation_id` VARCHAR(36) NOT NULL,
    `content` TEXT NOT NULL,
    `type` ENUM('USER', 'ASSISTANT', 'SYSTEM', 'TOOL') NOT NULL,
    `timestamp` TIMESTAMP NOT NULL,

    INDEX `SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX` (`conversation_id`, `timestamp`)
);

配置成功后再次启动发送的消息就会自动存储到该表里面。


Spring AI更新迭代比较快,不同版本的差异也比较大,如果发现本文与你实际体验不符合可以参考官方的文档。

相关推荐
惊鸿一博19 分钟前
自动驾驶的 BEV 特征(Bird’s Eye View Feature)
人工智能·机器学习·自动驾驶
Lyyaoo.1 小时前
【JAVA基础面经】JVM的内存模型
java·开发语言·jvm
杨凯凡1 小时前
【017】泛型与通配符:API 设计里怎么用省心
java·开发语言
IT利刃出鞘1 小时前
Spring工具类--ObjectUtils的使用
java·后端·spring
碳基硅坊1 小时前
Mac Studio M3 Ultra 运行大模型实测:Qwen3.6 vs 6款主流模型工具调用对比
人工智能·qwen·qwen3.6
TeDi TIVE8 小时前
开源模型应用落地-工具使用篇-Spring AI-高阶用法(九)
人工智能·spring·开源
MY_TEUCK8 小时前
Sealos 平台部署实战指南:结合 Cursor 与版本发布流程
java·人工智能·学习·aigc
三毛的二哥8 小时前
BEV:典型BEV算法总结
人工智能·算法·计算机视觉·3d
张忠琳8 小时前
【vllm】vLLM v1 KV Offload — 模块超深度逐行分析之一(七)
ai·架构·vllm
我爱cope8 小时前
【从0开始学设计模式-10| 装饰模式】
java·开发语言·设计模式