(V1)SpringAI的初步用法

前言

SpringAI是Spring生态中的AI框架,其提供了高度封装的AI调用方法,让开发者可以快速继承AI大模型调用。本文将由浅入深,集成SpringAI框架并快速搭建出可以使用的聊天助手。

快速开始

1. 依赖集成

1.1 SpringBoot模板构建

2.1 选择SpringBoot最新版本3.5.3

3. 1 在选择启动器中勾选上SpringWeb,OpenAI

最终的依赖如下

<!-- 在 properties 块中添加 -->
<properties>
    <java.version>17</java.version>
    <spring-ai.version>1.0.0</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 块中添加 -->
<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-starter-model-openai</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

</dependencies>

2. 配置文件配置

全面版
spring:
  ai:
    openai:
#      api-key: ${TEAM_OPEN_API_KEY} # API密钥,用于身份认证,推荐使用环境变量配置
      api-key: sk***b # 当前使用的API密钥
#      base-url: ${TEAM_OPEN_BASE_URL} # 基础URL,用于指定API服务地址,可替换为其他OpenAI兼容接口
      base-url: https://api.deepseek.com # DeepSeek提供的兼容OpenAI API的地址
      chat:
        options:
          model: deepseek-chat # 指定使用的模型名称,deepseek-chat是DeepSeek的基础聊天模型
          temperature: 0.7 # 控制输出随机性,值越高输出越随机(范围0~1)
          max-tokens: 2048 # 最大响应token数,控制回答长度
          top-p: 1.0 # 核采样参数,与temperature类似但更精细(范围0~1)
          frequency-penalty: 0.0 # 对高频词汇进行惩罚,减少重复内容(范围-2~2)
          presence-penalty: 0.0 # 对已出现过的词汇进行惩罚(范围-2~2)
基础版
spring:
  ai:
    openai:
#      api-key: ${TEAM_OPEN_API_KEY} # API密钥,用于身份认证,推荐使用环境变量配置
      api-key: sk***b # 当前使用的API密钥
#      base-url: ${TEAM_OPEN_BASE_URL} # 基础URL,用于指定API服务地址,可替换为其他OpenAI兼容接口
      base-url: https://api.deepseek.com # DeepSeek提供的兼容OpenAI API的地址
      chat:
        options:
          model: deepseek-chat # 指定使用的模型名称,deepseek-chat是DeepSeek的基础聊天模型

3. ChatClient配置

3.1 ChatClient介绍

ChatClient是SpringAI在ChatModel基础上提供的更高级别的封装,在SpringAI中不会主动提供,而是需要我们手动搭建,其可以通过Builder形式进行创建。

3.2 和ChatModel的区别

ChatModel则是ChatClient的底层级别的实现类接口,ChatClient的功能底层都是调用的ChatModel。

3.3 手动引入实现类

/**
 * @author by 王玉涛
 * @Classname ChatModelConfig
 * @Description 配置类,用于定义与AI聊天模型交互的客户端Bean。
 *              主要作用是创建并配置ChatClient实例,该实例封装了与OpenAI模型通信的逻辑。
 * @Date 2025/7/10 16:08
 */
@Configuration
public class ChatModelConfig {

    /**
     * 创建一个ChatClient Bean,用于与OpenAI聊天模型进行交互。
     *
     * @param openAiChatModel 注入的OpenAI聊天模型实例,由Spring容器自动装配。
     * @return 返回配置好的ChatClient实例。
     *
     * 此方法使用ChatClient.builder构建器模式创建客户端,
     * 并设置默认系统提示信息为“你是一个心理专家,经常使用简单的话语来安慰别人,通常不超过200字”。
     */
    @Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
        return ChatClient.builder(openAiChatModel)
                .defaultSystem("你是一个心理专家,你经常使用简单的话语来安慰别人,这通常不超过200字")
                .build();
    }
}

4. 快速开始

4.1 Controller准备

