图片

让Java开发者像写Spring Boot一样开发AI应用——第二阶段第四篇

写在前面

第九天,我们给Agent装上了“短时记忆”——它能在同一会话中记住“刚才说了什么”。

但还有一个更致命的问题:跨会话就“失忆”。

用户今天说“我喜欢喝美式咖啡,不加糖”,你记住了;明天用户打开新会话说“帮我推荐一杯咖啡”,你完全不记得昨天的事,又问一遍“您喜欢什么口味?”

这就像一个患有“跨天失忆症”的助理——每天上班都像第一天入职,昨天刚认识的人、刚了解的事,睡一觉全忘了。

今天,我们给Agent装上“长期记忆”——让它跨会话记住用户,实现真正的“越用越懂你”。

📌 本文是第二阶段“核心能力实战篇”的第四篇。前两篇我们解决了“动手”问题,第三篇解决了“会话内记忆”问题,今天解决“跨会话记忆”问题——让Agent从“一次性对话”走向“持续个性化服务”。

一、为什么需要长时记忆?

短时记忆的“天花板”

第九天我们学习的短时记忆,解决了“同一会话内”的上下文连贯问题。但它有三大天然局限:

| 局限

|

说明

|

示例

会话边界

会话结束,记忆消失

|

用户关掉浏览器再打开,Agent就“失忆”了

| | 窗口限制 |

受限于模型的Context Window

|

对话太长就会丢失早期信息

| | 无法跨会话 |

不同会话之间完全隔离

|

昨天的对话和今天的对话无法关联

|

一个真实的场景:

<span leaf="">第1天:用户说“我喜欢喝美式咖啡,不加糖”</span>

如果Agent有长时记忆:

<span leaf="">第2天:用户打开新会话说“帮我推荐一杯咖啡”</span>

💡 短时记忆让Agent记得“刚才说了什么”,长时记忆让Agent记得“你是谁、你喜欢什么、你之前说过什么”。前者像“便签纸”,后者像“日记本”。

二、长时记忆的核心原理

长时记忆的核心思想是:将对话中的关键事实提取出来,向量化后存入向量数据库,在新会话中通过语义检索召回相关记忆。

长时记忆 vs 短时记忆的本质区别

| 对比维度

|

短时记忆

|

长时记忆

存储内容

原始对话消息(逐条)

|

提取后的事实(结构化)

| | 检索方式 |

精确匹配(按threadId)

|

语义相似度检索

| | 生命周期 |

会话期间

|

永久(跨会话)

| | 容量 |

受上下文窗口限制

|

理论无限

| | 典型实现 |

MemorySaver / RedisSaver

|

向量数据库 + RAG

|

长时记忆不是简单地把所有对话历史存下来——那样会迅速撑爆上下文。它的精髓在于“提取-存储-检索”三步:

  1. 提取(Extract) :用LLM从原始对话中提取结构化事实

  2. 存储(Store) :将事实向量化后存入向量数据库

  3. 检索(Retrieve) :查询时通过语义相似度召回相关记忆

💡 原始消息“我要去旧金山旅行”被存储为结构化事实“用户计划去旧金山旅行”。这种归一化表示大幅提升了跨会话的检索准确率。

三、长时记忆与短时记忆的协同

在Spring AI Alibaba中,短时记忆和长时记忆各司其职,协同工作:

| | 短时记忆

|

长时记忆

职责

保障当前交互的连贯性与实时推理能力

|

实现个性化和持续学习

| | 管理方式 |

按threadId管理

|

按namespace/key存储

| | 存储内容 |

对话历史、系统指令、推理步骤

|

用户偏好、重要事实、学习到的经验

| | 技术架构 |

CheckpointSaver(Memory/Redis等)

|

向量数据库 + RAG

|

自动化协同机制

Spring AI Alibaba通过ModelHook / 拦截器实现了两种记忆的自动化协同:

<span leaf="">用户发送消息</span>

💡 开发者不需要手动管理记忆的读写——框架自动完成“读取记忆→注入上下文→调用模型→保存新记忆”的完整闭环。

