Spring AI企业级应用实战(4):Chat Memory、会话隔离、持久化与上下文压缩
文章摘要前几篇已经完成Spring AI统一调用层和流式输出。本篇继续实现企业级多轮对话使用MessageChatMemoryAdvisor管理近期消息要求每次请求显式提供conversationId通过PostgreSQL保存完整Chat History与持久化Memory校验租户和用户所有权并在上下文接近预算时生成结构化摘要。最终形成一个支持多实例部署、流式调用、审计和安全删除的会话系统。一、本篇目标完成以下能力创建会话 稳定conversationId 多租户所有权校验 Chat Memory持久化 完整Chat History 同步与流式调用 窗口控制 上下文摘要 清空与删除 可观测性最终链路HTTP请求 → 身份认证 → 会话所有权校验 → 写入Chat History → MessageChatMemoryAdvisor → ChatClient → 模型 → 保存结果 → 更新指标二、项目结构src/main/java/com/zyentor/ai ├── config │ └── ChatMemoryConfig.java ├── conversation │ ├── Conversation.java │ ├── ConversationRepository.java │ ├── ConversationService.java │ └── ConversationController.java ├── history │ ├── ChatMessageRecord.java │ ├── ChatHistoryRepository.java │ └── JdbcChatHistoryRepository.java ├── memory │ ├── MemoryCompactionService.java │ └── ConversationSummary.java ├── service │ └── EnterpriseConversationAiService.java └── security └── UserContext.java三、依赖dependencyManagementdependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-bom/artifactIdversion2.0.0/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementdependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-deepseek/artifactId/dependencydependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-chat-memory-repository-jdbc/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdorg.postgresql/groupIdartifactIdpostgresql/artifactIdscoperuntime/scope/dependency/dependencies具体Starter名称应以当前Spring AI 2.0.x文档和依赖清单为准。四、配置数据源和模型spring:datasource:url:jdbc:postgresql://localhost:5432/spring_ai_demousername:ai_userpassword:${DB_PASSWORD}ai:model:chat:deepseekdeepseek:api-key:${DEEPSEEK_API_KEY}chat:model:deepseek-v4-flashtemperature:0.2max-tokens:2048生产环境不要把密钥写进仓库。五、配置Chat MemoryConfigurationpublicclassChatMemoryConfig{BeanChatMemorychatMemory(ChatMemoryRepositoryrepository){returnMessageWindowChatMemory.builder().chatMemoryRepository(repository).maxMessages(30).build();}Bean(conversationChatClient)ChatClientconversationChatClient(ChatClient.Builderbuilder,ChatMemorychatMemory){returnbuilder.defaultSystem( 你是企业AI助手。 只能使用当前用户有权访问的上下文。 不得泄露其他用户或租户的信息。 不确定时明确说明。 ).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}maxMessages30只是示例生产应通过真实Token分布评测。六、为什么每次请求必须传conversationIdSpring AI 2.0内置Memory Advisor要求显式提供ChatMemory.CONVERSATION_ID调用chatClient.prompt().advisors(spec-spec.param(ChatMemory.CONVERSATION_ID,conversationId)).user(message).call().content();不要使用默认会话也不要把conversationId写死在Advisor Bean中。七、会话表CREATETABLEai_conversation(idVARCHAR(64)PRIMARYKEY,tenant_idVARCHAR(64)NOTNULL,user_idVARCHAR(64)NOTNULL,titleVARCHAR(200),statusVARCHAR(20)NOTNULL,memory_versionBIGINTNOTNULLDEFAULT1,created_atTIMESTAMPNOTNULL,updated_atTIMESTAMPNOTNULL);memory_version可以用于缓存失效摘要版本调试会话重置。八、完整消息表CREATETABLEai_chat_message(idVARCHAR(64)PRIMARYKEY,conversation_idVARCHAR(64)NOTNULL,tenant_idVARCHAR(64)NOTNULL,user_idVARCHAR(64)NOTNULL,roleVARCHAR(20)NOTNULL,contentTEXTNOTNULL,statusVARCHAR(20)NOTNULL,request_idVARCHAR(64)NOTNULL,modelVARCHAR(100),prompt_versionVARCHAR(50),input_tokensBIGINT,output_tokensBIGINT,created_atTIMESTAMPNOTNULL);Chat Memory表只服务模型上下文该表保存完整历史。九、会话创建ServicepublicclassConversationService{privatefinalConversationRepositoryrepository;publicConversationcreate(UserContextuser){InstantnowInstant.now();ConversationconversationnewConversation(conv_UUID.randomUUID(),user.tenantId(),user.userId(),null,ConversationStatus.ACTIVE,1L,now,now);repository.save(conversation);returnconversation;}}tenantId和userId来自认证上下文。十、所有权校验publicConversationrequireOwned(UserContextuser,StringconversationId){returnrepository.findOwned(conversationId,user.tenantId(),user.userId()).orElseThrow(()-newAccessDeniedException(无权访问该会话));}不能只验证会话存在。十一、同步对话服务ServicepublicclassEnterpriseConversationAiService{privatefinalChatClientchatClient;privatefinalConversationServiceconversationService;privatefinalChatHistoryRepositoryhistoryRepository;publicStringchat(UserContextuser,StringconversationId,Stringmessage){conversationService.requireOwned(user,conversationId);StringrequestIdUUID.randomUUID().toString();historyRepository.saveUserMessage(user,conversationId,requestId,message);try{StringanswerchatClient.prompt().advisors(spec-spec.param(ChatMemory.CONVERSATION_ID,conversationId).param(tenantId,user.tenantId())).user(message).call().content();historyRepository.saveAssistantMessage(user,conversationId,requestId,answer,MessageStatus.COMPLETED);returnanswer;}catch(RuntimeExceptionexception){historyRepository.markFailed(conversationId,requestId,exception.getClass().getSimpleName());throwexception;}}}十二、避免长数据库事务模型调用可能持续数秒。不要开启数据库事务 → 写用户消息 → 等模型十几秒 → 写助手消息 → 提交推荐事务1写用户消息 → 模型调用 → 事务2写助手消息或失败状态通过request_id关联两段记录。十三、流式调用publicFluxServerSentEventChatStreamEventstream(UserContextuser,StringconversationId,Stringmessage){conversationService.requireOwned(user,conversationId);StringrequestIdUUID.randomUUID().toString();historyRepository.saveUserMessage(user,conversationId,requestId,message);StringBuilderbuffernewStringBuilder();returnchatClient.prompt().advisors(spec-spec.param(ChatMemory.CONVERSATION_ID,conversationId)).user(message).stream().content().doOnNext(buffer::append).map(chunk-ServerSentEvent.builder(newChatStreamEvent(requestId,delta,chunk)).build()).doOnComplete(()-historyRepository.saveAssistantMessage(user,conversationId,requestId,buffer.toString(),MessageStatus.COMPLETED)).doOnCancel(()-historyRepository.markCancelled(conversationId,requestId,buffer.toString()));}需要继续验证Provider在取消订阅后是否真正终止上游生成。十四、半段回答是否进入Memory用户取消后可能只生成根据你的问题主要有三个方面第一……不建议把这段内容当作完整Assistant消息进入稳定Memory。可选策略取消时不写Memory 完整Chat History保存CANCELLED消息 下一轮提示用户上一轮已中断十五、为什么需要上下文压缩长期会话会不断消耗Token。只扩大Message Window会导致成本上升延迟增加重要信息被噪声淹没超出上下文窗口。推荐上下文结构化摘要 最近若干轮消息 当前RAG证据十六、摘要表CREATETABLEai_conversation_summary(idVARCHAR(64)PRIMARYKEY,conversation_idVARCHAR(64)NOTNULL,tenant_idVARCHAR(64)NOTNULL,summary_versionBIGINTNOTNULL,covered_until_message_idVARCHAR(64)NOTNULL,content JSONBNOTNULL,created_atTIMESTAMPNOTNULL);结构化内容{goal:构建企业RAG方案,facts:[客户使用PostgreSQL,数据不能离开私有云],decisions:[向量存储选择pgvector],openQuestions:[峰值并发尚未确认]}十七、什么时候触发压缩可以使用消息数量阈值 Token预算阈值 会话持续时间 工具事件数量推荐以Token预算为主预计上下文Token 可用历史预算的80% → 触发压缩十八、压缩流程1. 读取上次摘要 2. 读取摘要之后的新消息 3. 生成新结构化摘要 4. 校验Schema 5. 保存summary_version 6. 更新covered_until_message_id 7. 后续Prompt加载摘要和近期消息原始消息不删除用于审计和重新生成摘要。十九、摘要不能替代业务事实模型摘要可能错误。以下信息必须从业务系统实时获取订单状态当前权限余额-审批结果产品库存合同版本。摘要只能作为对话背景不能作为强一致事实来源。二十、会话清空与删除清空模型上下文chatMemory.clear(conversationId);同时增加memory_version使缓存失效。删除会话流程标记DELETING → 删除Memory → 删除摘要和向量记忆 → 处理附件 → 按策略删除或匿名化History → 标记DELETED二十一、监控指标chat_conversation_created_count chat_memory_message_count chat_memory_load_duration chat_memory_clear_count conversation_cross_owner_denied_count summary_generation_count summary_validation_failed_count stream_cancelled_count history_memory_write_mismatch_count二十二、测试场景同一会话连续多轮 同一用户两个窗口 同租户两个用户 两个不同租户 应用重启 请求进入不同实例 流式取消 模型超时 Memory清空 摘要触发 非法conversationId访问最重要的测试是多租户隔离。二十三、本篇完整架构认证用户 → Conversation所有权 → 完整History写入 → 显式conversationId → MessageChatMemoryAdvisor → 持久化Memory Repository → ChatClient → 模型 → 保存状态 → Token预算触发摘要总结生产级Spring AI多轮对话不能只注册一个Memory Advisor。完整方案必须同时解决稳定会话ID 租户与用户隔离 持久化Memory 独立Chat History 流式状态 上下文压缩 审计与删除下一篇将继续实现Spring AI企业级应用实战5Tool Calling、权限校验、幂等与人工确认。

