首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Spring AI 实战:聊天记忆之带记忆能力的智能行程规划 Agent 开发

Spring AI 实战:聊天记忆之带记忆能力的智能行程规划 Agent 开发

作者头像
章为忠学架构
发布2026-03-09 10:51:55
发布2026-03-09 10:51:55
1200
举报
文章被收录于专栏:AI大模型AI大模型

在之前的文章中,我们搭建了基础版智能行程规划 Agent,但未具备记忆能力 —— 用户每次查询都需重复偏好信息(如 “不吃辣”“偏好人文景点”)。本文作为 Spring AI 系列的 Agent 进阶篇,将基于 Spring AI 的聊天记忆功能,为 Agent 新增记忆能力,使其能存储用户偏好、自动复用历史信息,让行程规划更个性化、更高效。

一、Agent 记忆能力核心原理

1.1 什么是 Agent 记忆?

Agent 记忆是指智能体存储历史交互信息(如用户偏好、需求细节)的能力,无需用户重复输入即可在后续任务中自动复用。比如用户第一次查询时说明 “不吃辣”,后续再规划行程,Agent 会自动避开辣味餐饮推荐。

1.2 Agent记忆体系

Agent 的记忆机制可划分为短期记忆长期记忆两类,二者协同支撑智能体的连续决策与个性化交互能力。

  • 短期记忆:如同智能体的 “临时草稿纸”,负责实时记录当前对话上下文、任务推理步骤与中间执行轨迹,为单次任务的闭环运行提供即时数据支撑。
  • 长期记忆:类似检索增强生成(RAG)系统的核心知识库,能够跨会话持久化存储用户偏好、历史交互记录与任务经验,让智能体具备 “长效记忆” 能力,实现个性化服务的持续优化。

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 的对话历史、行为日志等

二、Spring AI 实现记忆的核心组件

Spring AI 提供了很多核心组件实现 记忆能力,比如:ChatMemory、 ChatMemoryRepository、MessageChatMemoryAdvisor等组件。

  • ChatMemory:记忆核心接口,定义了记忆的添加、获取、清除方法。
  • ChatMemoryRepository:记忆存储接口,负责实际存储聊天记忆,Spring AI 提供内存、JDBC、Redis 等实现,也支持自定义。
  • MessageChatMemoryAdvisor:记忆增强器,将聊天记忆以角色对话形式传递给大模型,确保上下文连贯。

三、【案例】开发带记忆能力的智能行程规划 Agent

3.1 案例目标

  1. 存储用户核心偏好:景点类型、饮食禁忌、交通方式、出行人数等。
  2. 自动复用记忆:用户后续查询时无需重复偏好,Agent 直接适配。
  3. 支持多用户隔离:通过 userId 区分不同用户的记忆,互不干扰。

3.2 技术选型

技术模块

选项方案

开发框架

Spring Boot 3.5.3 + Spring AI 1.0.0

大模型

智普 AI(Chat:GLM-4-Flash)

核心依赖

Spring Web、Spring AI 智普 AI Starter

记忆组件

MessageChatMemory + InMemoryChatMemoryRepository

辅助工具

Lombok(简化代码)

3.3 核心原理

  1. 带记忆能力的 Agent 核心开发流程:
    1. 配置记忆组件:通过ChatMemory接口指定存储介质和记忆窗口;
    2. 注入记忆增强器:MessageChatMemoryAdvisor 让 ChatClient具备记忆能力;
    3. 关联用户标识:通过userId(即 conversationId)隔离不同用户记忆;
    4. 定义 Agent 规则:通过系统提示词引导 Agent 提取、复用记忆。

3.4 项目初始化与配置

1. 创建 Spring Boot 项目
  • 项目名称:Weiz-SpringAI-Agent-Memory
  • JDK 版本:17
  • Spring Boot 版本:3.5.3
  • 核心依赖:Spring Web、Spring AI 智普 AI Starter、Lombok
2. 配置 pom.xml 依赖
代码语言:javascript
复制
<?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

