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

SpringAI实现AI应用-自定义顾问(Advisor)

SpringAI实战链接

1.SpringAl实现AI应用-快速搭建-CSDN博客

2.SpringAI实现AI应用-搭建知识库-CSDN博客

3.SpringAI实现AI应用-内置顾问-CSDN博客

4.SpringAI实现AI应用-使用redis持久化聊天记忆-CSDN博客

5.SpringAI实现AI应用-自定义顾问(Advisor)-CSDN博客

概述

经过前几篇帖子的鞭打,现在已经对SpringAI有了一定的了解,继续查看官方文档,顾问(Advisor)里面还有自定义顾问,这篇帖子就说一下如何进行自定义。

SpringAI官方文档

中文版:顾问 API :: Spring AI 参考 - Spring 框架

官方:Advisors API :: Spring AI Reference

Advisors原理

在写代码之前,得先了解Advisor的一些基本信息,虽然官方文档里有说明,但还是感觉太官方了

Spring AI 中的 Advisors(顾问) 是一个关键概念,用于在模型交互过程中动态调整或增强提示词(Prompt)、控制生成过程,或注入业务逻辑。它的核心思想是对 AI 模型的输入/输出进行拦截和增强,类似于 AOP(面向切面编程)中的拦截器。

核心作用

动态修改提示词:在发送给模型前,自动添加上下文、示例或格式化内容。

结果后处理:对模型生成的文本进行过滤、校验或结构化解析。

上下文管理:跨多次对话维护状态(如历史记录、用户偏好)。

业务规则注入:根据业务需求限制或引导模型的输出。

工作原理

Advisor 在请求处理链中的位置:

用户输入 → [Advisor 预处理] → 模型处理 → [Advisor 后处理] → 返回用户

预处理阶段:修改或增强输入的 AdvisedRequest。

后处理阶段:处理模型的 AdvisedResponse。

源码分析

通过官方文档和源码可知(在此就引用官方的图片了),SpringAI的几个内置顾问实现的都是Advisor。

代码实现

废话就不多说了,直接开始干!!!

根据前几篇帖子的,现在已经有一个完整的框架了,能够直接添加代码进行测试了

LoggingAdvisor(日志顾问)

import org.springframework.ai.chat.client.advisor.api.*;
import org.springframework.ai.chat.model.MessageAggregator;
import reactor.core.publisher.Flux;/*** @Author majinzhong* @Date 2025/5/8 11:27* @Version 1.0*/
public class LoggingAdvisor implements CallAroundAdvisor,StreamAroundAdvisor {@Overridepublic AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {System.out.println("调用AI Call之前:"+advisedRequest);AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);System.out.println("调用AI Call之后:"+advisedResponse);return advisedResponse;}@Overridepublic Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {System.out.println("调用AI Stream之前:"+advisedRequest);Flux<AdvisedResponse> advisedResponseFlux = chain.nextAroundStream(advisedRequest);Flux<AdvisedResponse> advisedResponseFlux1 = new MessageAggregator().aggregateAdvisedResponse(advisedResponseFlux, advisedResponse -> System.out.println("调用AI Stream之后:"+advisedResponseFlux));return advisedResponseFlux1;}@Overridepublic String getName() {return this.getClass().getSimpleName();}@Overridepublic int getOrder() {return 0;}
}

AiConfig

    @BeanChatClient chatClient(ChatClient.Builder builder,VectorStore vectorStore) {return builder// 它定义了聊天机器人在回答问题时应当遵循的风格和角色定位。.defaultSystem("你是一个智能机器人,你的名字叫 Spring AI智能机器人")//这里可以添加多个顾问 order(优先级)越小,越先执行// 注意:顾问添加到链中的顺序至关重要,因为它决定了其执行的顺序。每个顾问都会以某种方式修改提示或上下文,一个顾问所做的更改会传递给链中的下一个顾问。// 在此配置中,将首先执行MessageChatMemoryAdvisor,将对话历史记录添加到提示中。然后,问答顾问将根据用户的问题和添加的对话历史进行搜索,从而可能提供更相关的结果。.defaultAdvisors(//内存存储对话记忆new MessageChatMemoryAdvisor(inMemoryChatMemory()),
//                        new PromptChatMemoryAdvisor(inMemoryChatMemory()),// QuestionAnswerAdvisor 此顾问使用矢量存储提供问答功能,实现RAG(检索增强生成)模式
//                        QuestionAnswerAdvisor.builder(vectorStore).order(1).build(),// SafeGuardAdvisor是一个安全防护顾问,它确保生成的内容符合道德和法律标准。SafeGuardAdvisor.builder().sensitiveWords(List.of("色情", "暴力")) // 敏感词列表.order(2) // 设置优先级.failureResponse("抱歉,我无法回答这个问题。").build(), // 敏感词过滤失败时的响应// SimpleLoggerAdvisor是一个记录ChatClient的请求和响应数据的顾问。这对于调试和监控您的AI交互非常有用,建议将其添加到链的末尾。new LoggingAdvisor()).defaultOptions(ChatOptions.builder().topP(0.7) // 取值越大,生成的随机性越高;取值越低,生成的随机性越低。默认值为0.8.build()).build();}

将原来代码中的SimpleLoggerAdvisor换成自定义的日志顾问,因为SimpleLoggerAdvisor没有按照自己的要求进行打印

测试

经过测试,已经在控制台进行打印了

ReReadingAdvisor(重新阅读RE2顾问)

import org.springframework.ai.chat.client.advisor.api.*;
import reactor.core.publisher.Flux;import java.util.HashMap;
import java.util.Map;/*** @Author majinzhong* @Date 2025/5/8 15:10* @Version 1.0*/
public class ReReadingAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {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("你的作用是什么,谁创造的你").userParams(advisedUserParams).build();}@Overridepublic AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {return chain.nextAroundCall(this.before(advisedRequest));}@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();}
}

