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

Spring AI Advisors API:AI交互的灵活增强利器

Spring AI Advisors API:AI交互的灵活增强利器

前言

在当今的软件开发领域,随着人工智能技术的飞速发展,将AI融入应用程序变得越来越普遍。Spring AI作为一个强大的框架,为开发者提供了便捷的方式来实现这一目标。其中的Advisors API更是一个亮点,它为拦截、修改和增强Spring应用程序中的AI驱动交互提供了灵活而强大的途径。无论是封装重复的生成式AI模式,还是转换与大型语言模型(LLM)交互的数据,Advisors API都能大显身手,助力开发者打造更复杂、可重用且可维护的AI组件。接下来,让我们深入探索Spring AI Advisors API的精彩世界。

一、核心组件与工作流程

在这里插入图片描述

(一)核心组件

  1. Advisor接口体系
    Spring AI Advisors API的核心接口是Advisor,它继承自Spring的Ordered接口,这意味着每个顾问都有一个顺序值,用于决定其在顾问链中的执行顺序。Advisor接口主要定义了获取顾问唯一名称的getName方法。在此基础上,有两个关键的子接口:
    • CallAroundAdvisor:用于非流式处理场景,其aroundCall方法围绕ChatModel#call(Prompt)方法进行增强。它接收AdvisedRequestCallAroundAdvisorChain作为参数,通过调用chain.nextAroundCall(advisedRequest)方法继续顾问链的执行,并返回AdvisedResponse
    • StreamAroundAdvisor:针对流式处理场景,aroundStream方法负责处理流式的请求和响应。它接收AdvisedRequestStreamAroundAdvisorChain,通过chain.nextAroundStream(advisedRequest)推进顾问链,返回Flux<AdvisedResponse>
  2. 请求与响应相关类
    • AdvisedRequest:表示未封装的Prompt请求,它包含了用户的输入以及其他相关参数,并且持有一个advise - context,用于在顾问链中共享状态。
    • AdvisedResponse:用于获取Chat Completion响应,同样也包含advise - context,方便各个顾问在处理响应时共享和修改相关状态。
    • CallAroundAdvisorChainStreamAroundAdvisorChain:这两个接口在顾问实现中用于继续顾问链的执行。CallAroundAdvisorChainnextAroundCall方法用于非流式处理,而StreamAroundAdvisorChainnextAroundStream方法用于流式处理。

(二)工作流程

Spring AI框架首先根据用户的Prompt创建一个AdvisedRequest对象,同时生成一个空的AdvisorContext对象。然后,顾问链中的每个顾问依次处理这个请求。顾问可以选择修改请求,也可以通过不调用链中的下一个实体来阻止请求的继续传递。如果顾问阻止了请求,那么它需要自行填写回复。当请求到达框架提供的最后一个顾问时,该顾问会将请求发送到Chat Model。Chat Model生成的响应会通过顾问链反向传回,并被转换为AdvisedResponse。在这个过程中,每个顾问都有机会处理或修改响应,最终提取出ChatCompletion
在这里插入图片描述

二、实施Advisor

(一)日志记录顾问

我们来看一个简单的日志记录顾问的实现。这个顾问的作用是在调用链中的下一个顾问之前记录AdvisedRequest,在之后记录AdvisedResponse,且不修改请求和响应。

public class SimpleLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {private static final Logger logger = LoggerFactory.getLogger(SimpleLoggerAdvisor.class);@Overridepublic String getName() {return this.getClass().getSimpleName();}@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);return new MessageAggregator().aggregateAdvisedResponse(advisedResponses,advisedResponse -> logger.debug("AFTER: {}", advisedResponse));}
}

在这个实现中,通过getName方法为顾问提供了唯一名称,通过getOrder方法设置了执行顺序(这里设置为0,表示较高优先级)。在aroundCallaroundStream方法中,分别实现了对非流式和流式请求及响应的日志记录。

(二)重读(Re2)顾问

另一个示例是应用Re - Reading(Re2)技术的顾问。该技术可以提高大型语言模型的推理能力,通过扩充输入提示来实现。

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();}
}

before方法负责扩充用户的输入查询,应用Re - Reading技术。aroundCallaroundStream方法分别拦截非流式和流式请求,并应用该技术。同样,通过getNamegetOrder方法设置顾问名称和执行顺序。

三、Spring AI内置顾问程序

(一)聊天记忆顾问

  1. MessageChatMemoryAdvisor:从聊天内存存储中检索内存,并将其作为消息集合添加到提示符中,这种方式能维护会话历史记录的结构,但并非所有AI模型都支持。
  2. PromptChatMemoryAdvisor:将检索到的内存合并到提示的系统文本中。
  3. VectorStoreChatMemoryAdvisor:从VectorStore中检索内存,并添加到提示符的系统文本中,可用于从大型数据集中高效搜索和检索相关信息。

(二)问题解答顾问

