项目的使用软件版本:
<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>
- 在学习spring AI的chatMemery功能,在看到官方上提供了Spring AI 2.0.0-M3 提供官方的 Redis ChatMemory 支持,于是就尝试使用redis做为存储
- 在按照官方的样例进行时,发现报错,一直提示RedisChatMemoryRepository无法依赖注入,于是查看官方的issue github.com/spring-proj…
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. 测试接口,接口正常返回
7. 查看redis的信息,名显示有2个数据,但是使用命令只查询了一条"type": "USER",,丢失了一条数据 "type": "ASSISTANT",
8. 此刻我在问AI我喜欢什么,看看能不能把上述的2个消息都发给AI。虽然他的答案是对的,但是我们从后台看日志就看出了端倪,只找到一条User的数据,没有ASSISTANT的数据
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}"
10.我再次问AI我喜欢什么,看看能不能把上述的3个消息都发给AI,发送成功
- 于是我看了Spring ai的源码
schemaFields.add(new TextField("$.type").as("type"));
应该修改
schemaFields.add(new TagField("\$.type").as("type"));

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