> 自媒体 > (AI)人工智能 > Spring AI[05]:聊天记忆(Chat Memory)—让 AI 记住上下文
Spring AI[05]:聊天记忆(Chat Memory)—让 AI 记住上下文
来源:kaiwill
2025-11-12 11:39:34
89
管理

CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY ( `conversation_id` VARCHAR(36) NOT NULL, `content` TEXT NOT NULL, `type` ENUM('USER', 'ASSISTANT', 'SYSTEM', 'TOOL') NOT NULL, `timestamp` TIMESTAMP NOT NULL, INDEX `SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX` (`conversation_id`, `timestamp`));

字段

类型

说明

conversation_id

VARCHAR

会话 ID(如用户 ID)

type

ENUM

类型:USER,ASSISTANT,SYSTEM,TOOL

content

TEXT

消息内容

timestamp

TIMESTAMP

创建时间

此时只需要在数据库中执行这个脚本即可。

还有一种方式就是在配置文件中,指定schema在项目启动的时候,让它自动创建。

spring: ai: chat: memory: repository: jdbc: initialize-schema: always # 自动建表 schema: classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-mysql.sql

这里我们采用手动创建的方式。

5.5 Advisor核心机制

有了记忆窗口和记忆存储,还需要将这些存储起来的记忆作为 Prompt消息发送给大模型,所以Spring AI 创建了 Advisor机制。

真正让 AI 在每次调用时自动携带上下文 的关键组件是 **Advisor** —— 它是 Spring AI 中用于增强 Prompt 的核心设计模式。

5.5.1 什么是Advisor? 它解决了什么问题?

通俗理解:AI 对话的“上下文注入器”

你可以把 Advisor 想象成一个“智能助手”,它在你每次向 AI 发送请求前,自动帮你做几件事:

“这个用户之前聊过什么?”“要不要把之前的对话加到这次请求里?”“怎么组织这些信息才最有效?”

Advisor 就是负责这些逻辑的组件。它会在 ChatClient 发送请求前,自动修改 Prompt,加入必要的上下文信息。

5.5.2 BaseChatMemoryAdvisor

BaseChatMemoryAdvisor这个聊天记忆的 Advisor 接口,这个接口其实是 Advisor的子接口,它有两个实现类MessageChatMemoryAdvisor和 PromptChatMemoryAdvisor. 下面的类图中省略了 Advisor接口

MessageChatMemoryAdvisor:以消息形式注入上下文。这是最直观的记忆方式 —— 将历史对话作为 消息列表 注入,LLM 会看到完整的对话历史,自然能记住上下文。

[用户输入] → [Advisor 查找历史消息] → [构造完整消息链] → [发送给 LLM]例如:[ {"role": "user", "content": "我叫小明"}, {"role": "assistant", "content": "你好,小明!"}, {"role": "user", "content": "我昨天去了北京"}]PromptChatMemoryAdvisor:以系统提示词形式注入。这种方式不把历史作为“消息”,而是将其拼接到 系统提示词(System Prompt) 中。

系统提示:你是我的助手。以下是我们的对话历史:"用户:我叫小明""AI:你好,小明!"---当前问题:我昨天去了北京5.6 实战:构建一个支持多种记忆策略的聊天系统

本小节将构建一个多种记忆的聊天系统。本次将使用MySQL 数据库来存储历史聊天记录,所以需要按照 5.4 小节的描述,引入依赖和配置,以及创建数据库表.

5.6.1 记忆存储仓库。

本次使用的是spring-ai-starter-model-chat-memory-repository-jdbc,前面提到,org.springframework.ai.model.chat.memory.repository.jdbc.autoconfigure.JdbcChatMemoryRepositoryAutoConfiguration自动配置中已经配置了bean:

public class JdbcChatMemoryRepositoryAutoConfiguration { ... @Bean @ConditionalOnMissingBean JdbcChatMemoryRepository jdbcChatMemoryRepository(JdbcTemplate jdbcTemplate, DataSource dataSource) { JdbcChatMemoryRepositoryDialect dialect = JdbcChatMemoryRepositoryDialect.from(dataSource); return JdbcChatMemoryRepository.builder().jdbcTemplate(jdbcTemplate).dialect(dialect).build(); } ...}5.6.2 记忆

ChatMemory自动配置类 org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration配置了 ChatMemory 这个Bean,我们可以自己写一个配置,让ChatMemory这个Bean使用 JdbcChatMemoryRepository

// chapter05/src/main/java/com/kaifamiao/chapter05/configuration/ChatMemoryConfiguration.javapublic class ChatMemoryConfiguration { // 让ChatMemory 使用 JdbcChatMemoryRepository @Bean ChatMemory chatMemory(JdbcChatMemoryRepository chatMemoryRepository) { return MessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository).build(); }}5.6.3 记忆advisor

