当前位置: 首页 > article >正文

Spring AI实战系列(七):Chat Memory对话记忆实战,基于Redis实现持久化多轮对话

一、系列回顾与本篇定位1.1 系列回顾第一篇完成Spring AI与阿里云百炼的基础集成基于ChatModel实现同步对话与API Key安全注入。第二篇解锁ChatClient实现全局统一配置与链式调用告别重复样板代码。第三篇实现DeepSeek/Qwen双模型无缝共存与动态切换完成双版本流式输出。第四篇深度拆解Prompt工程全体系从底层Message到模板化动态生成掌握与大模型高效沟通的方法论。第五篇掌握结构化输出能力实现大模型输出到 Java 实体的自动映射解决业务系统对接痛点。第六篇掌握Tool Calling核心能力让大模型自动调用业务接口实现 “大模型 业务系统” 的深度融合。1.2 本篇定位大模型有一个缺陷它是无状态的。每次请求对大模型来说都是 “全新的开始”它不会记住之前的对话内容 —— 你刚告诉它 “我叫张三”下一句问 “我叫什么”它就会一脸茫然。而Chat Memory对话记忆正是解决这个问题的核心能力它通过存储和检索历史对话消息让大模型 “记住” 之前的交互实现上下文感知的多轮对话。更重要的是生产环境中我们不仅需要记忆还需要持久化记忆—— 服务重启后记忆不能丢失同时需要会话隔离—— 不同用户的对话记忆必须完全独立不能串线。本篇是系列企业级落地核心篇我们将深度拆解 Spring AI Chat Memory 的全体系从核心原理出发彻底理解 Chat Memory 的工作流程与 Spring AI 的核心抽象。基于 Redis 实现持久化对话记忆完成从配置、集成到会话隔离的全流程实战。覆盖消息窗口控制、内存记忆与持久化记忆对比、会话管理等企业级高频场景。补充生产环境最佳实践与高频踩坑避坑指南解决 Chat Memory 落地的核心问题。二、核心概念拆解Spring AI Chat Memory2.1 什么是Chat MemoryChat Memory是Spring AI提供的对话记忆抽象核心作用是存储历史对话在每次对话完成后自动将用户消息和大模型响应保存到记忆仓库。检索历史对话在每次新请求发起前自动从记忆仓库中检索历史消息注入到当前 Prompt 中。会话隔离通过conversationId会话 ID区分不同用户的对话确保记忆完全独立。简单来说Chat Memory就是给大模型 “装了个记忆大脑”让它能记住之前的对话内容实现连贯的多轮交互。2.2 Spring AI Chat Memory 核心组件Spring AI 的 Chat Memory 体系设计非常优雅核心组件只有四个职责清晰学习成本低核心组件作用典型实现ChatMemory对话记忆的顶层抽象接口定义了记忆的存储、检索、清除能力MessageWindowChatMemory基于消息窗口的记忆ChatMemoryRepository记忆的持久化仓库抽象负责将对话历史持久化到外部存储RedisChatMemoryRepositoryRedis 持久化实现MessageChatMemoryAdvisorAdvisor 机制的核心实现将记忆能力动态注入到 ChatClient的调用流程中MessageChatMemoryAdvisor.builder(chatMemory).build()conversationId会话 ID用于隔离不同用户的对话记忆是实现多用户独立对话的关键通常使用UUID或用户ID作为会话ID2.3 核心工作流程Spring AI Chat Memory 的完整工作流程如下请求发起用户发送新问题同时传入conversationId。历史检索MessageChatMemoryAdvisor自动根据conversationId从ChatMemoryRepository中检索历史消息。Prompt 组装将历史消息注入到当前 Prompt 中放在用户新问题之前。模型调用ChatClient 将包含历史消息的 Prompt 发送给大模型。结果生成大模型基于历史消息和当前问题生成响应。记忆保存MessageChatMemoryAdvisor自动将当前用户消息和大模型响应保存到ChatMemoryRepository中。整个流程完全自动开发者无需手动处理记忆的存储和检索只需关注业务逻辑即可。三、实战落地基于 Redis 实现持久化多轮对话为了满足生产环境的需求我们不再使用简单的内存记忆服务重启后丢失而是使用Redis 作为持久化记忆仓库同时实现会话隔离确保不同用户的对话记忆完全独立。3.1 环境前提已完成 JDK 17、Spring Boot 3.2.x 环境搭建已完成 Spring AI 基础配置项目中已注册ChatModel和ChatClient实例已配置阿里云百炼 API Key 环境变量DASHSCOPE_API_KEY已安装并启动 Redis 服务本地或远程均可已在pom.xml中引入 Redis 依赖!-- Spring Boot Redis 依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency !-- Spring AI Alibaba 依赖已包含RedisChatMemoryRepository -- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-dashscope/artifactId version1.0.0.2/version /dependency3.2 第一步配置 Redis 连接与持久化仓库首先在application.yml中配置 Redis 连接信息然后编写RedisMemoryConfig配置类注册RedisChatMemoryRepositoryBean。application.yml 配置spring: data: redis: host: localhost # Redis主机地址 port: 6379 # Redis端口 password: 123456 # Redis密码生产环境请从环境变量读取 database: 0 # Redis数据库索引 timeout: 3000ms # 连接超时时间 lettuce: pool: max-active: 8 # 连接池最大连接数 max-idle: 8 # 连接池最大空闲连接数 min-idle: 0 # 连接池最小空闲连接数RedisMemoryConfig 配置类import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Redis 持久化记忆仓库配置类 */ Configuration public class RedisMemoryConfig { // 从配置文件读取Redis连接信息 Value(${spring.data.redis.host}) private String redisHost; Value(${spring.data.redis.port}) private int redisPort; Value(${spring.data.redis.password:}) // 生产环境建议从环境变量读取 private String redisPassword; /** * 注册RedisChatMemoryRepository Bean * 负责将对话历史持久化到Redis中 */ Bean public RedisChatMemoryRepository redisChatMemoryRepository() { return RedisChatMemoryRepository.builder() .host(redisHost) .port(redisPort) .password(redisPassword) // 生产环境建议使用System.getenv()读取 .build(); } }关键说明生产环境中Redis 密码不要硬编码在配置类中建议通过System.getenv(REDIS_PASSWORD)从环境变量读取或者使用 Spring Cloud Config 等配置中心管理。RedisChatMemoryRepository会自动将对话历史序列化为 JSON 格式存储到 Redis 中无需开发者手动处理序列化。3.3 第二步将Chat Memory集成到ChatClient修改我们之前的LLMConfig配置类给qwenChatClient添加MessageChatMemoryAdvisor同时配置MessageWindowChatMemory基于消息窗口的记忆实现防止历史消息占用过多 Token。import com.alibaba.cloud.ai.dashscope.api.DashScopeApi; import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel; import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; import org.springframework.ai.chat.memory.MessageWindowChatMemory; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * ChatModelChatClient多模型共存Redis持久化记忆配置类 */ Configuration public class LLMConfig { // 模型名称常量统一管理 private final String DEEPSEEK_MODEL deepseek-v3; private final String QWEN_MODEL qwen-plus; // ChatModel 实例注册 Bean(name deepseek) public ChatModel deepSeekChatModel() { return DashScopeChatModel.builder() .dashScopeApi(DashScopeApi.builder() .apiKey(System.getenv(DASHSCOPE_API_KEY)) .build()) .defaultOptions(DashScopeChatOptions.builder() .withModel(DEEPSEEK_MODEL) .withTemperature(0.7) .build()) .build(); } Bean(name qwen) public ChatModel qwenChatModel() { return DashScopeChatModel.builder() .dashScopeApi(DashScopeApi.builder() .apiKey(System.getenv(DASHSCOPE_API_KEY)) .build()) .defaultOptions(DashScopeChatOptions.builder() .withModel(QWEN_MODEL) .withTemperature(0.7) .build()) .build(); } // 带Redis记忆的ChatClient 实例注册 Bean(name qwenChatClient) public ChatClient qwenChatClient( Qualifier(qwen) ChatModel qwenChatModel, RedisChatMemoryRepository redisChatMemoryRepository) { // 1. 配置基于消息窗口的记忆只保留最近10条消息防止Token超限 MessageWindowChatMemory windowChatMemory MessageWindowChatMemory.builder() .chatMemoryRepository(redisChatMemoryRepository) // 绑定Redis持久化仓库 .maxMessages(10) // 最大保留消息数包含用户消息和助手响应 .build(); // 2. 配置MessageChatMemoryAdvisor将记忆能力注入到ChatClient MessageChatMemoryAdvisor memoryAdvisor MessageChatMemoryAdvisor.builder(windowChatMemory) .build(); // 3. 构建ChatClient通过defaultAdvisors全局启用记忆 return ChatClient.builder(qwenChatModel) .defaultOptions(ChatOptions.builder().model(QWEN_MODEL).build()) .defaultAdvisors(memoryAdvisor) // 全局默认启用记忆 .build(); } // 家庭作业给DeepSeek也加上Redis记忆 Bean(name deepseekChatClient) public ChatClient deepseekChatClient( Qualifier(deepseek) ChatModel deepSeekChatModel, RedisChatMemoryRepository redisChatMemoryRepository) { MessageWindowChatMemory windowChatMemory MessageWindowChatMemory.builder() .chatMemoryRepository(redisChatMemoryRepository) .maxMessages(10) .build(); return ChatClient.builder(deepSeekChatModel) .defaultOptions(ChatOptions.builder().model(DEEPSEEK_MODEL).build()) .defaultAdvisors(MessageChatMemoryAdvisor.builder(windowChatMemory).build()) .build(); } }关键说明MessageWindowChatMemory的作用大模型的上下文窗口是有限的如果历史消息太多会占用大量Token导致请求失败。MessageWindowChatMemory通过maxMessages参数只保留最近的 N 条消息自动丢弃更早的消息防止 Token 超限。defaultAdvisors的作用通过defaultAdvisors将MessageChatMemoryAdvisor设置为 ChatClient 的全局默认 Advisor这样所有通过该 ChatClient 发起的请求都会自动启用记忆能力无需每次调用时手动配置。家庭作业完成我们已经给deepseekChatClient也加上了 Redis 记忆实现了双模型的持久化多轮对话。3.4 第三步实现带会话隔离的对话接口创建ChatMemoryRedisController实现带会话隔离的多轮对话接口通过userId或conversationId隔离不同用户的对话记忆。import jakarta.annotation.Resource; import org.springframework.http.HttpStatus; import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID; import java.util.UUID; /** * Redis持久化多轮对话接口 */ RestController public class ChatMemory4RedisController { Resource(name qwenChatClient) private ChatClient qwenChatClient; /** * 带会话隔离的多轮对话接口 */ GetMapping(/chatmemory/chat) public String chat( RequestParam(name msg) String msg, RequestParam(name userId, required false) String userId) { // 1. 参数校验 if (msg null || msg.isBlank()) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, Missing required query param: msg); } // 2. 生成/获取会话ID如果传入userId则使用userId否则生成随机UUID String conversationId (userId null || userId.isBlank()) ? UUID.randomUUID().toString() : userId.trim(); // 3. 调用ChatClient通过advisors传入会话ID实现会话隔离 return qwenChatClient .prompt(msg) // 核心传入CONVERSATION_ID参数隔离不同用户的对话记忆 .advisors(advisorSpec - advisorSpec.param(CONVERSATION_ID, conversationId)) .call() .content(); } }接口测试说明第一次访问http://localhost:xxx/chatmemory/chat?msg我叫张三系统会自动生成一个会话 ID大模型会记住 “你叫张三”。第二次访问传入第一次返回的会话ID或使用固定的 userId访问http://localhost:xxx/chatmemory/chat?msg我叫什么userId你的会话ID大模型会回答 “你叫张三”说明记忆生效了。重启服务后再次访问记忆仍然存在说明Redis持久化生效了。四、进阶场景高频需求实现4.1 清除特定会话的记忆生产环境中我们经常需要清除特定用户的对话记忆如用户主动清除、会话过期。Spring AI 的ChatMemory接口提供了clear()方法可以轻松实现记忆清除。import jakarta.annotation.Resource; import org.springframework.ai.chat.memory.ChatMemory; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * 会话管理接口 */ RestController public class ChatMemoryManageController { Resource private ChatMemory chatMemory; // 直接注入ChatMemory /** * 清除特定会话的记忆 * 访问示例http://localhost:xxx/chatmemory/clear?userId你的用户ID */ DeleteMapping(/chatmemory/clear) public String clearMemory(RequestParam(name userId) String userId) { chatMemory.clear(userId); return String.format(会话【%s】的记忆已清除, userId); } }4.2 内存记忆vsRedis持久化记忆对比Spring AI 提供了两种记忆实现内存记忆和持久化记忆我们可以根据场景灵活选择对比维度内存记忆InMemoryChatMemoryRedis 持久化记忆RedisChatMemoryRepository存储位置JVM 内存Redis 数据库持久化服务重启后丢失服务重启后仍然存在性能极高无需网络 IO高有少量网络IO会话隔离支持支持适用场景开发测试、单实例服务、临时对话生产环境、多实例集群、需要持久化的对话内存记忆的实现方式如果不需要持久化只想在开发测试时使用内存记忆可以这样配置// 内存记忆配置无需Redis Bean public ChatClient qwenChatClient(Qualifier(qwen) ChatModel qwenChatModel) { // 使用InMemoryChatMemory服务重启后记忆丢失 MessageWindowChatMemory windowChatMemory MessageWindowChatMemory.builder() .maxMessages(10) .build(); return ChatClient.builder(qwenChatModel) .defaultAdvisors(MessageChatMemoryAdvisor.builder(windowChatMemory).build()) .build(); }4.3 基于Token数量的记忆窗口除了MessageWindowChatMemory基于消息数量的窗口Spring AI还提供了TokenWindowChatMemory基于 Token 数量的窗口可以更精确地控制历史消息占用的 Token 数量避免浪费模型的上下文窗口。import org.springframework.ai.chat.memory.TokenWindowChatMemory; import org.springframework.ai.chat.model.ChatModel; // 基于Token数量的记忆窗口配置 Bean(name qwenChatClient) public ChatClient qwenChatClient( Qualifier(qwen) ChatModel qwenChatModel, RedisChatMemoryRepository redisChatMemoryRepository) { // 基于Token数量的记忆最多保留8000 Token的历史消息 TokenWindowChatMemory tokenWindowChatMemory TokenWindowChatMemory.builder() .chatModel(qwenChatModel) // 传入ChatModel用于计算Token数量 .chatMemoryRepository(redisChatMemoryRepository) .maxTokens(8000) // 最大保留Token数 .build(); return ChatClient.builder(qwenChatModel) .defaultAdvisors(MessageChatMemoryAdvisor.builder(tokenWindowChatMemory).build()) .build(); }五、实践建议5.1 Redis 配置最佳实践使用 Redis 集群生产环境建议使用 Redis 主从复制或 Redis Cluster避免单点故障保证高可用。连接池配置合理配置 Redis 连接池的max-active、max-idle、min-idle参数避免连接泄漏和性能瓶颈。密码安全Redis 密码必须从环境变量或配置中心读取绝对不要硬编码在代码或配置文件中。内存过期策略给 Redis 设置合理的内存过期策略如allkeys-lru避免对话历史占用过多内存导致 Redis OOM。序列化优化Spring AI 默认使用 JSON 序列化确保序列化后的消息大小合理避免过大的消息占用过多 Redis 内存。5.2 会话管理最佳实践会话 ID 生成策略对于已登录用户直接使用用户 ID 作为conversationId确保用户的对话记忆永久关联。对于未登录用户使用 UUID 生成临时会话 ID同时设置会话过期时间如 24 小时过期后自动清除记忆。会话过期机制生产环境建议实现会话过期机制定期清除长时间未使用的对话记忆避免 Redis 内存无限增长。会话安全会话 ID 必须与用户身份绑定防止未授权访问他人的对话记忆。不要在 URL 中明文传递会话 ID建议通过请求头或 Cookie 传递如果是 Web 应用。5.3 记忆窗口配置最佳实践根据模型上下文窗口设置模型上下文窗口为 32K TokenmaxMessages设置为 10-20或maxTokens设置为 8000-16000。模型上下文窗口为 128K TokenmaxMessages设置为 30-50或maxTokens设置为 32000-64000。预留足够的 Token 空间不要把记忆窗口设置得太大要预留足够的 Token 空间给当前用户问题和大模型响应避免请求失败。动态调整记忆窗口可以根据用户等级动态调整记忆窗口大小如 VIP 用户保留更多历史消息提升用户体验。5.4 监控与运维最佳实践记忆存储监控监控 Redis 的内存使用情况、对话历史的存储数量、平均每条对话的大小及时发现内存增长异常。调用次数监控监控每个会话的对话次数、记忆的检索和保存次数识别高频使用的会话。异常监控监控 Redis 连接失败、记忆检索失败、记忆保存失败等异常及时告警和处理。备份与恢复定期备份 Redis 中的对话历史数据防止数据丢失。六、避坑指南6.1 坑点 1Redis 连接失败现象启动服务时报错提示无法连接到 Redis。原因Redis 服务未启动。application.yml中的 Redis 主机、端口、密码配置错误。防火墙阻止了 Redis 连接。解决方案检查 Redis 服务是否正常启动。核对application.yml中的 Redis 配置信息。检查防火墙规则确保应用服务器能访问 Redis。6.2 坑点 2会话ID丢失记忆不生效现象每次请求都是新的开始大模型记不住之前的对话。原因没有在请求中传入conversationId。conversationId每次都不一样没有复用。传入conversationId的方式错误没有使用advisorSpec.param(CONVERSATION_ID, conversationId)。解决方案确保每次请求都传入相同的conversationId或使用固定的 userId。确保通过advisors(advisorSpec - advisorSpec.param(CONVERSATION_ID, conversationId))传入会话 ID。6.3 坑点 3记忆窗口太大导致 Token 超限现象请求报错提示 “Prompt too large” 或 “Token limit exceeded”。原因maxMessages设置得太大历史消息占用了过多 Token。没有预留足够的 Token 空间给当前用户问题和大模型响应。解决方案调小maxMessages或maxTokens参数。优先使用TokenWindowChatMemory更精确地控制 Token 数量。6.4 坑点 4多个 ChatClient共享记忆现象不同模型的对话记忆串线了Qwen的对话出现在DeepSeek的记忆中。原因多个ChatClient 使用了相同的ChatMemory实例且没有区分会话ID前缀。解决方案给不同模型的会话ID加上不同的前缀如 Qwen 用qwen_开头DeepSeek 用deepseek_开头。或者给不同模型使用独立的ChatMemory实例。6.5 坑点 5Redis 内存溢出现象Redis内存占用持续增长最终导致OOM。原因没有设置会话过期机制对话历史无限增长。Redis 的内存过期策略设置不合理。解决方案实现会话过期机制定期清除长时间未使用的对话记忆。给 Redis 设置合理的内存过期策略如allkeys-lru。监控 Redis 内存使用情况及时扩容或清理数据。七、本篇总结本篇我们深度掌握了Spring AI Chat Memory的全体系从核心原理出发理解了 Chat Memory 的工作流程与 Spring AI 的核心抽象。基于 Redis 实现了持久化对话记忆完成了从配置、集成到会话隔离的全流程实战。覆盖了记忆窗口控制、内存记忆与持久化记忆对比、会话管理等企业级高频场景。补充了生产环境最佳实践与高频踩坑避坑指南为 Chat Memory 的生产落地提供了完整的解决方案。Chat Memory 是实现连贯多轮对话的核心能力只有掌握了持久化记忆与会话隔离才能真正开发出面向多用户的企业级 AI 应用。八、下篇预告本篇我们掌握了Chat Memory核心能力实现了带持久化记忆的多轮对话。至此Spring AI 的核心基础能力基础集成、ChatClient、Prompt 工程、结构化输出、Tool Calling、Chat Memory我们已经全部掌握。在本系列的下一篇中我们将进入Spring AI企业级高级能力的最后一块拼图 ——RAG检索增强生成如果本文对你有帮助欢迎点赞、收藏、评论跟着系列教程一步步完成 Spring AI 企业级应用的全流程落地。