相关新闻

Python异常嵌套日志处理与结构化日志实践

Python异常嵌套日志处理与结构化日志实践

1. 异常嵌套日志的痛点解析在Python项目开发中,异常嵌套场景几乎无处不在。当外层异常捕获内层异常时,传统的日志记录方式往往存在三个典型问题:信息割裂:内层异常被外层捕获后,原始堆栈信息可能被覆盖日志冗余&#x…

2026/7/28 20:38:17 阅读更多 →
系统化调试方法论与高效工具链实践

系统化调试方法论与高效工具链实践

1. 为什么我们需要系统化的调试方法论在十五年的开发生涯中,我见过太多工程师把调试当成碰运气的过程——反复修改代码、盲目添加打印语句、甚至迷信地调整缩进格式。这种低效的调试方式不仅浪费时间,更会掩盖问题的本质。真正高效的调试应该像法医解剖一…

2026/7/28 20:38:17 阅读更多 →
从4K短片《巫魍之灾》拆解影视制作:技术分析与实践指南

从4K短片《巫魍之灾》拆解影视制作:技术分析与实践指南

这次我们来看一个名为《巫魍之灾》的4K画质短片项目。这不是一个技术工具或开源模型,而是一部风格独特、叙事紧凑的独立短片。对于技术创作者和影视爱好者而言,这类高画质、强氛围的短片是极佳的学习和分析素材。本文将重点拆解如何从技术角度欣赏、分析…