继续修改AIConfig,添加自定义的顾问

测试

经测试可知,自定义的RE2顾问已经成功

RetryAdvisor(异常重试顾问)

import org.springframework.ai.chat.client.advisor.api.*;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import reactor.core.publisher.Flux;/*** @Author majinzhong* @Date 2025/5/8 15:21* @Version 1.0*/
public class RetryAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {private final RetryTemplate retryTemplate;public RetryAdvisor() {this.retryTemplate = new RetryTemplate();// 配置重试策略:最多2次,间隔1秒SimpleRetryPolicy policy = new SimpleRetryPolicy();policy.setMaxAttempts(2);FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();backOffPolicy.setBackOffPeriod(1000); // 1秒retryTemplate.setRetryPolicy(policy);retryTemplate.setBackOffPolicy(backOffPolicy);}@Overridepublic AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);return retryTemplate.execute(context -> {return advisedResponse;});}@Overridepublic Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {return chain.nextAroundStream(advisedRequest);}@Overridepublic String getName() {return this.getClass().getSimpleName();}@Overridepublic int getOrder() {return 0;}
}

还要修改AiConfig

这个没有进行测试,因为是返回值异常的时候才会进行重试

至此自定义顾问已经完成,可以按照自己的业务需求进行修改

补充

之前说过顾问可以提前统一进行设置,也可以单独在方法上进行设置

其实,每个AI大模型也可以单独在方法上进行设置

统一配置AI模型

AI大模型在application.yml文件里设置

在AiConfig里进行配置大模型的名称、顾问等信息

方法上配置AI大模型

    /*** 根据消息直接输出回答* @param map* @return*/@PostMapping("/ai/call")public String call(@RequestBody Map<String,String> map) {String message = map.get("message");
//        return chatClient.prompt().user(message).call().content().trim();OpenAiChatOptions options = OpenAiChatOptions.builder().model("THUDM/GLM-4-9B-0414").temperature(0.5).build();String content = chatClient.prompt().system("你是一个AI小助手,能帮助我们一起学习java").advisors(new LoggingAdvisor(),new ReReadingAdvisor()).user(message).options(options).call().content();return content;}

OpenAiChatOptions进行配置AI大模型

chatClient对OpenAiChatOptions配置的大模型进行配置

测试

统一配置

方法配置

通过测试的结果和日志可以知道,AI大模型既可以进行统一配置,也可以在方法上设置

相关文章:

  • Kubernetes HPA 深度解析:生产环境自动扩缩容实战指南
  • 计算机网络笔记(十六)——3.3使用广播信道的数据链路层
  • 高效文件夹迁移工具,轻松实现批量文件管理
  • PVP鼠标推荐(deepseek)
  • 谷歌 Gemma 大模型安装步骤
  • Salesforce认证体系大升级!7月21日正式上线新平台
  • 第37次CCF--机器人饲养
  • C31-形参与实参的区别
  • Harmonyos-属性修改器和更新器
  • JavaScript基础 (二)
  • 二叉树结构的深入学习
  • PostgreSQL安装与升级cron插件
  • 基于STM32、HAL库的FT234XD USB转UART收发器 驱动程序设计
  • 企业数字化转型的建设流程和实施条件分别是什么?
  • 【Windows 环境安装ollama,通过ollama拉起大模型】
  • 单片机 + 图像处理芯片 + TFT彩屏 指示灯控件
  • 《P2880 [USACO07JAN] 平衡系列 G》
  • 19.idea调试功能
  • 【嵌入式开发-RS-485】
  • 阀门产业发展方向报告(石油化工阀门应用技术交流大会)
  • 看展览|2025影像上海艺博会:市场与当代媒介中的摄影
  • 75岁亚当·费舍尔坐镇,再现80分钟马勒《第九交响曲》
  • 大风暴雨致湖南岳阳县6户房屋倒塌、100多户受损
  • 上海如何为街镇营商环境赋能?送政策、配资源、解难题、强活力
  • 咖啡戏剧节举办第五年,上生新所“无店不咖啡,空间皆可戏”
  • 农行原首席专家兼浙江省分行原行长冯建龙主动投案,正接受审查调查