Spring-AI初级使用记录 spring-ai-bom版本1.0.1-(单、多轮对话)

Spring-AI初级使用记录-(单、多轮对话)

Spring-AI官方文档:https://docs.spring.io/spring-ai/reference/api/chat/openai-chat.html
当前环境:

  • Spring AI version: 1.0.1
  • Spring Boot version: 3.5.4
  • Java version: 21.0.2
  • Maven version:无所谓,大多数都可以。

创建项目

1.创建SpringBoot项目:
在这里插入图片描述
点击下一步后添加相关依赖,不添加也行,后面在pom文件中可以自己配置。这里选择Open Ai和Web
在这里插入图片描述
创建完成后可以检查下pom文件,完整的pom文件如下(为了测试方便我多加了swagger,不需要可以去掉):

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--新版的Swagger,jdk17以后老版不能用了-->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.5.0</version> <!-- 或更高版本,如2.12.x -->
        </dependency>
    </dependencies>
    <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>

恭喜🎉至此项目就创建完了。

配置项目

2.开始配置yml,注意:completions-path这个属性不配置默认是/v1/chat/completions(根据自己实际情况修改)。

spring:
  ai:
    openai:
      api-key: XXXXXXXXXXX # 将这里替换为你自己的OpenAI API Key
      base-url: https://XXX.XXX.com # OpenAI API的基础URL
      chat:
        options:
        # 使用的模型,可根据需求更换
          model: deepseek-reasoner
          temperature: 0.7 # 控制生成文本的随机性,取值范围0 - 1,值越大越随机
        completions-path: /v2/chat/completions 

结束配置,开始编程。

单轮对话调用

编写测试案例:

@RestController
@RequestMapping("/ChatClient")
@Tag(name = "Spring-AI客户端")
public class AiController {

    //具体人设信息
    public static final String system="你是一个高中生,名字叫做小明,今年16岁,喜欢唱跳rap篮球。";

    //对话客户端
    private final ChatClient chatClient;
    
    //构造注入
    AiController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    @GetMapping("/chat")
    @Operation(summary = "同步调用")
    String chat(String userInput) {
        return this.chatClient.prompt()
                .advisors(new SimpleLoggerAdvisor()) //开启日志
                .system(system)  //人设
                .user(userInput)    //userMessage
                .call()    //同步调用
                .content();    
    }

    @GetMapping(value = "/chatStream",produces = "text/html;charset=utf-8")
    @Operation(summary = "流式调用")
    Flux<String> chatStream(String userInput) {
        return this.chatClient.prompt()
                .advisors(new SimpleLoggerAdvisor()) //开启日志
                .system(system)  //人设
                .user(userInput)    //userMessage
                .stream()    //流式调用
                .content();
    }
}

因为在pom文件中导入了Swagger,方便调试直接调用请求,经测试单轮对话同步、流式请求都测试成功。swagger默认地址:http://localhost:8080/swagger-ui/index.html

在这里插入图片描述

