顾问API
Spring AI Advisors API 提供了一种灵活且强大的方式,拦截、修改和增强您在 Spring 应用中的 AI 驱动交互。 通过利用 Advisors API,开发者可以创建更复杂、可重复使用且易于维护的 AI 组件。
其主要优势包括封装重复生成式人工智能模式、转换与大型语言模型(LLM)之间的数据转换,以及提供跨多种模型和用例的可移植性。
你可以像以下示例中所示,使用 ChatClient API 配置现有顾问:
ChatMemory chatMemory = ... // Initialize your chat memory store
VectorStore vectorStore = ... // Initialize your vector store
var chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(), // chat-memory advisor
QuestionAnswerAdvisor.builder(vectorStore).build() // RAG advisor
)
.build();
var conversationId = "678";
String response = this.chatClient.prompt()
// Set advisor parameters at runtime
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, conversationId))
.user(userText)
.call()
.content();
建议在建设时通过架构商注册顾问defaultAdvisors()方法。
顾问还参与可观测性堆栈,因此你可以查看与其执行相关的指标和痕迹。
核心组成部分
该 API 包括呼叫顾问和呼叫顾问链对于非流媒体场景,StreamAdvisor和StreamAdvisorChain用于流媒体场景。
它还包括聊天客户端请求代表未封存的提示请求,聊天客户响应聊天补全回复。两者都持有建议上下文通过顾问链共享州份信息。
这建议呼叫()以及adviseStream()是关键的顾问方法,通常执行诸如检查未封存提示词数据、定制和增强提示词数据、调用顾问链中的下一个实体、可选地阻断请求、检查聊天补全响应以及抛出异常以表示处理错误等作。
此外getOrder()方法决定了链中的顾问顺序,而getName()提供独特的顾问名称。
由 Spring AI 框架创建的顾问链允许依序调用多个顾问,按其顺序排列getOrder()值。
较低的数值先执行。
最后一个顾问会自动添加,将请求发送给LLM。
以程图展示了顾问链与聊天模型之间的互动:
-
Spring AI 框架创建了一个
聊天客户端请求来自用户的提示还有一个空洞的顾问上下文对象。 -
链中的每个顾问处理请求,可能会对其进行修改。或者,它可以通过不调用下一个实体来阻止请求。在后一种情况下,顾问负责填写答复。
-
最终顾问由框架提供的,将请求发送给
聊天模式. -
聊天模型的响应随后会通过顾问链返回并转换为
聊天客户响应.后期包含共享顾问上下文实例。 -
每位顾问都可以处理或修改该回复。
-
决赛
聊天客户响应通过提取 返回给客户端聊天补全.
顾问团
链中顾问的执行顺序由getOrder()方法。需要了解的关键点:
-
低阶顾问优先执行。
-
顾问链以堆栈形式运作:
-
链条中的第一位顾问是第一个处理请求的人。
-
它也是最后处理回复的。
-
-
控制执行顺序:
-
将订单设置为
Ordered.HIGHEST_PRECEDENCE以确保顾问在链中首先执行(请求处理最先,响应处理最后)。 -
将订单设置为
Ordered.LOWEST_PRECEDENCE以确保顾问在链中最后被执行(请求处理时最后执行,响应处理时排在最前面)。
-
-
更高的值被解释为优先级较低。
-
如果多个顾问的订单金额相同,他们的执行顺序就无法保证。
|
顺序与执行顺序之间看似矛盾,源于顾问链的堆叠状特性:
|
提醒一下,这里是Spring的语义命令接口:
public interface Ordered {
/**
* Constant for the highest precedence value.
* @see java.lang.Integer#MIN_VALUE
*/
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
/**
* Constant for the lowest precedence value.
* @see java.lang.Integer#MAX_VALUE
*/
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
/**
* Get the order value of this object.
* <p>Higher values are interpreted as lower priority. As a consequence,
* the object with the lowest value has the highest priority (somewhat
* analogous to Servlet {@code load-on-startup} values).
* <p>Same order values will result in arbitrary sort positions for the
* affected objects.
* @return the order value
* @see #HIGHEST_PRECEDENCE
* @see #LOWEST_PRECEDENCE
*/
int getOrder();
}
|
对于需要在输入和输出端都处于链条首位的用例:
|
API 概述
主要的 Advisor 接口位于该软件包中org.springframework.ai.chat.client.advisor.api.以下是您在创建自己顾问时会遇到的关键界面:
public interface Advisor extends Ordered {
String getName();
}
同步和响应式顾问的两个子接口分别是
public interface CallAdvisor extends Advisor {
ChatClientResponse adviseCall(
ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain);
}
和
public interface StreamAdvisor extends Advisor {
Flux<ChatClientResponse> adviseStream(
ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain);
}
要继续建议链,请使用呼叫顾问链和StreamAdvisorChain在您的建议实施中:
接口包括
public interface CallAdvisorChain extends AdvisorChain {
/**
* Invokes the next {@link CallAdvisor} in the {@link CallAdvisorChain} with the given
* request.
*/
ChatClientResponse nextCall(ChatClientRequest chatClientRequest);
/**
* Returns the list of all the {@link CallAdvisor} instances included in this chain at
* the time of its creation.
*/
List<CallAdvisor> getCallAdvisors();
}
和
public interface StreamAdvisorChain extends AdvisorChain {
/**
* Invokes the next {@link StreamAdvisor} in the {@link StreamAdvisorChain} with the
* given request.
*/
Flux<ChatClientResponse> nextStream(ChatClientRequest chatClientRequest);
/**
* Returns the list of all the {@link StreamAdvisor} instances included in this chain
* at the time of its creation.
*/
List<StreamAdvisor> getStreamAdvisors();
}
实施顾问
要创建顾问,可以实现以下一方案呼叫顾问或StreamAdvisor(或者两者兼有)。实现的关键方法是nextCall()对于非流媒体或nextStream()给流媒体顾问。
例子
我们将提供一些实践示例,以说明如何实施顾问以观察和增强用例。
Logging顾问
我们可以实现一个简单的日志管理器,记录聊天客户端请求之前和聊天客户响应在给下一位顾问的电话之后。
注意,顾问只观察请求和响应,不会修改它们。
该实现支持非流媒体和流媒体两种场景。
public class SimpleLoggerAdvisor implements CallAdvisor, StreamAdvisor {
private static final Logger logger = LoggerFactory.getLogger(SimpleLoggerAdvisor.class);
@Override
public String getName() { (1)
return this.getClass().getSimpleName();
}
@Override
public int getOrder() { (2)
return 0;
}
@Override
public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
logRequest(chatClientRequest);
ChatClientResponse chatClientResponse = callAdvisorChain.nextCall(chatClientRequest);
logResponse(chatClientResponse);
return chatClientResponse;
}
@Override
public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest,
StreamAdvisorChain streamAdvisorChain) {
logRequest(chatClientRequest);
Flux<ChatClientResponse> chatClientResponses = streamAdvisorChain.nextStream(chatClientRequest);
return new ChatClientMessageAggregator().aggregateChatClientResponse(chatClientResponses, this::logResponse); (3)
}
private void logRequest(ChatClientRequest request) {
logger.debug("request: {}", request);
}
private void logResponse(ChatClientResponse chatClientResponse) {
logger.debug("response: {}", chatClientResponse);
}
}
| 1 | 为顾问提供独特的名称。 |
| 2 | 你可以通过设置顺序值来控制执行顺序。较低的数值先执行。 |
| 3 | 这消息聚合器是一个将 Flux 响应聚合为单一 ChatClientResponse 的工具类。
这对于日志记录或其他处理方式非常有用,这些处理可以观察整个响应,而非流中单个项目。
注意你不能更改消息聚合器因为它是只读作。 |
重读(Re-Read,RE2)顾问
《重读提升大型语言模型中的推理能力》一文介绍了一种称为重读(Re-Reading,简称Re2)的技术,它提升了大型语言模型的推理能力。 生化危机2的技巧需要像这样增强输入提示:
{Input_Query}
Read the question again: {Input_Query}
实现一个将Re2技术应用于用户输入查询的顾问,可以如下作:
public class ReReadingAdvisor implements BaseAdvisor {
private static final String DEFAULT_RE2_ADVISE_TEMPLATE = """
{re2_input_query}
Read the question again: {re2_input_query}
""";
private final String re2AdviseTemplate;
private int order = 0;
public ReReadingAdvisor() {
this(DEFAULT_RE2_ADVISE_TEMPLATE);
}
public ReReadingAdvisor(String re2AdviseTemplate) {
this.re2AdviseTemplate = re2AdviseTemplate;
}
@Override
public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) { (1)
String augmentedUserText = PromptTemplate.builder()
.template(this.re2AdviseTemplate)
.variables(Map.of("re2_input_query", chatClientRequest.prompt().getUserMessage().getText()))
.build()
.render();
return chatClientRequest.mutate()
.prompt(chatClientRequest.prompt().augmentUserMessage(augmentedUserText))
.build();
}
@Override
public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {
return chatClientResponse;
}
@Override
public int getOrder() { (2)
return this.order;
}
public ReReadingAdvisor withOrder(int order) {
this.order = order;
return this;
}
}
| 1 | 这以前方法通过重读技术增强用户输入查询。 |
| 2 | 你可以通过设置顺序值来控制执行顺序。较低的数值先执行。 |
Spring AI 内置顾问
Spring AI 框架提供多个内置顾问,帮助提升你的 AI 互动能力。以下是可用顾问的概览:
聊天记忆顾问
这些顾问在聊天记忆存储中管理对话历史:
-
消息聊天记忆顾问检索内存并将其作为一组消息添加到提示中。这种方法保持了对话历史的结构。注意,并非所有AI模型都支持这种方法。
-
提示聊天记忆顾问检索内存并将其整合到提示的系统文本中。
-
向量存储聊天记忆顾问从矢量存储器中获取内存并将其添加到提示词的系统文本中。该顾问对于高效搜索和检索大型数据集中的相关信息非常有用。
问答顾问
-
问答顾问该顾问使用向量存储器提供问答功能,实现了朴素RAG(检索增强生成)模式。
-
检索增强顾问Advisor that implements common 检索增强生成(RAG) flows using the building blocks defined in the `org.springframework.ai.rag` package and following the Modular RAG Architecture.
推理顾问
-
重读顾问实现了一种名为RE2的大型语言模型推理重读策略,以增强输入阶段的理解。 基于文章:[重读提升大型语言模型的推理能力](arxiv.org/pdf/2309.06275)。
流媒体与非流媒体
-
非流派顾问负责完整的请求和回复。
-
流式顾问将请求和响应作为连续流处理,采用响应式编程概念(例如,响应用 Flux 表示响应)。
@Override
public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain chain) {
return Mono.just(chatClientRequest)
.publishOn(Schedulers.boundedElastic())
.map(request -> {
// This can be executed by blocking and non-blocking Threads.
// Advisor before next section
})
.flatMapMany(request -> chain.nextStream(request))
.map(response -> {
// Advisor after next section
});
}
破坏API变更
顾问接口
-
在1.0 M2中,有独立的
请求顾问和响应顾问接口。-
请求顾问在ChatModel.call和ChatModel.stream方法。 -
响应顾问以这些方法命名。
-
-
在1.0 M3中,这些接口被以下内容取代:
-
CallAroundAdvisor -
StreamAroundAdvisor
-
-
这
流响应模式,之前是响应顾问,已被移除。 -
在1.0.0版本中,以下接口被替换:
-
CallAroundAdvisor→呼叫顾问,StreamAroundAdvisor→StreamAdvisor,CallAroundAdvisorChain→呼叫顾问链和StreamAroundAdvisorChain→StreamAdvisorChain. -
建议请求→聊天客户端请求和AdivsedResponse(回复)→聊天客户响应.
-