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());

    }
}
相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
大勇前进3 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
vipxieliang3 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
yuzhi_liu3 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile3 天前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白803 天前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端
二月龙3 天前
PHP 接口返回统一响应封装,让前后端对接更省心
后端