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

Spring AI alibaba Prompt模板Advisor自定义 - 实践

本文为个人学习笔记整理,仅供交流参考,非专业教学资料,内容请自行甄别。

文章目录

  • 前言
  • 一、Prompt
  • 二、Prompt模板化配置
  • 三、Advisor
  • 四、自定义Advisor


前言

  本篇主要介绍Spring AI alibaba Prompt的概念,以及如何模板化配置,自定义Advisor拦截器。

一、Prompt

  Prompt是提示词,简单来说,每次使用AI,在对话框中输入的提问内容,对于大模型来说就是提示词。
在这里插入图片描述
  提示词也可以进行细分,主要可分为以下三种类型:

  这三类提示词在代码中的体现,都实现了Message接口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、Prompt模板化配置

  在AI应用开发中,需要定义系统提示词。可以将提示词作为常量定义,或者保存在数据库中。Spring AI的官方提供了模板化配置的功能。模板化配置
  Spring AI 中快速模板化的一个关键组件是PromptTemplate类,旨在方便创建结构化提示,然后发送到人工智能模型进行处理。
在这里插入图片描述
  Spring AI 提供了PromptTemplate的不同实现类,对应不同角色的消息:

  同时Spring AI 支持从模板文件中读取Prompt信息,并且动态替换占位符的功能,首先在项目的resources目录下定义一个文件:system-message.st,文件中的内容带有占位符:

“扮演深耕{field}领域的专家。开场向用户表明身份,告知用户可倾诉{type}难题。引导用户详述事情经过、对方反应及自身想法,以便给出专属解决方案。”

  因为上述的文案,是给AI大模型预设的,所以应该构造一个SystemPromptTemplate,并且将读取到的文件内容赋值给它:

@Value("classpath:/promts/system-message.st")
Resource systemResource;
//.....
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);

  然后使用SystemPromptTemplatecreateMessageAPI,进行占位符填充,并获取最终的提示词。

String text = systemPromptTemplate.createMessage(Map.of("field", "JAVA编程", "type", "学习方向")).getText();

三、Advisor

  Spring AI中的Advisor,相当于Spring 的AOP切面,允许用户在调用大模型前后,执行一些操作,getOrder()方法决定多个Advisor组成的责任链的执行顺序(较低的值首先被执行),而getName()则是提供一个自定义的名称。
在这里插入图片描述
  它有两个实现类,分别是CallAroundAdvisorStreamAroundAdvisor。代表了不同的模式(流式或非流式)。用户在自定义实现时最好两个都要实现。
在这里插入图片描述
  和Spring 的 AOP切面一样,多个Advisor会组成责任链,责任链和大模型之间的交互:

  1. Spring AI从用户的Prompt提示词,创建一个ChatClientRequest ,并且创建一个context 上下文对象,用于在整个责任链中进行消息传递。
  2. 链中的每个Advisor都会处理请求,并可能对请求的内容进行修改。也可以直接拦截请求,不向下一个Advisor传递,并且构造响应,返回结果。
  3. 由框架提供的最终Advisor将请求发送至大模型。
  4. 模型的响应随后通过责任链进行传递并转化为ChatClientResponse(包含了context 上下文对象),每个后置的Advisor也可以对响应进行处理。
  5. 最终的ChatClientResponse通过提取ChatCompletion返回客户端。

  Spring AI提供了一些内置的Advisor,对功能进行扩展:

在这里插入图片描述
日志拦截器,在请求和响应时打印日志,但是级别是debug
在这里插入图片描述
敏感词拦截器,拦截用户自定义的敏感词,如果发现用户提问包含敏感词,就直接拦截,构造响应返回给用户,响应内容也是可以用户自定义的

  可以通过ChatClientdefaultAdvisorsAPI,加入自定义的拦截器。

chatClient = ChatClient.builder(
dashScopeChatModel
).defaultSystem(text)
//基于数据库的会话记忆保存
.defaultAdvisors(new MessageChatMemoryAdvisor(dbBasedChatMemory),
//自定义日志拦截器
new MyLogAdvisor(),
//敏感词检测
new SensitiveWordCheckAdvisor())
.build();