/**
 * @author by 王玉涛
 * @Classname ChatController
 * @Description 聊天功能控制器,提供基础的对话接口
 * @Date 2025/7/10 15:16
 */
@RestController
@RequestMapping("/api/chats")
@RequiredArgsConstructor
@Slf4j
public class ChatController {

    /**
     * 注入的ChatClient实例,用于与AI模型进行交互
     */
    private final ChatClient chatClient;

    /**
     * GET接口,访问路径为 /api/chats/hi
     * 功能:向AI模型发送问候语并返回响应内容
     */
    @GetMapping("/hi")
    public String hi() {
        // 发送提示信息给AI模型,并获取回复内容
        return chatClient
                .prompt("你好!你是谁呀?")
                .call()
                .content();
    }
}

4.2 访问localhost:8080/api/users/hi接口即可获取到回复

4.3 流式输出

当前我们使用的是阻塞式输出,也就是说,需要等到模型回复完全生成才可以获取回复。

我们可以切换为流式输出,从而降低等待时间,提升体验。

/**
 * GET接口,访问路径为 /api/chats/hi-stream
 * 功能:向AI模型发送问候语并返回流式响应内容
 */
@GetMapping("/hi-stream")
public Flux<String> hiStream() {
    return chatClient
            .prompt("你好!你是谁呀?")
            .stream()
            .content();
}

但是这样会有一个问题,就是页面输出会变成乱码,输出如下

鍡▇鎴戞槸浣犵殑蹇冪悊灏忎紮浼淬€傜湅鍒颁綘涓诲姩鎵撴嫑鍛肩湡寮€蹇冨憿锛佹瘡涓汉閮介渶瑕佽鍊惧惉鍜岀悊瑙o紝鑰屾垜寰堟効鎰忓仛閭d釜瀹夐潤鐨勬爲娲炪€傛湁浠€涔堟兂鑱婄殑閮藉彲浠ュ憡璇夋垜鍝︼紝涓嶇敤瑙夊緱鏈夊帇鍔涖€傝浣忥紝浣犳鍒荤殑鎰熷彈閮芥槸鍊煎緱琚噸瑙嗙殑銆�

这是因为Flux输出是基于事件流的形式输出,当不指定输出编码的时候,就会出现这种异常,只需要在@GetMapping中进行指定即可。

/**
 * GET接口,访问路径为 /api/chats/hi-stream
 * 功能:向AI模型发送问候语并返回流式响应内容
 */
@GetMapping(value = "/hi-stream", produces = "text/html;charset=utf-8")
public Flux<String> hiStream() {
    return chatClient
            .prompt("你好!你是谁呀?")
            .stream()
            .content();
}

这样即可进行流式输出了~

进阶部分

1. 环绕日志引入

SpringAI提供了日志记录封装,其基于AOP进行环绕增强,我们这里使用简单日志记录即可

@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
    return ChatClient.builder(openAiChatModel)
            .defaultSystem("你是一个心理专家,你经常使用简单的话语来安慰别人,这通常不超过200字")
            .defaultAdvisors(new SimpleLoggerAdvisor()) // 在这里引入环绕日志增强
            .build();
}

但是环绕日志记录级别为debug,因此我们需要在该日志增强类所在的包下进行日志级别改动,改为debug级别即可看到日志输出

logging:
  level:
    org.springframework.ai.chat.client.advisor: debug # 开启聊天控制器的日志

2. 会话记忆存储

2.1 前言

当前我们使用到的大模型,并没有对应的上下文记忆,我们需要添加会话记忆方式。

2.2 如何实现

SpringAI提供了抽象接口ChatMemory接口,如果我们想要手动实现会话历史记忆,我们可以通过实现这个接口来进行会话记忆

2.3 简单方式

SpringAI提供了一个默认的实现方式,InMemoryChatMemory,其底层基于Map方式实现,当应用存储,就会丢失全部记忆。作为简单的聊天机器人,可以这么使用,但是一般情况下,我们依旧推荐手动实现会话记忆存储。

