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的精彩世界。
一、核心组件与工作流程
(一)核心组件
- Advisor接口体系
Spring AI Advisors API的核心接口是Advisor
,它继承自Spring的Ordered
接口,这意味着每个顾问都有一个顺序值,用于决定其在顾问链中的执行顺序。Advisor
接口主要定义了获取顾问唯一名称的getName
方法。在此基础上,有两个关键的子接口:CallAroundAdvisor
:用于非流式处理场景,其aroundCall
方法围绕ChatModel#call(Prompt)
方法进行增强。它接收AdvisedRequest
和CallAroundAdvisorChain
作为参数,通过调用chain.nextAroundCall(advisedRequest)
方法继续顾问链的执行,并返回AdvisedResponse
。StreamAroundAdvisor
:针对流式处理场景,aroundStream
方法负责处理流式的请求和响应。它接收AdvisedRequest
和StreamAroundAdvisorChain
,通过chain.nextAroundStream(advisedRequest)
推进顾问链,返回Flux<AdvisedResponse>
。
- 请求与响应相关类
AdvisedRequest
:表示未封装的Prompt请求,它包含了用户的输入以及其他相关参数,并且持有一个advise - context
,用于在顾问链中共享状态。AdvisedResponse
:用于获取Chat Completion响应,同样也包含advise - context
,方便各个顾问在处理响应时共享和修改相关状态。CallAroundAdvisorChain
和StreamAroundAdvisorChain
:这两个接口在顾问实现中用于继续顾问链的执行。CallAroundAdvisorChain
的nextAroundCall
方法用于非流式处理,而StreamAroundAdvisorChain
的nextAroundStream
方法用于流式处理。
(二)工作流程
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,表示较高优先级)。在aroundCall
和aroundStream
方法中,分别实现了对非流式和流式请求及响应的日志记录。
(二)重读(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技术。aroundCall
和aroundStream
方法分别拦截非流式和流式请求,并应用该技术。同样,通过getName
和getOrder
方法设置顾问名称和执行顺序。
三、Spring AI内置顾问程序
(一)聊天记忆顾问
- MessageChatMemoryAdvisor:从聊天内存存储中检索内存,并将其作为消息集合添加到提示符中,这种方式能维护会话历史记录的结构,但并非所有AI模型都支持。
- PromptChatMemoryAdvisor:将检索到的内存合并到提示的系统文本中。
- VectorStoreChatMemoryAdvisor:从VectorStore中检索内存,并添加到提示符的系统文本中,可用于从大型数据集中高效搜索和检索相关信息。
(二)问题解答顾问
QuestionAnswerAdvisor:使用向量存储来提供问答功能,实现RAG(检索增强生成)模式,能有效提升问答场景下的AI交互效果。
(三)内容安全顾问
SafeGuardAdvisor:用于防止模型生成有害或不适当的内容,保障AI交互的安全性和合规性。
四、流式处理与非流式处理
非流式处理顾问处理完整的请求和响应,而流式处理顾问则使用反应式编程概念(如Flux
)将请求和响应作为连续流处理。例如,在流式处理的aroundStream
方法实现中,可以通过Mono
和Flux
的操作来对请求和响应流进行处理。
@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});
}
五、最佳实践与注意事项
- 专注特定任务:让每个顾问专注于特定的任务,这样可以实现更好的模块化,提高代码的可维护性和可扩展性。
- 共享状态:合理使用
adviseContext
在顾问之间共享状态,确保各个顾问之间能够协同工作,实现复杂的AI交互逻辑。 - 实现流式与非流式版本:为了实现最大的灵活性,尽量实施顾问的流式处理和非流式处理版本,以适应不同的应用场景。
- 考虑执行顺序:仔细考虑顾问在供应链中的顺序,根据业务需求确保数据能够正常流动,避免因顺序不当导致的错误或性能问题。
六、向后兼容性与重大API更改
(一)向后兼容性
AdvisedRequest
类被移动到了新的package中,在进行代码升级时需要注意相关的包路径更改。
(二)重大API更改
从1.0 M2版本到1.0 M3版本,Spring AI Advisor链发生了重大变化。在1.0 M2中,有单独的RequestAdvisor
和ResponseAdvisor
接口,分别在ChatModel.call
和ChatModel.stream
方法前后调用。而在1.0 M3中,这些接口被替换为CallAroundAdvisor
和StreamAroundAdvisor
,并且StreamResponseMode
(以前是ResponseAdvisor
的一部分)已被删除。此外,上下文映射的处理方式也发生了改变,从1.0 M2中的可变、单独方法参数传递,变为1.0 M3中的AdvisedRequest
和AdvisedResponse
记录中的不可变映射,并且需要使用updateContext
方法来更新上下文。
总结
Spring AI Advisors API为开发者在Spring应用程序中实现灵活、强大的AI驱动交互提供了丰富的工具和机制。通过自定义顾问以及利用内置顾问程序,我们能够轻松地封装复杂的AI逻辑、转换数据并实现各种实用功能。在使用过程中,遵循最佳实践,注意向后兼容性和API的变化,能够帮助我们更好地利用这一强大的API。无论是构建智能聊天应用,还是为其他业务场景添加AI支持,Spring AI Advisors API都能成为我们开发过程中的得力助手,助力我们打造出更具创新性和竞争力的应用程序。希望本文能帮助大家对Spring AI Advisors API有更深入的理解和应用,在AI开发的道路上更进一步。