
在之前的文章中,我们搭建了基础版智能行程规划 Agent,但未具备记忆能力 —— 用户每次查询都需重复偏好信息(如 “不吃辣”“偏好人文景点”)。本文作为 Spring AI 系列的 Agent 进阶篇,将基于 Spring AI 的聊天记忆功能,为 Agent 新增记忆能力,使其能存储用户偏好、自动复用历史信息,让行程规划更个性化、更高效。
Agent 记忆是指智能体存储历史交互信息(如用户偏好、需求细节)的能力,无需用户重复输入即可在后续任务中自动复用。比如用户第一次查询时说明 “不吃辣”,后续再规划行程,Agent 会自动避开辣味餐饮推荐。
1.2 Agent记忆体系
Agent 的记忆机制可划分为短期记忆与长期记忆两类,二者协同支撑智能体的连续决策与个性化交互能力。
1.3 Agent记忆模式
各类 Agent 框架集成记忆系统时,虽具体实现方式存在差异,但均遵循相通的架构设计模式,理解这类通用模式,能为记忆系统的设计与落地提供有效指引。具体架构如下:

Agent 框架集成记忆系统通常遵循以下通用模式:
Step1:推理前加载 - 根据当前 user-query 从长期记忆中加载相关信息;
Step2:上下文注入 - 从长期记忆中检索的信息加入当前短期记忆中辅助模型推理;
Step3:记忆更新 - 短期记忆在推理完成后加入到长期记忆中;
Step4:信息处理 - 长期记忆模块中结合 LLM+向量化模型进行信息提取和检索;
1.4 长期记忆与 RAG 的区别
通过前文介绍,读者或许会发现 Agent 长期记忆系统与检索增强生成(RAG)存在较高相似性,又有哪些区别呢?
技术层面的相似点:
1. 向量化存储:都将文本内容通过 Embedding 模型转为向量,存入向量数据库;
2. 相似性检索:在用户提问时,将当前 query 向量化,在向量库中检索 top-k 最相关的条目;
3. 注入上下文生成:将检索到的内容注入到模型交互上下文中,辅助 LLM 生成最终回答;
虽然长期记忆和RAG 在技术成本有一些相似点,但二者在功能定位与适用场景上有着显著区别,具体如下:
对比条目 | RAG | 长期记忆 |
|---|---|---|
主要目的 | 为大模型提供外部知识,弥补训练数据的局限性(如时效性、专业性) | 为 AI Agent 记录并利用特定用户的历史交互信息,实现个性化、上下文连续的服务 |
服务对象 | 全体用户或任务 | 特定用户或会话主体(高度个性化) |
知识来源 | 结构化 / 非结构化文档(如 PDF、网页、数据库) | 用户与 Agent 的对话历史、行为日志等 |
userId 区分不同用户的记忆,互不干扰。技术模块 | 选项方案 |
|---|---|
开发框架 | Spring Boot 3.5.3 + Spring AI 1.0.0 |
大模型 | 智普 AI(Chat:GLM-4-Flash) |
核心依赖 | Spring Web、Spring AI 智普 AI Starter |
记忆组件 | MessageChatMemory + InMemoryChatMemoryRepository |
辅助工具 | Lombok(简化代码) |
ChatMemory接口指定存储介质和记忆窗口;MessageChatMemoryAdvisor 让 ChatClient具备记忆能力;userId(即 conversationId)隔离不同用户记忆;<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringAIAgentMemoryDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringAIAgentMemoryDemo</name>
<description>带记忆能力的 Spring AI Agent 入门案例</description>
<properties>
<java.version>17</java.version>
</properties>
<!-- 导入 Spring AI BOM 统一管理版本 -->
<dependencyManagement>
<<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</</dependencies>
</dependencyManagement>
<<dependencies>
<!-- Spring Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 智普 AI 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<!-- Lombok 依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</</dependencies>
<!-- 仓库配置 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>3. 配置 application.properties
# 应用基础配置
spring.application.name=SpringAIAgentMemoryDemo
server.port=8085
# 智普 AI 配置
spring.ai.zhipuai.api-key=你的智普 AI API Key
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas
spring.ai.zhipuai.chat.options.model=GLM-4-Flash
spring.ai.zhipuai.chat.options.temperature=0.7
# 日志配置(便于调试)
logging.level.org.springframework.ai=INFO
logging.level.com.example=DEBUG3.4 核心开发:配置记忆组件与 Agent 服务
1. 配置聊天记忆
创建 com.example.weizspringai.config.MemoryConfig 类,初始化记忆组件:
package com.example.springaiagentmemorydemo.config;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.InMemoryChatMemoryRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MemoryConfig {
/**
* 配置内存型聊天记忆:
* 1. 存储介质:InMemoryChatMemoryRepository(内存存储,适合测试)
* 2. 记忆窗口:最多保留 20 条消息(避免记忆过载)
*/
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.chatMemoryRepository(new InMemoryChatMemoryRepository()) // 内存存储
.maxMessages(20) // 最大记忆条数
.build();
}
}创建 com.example.weizspringai.service.MemoryTripAgentService 类,封装带记忆的行程规划能力:
package com.example.springaiagentmemorydemo.service;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class MemoryTripAgentService {
private final ChatClient chatClient;
private final ChatMemory chatMemory;
/**
* 带记忆的行程规划:通过 userId 关联用户记忆
* @param userId 用户唯一标识(隔离不同用户记忆)
* @param tripDemand 出行需求(可包含新需求或仅查询)
* @return 个性化行程规划
*/
public String planTripWithMemory(String userId, String tripDemand) {
// 定义带记忆的 Agent 行为规则:提取并复用用户偏好
String systemPrompt = """
你是带记忆的智能行程规划 Agent,核心规则如下:
1. 优先从历史对话中提取用户偏好(景点类型、饮食禁忌、交通方式、出行人数等);
2. 若用户未重复说明偏好,自动复用记忆中的信息;若有新偏好,覆盖旧记忆;
3. 行程按天/时段拆分,包含景点、交通、餐饮、实用提示,贴合用户偏好;
4. 语言简洁明了,结构清晰,无需重复用户已说明的偏好。
""";
// 构建带记忆的 ChatClient:通过 MessageChatMemoryAdvisor 注入记忆
ChatClient memoryChatClient = chatClient.builder()
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.defaultSystem(systemPrompt)
.build();
// 调用大模型:通过 conversationId(即 userId)关联用户记忆
return memoryChatClient.prompt()
.user(tripDemand)
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, userId)) // 用 userId 隔离记忆
.call()
.content();
}
/**
* 清除用户记忆(可选功能)
*/
public void clearUserMemory(String userId) {
chatMemory.clear(userId);
}
}创建com.example.weizspringai.controller.AgentController 类,提供 HTTP 接口:
package com.example.springaiagentmemorydemo.controller;
import com.example.springaiagentmemorydemo.service.MemoryTripAgentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/agent/trip")
@RequiredArgsConstructor
public class AgentController {
private final MemoryTripAgentService memoryTripAgentService;
/**
* 带记忆的行程规划接口
* @param userId 用户唯一标识(如 1001、1002)
* @param demand 出行需求
*/
@GetMapping("/plan-with-memory")
public Map<String, String> planTripWithMemory(
@RequestParam("userId") String userId,
@RequestParam("demand") String demand) {
String tripPlan = memoryTripAgentService.planTripWithMemory(userId, demand);
return Map.of(
"userId", userId,
"userDemand", demand,
"tripPlan", tripPlan,
"agentType", "带记忆的智能行程规划 Agent"
);
}
/**
* 清除用户记忆接口(可选)
*/
@DeleteMapping("/clear-memory")
public Map<String, String> clearMemory(@RequestParam("userId") String userId) {
memoryTripAgentService.clearUserMemory(userId);
return Map.of(
"userId", userId,
"message", "用户记忆已清除"
);
}
}访问接口:http://localhost:8080/agent/trip/plan-with-memory?userId=1001&demand=周末两天成都短途游,2人,偏好自然景点,不吃辣,交通以地铁和打车为主 。响应结果:
{
"userDemand": "周末两天成都短途游,2人,偏好自然景点,不吃辣,交通以地铁和打车为主",
"tripPlan": "根据您的历史偏好,我为您规划了以下成都周末两天短途游行程:\n\n**第一天:**\n\n- **上午**\n - 9:00 AM:乘坐地铁2号线至“人民公园”站,游览人民公园,体验成都的悠闲生活。\n - 11:00 AM:步行至“武侯祠”附近,品尝不辣的川味小吃,如担担面、甜水面等。\n\n- **下午**\n - 12:30 PM:前往“青羊宫”,参观古建筑,感受道教文化。\n - 2:30 PM:乘坐地铁4号线至“宽窄巷子”站,游览宽窄巷子,享受悠闲的下午时光。\n\n- **晚上**\n - 5:00 PM:在宽窄巷子附近寻找不辣的晚餐。\n - 7:00 PM:乘坐地铁4号线返回酒店休息。\n\n**第二天:**\n\n- **上午**\n - 9:00 AM:乘坐地铁3号线至“熊猫大道”站,游览成都大熊猫繁育研究基地,近距离观察大熊猫。\n\n- **下午**\n - 12:00 PM:在基地附近享用午餐,避免辣味。\n - 2:00 PM:乘坐地铁3号线至“杜甫草堂”站,参观杜甫草堂,了解唐代诗人杜甫的生活。\n\n- **晚上**\n - 5:00 PM:在草堂附近寻找不辣的晚餐。\n - 7:00 PM:根据返程时间,选择合适的交通方式返回酒店。\n\n**实用提示:**\n- 请随身携带雨具,成都天气多变。\n- 保持手机电量充足,以便导航和拍照。\n- 注意个人财物安全。\n\n希望这个行程符合您的喜好,祝您旅途愉快!",
"agentType": "带记忆的智能行程规划 Agent",
"userId": "1001"
}访问接口(用户 1001 二次查询,未重复偏好):http://localhost:8080/agent/trip/plan-with-memory?userId=1001&demand=下周工作日三天,再规划一次成都周边游 。响应结果:
{
"userDemand": "下周工作日三天,再规划一次成都周边游",
"tripPlan": "根据您之前提到的偏好,以下是为您规划的成都周边三天工作日游行程。此行程将优先考虑自然景点,避免辣味食物,并主要使用地铁和打车作为交通方式。\n\n**第一天:都江堰一日游**\n\n- **上午**\n - 8:00 AM:从成都出发,乘坐地铁2号线转乘成灌快铁至都江堰站。\n - 9:00 AM:抵达都江堰后,游览都江堰水利工程,了解中国古代水利建筑的智慧。\n\n- **中午**\n - 12:00 PM:在都江堰附近寻找不辣的川菜馆享用午餐。\n\n- **下午**\n - 1:30 PM:参观青城山,感受道教文化,攀登青城山,享受户外活动。\n\n- **傍晚**\n - 5:00 PM:下山后,返回成都市区。\n\n**第二天:峨眉山一日游**\n\n- **上午**\n - 7:00 AM:从成都出发,乘坐高铁至峨眉山站。\n - 8:00 AM:抵达峨眉山后,游览报国寺,了解寺庙文化。\n\n- **中午**\n - 12:00 PM:在峨眉山附近找一家不辣的餐厅用餐。\n\n- **下午**\n - 1:30 PM:游览峨眉山金顶,观赏云海和日出(视天气而定)。\n\n- **傍晚**\n - 5:00 PM:返回峨眉山站,乘坐高铁返回成都市区。\n\n**第三天:乐山大佛一日游**\n\n- **上午**\n - 7:00 AM:从成都出发,乘坐汽车或高铁至乐山站。\n - 8:00 AM:抵达乐山后,游览乐山大佛,欣赏世界最大的石刻佛像。\n\n- **中午**\n - 12:00 PM:在乐山城区寻找不辣的午餐。\n\n- **下午**\n - 1:30 PM:参观乐山大佛附近的乌尤寺,了解佛教文化。\n\n- **傍晚**\n - 5:00 PM:结束行程,返回成都市区。\n\n**实用提示:**\n- 由于峨眉山和乐山都在成都周边,建议提前规划好交通和住宿。\n- 高铁和汽车都是不错的选择,具体根据您的出发时间来决定。\n- 请随身携带个人必需品,如防晒霜、雨具等。\n- 由于峨眉山海拔较高,注意防寒保暖。\n\n希望这个行程能满足您的需求,祝您旅途愉快!",
"agentType": "带记忆的智能行程规划 Agent",
"userId": "1001"
}访问接口:http://localhost:8080/agent/trip/plan-with-memory?userId=1002&demand=周末一天重庆游,1人,喜欢人文景点,吃辣,地铁出行。响应结果(未复用用户 1001 的记忆,适配新偏好):
{
"userDemand": "周末一天重庆游,1人,喜欢人文景点,吃辣,地铁出行",
"tripPlan": "根据您的历史偏好,我为您规划了以下重庆一天的行程:\n\n**行程安排:**\n\n**上午:**\n- 9:00 AM - 江北观音桥步行街\n - 体验重庆的繁华商业区,品尝当地特色小吃,如酸辣粉、串串香等。\n\n**中午:**\n- 12:00 PM - 地铁2号线到解放碑站\n - 沿途欣赏重庆的老街风貌。\n- 12:30 PM - 解放碑小吃街\n - 尝试更多重庆特色美食,如辣子鸡、辣子牛蛙等。\n\n**下午:**\n- 2:00 PM - 重庆人民大礼堂\n - 参观这座具有重庆特色的人文建筑,了解其历史和建筑风格。\n\n**傍晚:**\n- 4:00 PM - 重庆洪崖洞\n - 沿着长江欣赏洪崖洞的夜景,感受重庆的夜景魅力。\n\n**晚餐:**\n- 7:00 PM - 长江索道\n - 在索道上享用晚餐,一边欣赏江景一边品尝重庆美食。\n\n**晚上:**\n- 8:30 PM - 重庆地铁3号线到磁器口站\n - 前往磁器口古镇,感受古街的历史韵味。\n\n**实用提示:**\n- 请注意地铁运营时间,确保有足够的时间在各个景点间移动。\n- 由于您喜欢辣食,建议在尝试当地美食时注意自己的口味承受能力。\n- 携带雨具,重庆天气多变,可能会有阵雨。\n\n希望这个行程能符合您的喜好,祝您在重庆有一个愉快的周末!",
"agentType": "带记忆的智能行程规划 Agent",
"userId": "1002"
}经功能测试验证,本方案实现的 Agent 记忆系统在实际应用中展现出良好的实用性与适配性,核心能力表现如下:
userId 区分记忆,不同用户偏好互不干扰;本文通过 Spring AI 的聊天记忆功能,为智能行程规划 Agent 新增了记忆能力,解决了 “重复输入偏好” 的痛点。Spring AI 封装了成熟的记忆组件,开发者无需关注底层存储细节,即可快速实现 Agent 的记忆功能,极大降低了开发门槛。
后续文章将继续深入 Agent 的高级特性,讲解如何集成工具调用(如调用天气 API 调整行程、调用预约 API 预订景点门票),实现 “规划 + 执行” 一体化的智能 Agent。
如果本文对你有帮助,欢迎点赞、在看、转发,关注我们获取更多 Spring AI 实战干货!