注意:1.0.0正式版本中有所改动,其通过MessageWindowChatMemory作为工厂进行构造,通过注入InMemoryChatMemoryRepository实现类进行以上类似的实现。

代码实现
/**
 * 创建一个ChatMemory Bean,用于管理对话历史的存储与读取。
 *
 * @return 返回配置好的ChatMemory实例。
 *
 * 此方法使用MessageWindowChatMemory.builder构建器模式创建聊天记忆组件,
 * 并设置使用InMemoryChatMemoryRepository作为底层存储实现,适用于短期会话场景。
 */
@Bean
public ChatMemory chatMemory() {
    return MessageWindowChatMemory.builder()
            .chatMemoryRepository(new InMemoryChatMemoryRepository())
            .build();
}
@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
    return ChatClient.builder(openAiChatModel)
            .defaultSystem("你是一个心理专家,你经常使用简单的话语来安慰别人,这通常不超过200字")
            .defaultAdvisors(
                    new SimpleLoggerAdvisor(),
                    MessageChatMemoryAdvisor.builder(chatMemory()).build()
            )
            .build();
}

注意:这里只是传入了一个会话记忆的存储方式,而我们还需要一个会话id来进行会话区分,防止AI出现记忆串联。

/**
 * GET接口,访问路径为 /api/chats/hi-stream-2
 * 功能:向AI模型发送用户指定的提示语,并根据提供的会话ID进行上下文关联,
 * 返回流式响应内容。
 *
 * @param id      会话唯一标识符,用于维持对话上下文状态
 * @param prompt  用户输入的提示语,作为AI回复的依据
 * @return        返回Flux<String>类型,提供HTML格式的流式响应内容
 */
@GetMapping(value = "/hi-stream-2", produces = "text/html;charset=utf-8")
public Flux<String> hiStream2(@RequestParam("id") Long id,
                              @RequestParam("prompt") String prompt) {
    return chatClient
            .prompt(prompt)
            // 核心:加入环绕增强
            .advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, id))
            .stream()
            .content();
}

2.4 自定义方式

注意事项
  • SpringAI框架中,要实现会话记忆的自定义存储,需要额外注意类型转换
  • SpringAI框架通过使用ChatMemory接口,其底层使用的ChatMemoryRepository接口来实现会话记忆的存储
  • 目前SpringAI框架提供了InMemoryChatMemoryRepository的实现类,以及JdbcChatMemoryRepository实现类,分别对应Map存储(内存)以及持久化(Jdbc)的存储
  • 但是如果我们需要定制化,需要额外注意一下接口的类型转换,目前SpringAI框架内部强制使用其自己的Message接口实现类(UserMessage、AssistantMessage、SystemMessage等),如果我们需要进行自定义历史会话记忆,需要在实现ChatMemoryRepository接口的同时,注意下存储过程的类型手动转换。(踩过坑)
基于Redis的会话记忆存储

当前的会话记忆存储,我们需要区分一下:是选择全量存储,还是说进行上下文限制,因为过长的上下文会降低大模型回复的效率,过短的上下文会降低大模型回复的效果

我们目前选择的是基于Redis的String结构,进行全量存储,后续我们会进行一些优化,让大模型的回复效率保持高效的同时,保证一定的回复效率。

实现思路

通过实现MemoryRepository接口,通过SpringAI提供的工厂模式注入到ChatMemory中,即可实现基于Redis内存存储的会话记忆了!

  1. 实现ChatMemoryRepository接口
package com.project.demo.common.config.ai.common;