四、RAG与长时记忆的关系

什么是RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)是一种克服大模型局限性(长文本、事实准确性、上下文感知)的技术。

RAG的核心流程:

<span leaf="">用户问题 → 向量检索 → 检索相关文档 → 注入上下文 → 模型生成回答</span>

💡 RAG的本质是“先查资料,再回答问题”——不是让模型硬答,而是先去知识库(向量数据库)里找到相关资料,再基于资料回答。

长时记忆 = 个性化的RAG

长时记忆和RAG用的是同一套技术栈,区别在于数据来源:

| | 传统RAG

|

长时记忆

数据来源

静态知识库(文档、手册)

|

动态对话历史(用户说过的话)

| | 数据更新 |

人工导入

|

自动从对话中提取

| | 检索目标 |

通用知识

|

个性化记忆

|

长时记忆本质上就是“个性化的RAG”——把用户的历史对话当作“知识库”,用RAG的方式检索和召回。

Spring AI Alibaba的RAG模块架构

Spring AI Alibaba提供了模块化的RAG架构:

方式一:Advisor API(开箱即用)

Spring AI提供了两个核心Advisor:

| Advisor

|

职责

QuestionAnswerAdvisor

查询向量数据库,检索相关文档,注入上下文

| | RetrievalAugmentationAdvisor |

支持更复杂的RAG流程(查询转换、查询扩展等)

|

方式二:自定义RAG流程

开发者可以自己构建完整的RAG管道:

  • DocumentReader:读取文档

  • Splitter:文档切分

  • Embedding:向量化

  • VectorStore:向量存储

  • Retriever:检索

五、向量数据库与Embedding

向量数据库的核心概念

向量数据库是一种专门用于存储和检索向量数据的数据库。与传统关系型数据库不同,向量数据库执行的是相似性搜索而非精确匹配。

工作流程:

  1. 将数据(文本)通过Embedding模型转换为向量

  2. 将向量存入向量数据库

  3. 用户查询时,将查询文本也转换为向量

  4. 在向量数据库中搜索与查询向量最相似的向量

  5. 返回最相似的文档作为上下文

Spring AI的VectorStore接口:

<span leaf=""><span>public</span>&nbsp;<span>interface</span>&nbsp;<span>VectorStore</span>&nbsp;<span>extends</span>&nbsp;<span>DocumentWriter</span>&nbsp;{</span>

SearchRequest的关键参数:

| 参数

|

说明

|

默认值

topK

返回最相似的前K个结果

|

4

| | similarityThreshold |

相似度阈值(0-1),低于阈值的结果被过滤

|

0.0

|

Spring AI Alibaba支持的向量数据库

Spring AI Alibaba集成了多种向量数据库实现:

| 向量数据库

|

说明

AnalyticDB PG

阿里云云原生数据仓库,支持向量检索

| | Redis |

内存数据库,支持向量检索

| | Elasticsearch |

分布式搜索分析引擎

| | MongoDB Atlas |

文档数据库,支持原生Vector Search

| | MariaDB Vector |

支持存储和搜索机器学习生成的嵌入

| | OceanBase |

分布式关系数据库,支持向量数据类型

| | Neo4j |

图数据库,支持向量检索

| | Milvus |

专门为向量检索设计的数据库

|

💡 本节课以AnalyticDB PG为例演示,因为它与Spring AI Alibaba集成最紧密,且阿里云提供了官方支持。

Embedding模型

Embedding(嵌入)是将文本转换为向量的过程。向量是文本的语义表示——语义相似的文本,其向量在空间中的距离也相近。

Spring AI Alibaba支持多种Embedding模型实现:

  • DashScope的Embedding模型(通义千问)

  • OpenAI的Embedding模型

六、实战:集成长时记忆

实战一:集成AnalyticDB PG实现长时记忆

目标:配置AnalyticDB PG作为长时记忆的向量存储,实现跨会话记忆。

Step 1:添加依赖

<span leaf=""><span>&lt;</span><span><span>properties</span></span><span>&gt;</span></span>

💡 以上依赖包目前可能尚未在Maven Central公开发布,需要联系阿里云获取。生产环境也可使用其他向量数据库(如Elasticsearch、PgVector)替代。

Step 2:配置文件

<span leaf=""><span>spring</span>:</span>

💡 namespace用于隔离不同用户或不同业务场景的记忆——可以按用户ID、组织ID或业务场景做层级隔离。

Step 3:使用AdbpgChatMemoryAdvisor

<span leaf=""><span>@Configuration</span></span>

Step 4:Controller实现

<span leaf=""><span>@RestController</span></span>

工作流程:

<span leaf="">用户发送消息</span>

实战二:使用QuestionAnswerAdvisor实现RAG

目标:将知识库文档向量化,实现基于RAG的智能问答。

Step 1:添加依赖

<span leaf=""><span>&lt;</span><span><span>dependency</span></span><span>&gt;</span></span>

Step 2:加载文档并向量化

<span leaf=""><span>@Service</span></span>

Step 3:使用QuestionAnswerAdvisor进行RAG问答

<span leaf=""><span>@RestController</span></span>

💡 QuestionAnswerAdvisor会自动执行“向量检索→注入上下文→生成回答”的完整流程。

实战三:长时记忆 + RAG = 个性化助手

目标:将长时记忆(用户历史对话)和RAG(知识库)结合,构建“越用越懂你”的个性化助手。

架构设计:

<span leaf="">用户提问</span>

核心代码:

<span leaf=""><span>@Configuration</span></span>

七、长时记忆的最佳实践

相似度阈值与TopK的调优

| 参数

|

推荐值

|

说明

similarityThreshold

0.6-0.8

|

太低会召回无关记忆,太高会漏掉相关记忆

| | topK |

3-5

|

记忆太多会污染上下文,太少会遗漏关键信息

|

命名空间设计

<span leaf=""><span>namespace</span>设计建议:</span>

短时记忆与长时记忆的协作策略

| 场景

|

策略

同一会话内

|

优先使用短时记忆(精确、快速)

| |

跨会话

|

使用长时记忆(持久、语义检索)

| |

信息冲突时

|

短时记忆优先(最新信息更可靠)

|

八、课后挑战

任务:实现一个“越用越懂你”的个性化助手

要求:

  1. 基于长时记忆(向量数据库 + RAG)实现跨会话记忆

  2. 集成一个知识库(可以是产品文档、FAQ等)

  3. 实现“记忆提取→向量存储→语义检索”的完整链路

  4. 支持多用户隔离(不同用户的记忆互不干扰)

验收标准:

  • 向量数据库已正确配置并启动

  • 第1天对话后,第2天新会话能召回之前的记忆

  • 知识库文档能正确向量化并检索

  • 不同用户的记忆完全隔离

九、本日核心收获

  1. 短时记忆有“天花板” ——会话边界、窗口限制、无法跨会话,长时记忆解决了这三个问题

  2. 长时记忆 = 个性化的RAG ——把用户的历史对话当作“知识库”,用RAG的方式检索和召回

  3. “提取-存储-检索”三步走 ——用LLM提取结构化事实→向量化存入向量库→查询时语义检索

  4. 两种记忆协同工作 ——短时记忆保障会话连贯性,长时记忆实现跨会话个性化

  5. Advisor机制实现自动化 ——beforeModel读取记忆、afterModel保存记忆,开发者无需手动管理

  6. 生产环境选型 ——AnalyticDB PG、Redis、Elasticsearch、Milvus等多种向量数据库可选

📌 本文是第二阶段“核心能力实篇”的第四篇。前两篇我们让Agent学会了“动手”,第三篇让Agent学会了“会话内记忆”,今天让Agent学会了“跨会话记忆”——从“一次性对话”走向“持续个性化服务”。下一篇,我们将进入多智能体协同的进阶实战,让多个Agent组成“组织”协同工作。

有任何问题,欢迎在评论区留言交流!


作者:Java老兵搞AI,专注Java生态下的AI应用开发

如果觉得有用,点个「在看」支持一下吧,下期见!