接着前面的内容: https://blog.csdn.net/DavidSoCool/article/details/160857790

这次在构建ReactAgent的时候增加了SummarizationHook,用于摘要多轮历史对话,防止上下文超出大模型窗口

// 构建React Agent
        ReactAgent build = ReactAgent.builder()
                .name("ai_agent")
                .model(chatModel)
                .tools(new WeatherTool().toolCallback(), new SearchTool().toolCallback())
                .systemPrompt("""
                        你是一个博学的智能聊天助手,必须调用工具获取信息,不能编造答案。
                        调用工具后,根据结果回答用户。
                        """)
                // 添加对话记忆,使用redis保存对话记忆
                .saver(RedisSaver.builder().redisson(redissonClient).build())
                // 添加摘要钩子,用于对话摘要,防止对话过长超过模型窗口
                .hooks(SummarizationHook.builder()
                        .model(chatModel) // 专用摘要模型,这里用的同一个,可以换一个专门做摘要的模型
                        .maxTokensBeforeSummary(4000) // 触发阈值(模型窗口的70%)
                        .messagesToKeep(10) // 保留最近10轮原始对话
                        .build())
                .interceptors(messageFilterInterceptor)
                .build();

多次调用接口后,触发了历史对话摘要

使用的记忆存储方式是redis,发现下图中的key会一直增大,经过查资料得知,里面存着该会话所有的历史记录.

为什么用了SummarizationHook,Key 的大小还在涨?
这里面有坑:
1. SummarizationHook 不负责 “清理历史快照”
Hook 只做了一件事:把内存里的对话上下文压缩成摘要,让 LLM 后续请求只携带精简的上下文。
但它不会主动清理 Redis 里的历史检查点数据。Redis 里存的是每一轮对话的状态快照(每轮对话都会生成新的 checkpoint),这些旧快照不会被自动删除,只会越积越多。
简单说:Hook 帮你 “瘦身了当前会话的上下文”,但 Redis 里的 “历史快照档案” 还在持续堆积。
2. RedisCheckpointSaver 默认没有 TTL 过期策略
从截图里能看到,这个 Key 的 TTL 是 -1 永不过期,所有会话的检查点数据会永久驻留,最终导致 Redis 内存溢出。
GitHub 上也有相关 PR 专门解决这个问题:feat: add TTL configuration support for RedisSaver。

https://github.com/alibaba/spring-ai-alibaba/pull/4564

#4564 是在 2026 年 4 月 22 日 合并到 main 分支的,目前还没有办法使用.
3. 摘要数据本身也会持续增长
摘要只是把多轮对话压缩成了一段文本,但对话还在继续,每一轮新的交互都会生成新的状态快照, 里面包含最新的摘要 + 新消息。
摘要会随着对话轮次增加而不断变长,所以即使没有旧快照堆积,单个会话的 Key 大小也会缓慢增长。

总结:

        需要在使用redis时设置一个合理的时间或者在会话过期时主动删除它.

更多推荐