import com.project.demo.chat.factory.MessageConvertor;
import com.project.demo.chat.model.bean.MessageInfo;
import com.project.demo.common.provider.CacheProvider;
import com.project.demo.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.messages.*;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author by 王玉涛
 * @Classname RedisMemoryRepository
 * @Description 基于Redis实现的聊天记忆存储库,用于管理对话历史记录。
 *              提供了对话ID查询、根据对话ID获取消息记录、保存消息记录和删除对话等功能。
 * @Date 2025/7/12 13:20
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class RedisMemoryRepository implements ChatMemoryRepository {

    /**
     * 存储所有对话ID的缓存键
     */
    private static final String AI_MEMORY_CONVERSATION_IDS_KEY = "ai:memory:conversation:ids";

    /**
     * 对话记录的缓存键前缀,后接具体 conversationId 构成完整键名
     */
    private static final String AI_MEMORY_CONVERSATION_KEY_PREFIX = "ai:memory:conversation:";

    /**
     * 缓存提供者,用于与Redis进行交互
     */
    private final CacheProvider cacheProvider;

    /**
     * 查询所有的对话ID列表。
     *
     * @return 返回存储在Redis中的所有对话ID列表
     */
    @Override
    public List<String> findConversationIds() {
        log.info("基于Redis内存的聊天历史记忆:查询所有的id");
        return cacheProvider.getList(AI_MEMORY_CONVERSATION_IDS_KEY, String.class);
    }

    /**
     * 根据指定的 conversationId 查询对应的聊天记录。
     *
     * @param conversationId 对话ID
     * @return 返回对应 conversationId 的聊天消息列表
     */
    @Override
    public List<Message> findByConversationId(String conversationId) {
        log.info("基于Redis内存的聊天历史记忆:查询id为{}的历史记忆", conversationId);
        String key = AI_MEMORY_CONVERSATION_KEY_PREFIX + conversationId;
        List<String> stringList = cacheProvider.getList(key, String.class);

        if (stringList == null) {
            return List.of();
        }

        // 将字符串列表反序列化为 MessageInfo 对象列表
        List<MessageInfo> messages = stringList.stream()
                .map(string -> StringUtils.jsonToClass(string, MessageInfo.class))
                .toList();

        // 转换为 Spring AI 所需的 Message 类型并返回
        return messages.stream()
                .map(MessageConvertor::myToAiMessage)
                .toList();
    }

    /**
     * 保存指定 conversationId 对应的所有消息记录到Redis中。
     *
     * @param conversationId 对话ID
     * @param messages       需要保存的消息列表
     */
    @Override
    public void saveAll(String conversationId, List<Message> messages) {
        log.info("基于Redis内存的聊天历史记忆:保存id为{}的历史记忆", conversationId);
        // 将 Spring AI 的 Message 列表转换为本地定义的 MessageInfo 列表
        List<MessageInfo> messageInfos = messages.stream().map(MessageConvertor::aiMessageToMy).toList();

        // 添加 conversationId 到全局对话ID集合中
        cacheProvider.addList(AI_MEMORY_CONVERSATION_IDS_KEY, conversationId);

        // 序列化消息列表并保存到对应 conversationId 的缓存中
        cacheProvider.addList(AI_MEMORY_CONVERSATION_KEY_PREFIX + conversationId, StringUtils.classToJson(messageInfos));
    }

    /**
     * 删除指定 conversationId 对应的聊天记录。
     *
     * @param conversationId 对话ID
     */
    @Override
    public void deleteByConversationId(String conversationId) {
        log.info("基于Redis内存的聊天历史记忆:删除id为{}的历史记忆", conversationId);
        // 删除该 conversationId 对应的对话记录和全局ID集合中的条目
        cacheProvider.delete(AI_MEMORY_CONVERSATION_IDS_KEY, conversationId);
    }
}
  1. MyMessage类(贴合业务的类,可以自行拓展,但要包含必要属性:文本内容,发送角色)
