使用Spring AI配置聊天大模型实现人机交互(初阶)

1.创建一个基础项目

2.创建父子工程

2.1 父工程中引入spring boot

在父工程的pom文件中引入 spring-boot-starter-parent 。(也就是引入spring boot)

因为后续我引入的是spring-ai-bom 版本是2.0.1,所以我就引入4.1.1版本的spring boot。大家看完文章之后可以使用其他版本的spring ai看看有什么区别。

<!-- 加入spring boot -->

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>4.1.1</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

注意,我们后续将要引入 spring-ai-bom,这个依赖的每个版本,可能需要的spring boot版本要求是不一样的。例:Spring AI 2.0.x与Spring AI 1.1.8 它们分别支持的spring boot版本区间

官方:Spring AI

2.2 创建子工程

2.2.1 子工程引入spring ai

(把spring-ai-bom引入父工程也行,这样所有的子工程就都相当于引入了这个依赖)

子工程引入依赖:

(你或许不知道"spring-ai-starter-model-openai"这个依赖是干什么的,但没关系,下面会讲解)

复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--  引入OpenAI API 协议  -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

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

2.2.2 spring-ai-starter-model-openai

Spring AI 生态专门为OpenAI及兼容其API服务的大模型设计了**"spring-ai-starter-model-openai"**用于快速集成大语言模型能力到spring boot应用中。(如DeepSeek也兼容了OpenAI)

同一个文档页面往下话到底,就看到:

该依赖核心价值包括:

  • 简化配置:自动封装OpenAI API的请求和响应
  • 统一接口:提供ChatClient等标准化接口,支持无缝切换不同模型提供商
  • Spring 生态集成:与Spring Boot的自动配置、依赖注入等特性深度整合

核心价值解释:

1.简化配置:兼容了OpenAI API格式的模型都可以引入"spring-ai-starter-model-openai"后,通过配置文件(如application.yml)或代码 组装成一个OpenAI API格式的API请求。

以发送DeepSeek API请求为例。DeepSeek兼容了OpenAI API格式,因此可以在application.yml文件中配置如下:

上图中,我申请的DeepSeek的api-key配置到了环境变量中,你也可以把api-key直接粘贴,例api-key: sk-123...321

3. 构建API请求的原理

上图配置操作非常简单,但是为什么如这样简单的配置就构建了一个API请求?------你猜的没错!引入的**"spring-ai-starter-model-openai"**依赖使用了OpenAI API请求模板:

nitice:以DeepSeek官方示例为例。DeepSeek官方提供了一些配置选项,选择后,API请求就会在带有哪些配置。

2.统一接口 和 3.Spring 生态集成 这两价值现在不好直接体现,请直接看实战。

4. DeepSeek AI聊天实战(ChatModel)

  1. 配置聊天大模型后,在需要使用时,直接注入ChatModel(OpenAiChatModel实现了ChatModel。也可以一个构造ChatClient,后面讲)
  2. call(String)方法,把用户输入的信息(用户提示词)传给聊天大模型,大模型通过自己已有的知识,回答你。是对话式AI应用最核心的方法,通过call调用AI
java 复制代码
package com.jusheshen.ai.controller;

import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/deepseek")
@RestController
public class DeepSeekController {
    @Autowired
    private OpenAiChatModel dsChatModel; //注入DeepSeek的deepseek-v4-flash模型,因为yml配置的base-url是deepseek

    @RequestMapping("/chat")
    public String chat(String prompt){ //用户输入提示词
        String call = dsChatModel.call(prompt); //用户提示词传给大模型,模型处理后返回处理结果
        return call;
    }
}

1.notice:Spring AI给我们提供了许多可配置的选项:

2.notice :在Spring AI 1.0.0-M6及更早,starter 还叫"spring-ai-openai-spring-boot-starter",‌Spring AI 1.0.0-M7及之后版本改名叫"spring-ai-starter-model-openai"

随着Spring AI版本的改变,有一些工件ID也发生了变化,如果哪天依赖用着用着出错了,就来Upgrade Notes :: Spring AI Reference 看看是否发生改变。

3.notice: Spring AI已经为主流的模型供应商提供了单独的适配器,如DeepSeek可引入"spring-ai-starter-model-deepseek"。但更提倡引用"spring-ai-starter-model-openai",因为许多供应商兼容OpenAI API格式,在切换大模型时可以省掉部分替换依赖的时间。