相关文章:

Spring AI实战系列(七):Chat Memory对话记忆实战,基于Redis实现持久化多轮对话

一、系列回顾与本篇定位1.1 系列回顾第一篇:完成Spring AI与阿里云百炼的基础集成,基于ChatModel 实现同步对话与API Key安全注入。第二篇:解锁ChatClient,实现全局统一配置与链式调用,告别重复样板代码。第三篇&#…...

101. 如何通过 Rancher Manager 收集指标

Environment 环境 Rancher 2.10 牧场主 2.10 Procedure 程序Rancher support might ask you to collect the Prometheus metrics for the cattle-cluster-agent. 牧场主支持可能会让你收集牛群集群代理的普罗米修斯指标。 They are available through the Rancher local clu…...

Qwen3.5-9B多模态能力:手写公式识别+LaTeX代码生成效果展示

Qwen3.5-9B多模态能力:手写公式识别LaTeX代码生成效果展示 1. 模型核心能力概览 Qwen3.5-9B是一款拥有90亿参数的开源大语言模型,在多模态理解和处理方面表现出色。这个模型特别适合处理需要结合图像和文本信息的复杂任务,比如手写公式识别…...

FlowState Lab问题排查大全:从依赖错误到显存溢出的解决方案

FlowState Lab问题排查大全:从依赖错误到显存溢出的解决方案 1. 引言 遇到技术问题时的挫败感,相信每个开发者都深有体会。特别是当你满怀期待地准备运行FlowState Lab时,突然蹦出的错误提示就像一盆冷水浇下来。别担心,这篇文章…...

