最新快照版本请使用Spring AI 1.1.0spring-doc.cadn.net.cn

顾问API

Spring AI Advisors API 提供了一种灵活且强大的方式,拦截、修改和增强您在 Spring 应用中的 AI 驱动交互。 通过利用 Advisors API,开发者可以创建更复杂、可重复使用且易于维护的 AI 组件。spring-doc.cadn.net.cn

其主要优势包括封装重复生成式人工智能模式、转换与大型语言模型(LLM)之间的数据转换,以及提供跨多种模型和用例的可移植性。spring-doc.cadn.net.cn

你可以像以下示例中所示,使用 ChatClient API 配置现有顾问:spring-doc.cadn.net.cn

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()方法。spring-doc.cadn.net.cn

顾问还参与可观测性堆栈,因此你可以查看与其执行相关的指标和痕迹。spring-doc.cadn.net.cn

核心组成部分

该 API 包括呼叫顾问呼叫顾问链对于非流媒体场景,StreamAdvisorStreamAdvisorChain用于流媒体场景。 它还包括聊天客户端请求代表未封存的提示请求,聊天客户响应聊天补全回复。两者都持有建议上下文通过顾问链共享州份信息。spring-doc.cadn.net.cn

Advisor API 类

建议呼叫()以及adviseStream()是关键的顾问方法,通常执行诸如检查未封存提示词数据、定制和增强提示词数据、调用顾问链中的下一个实体、可选地阻断请求、检查聊天补全响应以及抛出异常以表示处理错误等作。spring-doc.cadn.net.cn

此外getOrder()方法决定了链中的顾问顺序,而getName()提供独特的顾问名称。spring-doc.cadn.net.cn

由 Spring AI 框架创建的顾问链允许依序调用多个顾问,按其顺序排列getOrder()值。 较低的数值先执行。 最后一个顾问会自动添加,将请求发送给LLM。spring-doc.cadn.net.cn

以程图展示了顾问链与聊天模型之间的互动:spring-doc.cadn.net.cn

Advisors API 流程
  1. Spring AI 框架创建了一个聊天客户端请求来自用户的提示还有一个空洞的顾问上下文对象。spring-doc.cadn.net.cn

  2. 链中的每个顾问处理请求,可能会对其进行修改。或者,它可以通过不调用下一个实体来阻止请求。在后一种情况下,顾问负责填写答复。spring-doc.cadn.net.cn

  3. 最终顾问由框架提供的,将请求发送给聊天模式.spring-doc.cadn.net.cn

  4. 聊天模型的响应随后会通过顾问链返回并转换为聊天客户响应.后期包含共享顾问上下文实例。spring-doc.cadn.net.cn

  5. 每位顾问都可以处理或修改该回复。spring-doc.cadn.net.cn

  6. 决赛聊天客户响应通过提取 返回给客户端聊天补全.spring-doc.cadn.net.cn

顾问团

链中顾问的执行顺序由getOrder()方法。需要了解的关键点:spring-doc.cadn.net.cn

顺序与执行顺序之间看似矛盾,源于顾问链的堆叠状特性:spring-doc.cadn.net.cn

提醒一下,这里是Spring的语义命令接口:spring-doc.cadn.net.cn

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

对于需要在输入和输出端都处于链条首位的用例:spring-doc.cadn.net.cn

  1. 为双方分别使用不同的顾问。spring-doc.cadn.net.cn

  2. 用不同的顺序值配置它们。spring-doc.cadn.net.cn

  3. 利用顾问的上下文在他们之间共享状态。spring-doc.cadn.net.cn

API 概述

主要的 Advisor 接口位于该软件包中org.springframework.ai.chat.client.advisor.api.以下是您在创建自己顾问时会遇到的关键界面:spring-doc.cadn.net.cn

public interface Advisor extends Ordered {

	String getName();

}

同步和响应式顾问的两个子接口分别是spring-doc.cadn.net.cn

public interface CallAdvisor extends Advisor {

	ChatClientResponse adviseCall(
		ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain);

}
public interface StreamAdvisor extends Advisor {

	Flux<ChatClientResponse> adviseStream(
		ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain);

}

要继续建议链,请使用呼叫顾问链StreamAdvisorChain在您的建议实施中:spring-doc.cadn.net.cn

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()给流媒体顾问。spring-doc.cadn.net.cn

例子

我们将提供一些实践示例,以说明如何实施顾问以观察和增强用例。spring-doc.cadn.net.cn

Logging顾问

我们可以实现一个简单的日志管理器,记录聊天客户端请求之前和聊天客户响应在给下一位顾问的电话之后。 注意,顾问只观察请求和响应,不会修改它们。 该实现支持非流媒体和流媒体两种场景。spring-doc.cadn.net.cn

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的技巧需要像这样增强输入提示:spring-doc.cadn.net.cn

{Input_Query}
Read the question again: {Input_Query}

实现一个将Re2技术应用于用户输入查询的顾问,可以如下作:spring-doc.cadn.net.cn

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 互动能力。以下是可用顾问的概览:spring-doc.cadn.net.cn

聊天记忆顾问

这些顾问在聊天记忆存储中管理对话历史:spring-doc.cadn.net.cn

问答顾问
  • 问答顾问spring-doc.cadn.net.cn

    该顾问使用向量存储器提供问答功能,实现了朴素RAG(检索增强生成)模式。spring-doc.cadn.net.cn

  • 检索增强顾问spring-doc.cadn.net.cn

    Advisor that implements common 检索增强生成(RAG) flows using the building blocks defined in the `org.springframework.ai.rag` package and following the Modular RAG Architecture.
推理顾问
内容安全顾问

流媒体与非流媒体

顾问流派与非流派流
  • 非流派顾问负责完整的请求和回复。spring-doc.cadn.net.cn

  • 流式顾问将请求和响应作为连续流处理,采用响应式编程概念(例如,响应用 Flux 表示响应)。spring-doc.cadn.net.cn

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

最佳实践

  1. 让顾问专注于具体任务,以实现更好的模块化。spring-doc.cadn.net.cn

  2. 使用该建议语境必要时在顾问之间共享状态。spring-doc.cadn.net.cn

  3. 同时实施流媒体和非流媒体版本的导师,以获得最大灵活性。spring-doc.cadn.net.cn

  4. 仔细考虑顾问链中的顺序,以确保数据流畅。spring-doc.cadn.net.cn

破坏API变更

顾问接口

上下文地图处理