代码语言:javascript
复制
# 应用基础配置
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=DEBUG

3.4 核心开发:配置记忆组件与 Agent 服务

1. 配置聊天记忆

创建 com.example.weizspringai.config.MemoryConfig 类,初始化记忆组件:

代码语言:javascript
复制
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();
    }
}
2. Agent 核心服务增加记忆功能

创建 com.example.weizspringai.service.MemoryTripAgentService 类,封装带记忆的行程规划能力:

代码语言:javascript
复制
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);
    }
}
3. 编写 Controller 提供接口

创建com.example.weizspringai.controller.AgentController 类,提供 HTTP 接口:

代码语言:javascript
复制
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", "用户记忆已清除"
        );
    }
}

3.5 系统测试与验证

测试 1:首次查询(存储用户偏好,用户 1001 首次查询,说明偏好)

访问接口:http://localhost:8080/agent/trip/plan-with-memory?userId=1001&demand=周末两天成都短途游,2人,偏好自然景点,不吃辣,交通以地铁和打车为主 。响应结果:

代码语言:javascript
复制
{
  "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"
}
测试 2:二次查询(自动复用记忆)

访问接口(用户 1001 二次查询,未重复偏好):http://localhost:8080/agent/trip/plan-with-memory?userId=1001&demand=下周工作日三天,再规划一次成都周边游 。响应结果:

代码语言:javascript
复制
{
  "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"
}
测试 3:多用户隔离(用户 1002 首次查询,不同偏好)

访问接口:http://localhost:8080/agent/trip/plan-with-memory?userId=1002&demand=周末一天重庆游,1人,喜欢人文景点,吃辣,地铁出行。响应结果(未复用用户 1001 的记忆,适配新偏好):

代码语言:javascript
复制
{
  "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"
}

3.6 测试结果分析

经功能测试验证,本方案实现的 Agent 记忆系统在实际应用中展现出良好的实用性与适配性,核心能力表现如下:

  • 记忆复用:用户二次查询无需重复偏好,Agent 自动适配,提升交互效率;
  • 多用户隔离:通过 userId 区分记忆,不同用户偏好互不干扰;
  • 灵活性:新查询可补充或覆盖旧偏好,记忆窗口(20 条)避免冗余;
  • 易用性:Spring AI 封装了记忆核心逻辑,无需手动管理上下文。

总结

本文通过 Spring AI 的聊天记忆功能,为智能行程规划 Agent 新增了记忆能力,解决了 “重复输入偏好” 的痛点。Spring AI 封装了成熟的记忆组件,开发者无需关注底层存储细节,即可快速实现 Agent 的记忆功能,极大降低了开发门槛。

后续文章将继续深入 Agent 的高级特性,讲解如何集成工具调用(如调用天气 API 调整行程、调用预约 API 预订景点门票),实现 “规划 + 执行” 一体化的智能 Agent。

如果本文对你有帮助,欢迎点赞、在看、转发,关注我们获取更多 Spring AI 实战干货!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师精进 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Agent 记忆能力核心原理
    • 1.1 什么是 Agent 记忆?
    • 二、Spring AI 实现记忆的核心组件
    • Spring AI 提供了很多核心组件实现 记忆能力,比如:ChatMemory、 ChatMemoryRepository、MessageChatMemoryAdvisor等组件。
  • 三、【案例】开发带记忆能力的智能行程规划 Agent
    • 3.1 案例目标
    • 3.2 技术选型
    • 3.3 核心原理
    • 3.4 项目初始化与配置
      • 1. 创建 Spring Boot 项目
      • 2. 配置 pom.xml 依赖
      • 2. Agent 核心服务增加记忆功能
      • 3. 编写 Controller 提供接口
    • 3.5 系统测试与验证
      • 测试 1:首次查询(存储用户偏好,用户 1001 首次查询,说明偏好)
      • 测试 2:二次查询(自动复用记忆)
      • 测试 3:多用户隔离(用户 1002 首次查询,不同偏好)
    • 3.6 测试结果分析
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档