终极指南:如何快速完成语雀文档批量导出与迁移

终极指南:如何快速完成语雀文档批量导出与迁移 【免费下载链接】yuque-exporter export yuque to local markdown 项目地址: https://gitcode.com/gh_mirrors/yuq/yuque-exporter 在当今数字化创作时代,语雀文档批量导出已成为许多创作者和团队的…...

深入解析ReID核心评价指标:从Rank1到mINP的实战应用

1. ReID评价指标入门:为什么我们需要这么多指标? 第一次接触ReID(行人重识别)的朋友可能会被各种评价指标搞得头晕——Rank1、mAP、ROC、mINP...这些字母组合到底在说什么?其实这些指标就像医生给病人做体检时的不同检…...

如祺出行2025年营收53亿:网约车贡献97%收入 净亏2.9亿

雷递网 乐天 4月1日如祺出行科技有限公司(股份代号:9680)日前发布截至2025年12月31日的财报。财报显示,如祺出行2025年营收为52.86亿元,较上年同期的24.63亿元增长114.6%。如祺出行收入主要来自网约车服务,…...

AI读脸术如何对接API?Flask服务封装部署教程

AI读脸术如何对接API?Flask服务封装部署教程 1. 为什么需要把“读脸术”变成API? 你可能已经试过这个AI读脸术镜像:上传一张照片,几秒内就能看到人脸框、性别和年龄段标签,效果干净利落。但如果你正开发一个用户管理…...