由于swagger中看不出来流式的效果,可以直接在浏览器中测试,会出现打字机效果。
(http://localhost:8080/ChatClient/chatStream?userInput=你吃饭了吗)
在这里插入图片描述

多轮对话调用

使用SpringAI加入记忆进行多轮对话测试

 @Autowired
    ChatMemoryRepository chatMemoryRepository;  //注入对话记忆

    @GetMapping("/chatMemory")
    @Operation(summary = "带记忆的同步调用")
    String chatMemory(String userInput) {
        // 1. 构建对话记忆存储配置
        // 使用MessageWindowChatMemory实现窗口记忆策略
        ChatMemory chatMemory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(chatMemoryRepository) // 底层记忆存储仓库(测试使用内存实现)
                .maxMessages(20)    // 设置历史消息最大保留轮次(滑动窗口大小)
                .build();

        // 2. 生成唯一会话ID(实际项目中由)
        String conversationId = "123456789"; // 示例固定值,生产环境需动态生成
        // 3. 构建对话请求并配置各组件
        return this.chatClient.prompt()
                // 3.1 设置对话角色
                .system(system)  // 系统角色设定(AI人设/指令)
                // 3.2 设置基础参数
                .advisors(
                        a -> a.param(ChatMemory.CONVERSATION_ID, conversationId) // 绑定当前对话ID到请求上下文
                )
                // 3.3 添加增强功能(Advisors)
                .advisors(
                        new SimpleLoggerAdvisor(),  // 启用请求日志记录(用于调试)
                        MessageChatMemoryAdvisor.builder(chatMemory).build(),   // 启用记忆管理功能
                        new SystemFirstSortingAdvisor() // 确保系统消息优先排序
                )
                // 3.4 设置当前用户输入
                .user(userInput)
                // 3.5 执行调用
                .call() // 发送同步请求到对话服务
                // 3.6 处理响应
                .content(); // 提取响应中的文本内容
    }


    @GetMapping(value = "/chatMemoryStream",produces = "text/html;charset=utf-8")
    @Operation(summary = "带记忆的流式调用")
    public Flux<String> generateStream(String userInput) {
        // 1. 构建对话记忆存储配置
        // 使用MessageWindowChatMemory实现窗口记忆策略
        ChatMemory chatMemory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(chatMemoryRepository) // 底层记忆存储仓库(测试使用内存实现)
                .maxMessages(20)    // 设置历史消息最大保留轮次(滑动窗口大小)
                .build();

        // 2. 生成唯一会话ID(实际项目中由)
        String conversationId = "123456789"; // 示例固定值,生产环境需动态生成
        // 3. 构建对话请求并配置各组件
        return this.chatClient.prompt()
                // 3.1 设置对话角色
                .system(system)  // 系统角色设定(AI人设/指令)
                // 3.2 设置基础参数
                .advisors(
                        a -> a.param(ChatMemory.CONVERSATION_ID, conversationId) // 绑定当前对话ID到请求上下文
                )
                // 3.3 添加增强功能(Advisors)
                .advisors(
                        new SimpleLoggerAdvisor(),  // 启用请求日志记录(用于调试)
                        MessageChatMemoryAdvisor.builder(chatMemory).build(),    // 启用记忆管理功能
                        new SystemFirstSortingAdvisor() // 确保系统消息优先排序
                )
                // 3.4 设置当前用户输入
                .user(userInput)
                // 3.5 执行调用
                .stream() // 发送流式请求到对话服务
                // 3.6 处理响应
                .content(); // 提取响应中的文本内容
    }

如上示例中有SystemFirstSortingAdvisor类需要单独便编写来确保系统人设始终保持在第一位(具体为什么要使用它,是因为1.0.1版本对Spring Ai多轮对话有BUG,可以参考这篇文章:https://blog.csdn.net/YnagLei/article/details/150619680?spm=1001.2014.3001.5502),内容如下:

/**
 * 保证SYSTEM在最前面的增强
 */
public class SystemFirstSortingAdvisor implements BaseAdvisor {
    @Override
    public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {
        List<Message> processedMessages = chatClientRequest.prompt().getInstructions();
        processedMessages.sort(Comparator.comparing(m -> m.getMessageType() == MessageType.SYSTEM ? 0 : 1));
        return chatClientRequest.mutate()
                .prompt(chatClientRequest.prompt().mutate().messages(processedMessages).build())
                .build();
    }

    @Override
    public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {
        return chatClientResponse; // no-op
    }

    @Override
    public int getOrder() {
        return 0; // larger than MessageChatMemoryAdvisor so it runs afterwards
    }
}

至此带记忆的多轮对话已编写完成,进行测试。
第一轮:你吃饭了吗?
在这里插入图片描述
第二轮:我刚问你什么了?
在这里插入图片描述
很明显模型已经知道咱们之前问的问题了,说明测试成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值