Spring AI中使用ChatMemory实现会话记忆功能

文章目录

  • 1、需求
  • 2、ChatMemory中消息的存储位置
  • 3、实现步骤
    • 1、引入依赖
    • 2、配置Spring AI
    • 3、配置chatmemory
    • 4、java层传递conversaionId
  • 4、验证
  • 5、完整代码
  • 6、参考文档

1、需求

我们知道大型语言模型 (LLM) 是无状态的,这就意味着他们不会保存之前的交互信息。当我们希望在一次会话中,模型支持多次交互,那么我们该如何实现呢? 在 Spring AI中提供了ChatMemory功能,它允许我们在与LLM的多次交互中存储与检索信息。此处我们借助Spring AI的ChatMemory功能实现一个简单的多轮对话。

    1. 集成ollama部署的本地模型
    1. 使用jdbc存储聊天历史信息(保存到mysql中)

2、ChatMemory中消息的存储位置

ChatMemory中消息的存储位置
默认情况下是存储在内存中,但是它也提供了JDBCCassandraNeo4j的实现。

如果我们想自定义实现存储该如何实现呢? 需要实现ChatMemoryRepository接口。此处我们不自己实现,使用Spring AI 提供的 JDBC存储实现。

注意:使用Spring AI 提供的JDBC实现需要引入 spring-ai-starter-model-chat-memory-repository-jdbc 包
ChatMemoryRepository

3、实现步骤

1、引入依赖

<properties><spring-ai.version>1.0.0</spring-ai.version><java.version>17</java.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target>        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
</properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 集成ollama --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-ollama</artifactId></dependency><!-- 使用jdbc存储模型的聊天记录 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency>
</dependencies>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

2、配置Spring AI

spring:application:name: spring-ai-advisor-chat-memoryai:ollama:base-url: http://localhost:11434 # 配置ollama的地址chat:model: deepseek-r1:14b  # 配置模型的名称options:temperature: 0.7 # 配置模型温度chat:memory:repository:jdbc:initialize-schema: always# 配置初始化脚本的位置schema: classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-mariadb.sqlplatform: mariadbdatasource:url: jdbc:mysql://127.0.0.1:3306/temp_work?useUnicode=true&characterEncoding=utf8&autoReconnectForPools=true&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverlogging:level:# 用于支持llm模型输入前和输入后的日志打印org.springframework.ai.chat.client.advisor: debug

指定脚本的位置