AI在测试中的应用:从测试用例生成到缺陷预测

随着软件开发流程向敏捷与DevOps的持续演进,软件测试面临着迭代周期缩短、系统复杂度飙升的双重压力。传统的测试方法,高度依赖人工经验与重复劳动,在效率、覆盖率和预测性上逐渐显现瓶颈。人工智能技术的引入,正从辅助工具演变为…...

FastAPI ORM 封装:FastAPI 与 SQLModel 的无缝集成与快速开发

更多内容请见: 《Python Web项目集锦》 - 专栏介绍和目录 核心价值: SQLModel 是 FastAPI 作者 Tiangolo 为 Python Web 开发量身打造的"ORM 终极解决方案",它将 Pydantic 模型与 SQLAlchemy 深度融合,让开发者在编写 API 时无需在数据库模型和 API 模型之间反复…...

小红书数据采集实战:5个Python技巧让爬虫更智能

小红书数据采集实战:5个Python技巧让爬虫更智能 【免费下载链接】xhs 基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/ 项目地址: https://gitcode.com/gh_mirrors/xh/xhs 在小红书这个拥有数亿用户的社交电商平台上,海量的用…...

C++ ODB ORM 实战指南

好的,这是一份关于在 C 中使用 ODB ORM 的指南,涵盖从基础概念到实际应用的各个方面。 1. ODB ORM 简介 对象关系映射 (ORM) 是一种编程技术,用于在面向对象的编程语言(如 C)和关系型数据库之间建立映射关系。它允许开…...

