SpringAI提供了Advisors API来实现请求和响应的拦截,修改,增强Spring应用程序和AI模型的互动。
可以使用ChatClient API来配置现有的advisor,例如:
var chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory), // chat-memory advisor
new QuestionAnswerAdvisor(vectorStore) // RAG advisor
)
.build();
String response = this.chatClient.prompt()
// Set advisor parameters at runtime
.advisors(advisor -> advisor.param("chat_memory_conversation_id", "678")
.param("chat_memory_response_size", 100))
.user(userText)
.call()
.content();
Advisor中的核心组件:
包括非流式场景中的CallAroundAdvisor和CallAroundAdvisorChain构成,其中CallAroundAdvisorChain是由一系列CallAroundAdvisor构成的链。非流式场景中的StreamAroundAdvisor和StreamAroundAdvisorChain构成。
还有AdvisorRequest用于表示没有密封的Prompt请求,AdvisorResponse表示聊天完成的响应,还有上下文AdviseContext,这个上下文用于保存
AdvisorRequest和AdvisorResponse在链中的共享状态。
callAroundNext()和streamAroundNext()是关键的方法,在这个方法中对请求和响应进行响应的操作,并且可以决定是否调用下一个advisor进行后续的操作。
getOrder()提供链中advisor的访问顺序,返回值越小的在链中的位置越靠前,还有getName()方法返回advisor的名称。最后一个advisor由SpringAI框架自动添加,并把请求发送到AI模型。
在链条中越靠前的advisor先执行对AdvisorRequest的操作,越后执行对AdvisorResponse的操作。注意:如果有多个advisor的getOrder()的返回值相同,可能无法保证顺序执行,因此要避免多个相同的order值。
SpringAI框架中的Advisor接口关系:
接下来自定义实现一个advisor:
上述实现了一个问题重读的advisor,就是让AI模型把问题读两遍。
SpringAI框架也提供了一些内置的advisor,比如:
1.MessageChatMemoryAdvisor:添加历史对话为消息列表,以.message(…)的形式插入到prompt,维护完整的对话结构,适用于完整对话上下文,高级模型(部分模型不支持该advisor)
2.PromptChatMemoryAdvisor:添加历史对话为系统提示,拼接成一个字符串插入到系统提示中。适用于简单记忆,对所有模型兼容。
3.VectorStoreChatMemoryAdvisor:从vectorStore中检索相关信息添加到系统提示中,通常用于提供背景信息。
4.QuestionAnswerAdvisor:用户提问时,自动从vectorStore中检索最相关的文档,添加到用户提示中,常用于RAG的精准回答。
SafeGardAdvisor:用于防止模型生成有害或不适信息
要更新 context,需要使用 .updateContext(...) 方法,它会创建一个新的不可变 map,并包含更新后的内容,例如:
@Override
public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {
this.advisedRequest = advisedRequest.updateContext(context -> {
context.put("aroundCallBefore" + getName(), "AROUND_CALL_BEFORE " + getName());
context.put("lastBefore", getName());
return context;
});
// 后续逻辑...
}