news 2026/8/21 16:01:19

Spring AI Alibaba 学习记录(记忆功能实现)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring AI Alibaba 学习记录(记忆功能实现)

1. “记忆”到底是什么

大语言模型本身通常是“无状态”的:每次请求只看得到你这一次发给它的内容。

之所以看起来“记得之前说过什么”,本质是应用在每次请求时,把一段历史对话一起带给模型

一个直观例子:

  • 第 1 轮
    • 问:10 个苹果分给 2 个人,每人多少个?
    • 模型看到:10 个苹果分给 2 个人,每人多少个?
    • 模型答:5 个
  • 第 2 轮
    • 问:如果有 5 个人呢?
    • 模型看到:10 个苹果分给 2 个人... + 模型答 5 个 + 如果有 5 个人呢?
    • 模型答:2 个

所以:把所有问题都塞在同一个对话里,历史越长,token 消耗越快,成本也越高。

2. Spring AI 的“记忆”怎么做

Spring AI 通常把“记忆”拆成三件事:

  • 存放聊天记录的地方:内存 / 数据库 / 其他存储
  • 控制取多少历史:常见是“只取最近 N 条”
  • 自动读写历史:每次调用模型前取历史、调用后把新消息写回去

需要特别记住一个概念:会话 ID(conversationId)

  • 这是用来区分“这一段对话属于谁/属于哪个聊天窗口”的标识
  • 每次请求都必须传同一个 conversationId,才能续上上一轮的历史

3. 存到内存(适合学习 / 开发)

3.1 手动管理(更直观,但不够优雅)

importorg.springframework.ai.chat.memory.ChatMemory;importorg.springframework.ai.chat.memory.MessageWindowChatMemory;importorg.springframework.ai.chat.messages.UserMessage;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.ai.chat.model.ChatResponse;importorg.springframework.ai.chat.prompt.Prompt;publicclassMemoryDemo{privatefinalChatModelchatModel;publicMemoryDemo(ChatModelchatModel){this.chatModel=chatModel;}publicvoidrun(){ChatMemorychatMemory=MessageWindowChatMemory.builder().maxMessages(10).build();StringconversationId="007";chatMemory.add(conversationId,newUserMessage("My name is James Bond"));ChatResponseres1=chatModel.call(newPrompt(chatMemory.get(conversationId)));chatMemory.add(conversationId,res1.getResult().getOutput());chatMemory.add(conversationId,newUserMessage("What is my name?"));ChatResponseres2=chatModel.call(newPrompt(chatMemory.get(conversationId)));chatMemory.add(conversationId,res2.getResult().getOutput());}}

3.2 自动管理(更常用、更优雅)

核心思路:给ChatClient加一个“记忆增强器”,让它自动做:

  • 调用前:按 conversationId 取历史
  • 调用后:把新消息写回去
importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.client.advisor.memory.MessageChatMemoryAdvisor;importorg.springframework.ai.chat.memory.ChatMemory;importorg.springframework.ai.chat.memory.MessageWindowChatMemory;importorg.springframework.ai.chat.model.ChatModel;publicclassChatService{privatefinalChatClientchatClient;privatefinalStringconversationId="007";publicChatService(ChatModelchatModel){ChatMemorychatMemory=MessageWindowChatMemory.builder().maxMessages(10).build();this.chatClient=ChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}@GetMapping("/ai")publicStringchat(StringuserInput){returnchatClient.prompt().user(userInput).advisors(a->a.param(ChatMemory.CONVERSATION_ID,conversationId)).call().content();}}

4. 存到数据库(JDBC,适合生产)

当你希望“重启不丢”“多实例共享”“可追溯”,就要把聊天记录存到数据库。

4.1 引入依赖

Maven:

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId></dependency>

4.2 建表(很关键)

JDBC 方式会用一张表保存聊天记录(默认表名SPRING_AI_CHAT_MEMORY)。