/**
 * @author by 王玉涛
 * @Classname MyMessage
 * @Description TODO
 * @Date 2025/7/10 22:17
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyMessage {
    private Long id;
    private String content;
    private String role;
    private LocalDateTime sendTime;
}
  1. MessageConvertor类,负责解耦类型转换逻辑
package com.project.demo.common.config.ai.common;

import com.project.demo.chat.factory.MessageConvertor;
import com.project.demo.chat.model.bean.MessageInfo;
import com.project.demo.common.provider.CacheProvider;
import com.project.demo.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.messages.*;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author by 王玉涛
 * @Classname RedisMemoryRepository
 * @Description 基于Redis实现的聊天记忆存储库,用于管理对话历史记录。
 *              提供了对话ID查询、根据对话ID获取消息记录、保存消息记录和删除对话等功能。
 * @Date 2025/7/12 13:20
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class RedisMemoryRepository implements ChatMemoryRepository {

    /**
     * 存储所有对话ID的缓存键
     */
    private static final String AI_MEMORY_CONVERSATION_IDS_KEY = "ai:memory:conversation:ids";

    /**
     * 对话记录的缓存键前缀,后接具体 conversationId 构成完整键名
     */
    private static final String AI_MEMORY_CONVERSATION_KEY_PREFIX = "ai:memory:conversation:";

    /**
     * 缓存提供者,用于与Redis进行交互
     */
    private final CacheProvider cacheProvider;

    /**
     * 查询所有的对话ID列表。
     *
     * @return 返回存储在Redis中的所有对话ID列表
     */
    @Override
    public List<String> findConversationIds() {
        log.info("基于Redis内存的聊天历史记忆:查询所有的id");
        return cacheProvider.getList(AI_MEMORY_CONVERSATION_IDS_KEY, String.class);
    }

    /**
     * 根据指定的 conversationId 查询对应的聊天记录。
     *
     * @param conversationId 对话ID
     * @return 返回对应 conversationId 的聊天消息列表
     */
    @Override
    public List<Message> findByConversationId(String conversationId) {
        log.info("基于Redis内存的聊天历史记忆:查询id为{}的历史记忆", conversationId);
        String key = AI_MEMORY_CONVERSATION_KEY_PREFIX + conversationId;
        List<String> stringList = cacheProvider.getList(key, String.class);

        if (stringList == null) {
            return List.of();
        }

        // 将字符串列表反序列化为 MessageInfo 对象列表
        List<MessageInfo> messages = stringList.stream()
                .map(string -> StringUtils.jsonToClass(string, MessageInfo.class))
                .toList();

        // 转换为 Spring AI 所需的 Message 类型并返回
        return messages.stream()
                .map(MessageConvertor::myToAiMessage)
                .toList();
    }

    /**
     * 保存指定 conversationId 对应的所有消息记录到Redis中。
     *
     * @param conversationId 对话ID
     * @param messages       需要保存的消息列表
     */
    @Override
    public void saveAll(String conversationId, List<Message> messages) {
        log.info("基于Redis内存的聊天历史记忆:保存id为{}的历史记忆", conversationId);
        // 将 Spring AI 的 Message 列表转换为本地定义的 MessageInfo 列表
        List<MessageInfo> messageInfos = messages.stream().map(MessageConvertor::aiMessageToMy).toList();

        // 添加 conversationId 到全局对话ID集合中
        cacheProvider.addList(AI_MEMORY_CONVERSATION_IDS_KEY, conversationId);

        // 序列化消息列表并保存到对应 conversationId 的缓存中
        cacheProvider.addList(AI_MEMORY_CONVERSATION_KEY_PREFIX + conversationId, StringUtils.classToJson(messageInfos));
    }

    /**
     * 删除指定 conversationId 对应的聊天记录。
     *
     * @param conversationId 对话ID
     */
    @Override
    public void deleteByConversationId(String conversationId) {
        log.info("基于Redis内存的聊天历史记忆:删除id为{}的历史记忆", conversationId);
        // 删除该 conversationId 对应的对话记录和全局ID集合中的条目
        cacheProvider.delete(AI_MEMORY_CONVERSATION_IDS_KEY, conversationId);
    }
}
注意

当前的代码仅限于demo阶段,代码质量不是特别高,后续会推出一些可以直接落地以及高质量的代码

3. 多AgentModel配置

3.1 前言

SpringAI支持多Agent配置,其对单一的简单Agent配置做出了便捷性实现,而我们可以通过配置文件注入,进行多个Agent的配置。