QuestionAnswerAdvisor:使用向量存储来提供问答功能,实现RAG(检索增强生成)模式,能有效提升问答场景下的AI交互效果。

(三)内容安全顾问

SafeGuardAdvisor:用于防止模型生成有害或不适当的内容,保障AI交互的安全性和合规性。

四、流式处理与非流式处理

非流式处理顾问处理完整的请求和响应,而流式处理顾问则使用反应式编程概念(如Flux)将请求和响应作为连续流处理。例如,在流式处理的aroundStream方法实现中,可以通过MonoFlux的操作来对请求和响应流进行处理。

@Override
public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {return Mono.just(advisedRequest).publishOn(Schedulers.boundedElastic()).map(request -> {// This can be executed by blocking and non - blocking Threads.// Advisor before next section}).flatMapMany(request -> chain.nextAroundStream(request)).map(response -> {// Advisor after next section});
}

在这里插入图片描述

五、最佳实践与注意事项

  1. 专注特定任务:让每个顾问专注于特定的任务,这样可以实现更好的模块化,提高代码的可维护性和可扩展性。
  2. 共享状态:合理使用adviseContext在顾问之间共享状态,确保各个顾问之间能够协同工作,实现复杂的AI交互逻辑。
  3. 实现流式与非流式版本:为了实现最大的灵活性,尽量实施顾问的流式处理和非流式处理版本,以适应不同的应用场景。
  4. 考虑执行顺序:仔细考虑顾问在供应链中的顺序,根据业务需求确保数据能够正常流动,避免因顺序不当导致的错误或性能问题。

六、向后兼容性与重大API更改

(一)向后兼容性

AdvisedRequest类被移动到了新的package中,在进行代码升级时需要注意相关的包路径更改。

(二)重大API更改

从1.0 M2版本到1.0 M3版本,Spring AI Advisor链发生了重大变化。在1.0 M2中,有单独的RequestAdvisorResponseAdvisor接口,分别在ChatModel.callChatModel.stream方法前后调用。而在1.0 M3中,这些接口被替换为CallAroundAdvisorStreamAroundAdvisor,并且StreamResponseMode(以前是ResponseAdvisor的一部分)已被删除。此外,上下文映射的处理方式也发生了改变,从1.0 M2中的可变、单独方法参数传递,变为1.0 M3中的AdvisedRequestAdvisedResponse记录中的不可变映射,并且需要使用updateContext方法来更新上下文。

总结

Spring AI Advisors API为开发者在Spring应用程序中实现灵活、强大的AI驱动交互提供了丰富的工具和机制。通过自定义顾问以及利用内置顾问程序,我们能够轻松地封装复杂的AI逻辑、转换数据并实现各种实用功能。在使用过程中,遵循最佳实践,注意向后兼容性和API的变化,能够帮助我们更好地利用这一强大的API。无论是构建智能聊天应用,还是为其他业务场景添加AI支持,Spring AI Advisors API都能成为我们开发过程中的得力助手,助力我们打造出更具创新性和竞争力的应用程序。希望本文能帮助大家对Spring AI Advisors API有更深入的理解和应用,在AI开发的道路上更进一步。

http://www.xdnf.cn/news/3813.html

相关文章:

  • ES6入门---第三单元 模块三:async、await
  • 网络:TCP三次握手、四次挥手
  • 介词:连接名词与句子其他成分的桥梁
  • 互联网大厂Java面试:从基础到实战
  • 【漫话机器学习系列】239.训练错误率(Training Error Rate)
  • vulkanscenegraph显示倾斜模型(6.4)-多线程下的记录与提交
  • Dalvik虚拟机和ART虚拟机
  • ART 下 Dex 加载流程源码分析 和 通用脱壳点
  • 【ArcGIS微课1000例】0145:如何按照自定义形状裁剪数据框?
  • 学习黑客Linux权限
  • 【中间件】brpc_基础_用户态线程中断
  • LeetCode每日一题5.4
  • 架构思维:利用全量缓存架构构建毫秒级的读服务
  • 2001-2023年 上市公司-企业广告支出数据-社科数据
  • 使用宝塔面板、青龙面板实现定时推送功能
  • 【数据结构】稀疏矩阵的快速转置
  • 单细胞测序数据分析试验设计赏析(二)
  • Android 输入控件事件使用示例
  • 信息系统监理师第二版教材模拟题第一组(含解析)
  • HTML学习笔记(7)
  • PostgreSQL 的 ANALYZE 命令
  • PostgreSQL 查看索引碎片的方法
  • 论文阅读笔记——STDArm
  • PostgreSQL 判断索引是否重建过的方法
  • 4电池_基于开关电容的均衡
  • Ubuntu 系统上广受好评的浏览器推荐
  • 蘑菇管理——AI与思维模型【94】
  • 【翻译、转载】使用 LLM 构建 MCP
  • 【五一培训】Day 3
  • 机器学习+多目标优化的算法如何设计?