默认情况下,只有“内嵌数据库”才会自动建表。对于 MySQL / PostgreSQL 这类常见数据库,一般需要显式开启:

spring.ai.chat.memory.repository.jdbc.initialize-schema=always

4.3 配置代码:把“窗口记忆”绑定到“JDBC 存储”

importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.client.advisor.memory.MessageChatMemoryAdvisor;importorg.springframework.ai.chat.memory.ChatMemory;importorg.springframework.ai.chat.memory.MessageWindowChatMemory;importorg.springframework.ai.chat.memory.repository.ChatMemoryRepository;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassAiMemoryConfig{@BeanpublicChatMemorychatMemory(ChatMemoryRepositorychatMemoryRepository){returnMessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository).maxMessages(10).build();}@BeanpublicChatClientchatClient(ChatModelchatModel,ChatMemorychatMemory){returnChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}

说明:

  • ChatMemoryRepository会由 JDBC starter 自动装配成数据库实现
  • MessageWindowChatMemory负责“只拿最近 N 条”,避免 token 失控

4.4 Controller 调用:每次都带 conversationId

importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.memory.ChatMemory;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassAIController{privatefinalChatClientchatClient;publicAIController(ChatClientchatClient){this.chatClient=chatClient;}@GetMapping("/ai")publicStringgeneration(@RequestParamStringuserInput,@RequestParamStringconversationId){returnthis.chatClient.prompt().user(userInput).advisors(a->a.param(ChatMemory.CONVERSATION_ID,conversationId)).call().content();}}

PS:由于本人学习的不够深刻可能会出现错误,请多多包涵

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 16:34:23

B站数据接口开发工具包:从数据获取到应用实现的完整解决方案

B站数据接口开发工具包&#xff1a;从数据获取到应用实现的完整解决方案 【免费下载链接】bilibili-api B站API收集整理及开发&#xff0c;不再维护 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-api 在信息爆炸的时代&#xff0c;B站作为年轻人聚集的文化社…

作者头像 李华
网站建设 2026/7/14 16:34:25

关于URBAN中水文参数无法赋值的研究

研究背景&#xff1a;本人在做某个模型构建的时候因为一些操作&#xff0c;导致部分水文参数赋值不上&#xff0c;经过一些研究&#xff0c;提出一种解决方法供大家参考。问题现象&#xff1a;urban水文参数批量赋值会出现部分无法赋值的情况&#xff1a;以往我的方法是放弃该模…

作者头像 李华
网站建设 2026/7/14 16:34:21

Fish-Speech-1.5与Vue.js前端集成:实时语音预览功能实现

Fish-Speech-1.5与Vue.js前端集成&#xff1a;实时语音预览功能实现 1. 引言 想象一下&#xff0c;你正在开发一个需要语音合成功能的前端应用。用户输入文字&#xff0c;希望能立即听到对应的语音效果&#xff0c;而不是等待整个音频文件生成完成。这种实时语音预览体验&…

作者头像 李华
网站建设 2026/7/14 16:34:22

全球海运业趋势晴雨表——能源与数字转型进展评估 劳氏船级社 2025-3

这份由劳氏船级社 2025 年 3 月发布的《全球海运业趋势晴雨表 —— 能源与数字转型进展评估》&#xff0c;以海事行业海洋贸易、能源、船舶、港口、人员五大关键组成部分为核心&#xff0c;评估了行业向 2050 年净零温室气体排放目标推进的能源转型与数字转型进展&#xff0c;指…

作者头像 李华
网站建设 2026/7/14 16:34:26

天梯赛整除光棍

代码&#xff1a;#include<stdio.h> int main() {int x;int m1,k1;scanf("%d",&x);if(x1){printf("1 1");return 0;}while(m<x){mm*101;k;}for(int i0;;i){int tm/x;printf("%d",t);int nm%x;if(n0) break;else{mn*101;k;}}printf(…

作者头像 李华