3大核心功能解锁Wallpaper Engine资源:RePKG工具全方位应用指南

3大核心功能解锁Wallpaper Engine资源:RePKG工具全方位应用指南 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 突破资源限制的三个关键能力 你是否曾遇到这样的困境&a…...

《算法竞赛从入门到国奖》算法基础:动态规划-最长子序列

💡Yupureki:个人主页 ✨个人专栏:《C》 《算法》《Linux系统编程》《高并发内存池》《MySQL数据库》 《个人在线OJ平台》 🌸Yupureki🌸的简介: 目录 1. 最长上升子序列 算法原理 代码示例 2. 合唱队形 算法原理 代码示例 3. 最长公共…...

实战演练:基于快马平台与AI模型打造一个智能电商导购Agent

最近在尝试将AI技术落地到实际业务场景中,发现电商导购是个非常实用的切入点。今天就来分享下如何用InsCode(快马)平台快速搭建一个智能电商导购Agent的全过程。 项目架构设计 这个导购Agent采用前后端分离架构,主要分为三个模块: 前端交互…...

OpenClaw技能市场:10个适配Qwen2.5-VL-7B的实用自动化模块

OpenClaw技能市场:10个适配Qwen2.5-VL-7B的实用自动化模块 1. 为什么需要为Qwen2.5-VL-7B定制技能? 当我第一次在本地部署Qwen2.5-VL-7B这个多模态模型时,最让我惊喜的是它对图像和文本的联合理解能力。但很快我发现一个问题:模…...