3、配置chatmemory

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepositoryDialect;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;/*** ai 配置* @author huan.fu* @date 2025/6/8 - 08:44*/
@Configuration
public class AiConfiguration {@Beanpublic JdbcChatMemoryRepository jdbcChatMemoryRepository(JdbcTemplate jdbcTemplate, DataSource dataSource) {JdbcChatMemoryRepositoryDialect dialect = JdbcChatMemoryRepositoryDialect.from(dataSource);return JdbcChatMemoryRepository.builder().jdbcTemplate(jdbcTemplate).dialect(dialect).build();}@Beanpublic ChatMemory chatMemory(ChatMemoryRepository jdbcChatMemoryRepository){return MessageWindowChatMemory.builder().chatMemoryRepository(jdbcChatMemoryRepository)// 每个会话最多记录20条信息.maxMessages(20).build();}@Beanpublic ChatClient chatClient(OllamaChatModel ollamaChatModel, ChatMemory chatMemory){// 配置模型 (因为我们使用的是 ollama, 所以此处写的是 OllamaChatModel)return ChatClient.builder(ollamaChatModel)// 默认系统提示词.defaultSystem("你是一个拥有丰富经验的编程小助手,擅长编写各种程序。")// 添加模型输入前和输入后日志打印.defaultAdvisors(new SimpleLoggerAdvisor(),// 配置 chat memory advisorMessageChatMemoryAdvisor.builder(chatMemory).build()).build();}
}

注入到advisor中

4、java层传递conversaionId

java层传递conversaionId
java层传递conversaionId

4、验证

依次访问如下2个http请求

http://localhost:8080/blockChat?prompt=介绍一下你自己&conversationId=123456789
http://localhost:8080/blockChat?prompt=我刚刚问的问题是什么&conversationId=123456789

验证结果
会话id需保持一致
从上图中可以,在第二次询问模型时,模型知道上次的问题是什么。

5、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/spring-ai/spring-ai-advisor-chat-memory

6、参考文档

1、https://docs.spring.io/spring-ai/reference/api/chat-memory.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86390.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 高级泛型实战:8 个场景化编程技巧

文章目录 一、通配符高级应用&#xff1a;灵活处理类型关系二、泛型方法与类型推断三、泛型类的嵌套使用四、受限泛型与边界条件五、泛型与反射结合六、泛型在函数式接口中的应用七、类型擦除与桥接方法八、自定义泛型注解总结 在Java编程中&#xff0c;泛型不仅是类型安全的保…

[蓝桥杯 2024 国 B] 立定跳远

问题描述 在运动会上&#xff0c;小明从数轴的原点开始向正方向立定跳远。项目设置了 n 个检查点 a1,a2,...,an且 ai≥ai−1>0。小明必须先后跳跃到每个检查点上且只能跳跃到检查点上。同时&#xff0c;小明可以自行再增加 m 个检查点让自己跳得更轻松。在运动会前&#xf…

2025年全国I卷数学压轴题解答

第19题第3问: b b b 使得存在 t t t, 对于任意的 x x x, 5 cos ⁡ x − cos ⁡ ( 5 x t ) < b 5\cos x-\cos(5xt)<b 5cosx−cos(5xt)<b, 求 b b b 的最小值. 解: b b b 的最小值 b m i n min ⁡ t max ⁡ x g ( x , t ) b_{min}\min_{t} \max_{x} g(x,t) bmi…

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…

解决网页导出PDF部分内容被遮挡问题

问题描述 以学习通为例&#xff0c;在使用CtrlP打印页面或截图时&#xff0c;固定侧边栏会遮挡部分内容&#xff0c;影响完整内容的获取。如下图所示&#xff1a; 解决办法 通过浏览器开发者工具临时移除固定侧边栏&#xff0c;具体步骤如下&#xff1a; 在目标页面右键点…

机器学习监督学习实战六:五种算法对新闻组英文文档进行文本分类(20类),词频统计和TF-IDF 转换特征提取方法理论和对比解析

本文主要介绍了20 Newsgroups数据集及其在文本分类任务中的应用。20 Newsgroups数据集包含约20,000篇新闻组文档&#xff0c;分为20个不同主题的新闻组&#xff0c;数据集被分为训练集和测试集。在数据预处理阶段&#xff0c;使用了CountVectorizer和TfidfVectorizer两种方法将…

易学探索助手-个人记录(十四)

项目背景 在大语言模型&#xff08;LLM&#xff09;完成指令微调&#xff08;SFT&#xff09;之后&#xff0c;虽然可以处理开放式问答任务&#xff0c;但在专业领域&#xff08;如《周易》&#xff09;仍面临知识更新滞后、事实性薄弱等问题。为此&#xff0c;本文介绍如何通…

从“人找政策”到“政策找人”:智能退税ERP数字化重构外贸生态

离境退税新政核心内容与外贸企业影响 &#xff08;一&#xff09;政策核心变化解析 退税商店网络扩容 新政明确鼓励在大型商圈、旅游景区、交通枢纽等境外旅客聚集地增设退税商店&#xff0c;并放宽备案条件至纳税信用M级企业。以上海为例&#xff0c;静安区计划新增1000家退…

Pandas 可视化集成:数据科学家的高效绘图指南

为什么选择 Pandas 进行数据可视化&#xff1f; 在数据科学和分析领域&#xff0c;可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具&#xff0c;如 Matplotlib、Seaborn、Plotly 等&#xff0c;但 Pandas 内置的可视化功能因其与数据结…

曼昆《经济学原理》第九版 第十一章公共物品与公共资源

一、物品分类的基本框架 排他性&#xff1a;能否阻止他人使用该物品的特性竞争性&#xff1a;一个人使用是否减少他人使用的特性 根据这两个特性可将物品分为四类&#xff1a; 私人物品&#xff1a;既有排他性又有竞争性&#xff08;如冰淇淋、衣服&#xff09;公共物品&…

基于大模型预测原发性急性闭角型青光眼的技术方案研究大纲

目录 一、引言二、技术方案概述三、术前阶段(一)数据采集与处理(二)大模型预测(三)手术方案制定(四)麻醉方案确定(五)术前健康教育四、术中阶段(一)实时数据监测与输入(二)手术策略动态调整(三)并发症预警与处理(四)术中健康教育五、术后阶段(一)恢复监测与…

基于React 的 AntD 库进行前端开发过程中的问题汇总

背景 最近写了半个月的 React 前端&#xff0c;三年没写过 React 前端了&#xff0c;有些生疏了&#xff0c;汇总一下 基于React 前端的 antD 库编写过程中的低级问题吧。 PS 一下&#xff0c;半个月没有发布博客了&#xff0c;C站产品经理又悄默默地改了样式&#xff0c;博客…

Spring @Scheduled vs XXL-JOB vs DolphinScheduler vs Airflow:任务调度框架全景对比

引言 从单机定时任务到分布式工作流调度&#xff0c;不同场景需要选择匹配的调度框架。 本文对比 Spring Scheduled、XXL-JOB、DolphinScheduler &#xff08;海豚调度器&#xff09;和 Apache Airflow 的核心差异&#xff0c;助你避免过度设计或功能不足。 一、核心定位与适用…

springMVC-10验证及国际化

验证 概述 ● 概述 1. 对输入的数据(比如表单数据)&#xff0c;进行必要的验证&#xff0c;并给出相应的提示信息。 2. 对于验证表单数据&#xff0c;springMVC提供了很多实用的注解, 这些注解由JSR303 验证框架提供. ●JSR 303 验证框架 1. JSR 303 的含义 JSR&#xff0…

OpenCV 滑动条调整图像对比度和亮度

一、知识点 1、int createTrackbar(const String & trackbarname, const String & winname, int * value, int count, TrackbarCallback onChange 0, void * userdata 0); (1)、创建一个滑动条并将其附在指定窗口上。 (2)、参数说明: trackbarname: 创建的…

ReadWriteLock(读写锁)和 StampedLock

1. ReadWriteLock&#xff08;读写锁&#xff09;&#xff1a;实现高性能缓存 总结&#xff1a; 要点 内容 适用场景 读多写少、高并发读取场景&#xff08;如缓存&#xff09; 锁类型 ReadWriteLock接口&#xff0c;ReentrantReadWriteLock实现 读锁 vs 写锁 多线程可…

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…

vue3 el-button 自定义本地图标

设置不生效的原因可能有&#xff1a;1.style标签里没加scoped <style scoped></style>2.本地图片路径指向错误3.自定义图片长宽没设置4.deep深度选择器使用错误&#xff0c;vue3用:deep() <el-tooltip content"重新匹配" placement"top"&g…

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…

6.8 note

paxos算法_初步感知 Paxos算法保证一致性主要通过以下几个关键步骤和机制&#xff1a; 准备阶段 - 提议者向所有接受者发送准备请求&#xff0c;请求中包含一个唯一的编号。 - 接受者收到请求后&#xff0c;会检查编号&#xff0c;如果编号比它之前见过的都大&#xff0c;就会承…