Spring AI开发跃迁指南(第二章:急速上手3——Advisor核心原理、源码讲解及使用实例)
1.Advisor简介
Spring AI 中的 Advisor 是一种核心机制,用于拦截和增强 AI 应用程序中的请求与响应流。其设计灵感来源于 Spring AOP(面向切面编程)中的切面(Aspect)概念,但专门针对 AI 交互场景进行了优化。
1.1.核心概念
- 定义与定位
Advisor 是 Spring AI 中负责动态干预聊天请求和响应流程的组件,通过链式结构(Chain of Responsibility 模式)串联多个处理单元。每个 Advisor 可以修改请求参数、增强数据、拦截敏感操作,甚至中断请求传递。
- 与AOP的关系
其功能类似于 Spring 的 AspectJ
,但更专注于 AI 交互场景。例如,通过 AroundAdvisor
接口实现请求前后的增强逻辑。
1.2.Advisord的核心特点
- 模块化封装
- 重复任务封装:将生成式 AI 的通用模式(如上下文记忆、敏感词过滤)抽象为可复用的组件。
- 数据转换:优化发送至语言模型(LLM)的输入数据格式,并处理返回的响应(如结构化输出转换)。
- 可移植性:同一 Advisor 可适配不同模型(如 OpenAI、HuggingFace)和用例,提升代码灵活性。
- 链式处理机制
多个 Advisor 按顺序执行,每个环节可修改请求或响应,并决定是否继续传递。某些 Advisor(如 SafeGuardAdvisor
)可能直接中断链式流程。
- 内置与扩展性
Spring AI 提供多种内置 Advisor,同时也支持开发者自定义扩展,满足个性化需求。
2.Advisor源码及核心原理
2.1.关键类与关系
-
核心接口
-
Ordered
定义getOrder()
方法,用于控制Advisor
的执行顺序(类似 Spring 的优先级机制)。小order先管请求、后管响应,大order反之;同值顺序随机。
-
Advisor
基础接口,定义getName()
方法标识 Advisor 名称。
-
-
具体 Advisor 实现
CallAroundAdvisor
同步调用增强器,通过aroundCall()
方法拦截请求并返回响应。StreamAroundAdvisor
流式调用增强器,通过aroundStream()
方法处理流式响应(返回Flux<AdvisedResponse>
)。
-
请求与响应对象
AdvisedRequest
包含可变的 Prompt 数据和上下文信息(adviseContext
)。AdvisedResponse
封装 Chat 响应和上下文信息。
-
调用链(Chain)类
CallAroundAdvisorChain
通过nextAroundCall()
方法传递请求,支持链式调用多个CallAroundAdvisor
。StreamAroundAdvisorChain
类似CallAroundAdvisorChain
,但用于流式场景的链式调用。
2.2.核心交互流程
-
请求初始化
Spring AI框架将用户的输入(Prompt
)转换为AdvisedRequest
,并创建一个空的共享上下文对象AdvisorContext
。 -
Advisor链处理请求
- 每个
Advisor
依次处理AdvisedRequest
,可以:- 修改请求内容(例如调整参数、添加元数据)。
- 直接拦截请求,阻止后续调用,并自行生成响应(
AdvisedResponse
)。
- 若未拦截,请求会传递到链中的下一个
Advisor
。
- 每个
-
调用Chat Model
最后一个框架内置的
Advisor
负责将处理后的请求发送给Chat Model(如GPT模型)。 -
响应逆向传递
- Chat Model生成的原始响应(
ChatResponse
)会转换为AdvisedResponse
,并携带共享的AdvisorContext
。 - 响应沿Advisor链反向传递,每个
Advisor
可对响应进行二次处理或修改(例如过滤敏感内容、格式化输出)。
- Chat Model生成的原始响应(
-
响应返回
最终的
AdvisedResponse
通过提取ChatCompletion
(响应核心内容)返回给客户端。
流程图如下:
flowchart TDsubgraph 请求阶段A[Client Prompt] --> B[生成 AdvisedRequest\n+ AdvisorContext]B --> C[Advisor1]C -->|修改请求| D[Advisor2]D -->|拦截请求| E[生成 AdvisedResponse]D -->|放行| F[调用 Chat Model]endsubgraph 响应阶段F --> G[ChatResponse → AdvisedResponse]G --> H[Advisor2 处理响应]H --> I[Advisor1 处理响应]I --> J[返回最终响应]endE --> JJ --> K[Client]
2.3.设计特点
- 责任链模式
通过AdvisorChain
实现多个 Advisor 的链式调用,支持动态扩展增强逻辑。 - 上下文传递
AdvisedRequest
和AdvisedResponse
中的adviseContext
允许在链式调用中共享数据。 - 同步与流式分离
通过CallAroundAdvisor
和StreamAroundAdvisor
区分处理普通请求和流式请求。
2.4.Avisor相关源码解析
Advisor 接口位于org.springframework.ai.chat.client.advisor.api
包中,是实现自定义Advisor的关键接口:
public interface Advisor extends Ordered {String getName();
}
同步和流式Advisor的两个子接口继承自Advisor:
- 同步的CallAroundAdvisor:
/*** Around advisor that wraps the ChatModel#call(Prompt) method.** @author Christian Tzolov* @author Dariusz Jedrzejczyk* @since 1.0.0*/public interface CallAroundAdvisor extends Advisor {/*** Around advice that wraps the ChatModel#call(Prompt) method.* @param advisedRequest the advised request* @param chain the advisor chain* @return the response*/AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain);}
- 流式的StreamAroundAdvisor:
/*** Around advisor that runs around stream based requests.** @author Christian Tzolov* @author Dariusz Jedrzejczyk* @since 1.0.0*/
public interface StreamAroundAdvisor extends Advisor {/*** Around advice that wraps the invocation of the advised request.* @param advisedRequest the advised request* @param chain the chain of advisors to execute* @return the result of the advised request*/Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain);}
要使用Advice链,需在你的Advice实现中使用CallAroundAdvisorChain
和StreamAroundAdvisorChain
:
public interface CallAroundAdvisorChain {AdvisedResponse nextAroundCall(AdvisedRequest advisedRequest);}
public interface StreamAroundAdvisorChain {Flux<AdvisedResponse> nextAroundStream(AdvisedRequest advisedRequest);}
自定义Advisor就需要实现
CallAroundAdvisor
和StreamAroundAdvisor
中的最少一个。其中的关键方法是nextAroundCall()
或nextAroundStream()
。
3.Spring AI内置的Advisor
-
MessageChatMemoryAdvisor
作用:
责维护对话的上下文记忆,将用户的问题与模型的回答保存到内存中,确保多轮对话的连贯性。例如,在连续对话中,历史记录会被自动附加到新请求中,帮助模型理解上下文。
核心特点:
- 上下文增强:通过
messages
参数传递历史对话记录。 - 模型兼容性要求:仅适用于支持
messages
参数的模型(如 OpenAI 的 GPT 系列)。 - 动态扩展:每次对话自动更新内存中的历史记录。
- 上下文增强:通过
-
PromptChatMemoryAdvisor
作用:
与
MessageChatMemoryAdvisor
类似,但将上下文历史记录封装到systemPrompt
提示词中,而非直接依赖messages
参数。这使得无论模型是否支持messages
参数,都能实现上下文记忆。核心特点:
- 灵活性:通过修改系统提示词(
systemPrompt
)嵌入历史对话,兼容性更广。 - 无侵入式设计:不依赖模型底层接口,仅通过提示词工程实现上下文管理。
- 灵活性:通过修改系统提示词(
-
QuestionAnswerAdvisor
作用:
实现检索增强生成(RAG),通过查询向量数据库或知识库获取相关文本片段,并将其附加到用户问题后,提升回答的准确性和相关性。
核心特点:
- 知识库集成:支持自定义向量数据库(如:Milvus、Weaviate、Elasticsearch、FAISS)。
- 默认拒绝机制:若知识库无匹配内容,则拒绝回答用户问题,避免生成错误信息。
- 提示词优化:内置默认提示词模板,确保回答与检索内容强相关。
-
SafeGuardAdvisor
作用:
敏感词过滤与安全拦截,防止用户输入或模型输出包含违规内容。当检测到敏感词时,直接中断请求链,避免调用大模型处理。
核心特点:
- 实时拦截:基于预定义规则或动态词库进行校验。
- 链式中断:直接终止后续处理,降低资源消耗与安全风险。
-
VectorStoreChatMemoryAdvisor
作用:
将对话历史长期存储到向量数据库中,并在每次提问时检索相关历史记录,增强上下文提示的准确性和长期记忆能力。
核心特点:
- 向量化存储:利用向量数据库高效检索相似历史对话片段。
- 关键参数管理:依赖
chat_memory_conversation_id
标识用户会话,避免数据冗余。 - 数据清理机制:需定期清理旧数据,防止数据库膨胀。
-
SimpleLoggerAdvisor
作用:
记录请求与响应的日志信息,便于调试和监控 AI 交互流程。例如,可打印用户输入、模型输出及处理耗时。
核心特点:
- 轻量级工具:无需复杂配置,快速集成日志功能。
- 可扩展性:支持自定义日志格式与存储方式。
4.自定义Advisor实现
4.1.自定义日志Advisor
我们自定义一个日志Advisor,在调用链中的下一个顾问之前记录AdvisedRequest
,之后记录AdvisedResponse
。
此advisor只观察请求和响应,不做任何膝盖且同时支持非流和流场景。
public class SimpleLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {private static final Logger logger = LoggerFactory.getLogger(SimpleLoggerAdvisor.class);// 为Advisor提供一个唯一的名称@Overridepublic String getName() {return this.getClass().getSimpleName();}// 设置order值来控制执行顺序,值较小的将优先执行@Overridepublic int getOrder() {return 0;}@Overridepublic AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {logger.debug("BEFORE: {}", advisedRequest);AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);logger.debug("AFTER: {}", advisedResponse);return advisedResponse;}@Overridepublic Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {logger.debug("BEFORE: {}", advisedRequest);Flux<AdvisedResponse> advisedResponses = chain.nextAroundStream(advisedRequest);// MessageAggregator是一个实用程序类,它将Flux响应聚合到单个AdvisedResponse中,// MessageAggregator为只读,不可更改其中的响应return new MessageAggregator().aggregateAdvisedResponse(advisedResponses,advisedResponse -> logger.debug("AFTER: {}", advisedResponse));}
}
4.2.Re2 Advisor
“重读提升大型语言模型的推理能力”一文介绍了一种名为重读(Re2)的技术,它可以提升大型语言模型的推理能力。Re2 技术需要像这样扩充输入提示:
{输入查询} 再次阅读问题:{Input_Query}
实现Re2技术的Advisor:
public class ReReadingAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {// 应用Re2增强用户的输入查询private AdvisedRequest before(AdvisedRequest advisedRequest) {Map<String, Object> advisedUserParams = new HashMap<>(advisedRequest.userParams());advisedUserParams.put("re2_input_query", advisedRequest.userText());return AdvisedRequest.from(advisedRequest).userText("""{re2_input_query}Read the question again: {re2_input_query}""").userParams(advisedUserParams).build();}// 拦截非流式请求并应用Re2@Overridepublic AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {return chain.nextAroundCall(this.before(advisedRequest));}// 拦截流试请求并应用Re2技术@Overridepublic Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {return chain.nextAroundStream(this.before(advisedRequest));}@Overridepublic int getOrder() {return 0;}@Overridepublic String getName() {return this.getClass().getSimpleName();}
}
5.Advisor使用示例
我们以MessageChatMemoryAdvisor
为例做一个advisor的使用实例,主要在ChatClient.builder中使用defaultAdvisors()方法配置Advisor,此方法可配置多个Advisor。
Builder defaultAdvisors(Advisor... advisor);Builder defaultAdvisors(Consumer<AdvisorSpec> advisorSpecConsumer);Builder defaultAdvisors(List<Advisor> advisors);
示例主要有controller、service及config配置,相关的pom依赖主要使用spring-ai-starter-model-minimax
包等,具体的pom及minimax模型的配置请参考:Spring AI开发跃迁指南(第二章:极速上手——ChatClient20行代码构建人工智能应用)
5.1.示例代码
- ChatConfig
package com.common;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ChatConfig {@Beanpublic ChatMemory chatMemory() {return new InMemoryChatMemory(); // 简单内存实现}// 2. 创建 MessageChatMemoryAdvisor@Beanpublic MessageChatMemoryAdvisor chatMemoryAdvisor(ChatMemory chatMemory) {return new MessageChatMemoryAdvisor(chatMemory);}// 配置 ChatClient,绑定 Advisor@Beanpublic ChatClient chatClient(ChatModel chatModel, MessageChatMemoryAdvisor advisor) {return ChatClient.builder(chatModel).defaultAdvisors(advisor) // 添加 Advisor.build();}
}
- service
@Service
public class TestSpringAIServiceImpl {@Autowiredprivate ChatClient chatClient;@Overridepublic String generate(String message) {return chatClient.prompt().advisors(advisorSpec -> advisorSpec.param("chat_memory_conversation_id", "111").param("chat_memory_response_size", 100)).user(message).call().content();}
}
- controller
@RestController
public class TestSpringAIController {@Autowiredprivate TestSpringAIServiceImpl service; @GetMapping("/ai/generate")public String generate(@RequestParam(value = "message", defaultValue = "生成一个中国女演员及其电影作品") String message) {return service.generate(message);}
}
- 运行结果
-
第一次运行结果:
-
第二次运行结果:
-
执行结果分析
- 第一次对话:声明自己的名字为“张三”,
MessageChatMemoryAdvisor
会将此对话记录(用户输入和模型回复)保存到内存中。 - 第二次对话:用户提问“我的名字是什么?”,模型会根据
MessageChatMemoryAdvisor
提供的上下文历史(包含第一次对话)生成正确回答。
5.2.关键机制解释
-
内存管理
InMemoryChatMemory
默认以List<Message>
形式存储对话历史,每次调用chatClient.call()
时,MessageChatMemoryAdvisor
会自动将历史记录附加到当前请求中(通过messages
参数传递)。 -
上下文传递
模型(如 OpenAI GPT)接收到完整的messages
列表后,会自动解析历史对话,确保回答的连贯性。 -
会话隔离
若需区分不同用户的对话,需通过ChatMemory
的conversationId
参数管理会话标识:// 为不同用户分配唯一会话 ID ChatMemory memory = new InMemoryChatMemory("user-123");
若需自定义历史记录的条数或存储策略:
@Bean
public ChatMemory chatMemory() {InMemoryChatMemory memory = new InMemoryChatMemory();memory.setMaxHistorySize(10); // 限制最多保留 10 条历史记录return memory;
}
注意:
- 模型兼容性:确保底层模型(如 OpenAI、MiniMax)支持
messages
参数格式。- 内存泄漏风险:若使用
InMemoryChatMemory
,需在长期运行的应用中定期清理过期会话。
相关文章:
Spring AI开发跃迁指南(第二章:急速上手3——Advisor核心原理、源码讲解及使用实例)
1.Advisor简介 Spring AI 中的 Advisor 是一种核心机制,用于拦截和增强 AI 应用程序中的请求与响应流。其设计灵感来源于 Spring AOP(面向切面编程)中的切面(Aspect)概念,但专门针对 AI 交互场景进行了优化…...
51c嵌入式~单片机~合集9
我自己的原文哦~ https://blog.51cto.com/whaosoft/13884964 一、单片机中hex、bin文件的区别 单片机程序编译之后,除了生成hex文件之外还生成了bin文件,实际它们都是单片机的下载文件,下文介绍它们的区别。 Hex Hex文件包含地址信息。…...
linux学习——数据库API创建
一.API操作 1.int sqlite3_open(char *filename,sqlite3 **db) 功能:打开sqlite数据库 参数: filename:数据库文件路径 db:指向sqlite句柄的指针 (splite3* db;) 返回值…...
21.2Linux中的LCD驱动实验(驱动)_csdn
1、修改设备树 1.1、LCD 屏幕使用的 IO 配置 编译: make uImage LOADADDR0XC2000040 -j8 //编译内核复制给内核的镜像路径:1.2、LDTC 接口节点修改 1.3、输出接口的编写 2、在 panel-simple.c 文件里面添加屏幕参数 显示波浪线是因为alientek_desc 保存参…...
Dubbo(89)如何设计一个支持多语言的Dubbo服务?
设计一个支持多语言的Dubbo服务需要考虑以下几个方面: 服务接口设计:确保服务接口的定义可以被不同语言实现。序列化协议:选择一个支持多语言的序列化协议,例如Protobuf、Thrift、gRPC等。服务注册与发现:确保服务注册…...
油气地震资料数据中“照明”的含义
油气地震资料数据中“照明”的含义 在地震勘探中,“照明”(Illumination)是一个比喻性术语,用于描述地下地质构造被地震波能量覆盖的程度。其核心含义包括: 能量覆盖:指地震波(如人工激发的地…...
[FPGA Video IP] Frame Buffer Read and Write
Xilinx Video Frame Buffer Read and Write IP (PG278) 详细介绍 概述 Xilinx LogiCORE™ IP Video Frame Buffer Read(帧缓冲读取)和 Video Frame Buffer Write(帧缓冲写入)核(PG278)是一对专为视频处理…...
新能源行业供应链规划及集成计划报告(95页PPT)(文末有下载方式)
资料解读:《数字化供应链规划及集成计划现状评估报告》 详细资料请看本解读文章的最后内容。 该报告围绕新能源行业 XX 企业供应链展开,全面评估其现状,剖析存在的问题,并提出改进方向和关键举措,旨在提升供应链竞争力…...
curl详解
curl 是一个常用的命令行工具,用于发送 HTTP 请求,支持包括 GET、POST、PUT、DELETE 等在内的多种 HTTP 方法。它非常适合用来测试 API、下载文件、与后端服务进行交互等。接下来,我会详细讲解 curl 的基本用法以及常见的应用场景。 &#x…...
博客打卡-人类基因序列功能问题动态规划
题目如下: 众所周知,人类基因可以被认为是由4个核苷酸组成的序列,它们简单的由四个字母A、C、G和T表示。生物学家一直对识别人类基因和确定其功能感兴趣,因为这些可以用于诊断人类疾病和设计新药物。 生物学家确定新基因序列功能…...
Runnable组件动态添加默认调用参数
01. bind 函数用途与使用技巧 在使用 LangChain 开发时,某些场景我们希望在一个 Runnable 队列中调用另一个 Runnable 并传递常量参数,这些参数既非前序 Runnable 的输出,也不是用户输入,而是组件自身的部分参数。此时可以使用 R…...
系统架构设计师:设计模式概述
面向对象技术为软件技术带来新的发展。人们运用面向对象的思想分析系统、为系统建模并设计系统,最后使用面向对象的程序语言来实现系统。 但是面向对象的设计并不是一件很简单的事情,尤其是要设计出架构良好的软件系统更不容易。 为了提高系统的复用性…...
天山流域流量数据集(1991-2019)
时间分辨率日空间分辨率/共享方式开放获取数据大小131.67 MB数据时间范围 1901-01-01 — 2019-12-31 元数据更新时间2025-03-24 数据集摘要 由于天山地区数据稀缺和水文条件复杂,中亚水塔的自然径流数据集在各种全球径流数据集(如GMIS、GRDC)…...
Linux 环境下 Mysql 5.7 数据定期备份
目录 一、创建数据备份脚本二、查看备份日志三、数据库数据恢复 备份策略: 系统环境 openEuler 22.03 (LTS-SP4) 单机备份 每天凌晨2点,指定数据库表全量备份,只保留近7次备份数据 每次的脚本执行,将会记录执行结果到日志…...
多模态大语言模型arxiv论文略读(五十二)
M3D: Advancing 3D Medical Image Analysis with Multi-Modal Large Language Models ➡️ 论文标题:M3D: Advancing 3D Medical Image Analysis with Multi-Modal Large Language Models ➡️ 论文作者:Fan Bai, Yuxin Du, Tiejun Huang, Max Q. -H. M…...
REST API、FastAPI与Flask API的对比分析
以下是关于REST API、FastAPI与Flask API的对比分析,涵盖架构设计、性能表现、开发效率等核心维度: 一、核心定位与架构差异 REST API 本质:一种基于HTTP协议的架构风格,强调资源化操作(通过URI定位资源)、…...
【论文阅读26】贝叶斯-滑坡预测-不确定性
📖 这篇论文主要说了什么? 📌 背景: 滑坡预测里,预测失稳时间(Slope Failure Time, SFT) 很关键,但它受两方面不确定性影响: 观测不确定性(监测数据本身的…...
【笔记】深度学习模型训练的 GPU 内存优化之旅④:内存交换与重计算的联合优化篇
开设此专题,目的一是梳理文献,目的二是分享知识。因为笔者读研期间的研究方向是单卡上的显存优化,所以最初思考的专题名称是“显存突围:深度学习模型训练的 GPU 内存优化之旅”,英文缩写是 “MLSys_GPU_Memory_Opt”。…...
边缘计算革命:大模型轻量化部署全栈实战指南
当ResNet-152模型能在树莓派4B上实现每秒27帧实时推理时,边缘智能时代真正到来。本文解析从模型压缩到硬件加速的完整技术栈,实测Transformer类模型在移动端的部署时延可压缩至16ms,揭示ARM芯片实现INT4量化的工程秘诀与十种典型场景优化方案…...
LangChain4j +DeepSeek大模型应用开发——7 项目实战 创建硅谷小鹿
这部分我们实现硅谷小鹿的基本聊天功能,包含聊天记忆、聊天记忆持久化、提示词 1. 创建硅谷小鹿 创建XiaoLuAgent package com.ai.langchain4j.assistant;import dev.langchain4j.service.*; import dev.langchain4j.service.spring.AiService;import static dev…...
python自动化测试
Python自动化测试指南 Python是自动化测试领域的首选语言之一,凭借其简洁的语法、丰富的库和强大的生态系统,能够高效地实现各种测试需求。本文将详细介绍Python在自动化测试中的应用,涵盖Web测试、API测试、单元测试、GUI测试等多个方面。 1. 自动化测试基础 测试金字塔…...
49、【OS】【Nuttx】【OSTest】参数解析:测试项
背景 接之前 blog 48、【OS】【Nuttx】【OSTest】内存监控:分配释放推演 解析完内存监控,继续看下一个测试项 getopt_test 测试项 getopt_test 如下 getopt,getopt_long,getopt_long_only getopt() 用来解析命令行短选项&am…...
String StringBuilder StringBuffer
文章目录 StringStringBuilderStringBuffer StringStringBuilderStringBuffer可变性不可变可变可变线程安全安全(天然不可变)不安全安全(同步方法)性能低(频繁操作生成新对象)高中(同步开销&…...
[FPGA 官方 IP] Binary Counter
Xilinx Binary Counter IP (PG121) 详细介绍 概述 Xilinx Binary Counter IP(二进制计数器 IP)是 AMD Xilinx 提供的 LogiCORE™ IP 核,用于在 FPGA 中实现高性能、面积高效的二进制计数器。该 IP 核支持上行计数器、下行计数器以及上/下计…...
【大模型实战篇】华为信创环境采用vllm部署QwQ-32B模型
1. 背景 本文分享在华为昇腾机器上部署QwQ-32B模型的实践。 首先华为自己是提供了一套在信创机器(NPU)上部署模型的方案【1】,但是部署之后,测试发现会有输出截断的现象。QwQ-32B本身是支持128k的最大上下文长度,定位…...
优雅关闭服务:深入理解 SIGINT / SIGTERM 信号处理机制
目录 为什么需要优雅关闭? 什么是 SIGINT 和 SIGTERM? 如何实现优雅关闭(以 C 为例) 示例代码(gRPC 服务 Boost 信号监听): 优雅关闭时的清理内容通常包括: 与 SIGKILL 的区别…...
2025五一杯数学建模竞赛选题建议+初步分析
完整内容请看文章最下面的推广群 2025五一杯数学建模竞赛选题建议初步分析 提示:C君认为的难度和开放度评级如下: 难度:B题 > A题 > C题,开放度:B题 > C题 > A题。综合来看:A题目标明确,数据…...
自动剪辑批量混剪视频过原创软件工具视频帧级处理技术实践批量截图解析
一、引言:视频素材精细化处理的技术需求 在视频内容生产与分析场景中,高效的帧级处理是素材解构的核心环节。本文结合实战经验,解析基于智能帧截取算法、参数化配置系统、多线程并行处理的批量帧处理技术方案,构建可复用的工程化…...
GD32F407单片机开发入门(二十五)HC-SR04超声波模块测距实战含源码
文章目录 一.概要二.HC-SR04主要参数1.模块引脚定义2.模块电气参数3.模块通讯时序4.模块原理图 三.GD32单片机超声波模块测距实验四.工程源代码下载五.小结 一.概要 HC-SR04超声波模块常用于机器人避障、物体测距、液位检测、公共安防、停车场检测等场所。HC-SR04超声波模块主…...
C++11新特性_Lambda 表达式
Lambda 表达式是 C11 引入的一项重要特性,它允许你在代码中创建匿名函数对象。Lambda 表达式为编写简洁、灵活的代码提供了便利,尤其适用于函数式编程和需要传递简短回调函数的场景。下面从基本语法、捕获列表、使用场景等方面详细介绍 Lambda 表达式。 …...
vue中$set原理
Vue 中的 $set 方法(Vue.set)主要用于 向响应式对象中添加一个新的属性,并确保这个新属性是响应式的,能够触发视图更新。 📌 背景问题:为什么需要 $set? 在 Vue 2 中,直接给对象新增…...
【C++重载操作符与转换】输入和输出操作符
目录 一、输入输出操作符概述 二、输入输出操作符重载的原理 2.1 为什么需要重载? 2.2 重载的限制 2.3 重载的方式 三、输入输出操作符重载的实现 3.1 输出操作符 << 的重载 3.2 输入操作符 >> 的重载 四、输入输出操作符重载的注意事项 4.1 …...
Vue 生命周期全解析:理解组件从创建到销毁的全过程
Vue 生命周期全解析:理解组件从创建到销毁的全过程 Vue.js 是一个流行的前端框架,它通过“组件化开发”提升了代码组织效率。要真正掌握 Vue,生命周期(Lifecycle) 是一个必须深入理解的核心概念。生命周期不仅决定了组…...
MySQL零基础入门:Ubuntu环境安装与操作精解
知识点1【数据库】 数据的存储方式,我们之前学的,从变量,数组,链表,最后到文件,文件之上,便是数据库,而我们要介绍的MySQL就是数据库的关系数据库中的其中一种。 1、数据库 本质&…...
【计算机视觉】语义分割:Mask2Former:统一分割框架的技术突破与实战指南
深度解析Mask2Former:统一分割框架的技术突破与实战指南 技术架构与创新设计核心设计理念关键技术组件 环境配置与安装指南硬件要求安装步骤预训练模型下载 实战全流程解析1. 数据准备2. 配置文件定制3. 训练流程4. 推理与可视化 核心技术深度解析1. 掩膜注意力机制…...
Qt二维码demo
使用QZXing库生成的二维码demo 运行结果 实现代码 c文件 #include "mainwindow.h" #include "ui_mainwindow.h" #include "src/myqrcodeheader.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui-&…...
Java 基础--数组(Array):存储数据的“排排坐”
作者:IvanCodes 发布时间:2025年5月1日🤓 专栏:Java教程 大家好!👋 咱们在编程时,经常需要处理一批相同类型的数据,比如班级里所有同学的成绩 💯、一周每天的最高气温 …...
OpenGL-ES 学习(10) ---- OpenGL-ES Shader语言语法
目录 Shader 举例Shader 语法版本规范声明变量和定法方法向量构造方法矩阵构造方法结构,数组,函数定义结构数组函数 内建函数条件语句和运算符统一变量统一变量块Shader 输入输出插值限定符预处理命令精度限定符不变性 Shader 举例 一个典型的简单的 Sh…...
Unity SpriteAtlas (精灵图集)
🏆 个人愚见,没事写写笔记 🏆《博客内容》:Unity3D开发内容 🏆🎉欢迎 👍点赞✍评论⭐收藏 🔎为什么要打图集? 💡打图集的目的就是减少DrawCall 提高性能 &a…...
(33)VTK C++开发示例 ---图片转3D
文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容👉内容导航 👈👉VTK开发 👈 1. 概述 这是 VTK 测试 clipArt.tcl 的改编版本。 提供带有 2D 剪贴画的 jpg 文件,该示例将创建 3D 多边形数据模…...
RAG工程-基于LangChain 实现 Advanced RAG(预检索-查询优化)(上)
Enrich 完善问题 完善问题流程概述 问题转述 在典型RAG架构中,用户问题的质量直接影响检索系统的表现。研究表明,未经优化的自然语言查询会导致: 关键实体识别缺失 语义漂移导致召回偏离 长尾问题检索失败率升高 大多数用户并非提示词工程…...
交我算使用保姆教程:在计算中心利用singularity容器训练深度学习模型
文章目录 准备工作步骤如何封装和使用容器安装创建 Singularity 容器编写 def 文件构建容器查看构建容器的 python 版本本地测试挂载数据集和代码 如何上传数据windows 系统Linux 系统 如何设置作业任务脚本的结构常用的 Slurm 参数一份完整的 slurm 作业示例 如何在 debug 队列…...
CMake中强制启用option定义变量的方法
在CMake中,若要在另一个CMake文件中强制启用由option()定义的变量,可使用set(... FORCE)覆盖缓存变量。具体步骤如下: 使用set命令强制覆盖缓存: 在需要强制启用选项的CMake文件中,使用set命令并指定CACHE和FORCE参数。…...
图解 Git 工作流:理解 Rebase、Merge 与 Pull Request 的区别
图解 Git 工作流:理解 Rebase、Merge 与 Pull Request 的区别 在多人协作开发中,选择合适的 Git 分支管理策略至关重要。Merge、Rebase 和 Pull Request 是最常见的三种方式,它们本质不同,使用场景也不同。 本文将通过流程图&am…...
图与网络模型
目录 图的基本概念 例题:比赛的安排 MATLAB作图 最短路径模型 Dijkstra算法步骤 最短路径的Dijkstra算法示例 Dijkstra算法的Matlab函数 最短路径的Floyd算法模型 最短路径的Floyd算法步骤 Floyd算法的Matlab函数 图的基本概念 图G是一个二重组: …...
连接linux虚拟机并运行C++【从0开始】
连接linux虚拟机并运行C【从0开始】 NetSarang安装后两个,其实更加常用的 安装VMware安装Ubuntu 的 ISO 镜像VMWare--TipsUbuntu快捷键,可以在设置里面修改 连接Linux运行cwhy剪不断,理还乱操作 因为好多判题系统,后台都是Linux环…...
多线程系列二:Thread类
Thread类是jvm用来管理线程的一个类,换句话说,每个线程都有一个唯一的Thread对象与之关联 1.Thread常见构造方法 Thread():创建线程对象Thread(Runnable target):使用Runnable对象创建线程对象Thread(String name):创…...
2025五一杯数学建模C题:社交媒体平台用户分析问题,完整第一问模型与求解+代码
完整代码模型请见文末名片 • 问题1分析: – 来龙去脉和与其他问题的内在联系: • 来龙去脉:社交媒体平台为了评估博主的价值,合理分配资源和优化内容推荐,需要准确预测博主的新增关注数。新增关注数是衡量博主影响…...
开源飞控软件:推动无人机技术进步的引擎
在过去的二十年里,众多开源自动驾驶仪项目极大地推动了无人机技术的发展。像 MatrixPilot、Baseflight、TauLabs、OpenPilot、Cleanflight、MultiWii 和 dRonin 等一些开源自动驾驶仪项目已经停止开发,然而,Ardupilot/APM、Pixhawk/PX4、Papa…...
Pinia: vue3状态管理
一、Pinia 的相关介绍 1. 什么是 Pinia Pinia 是一个专门配合 vue.js 使用的状态管理, 从而实现跨组建通信或实现多个组件共享数据的一种技术 2. 使用 Pinia 的目的 我们的vuejs有俩个特性: 1> 数据驱动视图. 2> 组件化开发 基于这俩个特性, 我们引出pinia的使用目的 …...