阿博图书馆管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

💡实话实说:用最专业的技术、最实惠的价格、最真诚的态度服务大家。无论最终合作与否,咱们都是朋友,能帮的地方我绝不含糊。买卖不成仁义在,这就是我的做人原则。摘要 在信息化时代背景下,图书馆作为知识传…...

杭州污水提升泵靠谱厂家

在杭州及周边地区进行地下室改造、商业空间建设或解决特殊排污需求时,选择一家技术可靠、服务专业的污水提升泵厂家至关重要。在众多厂家中,杭州富阳赛特仪表阀门有限公司(赛斯瑞特) 凭借其深厚的技术积淀、过硬的产品品质和完善的…...

绝地求生游戏辅助工具:罗技鼠标宏自动化配置指南

绝地求生游戏辅助工具:罗技鼠标宏自动化配置指南 【免费下载链接】logitech-pubg PUBG no recoil script for Logitech gaming mouse / 绝地求生 罗技 鼠标宏 项目地址: https://gitcode.com/gh_mirrors/lo/logitech-pubg 在《绝地求生》这款高强度的战术竞技…...

精选 Skills 推荐:10 个让 Coding Agent 如虎添翼的Skills + 优质来源分享

精选 Skills 推荐:10 个让 Coding Agent 如虎添翼的Skills 优质来源分享 本篇是 Vibecoding 系列教程 的工具导向专题篇。 前篇:进阶教程(一):MCP Skills 让 coding agent 有自己的工具系列合集:Vibecodi…...