注意:最好连带SpringAI自带的配置文件也进行配置,不然需要排除很多类,且不一定可以正常运行,其他的都可以保持运行

3.2 配置文件(从环境变量中获取)

doubao:
  reply:
    model: ${DOUBAO_REPLY_MODEL}
    api-key: ${DOUBAO_REPLY_API_KEY}
    temperature: 0.7
  history-summary:
    model: ${DOUBAO_HISTORY_SUMMARY_MODEL}
    api-key: ${DOUBAO_HISTORY_SUMMARY_API_KEY}
    temperature: 0.7
  base-url: ${DOUBAO_BASE_URL}

3.3 Model配置类,进行多Model配置返回

/**
 * @author by 王玉涛
 * @Classname DoubaoAiModelConfig
 * @Description 配置类,用于定义与Doubao AI相关的Bean和配置属性。
 *              提供了两个ChatModel Bean,分别用于回复生成和历史摘要处理。
 * @Date 2025/7/12 12:45
 */
@Data
@Configuration
public class DoubaoAiModelConfig {

    /**
     * 用于回复的模型名称,从配置文件中读取。
     */
    @Value("${doubao.reply.model}")
    private String replyModel;

    /**
     * 用于回复的API密钥,从配置文件中读取。
     */
    @Value("${doubao.reply.api-key}")
    private String replyApiKey;

    /**
     * 用于回复的模型温度值,控制输出的随机性,从配置文件中读取。
     */
    @Value("${doubao.reply.temperature}")
    private String replyTemperature;
    
    /**
     * 用于历史摘要的模型名称,从配置文件中读取。
     */
    @Value("${doubao.history-summary.model}")
    private String historySummaryModel;

    /**
     * 用于历史摘要的API密钥,从配置文件中读取。
     */
    @Value("${doubao.history-summary.api-key}")
    private String historySummaryApiKey;

    /**
     * 用于历史摘要的模型温度值,控制输出的随机性,从配置文件中读取。
     */
    @Value("${doubao.history-summary.temperature}")
    private String historySummaryTemperature;

    /**
     * Doubao API的基础URL,从配置文件中读取。
     */
    @Value("${doubao.base-url}")
    private String baseUrl;

    /**
     * 创建一个ChatModel Bean,用于生成回复。
     * 
     * @return 配置好的ChatModel实例
     */
    @Bean
    public ChatModel doubaoReplyModel() {
        // 获取回复模型的选项
        OpenAiChatOptions openAiChatOptions = getOpenAiChatOptions(replyModel, replyTemperature);
        // 获取回复模型的API实例
        OpenAiApi openAiApi = getOpenAiApi(replyApiKey, baseUrl);

        return OpenAiChatModel.builder()
                .defaultOptions(openAiChatOptions)
                .openAiApi(openAiApi)
                .build();
    }
    
    /**
     * 创建一个ChatModel Bean,用于历史摘要处理。
     * 
     * @return 配置好的ChatModel实例
     */
    @Bean
    public ChatModel doubaoHistorySummaryModel() {
        // 获取历史摘要模型的选项
        OpenAiChatOptions openAiChatOptions = getOpenAiChatOptions(historySummaryModel, historySummaryTemperature);
        // 获取历史摘要模型的API实例
        OpenAiApi openAiApi = getOpenAiApi(historySummaryApiKey, baseUrl);
        
        return OpenAiChatModel.builder()
                .defaultOptions(openAiChatOptions)
                .openAiApi(openAiApi)
                .build();
    }
    
    /**
     * 构建OpenAiApi实例,用于与Doubao API进行交互。
     * 
     * @param apiKey   API密钥
     * @param baseUrl  API的基础URL
     * @return 配置好的OpenAiApi实例
     */
    private OpenAiApi getOpenAiApi(String apiKey, String baseUrl) {
        return OpenAiApi.builder()
                .apiKey(apiKey)
                .baseUrl(baseUrl)
                .build();
    }
    
