Spring AI 使用RedisChatMemoryRepository的坑

30 阅读2分钟

项目的使用软件版本:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.4</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <java.version>21</java.version>
    <spring-ai.version>2.0.0-M3</spring-ai.version>
</properties>

<!-- 注意:Spring AI 2.0.0-M3 提供官方的 Redis ChatMemory 支持 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-redis</artifactId>
</dependency>
  1. 在学习spring AI的chatMemery功能,在看到官方上提供了Spring AI 2.0.0-M3 提供官方的 Redis ChatMemory 支持,于是就尝试使用redis做为存储

image.png

  1. 在按照官方的样例进行时,发现报错,一直提示RedisChatMemoryRepository无法依赖注入,于是查看官方的issue github.com/spring-proj…

image.png

image.png

3.于是采用其他的方案解决,手动注入JedisPooled(这里注意只能使用jedis的连接池,因为我们要使用redis stack),而不是redis

@Bean
public ChatMemory chatMemory() {
    JedisPooled jedisClient = new JedisPooled("localhost", 6379);

    ChatMemoryRepository redisChatMemoryRepository = RedisChatMemoryRepository.builder()
            .jedisClient(jedisClient)
            .indexName("my-chat-index").initializeSchema(true)
            .keyPrefix("my-chat:")
            .timeToLive(Duration.ofHours(24))
            .build();

    return MessageWindowChatMemory.builder()
            .chatMemoryRepository(redisChatMemoryRepository)
            .maxMessages(20) // 保留最近20条消息
            .build();
}

@Bean

ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {
    ChatClient chatClient = ChatClient.builder(chatModel).
            defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build(),
                    new SimpleLoggerAdvisor()).defaultSystem("我是的AI助手").build();
    return chatClient;
}

4. 然后启动项目,项目正常启动。配置文件

spring.application.name=AI-Demo
spring.ai.openai.api-key=sk-xxxx
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.options.model=deepseek-chat
server.port=8080
management.endpoints.web.exposure.include=health,metrics,prometheus
spring.ai.chat.observations.log-completion=true
spring.ai.chat.observations.log-prompt=true
#????????SimpleLoggerAdvisor??????
logging.level.org.springframework.ai.chat.client.advisor=debug
logging.level.org.springframework.ai.chat.memory.repository.redis=debug
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.database=0
spring.data.redis.timeout=5000ms
spring.ai.chat.memory.redis.host=localhost
spring.ai.chat.memory.redis.key-prefix="chat:memory:"
spring.ai.chat.memory.redis.initialize-schema=true

6. 写了一个简单的controller

/**
 * 会话记忆
 */
@RestController
@RequestMapping("/memory")
public class MemoryrController {

    @Autowired
    ChatClient chatClient;

    /**
     *
     * @param msg
     * @param sessionId
     * @return
     */
    @GetMapping("/chat")
    public String chat(@RequestParam("msg") String msg,@RequestParam("sessionId") String sessionId){
        String content = this.chatClient.prompt().user(msg).
                advisors(a -> a.param(ChatMemory.CONVERSATION_ID, sessionId))
                .call().content();
        return content;
    }


}

6. 测试接口,接口正常返回

image.png 7. 查看redis的信息,名显示有2个数据,但是使用命令只查询了一条"type": "USER",,丢失了一条数据 "type": "ASSISTANT",

image.png

image.png 8. 此刻我在问AI我喜欢什么,看看能不能把上述的2个消息都发给AI。虽然他的答案是对的,但是我们从后台看日志就看出了端倪,只找到一条User的数据,没有ASSISTANT的数据

image.png

image.png

image.png 9. 于是继续排除,使用AI给出的答案是创建的索引有问题,于是重新使用命令的方式重新创建索引

# 一键修复
redis-cli FT.DROPINDEX my-chat-index
redis-cli FT.CREATE my-chat-index ON JSON PREFIX 1 "my-chat:" SCHEMA $.conversation_id AS conversation_id TAG $.type AS type TAG $.content AS content TEXT $.timestamp AS timestamp NUMERIC SORTABLE

# 验证
redis-cli FT.SEARCH my-chat-index "@conversation_id:{1}"

image.png

10.我再次问AI我喜欢什么,看看能不能把上述的3个消息都发给AI,发送成功

image.png

image.png

image.png

  1. 于是我看了Spring ai的源码
schemaFields.add(new TextField("$.type").as("type"));
应该修改
schemaFields.add(new TagField("\$.type").as("type"));


![image.png](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/f442d367d7f640c38dc93f379be0f72f~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5bCP5qOL5a2QMDA2:q75.awebp?rk3s=f64ab15b&x-expires=1776848506&x-signature=1fu%2FRRiaPL0eaBbbzW7vYZbdKrw%3D)

13. 于是我给你了Spring AI提了一个问题单,不晓得spring团队的思考点<https://github.com/spring-projects/spring-ai/issues/5670>

![image.png](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/cb2439d8afbd4eb587318e2933c3d7df~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5bCP5qOL5a2QMDA2:q75.awebp?rk3s=f64ab15b&x-expires=1776848506&x-signature=nlVtfjzhqZRELjsu89gNmgSP%2Fdo%3D)