OpenClaw+Qwen3-14b_int4_awq:自动化内容处理与发布流水线

OpenClawQwen3-14b_int4_awq:自动化内容处理与发布流水线 1. 为什么需要自动化内容流水线 作为一个长期与文字打交道的创作者,我每天要处理大量重复性工作:从各个渠道收集素材、整理成结构化内容、撰写初稿、调整格式、最后发布到不同平台。…...

嵌入式开发中的寄存器操作与函数指针应用

1. 嵌入式开发中的寄存器操作技巧在嵌入式系统开发中,直接操作硬件寄存器是最基础也是最核心的技能之一。寄存器是CPU与外围设备交互的窗口,通过读写特定内存地址的寄存器,我们可以控制硬件的行为。下面我将详细介绍几种常见的寄存器操作方法…...

OpenClaw自动化边界:千问3.5-27B不适合处理的五类任务

OpenClaw自动化边界:千问3.5-27B不适合处理的五类任务 1. 为什么需要明确自动化边界? 去年冬天,我花了整整三天时间调试一个OpenClaw自动化流程——让AI帮我整理电脑里积压的200GB设计素材。当看到脚本误删了未备份的客户源文件时&#xff…...

环境科研必备:从入门到精通:大气颗粒物PMF源解析技术全案解析(含软件实操)