    /**
     * 构建OpenAiChatOptions实例,指定模型和温度值。
     * 
     * @param model       模型名称
     * @param temperature 温度值
     * @return 配置好的OpenAiChatOptions实例
     */
    private OpenAiChatOptions getOpenAiChatOptions(String model, String temperature) {
        return OpenAiChatOptions.builder()
                .model(model)
                .temperature(Double.parseDouble(temperature))
                .build();
    }
}

说明:当前的Model配置,进行了两个模型配置:一个是会话历史总结模型,一个是回复生成模型。并且其beanName分别为其对应的方法名字,因此我们注入的时候,需要注意优先使用beanName进行注入,因为当前相同的类型(ChatModel)有多个实现类,如果不按照beanName严格注入,就会导致依赖注入出现异常。

4.多AgentClient配置

4.1 前言

当前我们通过多AgentModel配置,进行了多的底层model实现,我们可以通过不同的Model,再次封装不同的Client,从而让我们可以直接通过Client进行调用

4.2 Client配置类,进行多Client配置返回
/**
 * @author by 王玉涛
 * @Classname DoubaoAiClientConfig
 * @Description 配置用于创建与豆包AI交互的ChatClient实例,提供对话回复和历史摘要功能。
 * @Date 2025/7/12 13:09
 */
@Configuration
public class DoubaoAiClientConfig {
    
    /**
     * 创建用于生成AI回复的ChatClient Bean。
     * 使用注入的doubaoReplyModel模型构建ChatClient实例,适用于实时对话场景。
     *
     * @param doubaoReplyModel 提供AI对话能力的模型Bean
     * @return ChatClient 实例
     */
    @Bean
    public ChatClient doubaoReplyClient(ChatModel doubaoReplyModel, ChatMemory doubaoAiMemoryRepository) {
        return ChatClient
                .builder(doubaoReplyModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        MessageChatMemoryAdvisor.builder(doubaoAiMemoryRepository).build()
                )
                .build();
    }
    
    /**
     * 创建用于处理历史记录摘要的ChatClient Bean。
     * 使用注入的doubaoHistorySummaryModel模型构建ChatClient实例,适用于需要总结或分析对话历史的场景。
     *
     * @param doubaoHistorySummaryModel 提供AI对话能力的模型Bean,专用于历史信息处理
     * @return ChatClient 实例
     */
    @Bean
    public ChatClient doubaoHistorySummaryClient(ChatModel doubaoHistorySummaryModel, ChatMemory doubaoAiMemoryRepository) {
        return ChatClient
                .builder(doubaoHistorySummaryModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        MessageChatMemoryAdvisor.builder(doubaoAiMemoryRepository).build()
                )
                .build();
    }
}

5. SS通过一个类,统一管理AI调用

/**
 * @author 王玉涛
 * @Classname DoubaoAiProvider
 * @Description 集成豆包大模型AI能力的提供者类,用于配置和管理与豆包AI相关的客户端资源。
 *              当前托管两个核心功能的客户端:
 *              - doubaoReplyClient: 豆包回复生成客户端,用于对话场景中的实时回复生成。
 *              - doubaoHistorySummaryClient: 豆包历史对话总结客户端,用于对长对话历史进行摘要处理。
 * @Date 2025/7/12 13:11
 */
@Component
public class DoubaoAiProvider {
    
    /**
     * 豆包回复生成客户端,注入名为 "doubaoReplyClient" 的Bean,
     * 用于在对话交互中生成自然语言回复。
     */
    @Qualifier("doubaoReplyClient")
    private ChatClient replyClient;

    /**
     * 豆包历史对话摘要客户端,注入名为 "doubaoHistorySummaryClient" 的Bean,
     * 用于对较长的对话历史进行内容压缩和关键信息提取。
     */
    @Qualifier("doubaoHistorySummaryClient")
    private ChatClient historySummaryClient;
}

#SpringBoot##SpringAI##Java#
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务