如上述,如果想把DeepSeek的模型换成ChatGPT的话直接改base-url、model和api-key就行。(base-url不写都可以,ChatGPT本身就是OpenAI的模型,有默认的base-url)


5. ChatClient接口

  • ChatModel和ChatClient 是Spring AI框架构建对话式AI应用的两大核心接口,上面使用了ChatModel完成与AI模型的交互。接下来介绍ChatModel和ChatClient的区别。
  • ChatClient 对ChatModel进行了封装,ChatModel更接近底层(大模型),ChatClient提供给用户开箱即用的服务。ChatClient实现了Fluent API可链式调用,它还支持同步和异步调用大模型。

官方示例:Chat Client API :: Spring AI Reference

java 复制代码
@RestController
class MyController {

    private final ChatClient chatClient;
    
    //ChatClient.Builder就是ChatModel,替换成ChatModel 更直观
    public MyController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @GetMapping("/ai")
    String generation(String userInput) {
        return this.chatClient.prompt()//链式调用
            .user(userInput)
            .call()
            .content();
    }
}

下面我接着以DeepSeek模型为例,你也可以配置其他厂商的模型。

6. DeepSeek AI聊天实战(ChatClient)

6.1 实战1(系统提示词)

6.2 实战2(结构化输出)

上述AI返回信息没有固定格式,有时候信息冗余在一块。ChatClient允许自定义AI返回类型,以下面为例:

构建一个输入菜名,返回所需配料的AI。并且自定义菜谱类。

其实代码层面,我根本没和AI说食谱类的dish属性是什么意思,ingredients是什么意思,但AI就是知道把菜名赋给dish,配料赋给ingredients。可看出AI很聪明。

6.3 实战3(流式输出)

平时在其他平台与AI对话时,你可能注意注意到 AI回复的信息都是一个字一个字的往外蹦的。我上面与AI所有的交互都是等AI大模型处理、返回完,再全部信息返回给后端,接着再return给前端,这就导致在处理复杂问题时,用户在前端要面对一个白板很长时间,这体验感真是糟糕透了,所以下面实现流式输出。

notice:一定要设置编码,否则输出的就是中文乱码!

java 复制代码
@RequestMapping(value = "/stream",produces = "text/html;charset=utf-8")
    public Flux<String> stream(String message){
        return chatClient.prompt()
                .user(message)
                //调用AI 流式输出
                .stream()
                //返回数据
                .content();
    }

7. Advisors介绍

Spring AI中的Advisors是基于AOP思想实现的,Advisors类似于Spring中的拦截器。下图是Advisor的执行时机,这种链式处理机制确保了每个Advisor都会被执行。Advisor的核心功能 在于对请求进行拦截过滤增强, 帮助我们在API调用前后解决各种问题。

以SimpleLoggleAdvisor为例。

7.1 SimpleLoggleAdvisor

SimpleLoggleAdvisor是Spring AI内置的Advisor之一,主要用来打印日志。手动添加到Advisor链中,即可自动打印所有经过大模型的聊天请求和响应。


可以为每⼀次的对话设置advisor. 如果default也设置了同⼀类型的Advisor, 那么对话级别的优先级
⾼于default.


SimpleLoggleAdvisor效果展示:

对于SimpleLoggleAdvisor打印的日志级别,可以自定义,而且自定义的模板与spring boot一样。

复制代码
logging:
  level:
    org.springframework.ai.chat.client.advisor: debug
相关推荐
代码不停1 小时前
子序列问题
java·算法
计算机学姐1 小时前
基于SpringBoot的高校爱心慈善管理系统
java·vue.js·spring boot·后端·spring·tomcat·mybatis
大梦想家a1 小时前
基于Servlet+JSP的小区物业管理系统设计与实现(Bootstrap+MySQL)
java·servlet·bootstrap
都叫我大帅哥1 小时前
Apache Tika 4.0 正式发布:RAG 时代文件解析的终极答案
java·spring boot·spring
ZYJCSZKJ4 小时前
基于地理位置围栏的短视频POI团购系统:LBS空间索引与流量分发实践
java·服务器·数据库
mldong9 小时前
引擎从不发一条消息:jeeflow 的两类扩展点与消息模块的分工
java·架构
君顾110 小时前
智慧零售实战指南:从技术架构到落地方案全解析
java·开发语言·零售
zhanghe68710 小时前
es的密码带有特殊字符,导出
java
pnoker11 小时前
IoT DC3 概念解读:把设备抽象成一套语义模板——位号、指令、事件与面向智能体的设备建模
java·人工智能·物联网·iot·dc3