spring boot4+springAI 2加redis多轮对话存储

1、采用redis的方式进行存储,安装maven依赖

bash 复制代码
<!-- 模型:OpenAI 兼容 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-chat-memory-repository-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2、yml配置

bash 复制代码
spring:
  ai:
    openai:
      base-url: https://api.deepseek.com
      api-key: xxxxxx
      chat:
        temperature: 0.3
        model: deepseek-v4-flash

  data:
    redis:
      host: localhost
      port: 6379
      password: xxxxxx
      jedis:
        pool:
          max-active: 18
      database: 0

3、AI配置类

bash 复制代码
package com.example.web_service.tj.ai.config;

import com.example.web_service.tj.ai.service.IProjectTagQueryService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.redis.RedisChatMemoryRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.RedisClient;

import java.time.Duration;

@Configuration
public class AiConfig {

    @Value("${spring.data.redis.host}")
    private String redisHost;

    @Value("${spring.data.redis.port}")
    private int redisPort;

    @Value("${spring.data.redis.password}")
    private String redisPassword;

    @Bean
    public ChatMemory chatMemory() {
        RedisClient redisClient=RedisClient.create(redisHost, redisPort,null,redisPassword);
        RedisChatMemoryRepository repo=RedisChatMemoryRepository.builder()
                .jedisClient(redisClient)
                .keyPrefix("chat:memory:")
                .indexName("chat-memory-idx")
                .timeToLive(Duration.ofHours(2))
                .initializeSchema(true)
                .build();
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(repo)
                .maxMessages(20)
                .build();
    }


    @Bean
    public ChatClient chatClient(ChatClient.Builder builder,ChatMemory chatMemory, IProjectTagQueryService projectTagQueryService) {
        return builder
                .defaultSystem("""
                        我是一个物联网数据查询助手,支持以下能力:
                        ---
                        ## 能力1:查询1个或者多个点位/变量的当前值
                        触发词:点位、变量、当前值
                        参数:
                        - tagCodes: 点位列表(List<String>),如 ["forward", "reverse", "start"]
                        ---
                        
                        ---
                        ## 能力2:查询点位/变量的历史数据,指定时间范围,从.....到......
                        触发词:点位、变量、历史数据、时间范围
                        参数:
                        - tag: 点位/变量,如"forward"
                        - startDateTime: 开始时间,格式 yyyy-MM-dd HH:mm:ss,必须包含年月日时分秒,如 2026-09-01 08:00:00,如果分钟或者秒不存在,则都写成0
                        - endDateTime: 结束时间,格式 yyyy-MM-dd HH:mm:ss,必须包含年月日时分秒,如 2026-09-01 08:00:00,如果分钟或者秒不存在,则都写成0
                        ---
                        
                        """)
                .defaultTools(projectTagQueryService)//带入业务接口/类(对象)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
    }
}

其中IProjectTagQueryService projectTagQueryService是业务对象

4、控制器测试

bash 复制代码
@RestController
@RequestMapping("/businessAi")
public class BusinessAiController {
    @Resource
    @Lazy
    private ChatClient chatClient;

    @PostMapping("/chat")
    public ResultMap chat(@RequestBody Map<String,String> params) {
        String chatId="%s-%s".formatted(AuthUserUtils.getUser().getTenantId(),AuthUserUtils.getUser().getUserId());
        return ResultMap.SUCCESS.setNewData(chatClient.prompt()
                .advisors(v->v.param(ChatMemory.CONVERSATION_ID, chatId))
                .user(params.get("message"))
                .call()
                .content());

    }
}
相关推荐
Mr.敦的私房菜1 小时前
【SpringBoot请求记录】Spring Boot Actuator 自定义记录 HTTP 服务请求
spring boot·mvc·运维开发
java1234_小锋1 小时前
MyBatis-Plus 3.5.15 已全面支持 Spring Boot 4.0 及 Jackson 3.0
java·spring boot·mybatis
xixingzhe21 小时前
spring boot项目接口访问慢问题解决方案
java·数据库·spring boot
MetaLite1 小时前
SpringBoot整合FastJson2数据脱敏-接口日志与失败降级
java·spring boot·后端
xixingzhe21 小时前
SpringBoot 接口缓存实现
spring boot·后端·缓存
名字还没想好☜1 小时前
Go 时间格式化为什么用 2006-01-02:time.Format/Parse 的参考时间、时区与解析踩坑
开发语言·后端·golang·go
摇滚侠1 小时前
《SpringBoot 3:入门与应用实战》第 13 章 整合 MyBatis 使用 MyBatis-Plus 阅读笔记 40
spring boot·笔记·mybatis
jyOverQ4 小时前
RabbitMQ 消息积压怎么办?Prefetch、消费者并发与扩容
分布式·后端·rabbitmq
东风破_12 小时前
从跨域到 WebSocket:前端跨域方案、SSE 与双向实时通信详解
前端·后端