四、自定义Advisor

  用户自定义Advisor,最好需要同时实现CallAroundAdvisor, StreamAroundAdvisor两个接口,分别重写流式和非流式的相关方法,例如自定义的日志拦截器:

/**
* 自定义日志拦截器
*/
@Slf4j
public class MyLogAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {
@Override
public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {
//前置增强
log.info("自定义日志拦截器,AI request:{}",advisedRequest.userText());
//调用下一个拦截器
AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);
//后置增强
log.info("自定义日志拦截器,AI response:{}",advisedResponse.response().getResult().getOutput().getText());
return advisedResponse;
}
@Override
public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {//前置增强log.info("自定义日志拦截器,AI request:{}",advisedRequest.userText());Flux<AdvisedResponse> advisedResponseFlux = chain.nextAroundStream(advisedRequest);return new MessageAggregator().aggregateAdvisedResponse(advisedResponseFlux, new Consumer<AdvisedResponse>() {@Overridepublic void accept(AdvisedResponse advisedResponse) {//后置增强log.info("自定义日志拦截器,AI response:{}",advisedResponse.response().getResult().getOutput().getText());}});}@Overridepublic String getName() {return this.getClass().getSimpleName();}@Overridepublic int getOrder() {return 0;}}

  自定义Re2拦截器,其实现方式是取出用户的提问词,然后重复发给AI。但是每次用户的对话是需要消耗token的,这样的做法相当于消耗了双倍的token。

/**
* 自定义 Re2 Advisor
* 可提高大型语言模型的推理能力
*/
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("""{re2_input_query}Read the question again: {re2_input_query}""").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();}}
http://www.jsqmd.com/news/23808/

相关文章:

  • 根号分治、分块、莫队
  • 11-文件上传
  • wqe
  • 集采带量下医疗器械生产厂家如何通过数字化转型实现降本增效
  • 告别命名误区!深度剖析TurtleBot3 vs. TurtleBot4 开源平台
  • 2025年锌铝镁桥架公司、口碑好的锌铝镁桥架品牌、行业内锌铝镁桥架供应商、锌铝镁桥架公司推荐榜、靠谱的锌铝镁桥架供应厂家综合评测
  • 嵌入式基础--第七周作业--OLED显示
  • TensorFlow与PyTorch深度对比分析:从基础原理到实战选择的完整指南 - 指南
  • 102302105汪晓红作业1
  • 【IEEE出版 | 重庆邮电大学主办 | 多届次、高层次】第六届人工智能与计算机工程国际学术会议(ICAICE 2025)
  • 普通幂转下降幂
  • 解决Java项目在复杂网络环境下访问外网不通的问题
  • 私有2.4G无线对讲机方案:BLE芯片+PA芯片
  • PyCharm 2024超详细下载安装教程(附安装包+激活教程)超详细图文步骤
  • 发布会回顾|袋鼠云发布多模态数据中台,重构AI时代的数据底座
  • Docker容器里面部署的Jenkins的Java17升级到21版本(无需删除之前容器,内部在线升级) - 攻城狮
  • 布谷直播系统源码:高并发直播架构设计到搭建部署配置
  • 医疗器械行业数字化破局:一体化平台正在淘汰多系统集成模式
  • 报表知识
  • 【IEEE出版 | 往届均已完成见刊检索 | 见刊检索稳定】第七届信息与计算机前沿术国际学术会议(ICFTIC 2025)
  • 动态点分树
  • 2025年隔热条厂家权威推荐榜:尼龙隔热条/PA66尼龙隔热条/建筑用隔热条/断桥铝门窗隔热条/幕墙隔热条/阳光房隔热条/国标隔热条精选
  • 【前端效率工具】:告别右键另存,不到 50 行代码一键批量下载网页图片
  • 特殊符号的输入
  • Luogu P3237 [HNOI2014] 米特运输 题解 [ 蓝 ] [ 树形 DP ] [ 哈希 ]
  • 「Gym 104901F」Say Hello to the Future
  • 渐进过程中大O与小o混用
  • Navicat 17 超详细保姆级下载安装教程:附激活工具使用步骤​
  • 消息队列的有序性
  • 【LTDC】DMA2D —— 嵌入式系统的 GPU