Spring AI Advisor API

📅 发布时间:2026/7/10 18:28:26 👁️ 浏览次数:
Spring AI Advisor API
Spring AI Advisor API 核心学习Spring AI 的 Advisor API 就像给 AI 对话加了一层「智能拦截器」—— 能在调用大模型比如GPT、文心一言的发请求前、收响应后插入你自己写的逻辑。比如自动加对话记忆、优化提示词、过滤敏感内容不用每次调用都重复写这些代码和咱们平时用的 Spring AOP 切面、Web 过滤器思路差不多核心包是org.springframework.ai.chat.client.advisor.api。一、为啥要用 Advisor代码复用把 RAG知识库问答、对话记忆这些常用功能封装成 Advisor不同业务场景直接复用不用重复写灵活改数据发请求前能改提示词收响应后能改返回结果适配不同大模型的格式要求统一管控所有 AI 调用的前置校验、日志记录、异常处理都能集中在 Advisor 里做不用散在业务代码里兼容多模型一套 Advisor 逻辑能在不同大模型OpenAI、百度文心上用不用针对每个模型改代码。二、核心组件大白话解释Advisor API 分「一次性返回结果」非流式和「边返回边显示」流式两种场景核心组件就这几个1. 核心接口你要实现的接口名作用核心方法Advisor所有 Advisor 的父接口getName()起个名字、getOrder()执行顺序CallAroundAdvisor处理非流式 AI 调用一问一答aroundCall(请求, 执行链)StreamAroundAdvisor处理流式 AI 调用连续输出aroundStream(请求, 执行链)2. 数据封装类传递数据用的AdvisedRequest包装要发给大模型的提示词Prompt还带一个「共享上下文」Map能在多个 Advisor 之间传数据AdvisedResponse包装大模型返回的结果同样带共享上下文你可以修改这个结果再返回给业务代码。3. 执行链控制顺序用的CallAroundAdvisorChain/StreamAroundAdvisorChain可以理解成「Advisor 排队器」调用nextAroundCall()/nextAroundStream()就会执行下一个 Advisor直到最后调用大模型。三、Advisor 怎么执行流程顺序1. 执行流程一步一步说就像流水线处理快递业务代码把提示词传给 Spring AI框架先把提示词包装成AdvisedRequest所有 Advisor 按顺序「处理请求」比如给提示词加对话历史、校验敏感词最后一个「框架内置 Advisor」把处理好的请求发给大模型拿到返回结果结果包装成AdvisedResponse再按相反顺序经过所有 Advisor比如过滤返回内容、记录响应日志最终结果返回给业务代码。2. 执行顺序谁先谁后靠getOrder()方法返回的数字决定数字越小越先执行比如Aorder-100→ Border0→ 大模型 → B → A常用常量Ordered.HIGHEST_PRECEDENCE最小数最高优先级、Ordered.LOWEST_PRECEDENCE最大数最低优先级同优先级执行顺序没法保证尽量避免。四、现成能用的 Advisor不用自己写Spring AI 已经做好了一些常用的 Advisor直接拿来用就行对话记忆类记住用户之前的对话比如MessageChatMemoryAdvisor把历史对话加到提示词里知识库问答RAGQuestionAnswerAdvisor从向量库查相关知识再发给大模型实现智能问答内容安全SafeGuardAdvisor过滤有害内容避免生成违规回复。五、自定义 Advisor手把手教写代码自己写 Advisor 分4步下面用「日志记录」和「提示词增强」两个例子代码加详细注释能直接复制用。前置准备先确保项目里引入了 Spring AI 核心依赖以 Maven 为例!-- Spring AI 核心依赖 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-core/artifactIdversion1.0.0-M3/version!-- 注意版本M3是较新的稳定版 --/dependency!-- 若用RAG/向量库需加这个 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-advisors-vector-store/artifactIdversion1.0.0-M3/version/dependency示例1日志记录 Advisor非流式流式都支持这个 Advisor 只做一件事记录 AI 调用的请求和响应不修改数据方便排查问题。importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.ai.chat.client.advisor.api.AdvisedRequest;importorg.springframework.ai.chat.client.advisor.api.AdvisedResponse;importorg.springframework.ai.chat.client.advisor.api.CallAroundAdvisor;importorg.springframework.ai.chat.client.advisor.api.CallAroundAdvisorChain;importorg.springframework.ai.chat.client.advisor.api.StreamAroundAdvisor;importorg.springframework.ai.chat.client.advisor.api.StreamAroundAdvisorChain;importorg.springframework.core.Ordered;importreactor.core.publisher.Flux;/** * 自定义日志Advisor记录AI调用的请求和响应 * 同时支持非流式Call和流式Stream调用 */publicclassLoggingAdvisorimplementsCallAroundAdvisor,StreamAroundAdvisor{// 日志对象用当前类名作为logger名称privatestaticfinalLoggerloggerLoggerFactory.getLogger(LoggingAdvisor.class);/** * 给Advisor起个名字方便后续排查问题/监控 * return Advisor名称 */OverridepublicStringgetName(){// 直接用类名清晰好认returnthis.getClass().getSimpleName();}/** * 设置执行顺序0是中等优先级数字越小越先执行 * 日志建议放中等优先级不影响核心逻辑 * return 执行顺序数值 */OverridepublicintgetOrder(){returnOrdered.LOWEST_PRECEDENCE-100;// 比最低优先级高一点最后处理请求最先处理响应}/** * 处理非流式AI调用一问一答一次性返回结果 * param advisedRequest 包装后的请求含提示词、上下文 * param chain 执行链调用nextAroundCall()会执行下一个Advisor * return 包装后的响应可修改后返回 */OverridepublicAdvisedResponsearoundCall(AdvisedRequestadvisedRequest,CallAroundAdvisorChainchain){// 1. 前置处理记录请求信息logger.info(【AI调用请求】提示词内容{}上下文参数{},advisedRequest.userText(),// 获取用户输入的提示词advisedRequest.adviseContext());// 获取共享上下文try{// 2. 调用下一个Advisor核心必须调用否则请求到不了大模型AdvisedResponseresponsechain.nextAroundCall(advisedRequest);// 3. 后置处理记录响应信息logger.info(【AI调用响应】返回内容{}响应状态{},response.chatResponse().getResult().getOutput().getContent(),// 获取大模型返回的文本response.chatResponse().getMetadata());// 获取响应的元数据比如耗时、模型名称// 4. 返回响应可以修改后返回这里直接返回returnresponse;}catch(Exceptione){// 5. 异常处理记录调用失败的日志logger.error(【AI调用异常】请求处理失败提示词{}异常信息{},advisedRequest.userText(),e.getMessage(),e);throwe;// 抛出异常让上层处理}}/** * 处理流式AI调用边返回边显示比如实时聊天 * param advisedRequest 包装后的请求 * param chain 流式执行链 * return 流式响应Flux是响应式编程的数据流 */OverridepublicFluxAdvisedResponsearoundStream(AdvisedRequestadvisedRequest,StreamAroundAdvisorChainchain){// 1. 前置处理记录流式请求信息logger.info(【AI流式调用请求】提示词内容{},advisedRequest.userText());// 2. 调用下一个Advisor获取流式响应FluxAdvisedResponseresponseFluxchain.nextAroundStream(advisedRequest);// 3. 处理每一段流式响应逐段记录returnresponseFlux.doOnNext(response-{// 每收到一段响应就记录Stringcontentresponse.chatResponse().getResult().getOutput().getContent();logger.info(【AI流式响应片段】内容{},content);}).doOnComplete(()-{// 流式响应结束记录完成日志logger.info(【AI流式调用完成】提示词{},advisedRequest.userText());}).doOnError(e-{// 流式调用异常记录错误logger.error(【AI流式调用异常】提示词{}异常{},advisedRequest.userText(),e.getMessage(),e);});}}示例2提示词增强 Advisor优化用户输入这个 Advisor 会自动给用户的提示词加「格式要求」让大模型返回更规范的结果。importorg.springframework.ai.chat.client.advisor.api.AdvisedRequest;importorg.springframework.ai.chat.client.advisor.api.AdvisedResponse;importorg.springframework.ai.chat.client.advisor.api.CallAroundAdvisor;importorg.springframework.ai.chat.client.advisor.api.CallAroundAdvisorChain;importorg.springframework.ai.chat.client.advisor.api.StreamAroundAdvisor;importorg.springframework.ai.chat.client.advisor.api.StreamAroundAdvisorChain;importorg.springframework.core.Ordered;importreactor.core.publisher.Flux;/** * 提示词增强Advisor自动给用户输入加格式要求让大模型返回更规范的结果 * 比如要求所有回答都用「分点说明」的格式 */publicclassPromptEnhanceAdvisorimplementsCallAroundAdvisor,StreamAroundAdvisor{/** * Advisor名称 */OverridepublicStringgetName(){returnthis.getClass().getSimpleName();}/** * 执行顺序比日志高数字更小先增强提示词再记录日志 */OverridepublicintgetOrder(){return0;// 中等优先级}/** * 通用方法修改提示词抽出来复用避免重复代码 * param originalRequest 原始请求 * return 修改后的请求 */privateAdvisedRequestenhancePrompt(AdvisedRequestoriginalRequest){// 1. 获取用户原始提示词StringoriginalTextoriginalRequest.userText();// 2. 拼接增强后的提示词要求分点说明StringenhancedTextoriginalText\n\n要求请用分点说明的格式回答语言简洁每点不超过20字。;// 3. 创建新的请求AdvisedRequest是不可变对象要重新构建returnAdvisedRequest.from(originalRequest).userText(enhancedText)// 替换增强后的提示词.build();}/** * 非流式处理增强提示词后再调用大模型 */OverridepublicAdvisedResponsearoundCall(AdvisedRequestadvisedRequest,CallAroundAdvisorChainchain){// 1. 增强提示词AdvisedRequestenhancedRequestthis.enhancePrompt(advisedRequest);// 2. 执行下一个Advisorreturnchain.nextAroundCall(enhancedRequest);}/** * 流式处理同样增强提示词 */OverridepublicFluxAdvisedResponsearoundStream(AdvisedRequestadvisedRequest,StreamAroundAdvisorChainchain){// 1. 增强提示词AdvisedRequestenhancedRequestthis.enhancePrompt(advisedRequest);// 2. 执行下一个Advisor返回流式响应returnchain.nextAroundStream(enhancedRequest);}}示例3注册并使用 Advisor写好 Advisor 后需要注册到 ChatClient 里才能生效importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.openai.OpenAiChatModel;/** * 注册Advisor并使用的示例 */publicclassAdvisorUsageExample{publicstaticvoidmain(String[]args){// 1. 创建大模型客户端以OpenAI为例替换成你自己的模型配置OpenAiChatModelchatModelnewOpenAiChatModel();chatModel.setApiKey(你的OpenAI API Key);chatModel.setBaseUrl(https://api.openai.com/v1);// 2. 构建ChatClient注册自定义AdvisorChatClientchatClientChatClient.builder(chatModel)// 注册默认Advisor全局生效.defaultAdvisors(newLoggingAdvisor(),// 日志AdvisornewPromptEnhanceAdvisor()// 提示词增强Advisor).build();// 3. 调用AI非流式StringresponsechatClient.prompt().user(介绍一下Spring AI)// 用户原始提示词.call()// 非流式调用.content();// 获取返回内容System.out.println(AI返回结果response);// 4. 流式调用边返回边打印chatClient.prompt().user(介绍一下Java的新特性).stream()// 流式调用.subscribe(// 每收到一段结果就打印message-System.out.print(message.getContent()),// 异常处理error-System.err.println(流式调用失败error.getMessage()),// 完成后提示()-System.out.println(\n流式调用完成));}}六、使用注意事项避坑指南必须调用 next 方法不管是nextAroundCall()还是nextAroundStream()一定要调用否则请求到不了大模型不可变对象AdvisedRequest/AdvisedResponse是不可变的修改后要重新构建对象比如示例2里的AdvisedRequest.from()异常处理建议在 Advisor 里加异常捕获记录日志方便排查问题单一职责一个 Advisor 只做一件事比如日志只记录日志提示词只做增强不要写大而全的 Advisor版本兼容Spring AI 1.0 M3 对比 M2 有破坏性变更老项目升级要注意接口替换比如RequestAdvisor换成CallAroundAdvisor。总结Spring AI Advisor 是 AI 调用的「拦截器」能在请求前/响应后插入自定义逻辑核心是CallAroundAdvisor非流式和StreamAroundAdvisor流式自定义 Advisor 需实现核心接口指定执行顺序且必须调用执行链的 next 方法才能让请求到达大模型使用 Advisor 要遵循「单一职责」做好异常处理同时注意版本兼容问题。