创建一个Controller,在Controller中创建 advisor, 并配置到 chatClient中:

// chapter05/src/main/java/com/kaifamiao/chapter05/MemoryController.java@RestControllerpublic class MemoryController { private final ChatClient chatClient; @Autowired public MemoryController(ChatClient.Builder chatClientBuilder , ChatMemory chatMemory) { // 通过不同角色Message方式传递聊天记忆 Advisor chatMemoryAdvisor = MessageChatMemoryAdvisor.builder(chatMemory).build(); // 通过提示词的方式传递聊天记忆 //Advisor promptChatMemoryAdvisor = MessageChatMemoryAdvisor.builder(chatMemory).build(); this.chatClient = chatClientBuilder // 通过Advisors设置聊天记忆 .defaultAdvisors(chatMemoryAdvisor) .build(); } /** * @param question 问题 * @param conversationId 聊天记忆的id */ // http://localhost:8080/chat/memory?question=我是小明,为我推荐10部周星驰的电影&conversationId=1001 @GetMapping(value = "/chat/memory", produces = "text/html;charset=UTF-8") public Flux memory(@RequestParam(value = "question", required = true) String question , @RequestParam(value = "conversationId", required = true) Integer conversationId) { return this.chatClient.prompt() .user(question) // conversationId 很重要,多次提问时,请确保conversationId一致。这与 WEB应用中的session概念一致。 .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)) .stream() .content(); }}5.6.4 启动测试验证

开始测试之前,先检查数据库SPRING_AI_CHAT_MEMORY表中的数据,此时是空的。启动服务:

第一次请求

GET http://localhost:8080/chat/memory?question=我是小明,为我推荐10部周星驰的电影&conversationId=1001AI 输出:你好,小明!周星驰是华语影坛最具影响力的喜剧演员和导演之一,他的电影融合无厘头幽默、深刻情感与社会讽刺,深受观众喜爱。.....祝你观影愉快,笑口常开,小明!

现在查看数据库,数据库中已经存储了发送给AI的问题和AI回答的内容:

源代码地址:https://github.com/kaiwill/kaifamiao

0
点赞
赏礼
赏钱
0
收藏
免责声明:本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本网证实,对本文以及其中全部或者 部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。 凡本网注明 “来源:XXX(非本站)”的作品,均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对 其真实性负责。 如因作品内容、版权和其它问题需要同本网联系的,请在一周内进行,以便我们及时处理。 QQ:617470285 邮箱:617470285@qq.com
相关文章
三菱退出中国?官方回应:将与现有伙伴继续合作
6月23日,有媒体报道称,三菱汽车将逐步取消包括欧洲、中国在内的市场业..
2026款三菱帕杰罗曝光,第二代超选四驱+2.4T/2.0T双动力..
硬派越野圈的“老将”居然换小排量了?2026款三菱帕杰罗刚露出消息,就把..
恩智浦计划退出5G功率放大器业务;三星或将退出SATA SSD市场;三菱化学出售..
五分钟了解产业大事每日头条芯闻 恩智浦计划退出5G功率放大器业务我国首..
实拍三菱全新欧蓝德!搭1.5T四缸,内饰配大屏,不比奇骏香?..
在重庆车展上,全新一代三菱欧蓝德终于在国内亮相了,相比其国外的发布时..
试驾广汽三菱奕歌:小巧灵动
■ 阅车试驾车型:广汽三菱奕歌长/宽/高(mm):4405/1805/1685轴距(mm..
新车 | 四驱越野MPV/配侧滑门/2.2T柴油机,新款三菱Delica D:5亮相..
文:懂车帝原创 高帅鹏[懂车帝原创 产品] 日前,2025东京车展开幕,新款..
三菱集团的传奇发家史
“三菱”两个字,在日本就像一把瑞士军刀:银行、飞机、汽车、火箭、寿司..
2026款三菱Montero曝光,S-AWC四驱+差速锁全配,普拉多见了..
当 “普拉多见了都得慌” 的话题在越野圈炸锅,2026 款三菱 Montero 的曝..
日韩巨擘数据,三星2.1万亿三菱21万亿,中国第一谁?..
图片来源于网络2025年,让人火大的资本较量又来一波。韩国三星手里握着2...
关于作者
搞印刷的黄先..(普通会员)
文章
1685
关注
0
粉丝
1
点击领取今天的签到奖励!
签到排行

成员 网址收录40418 企业收录2986 印章生成263572 电子证书1157 电子名片68 自媒体91237

@2022 All Rights Reserved 浙ICP备19035174号-7
0
0
分享
请选择要切换的马甲:

个人中心

每日签到

我的消息

内容搜索