Java后端
·2025-10-13AI零代码生成平台第六期总结
1、第六期实现了对话历史的功能,此对话历史包括两部分,第一部分是将用户和AI的对话历史保存在数据库中,便于页面上回显。第二部分则是将对话历史和langchain4j进行整合,存储到redis中,便于AI理解上下文。
2、在展示对话历史时,分页采用的是游标分页的形式,传统的分页,是相对偏移,如果在查询的过程中,数据库中频繁发生新增或修改,那么可能会发生重复查询的问题。同时,在查询条数相同的场景下,页数越靠后,查询的效率就越低,因为要跳过前n页再去查m条。游标分页,是绝对偏移,如果主键ID是自增的(企业开发中很少用自增),那么自然推荐是用ID作为游标,因为ID不会重复并且有索引。在实际开发中,可以使用创建时间,或者专门的不会重复的排序字段作为游标。在查询时,也应该建立联合索引,伪代码:where 条件 = xxx and 游标 > xxx limit 每页展示多少条。
3、与AI的对话记忆,本项目中采用的是langchain4j整合redis,利用RedisChatMemoryStore类。在工厂类中,是给每一个应用ID,都创建了一个代理类的实例。同时引入了caffine本地缓存(因为项目目前是单体项目),key是appId,value是对应的AiCodeGeneratorService。整体流程,在获取AiCodeGeneratorService实例前,首先去caffine中查询,如果查询不到,就去新建。
4、在创建AiCodeGeneratorService对象时,需要从数据库中读取历史消息,保存到RedisChatMemoryStore中。在保存之前,需要清理掉RedisChatMemoryStore中的历史信息。能走到新建AiCodeGeneratorService对象这一步,说明有两种情况,第一是第一次创建了一个appId为1的caffine缓存,还有可能是之前appId为1的caffine缓存到期了,如果是后者,就体现出清理RedisChatMemoryStore中的历史信息的必要性。
这里有一个疑问:我第一次用appId为1的创建了一个MessageWindowChatMemory,第二次依旧用appId为1的创建了一个MessageWindowChatMemory,这两个MessageWindowChatMemory都不是同一个实例,为什么第二个MessageWindowChatMemory会有第一个的记忆?
答案是虽然是不同的实例,但是在创建时共享了同一个redisChatMemoryStore。redisChatMemoryStore是作为成员变量定义的。导致底层存储的数据被复用。
接下来完成第五期和第六期的扩展点,然后再继续向后学习
4
0
分享
操作
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