2026/7/28 20:37:16 阅读更多 →

最新新闻

优秀青年/优秀党员评选投票制作教程|2026政务场景合规投票工具测评

优秀青年/优秀党员评选投票制作教程|2026政务场景合规投票工具测评

优秀党员、优秀青年、先进工作者等政务基层评优活动,具备严肃性、公正性、合规性三大核心要求。区别于普通娱乐类投票,政务评选需要满足页面庄重正式、无娱乐化元素、评选数据留痕可存档、投票过程公平可控等硬性条件,确保评选结果经得起群众…

2026/7/28 20:51:22 阅读更多 →
SteamAutoCrack终极指南:3步实现Steam游戏自动破解与备份

SteamAutoCrack终极指南:3步实现Steam游戏自动破解与备份

SteamAutoCrack终极指南:3步实现Steam游戏自动破解与备份 【免费下载链接】Steam-auto-crack Steam Game Automatic Cracker 项目地址: https://gitcode.com/gh_mirrors/st/Steam-auto-crack SteamAutoCrack是一款专业的Steam游戏自动破解工具,能…

2026/7/28 20:51:22 阅读更多 →
AI模型不确定性解析:从技术原理到伦理工程实践

AI模型不确定性解析:从技术原理到伦理工程实践

在人工智能和机器学习领域,模型与创造者之间的关系是一个深刻且常被忽视的哲学与技术交叉点。当像 Opus 5 这样的高级模型被问及是否“同意”被创造时,其回答的“不确定性”并非程序缺陷,而是触及了当前 AI 系统在自我意识、意图理解和伦理边…

2026/7/28 20:51:22 阅读更多 →
解决Python C++扩展编译错误:Ninja构建工具安装与配置全指南

解决Python C++扩展编译错误:Ninja构建工具安装与配置全指南

1. 问题背景与核心痛点 如果你在配置深度学习环境,或者编译一些依赖C扩展的Python包(比如PyTorch的某些自定义算子、或者一些需要编译的加速库)时,突然在终端或命令行里看到一行刺眼的红色错误信息: raise RuntimeErr…

2026/7/28 20:51:22 阅读更多 →
AIGC改写工具实测:语义保持与创意增强的突破

AIGC改写工具实测:语义保持与创意增强的突破

1. 项目背景:为什么我们需要专业的文本改写工具?在内容创作领域,文本改写是个永恒的需求。无论是自媒体运营者需要批量生产差异化内容,还是学术研究者需要优化论文表达,亦或是市场营销人员需要为不同平台适配文案版本&…

2026/7/28 20:51:22 阅读更多 →
2026第一期GCDW云数据仓库系统认证培训圆满结束

2026第一期GCDW云数据仓库系统认证培训圆满结束

南大通用GBASE培训中心举办的“2026第一期GCDW云数据仓库系统认证培训班”于7月底圆满结束。本次培训共466人报名,经过10天的学习,共有335人通过考试,获得“GCDW数据库管理工程师”证书。所有获得的电子证书可通过南大通用官网查看和下载。首…

2026/7/28 20:50:22 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