在大气环境科研领域,源解析是精准治污的“眼睛”。而在众多源解析方法中,PMF(正定矩阵因子分解)模型因其无需先验信息、结果物理意义明确等优势,成为了科研人员手中的“金标准”。然而,很多同学在实操中常常…...

【网络层-IP数据报】

网络层-IP数据报一、概念二、内容三、分片一、概念 1.IP 属于网络层协议,提供不可靠、无连接的数据包交付服务,核心单元就是 IP 数据报。 2.无连接:每个数据报独立路由,走不同路径也可以。 3.不可靠:不保证一定送达、…...

化整为零、分而治之、异步编排:一文读懂现代并发的底层心法

LongAdder:化整为零,热点分散 在Java多线程编程中,‌原子变量(如AtomicLong)‌通过CAS操作实现线程安全的累加。然而,在高并发场景下,大量线程争抢同一原子变量会引发严重的‌缓存一致性问题‌。…...

曾经我和大模型交流业务实现记录

第一次: 我有一组子组件11个,通过子组件的不同组合,可以组成表单,这些表单让不同的用户使用,表单组成公共的内容,让大部分用户使用,当然用户可以在这些表单的基础上修改一些默认值,变…...

Pixel Aurora Engine应用场景:独立开发者低成本构建像素IP资产库

Pixel Aurora Engine应用场景:独立开发者低成本构建像素IP资产库 1. 像素艺术创作新纪元 在游戏开发领域,像素艺术始终保持着独特的魅力。从早期的《超级马里奥》到现代的《星露谷物语》,像素风格游戏凭借其怀旧感和艺术表现力,…...

数据库表的性能优化过程

问题背景做一个数据库表查看、标注与分析的工具软件。是数据库中表的信息(information_schema.tables);是的数据字典文档,存储在本地文件中;是对的额外标注信息,存储在另一个数据库中。每一条,最…...

新手福音:通过快马平台零代码基础理解qun329群聊应用开发

作为一个刚接触编程的新手,想要理解群聊应用开发确实容易一头雾水。最近我在尝试用InsCode(快马)平台搭建类似qun329的简单群聊网页时,发现整个过程比想象中简单很多。下面分享我的学习过程,希望能帮到同样零基础的朋友。 项目结构规划 首先明…...